xref: /reactos/dll/win32/netcfgx/netcfg_iface.c (revision 40462c92)
1 #include "precomp.h"
2 
3 typedef struct
4 {
5     const INetCfg * lpVtbl;
6     const INetCfgLock * lpVtblLock;
7     const INetCfgPnpReconfigCallback *lpVtblPnpReconfigCallback;
8     LONG                       ref;
9     BOOL bInitialized;
10     HANDLE hMutex;
11     NetCfgComponentItem *pNet;
12     NetCfgComponentItem * pService;
13     NetCfgComponentItem * pClient;
14     NetCfgComponentItem * pProtocol;
15 } INetCfgImpl, *LPINetCfgImpl;
16 
17 static __inline LPINetCfgImpl impl_from_INetCfgLock(INetCfgLock *iface)
18 {
19     return (INetCfgImpl*)((char *)iface - FIELD_OFFSET(INetCfgImpl, lpVtblLock));
20 }
21 
22 static __inline LPINetCfgImpl impl_from_INetCfgPnpReconfigCallback(INetCfgPnpReconfigCallback *iface)
23 {
24     return (INetCfgImpl*)((char *)iface - FIELD_OFFSET(INetCfgImpl, lpVtblPnpReconfigCallback));
25 }
26 
27 
28 HRESULT
29 WINAPI
30 INetCfgLock_fnQueryInterface(
31     INetCfgLock * iface,
32     REFIID iid,
33     LPVOID * ppvObj)
34 {
35     INetCfgImpl * This = impl_from_INetCfgLock(iface);
36     return INetCfg_QueryInterface((INetCfg*)This, iid, ppvObj);
37 }
38 
39 
40 ULONG
41 WINAPI
42 INetCfgLock_fnAddRef(
43     INetCfgLock * iface)
44 {
45     INetCfgImpl * This = impl_from_INetCfgLock(iface);
46 
47     return INetCfg_AddRef((INetCfg*)This);
48 }
49 
50 ULONG
51 WINAPI
52 INetCfgLock_fnRelease(
53     INetCfgLock * iface)
54 {
55     INetCfgImpl * This = impl_from_INetCfgLock(iface);
56     return INetCfg_Release((INetCfg*)This);
57 }
58 
59 HRESULT
60 WINAPI
61 INetCfgLock_fnAcquireWriteLock(
62     INetCfgLock * iface,
63     DWORD cmsTimeout,
64     LPCWSTR pszwClientDescription,
65     LPWSTR *ppszwClientDescription)
66 {
67     DWORD dwResult;
68     HKEY hKey;
69     WCHAR szValue[100];
70     INetCfgImpl * This = impl_from_INetCfgLock(iface);
71 
72     if (This->bInitialized)
73         return NETCFG_E_ALREADY_INITIALIZED;
74 
75     dwResult = WaitForSingleObject(This->hMutex, cmsTimeout);
76     if (dwResult == WAIT_TIMEOUT)
77     {
78         if (ppszwClientDescription)
79         {
80             if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Network\\NetCfgLockHolder", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
81             {
82                 dwResult = sizeof(szValue);
83                 if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)szValue, &dwResult) == ERROR_SUCCESS)
84                 {
85                      szValue[(sizeof(szValue)/sizeof(WCHAR))-1] = L'\0';
86                      *ppszwClientDescription = CoTaskMemAlloc((wcslen(szValue)+1) * sizeof(WCHAR));
87                      if (*ppszwClientDescription)
88                          wcscpy(*ppszwClientDescription, szValue);
89                 }
90                 RegCloseKey(hKey);
91             }
92         }
93         return S_FALSE;
94     }
95     else if (dwResult == WAIT_OBJECT_0)
96     {
97         if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Network\\NetCfgLockHolder", 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
98         {
99             RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)pszwClientDescription, (wcslen(pszwClientDescription)+1) * sizeof(WCHAR));
100             RegCloseKey(hKey);
101         }
102         return S_OK;
103     }
104 
105     return E_FAIL;
106 }
107 
108 HRESULT
109 WINAPI
110 INetCfgLock_fnReleaseWriteLock(
111     INetCfgLock * iface)
112 {
113     INetCfgImpl * This = impl_from_INetCfgLock(iface);
114 
115     if (This->bInitialized)
116         return NETCFG_E_ALREADY_INITIALIZED;
117 
118 
119     if (ReleaseMutex(This->hMutex))
120         return S_OK;
121     else
122         return S_FALSE;
123 }
124 
125 HRESULT
126 WINAPI
127 INetCfgLock_fnIsWriteLocked(
128     INetCfgLock * iface,
129     LPWSTR *ppszwClientDescription)
130 {
131     HKEY hKey;
132     WCHAR szValue[100];
133     DWORD dwSize, dwType;
134     HRESULT hr;
135 
136     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Network\\NetCfgLockHolder", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
137         return S_FALSE;
138 
139     dwSize = sizeof(szValue);
140     if (RegQueryValueExW(hKey, NULL, NULL, &dwType, (LPBYTE)szValue, &dwSize) == ERROR_SUCCESS && dwType == REG_SZ)
141     {
142         hr = S_OK;
143         szValue[(sizeof(szValue)/sizeof(WCHAR))-1] = L'\0';
144         *ppszwClientDescription = CoTaskMemAlloc((wcslen(szValue)+1) * sizeof(WCHAR));
145         if (*ppszwClientDescription)
146             wcscpy(*ppszwClientDescription, szValue);
147         else
148             hr = E_OUTOFMEMORY;
149     }
150     else
151     {
152         hr = E_FAIL;
153     }
154     RegCloseKey(hKey);
155     return hr;
156 }
157 
158 static const INetCfgLockVtbl vt_NetCfgLock =
159 {
160     INetCfgLock_fnQueryInterface,
161     INetCfgLock_fnAddRef,
162     INetCfgLock_fnRelease,
163     INetCfgLock_fnAcquireWriteLock,
164     INetCfgLock_fnReleaseWriteLock,
165     INetCfgLock_fnIsWriteLocked
166 };
167 
168 /***************************************************************
169  * INetCfgPnpReconfigCallback
170  */
171 
172 HRESULT
173 WINAPI
174 INetCfgPnpReconfigCallback_fnQueryInterface(
175     INetCfgPnpReconfigCallback * iface,
176     REFIID iid,
177     LPVOID * ppvObj)
178 {
179     INetCfgImpl * This = impl_from_INetCfgPnpReconfigCallback(iface);
180     return INetCfg_QueryInterface((INetCfg*)This, iid, ppvObj);
181 }
182 
183 ULONG
184 WINAPI
185 INetCfgPnpReconfigCallback_fnAddRef(
186     INetCfgPnpReconfigCallback * iface)
187 {
188     INetCfgImpl * This = impl_from_INetCfgPnpReconfigCallback(iface);
189 
190     return INetCfg_AddRef((INetCfg*)This);
191 }
192 
193 ULONG
194 WINAPI
195 INetCfgPnpReconfigCallback_fnRelease(
196     INetCfgPnpReconfigCallback * iface)
197 {
198     INetCfgImpl * This = impl_from_INetCfgPnpReconfigCallback(iface);
199     return INetCfg_Release((INetCfg*)This);
200 }
201 
202 HRESULT
203 WINAPI
204 INetCfgPnpReconfigCallback_fnSendPnpReconfig(
205     INetCfgPnpReconfigCallback * iface,
206     NCPNP_RECONFIG_LAYER Layer,
207     LPCWSTR pszwUpper,
208     LPCWSTR pszwLower,
209     PVOID pvData,
210     DWORD dwSizeOfData)
211 {
212     /* FIXME */
213     return E_NOTIMPL;
214 }
215 
216 static const INetCfgPnpReconfigCallbackVtbl vt_NetCfgPnpReconfigCallback =
217 {
218     INetCfgPnpReconfigCallback_fnQueryInterface,
219     INetCfgPnpReconfigCallback_fnAddRef,
220     INetCfgPnpReconfigCallback_fnRelease,
221     INetCfgPnpReconfigCallback_fnSendPnpReconfig
222 };
223 
224 
225 /***************************************************************
226  * INetCfg
227  */
228 
229 HRESULT
230 ReadBindingString(
231     NetCfgComponentItem *Item)
232 {
233     WCHAR szBuffer[200];
234     HKEY hKey;
235     DWORD dwType, dwSize;
236 
237     if (Item == NULL || Item->szBindName == NULL)
238         return S_OK;
239 
240     wcscpy(szBuffer, L"SYSTEM\\CurrentControlSet\\Services\\");
241     wcscat(szBuffer, Item->szBindName);
242     wcscat(szBuffer, L"\\Linkage");
243 
244     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
245     {
246         dwSize = 0;
247         RegQueryValueExW(hKey, L"Bind", NULL, &dwType, NULL, &dwSize);
248 
249         if (dwSize != 0)
250         {
251             Item->pszBinding = CoTaskMemAlloc(dwSize);
252             if (Item->pszBinding == NULL)
253                 return E_OUTOFMEMORY;
254 
255             RegQueryValueExW(hKey, L"Bind", NULL, &dwType, (LPBYTE)Item->pszBinding, &dwSize);
256         }
257 
258         RegCloseKey(hKey);
259     }
260 
261     return S_OK;
262 }
263 
264 HRESULT
265 EnumClientServiceProtocol(HKEY hKey, const GUID * pGuid, NetCfgComponentItem ** pHead)
266 {
267     DWORD dwIndex = 0;
268     DWORD dwSize;
269     DWORD dwType;
270     WCHAR szName[100];
271     WCHAR szText[100];
272     HKEY hSubKey, hNDIKey;
273     NetCfgComponentItem * pLast = NULL, *pCurrent;
274 
275     *pHead = NULL;
276     do
277     {
278         szText[0] = L'\0';
279 
280         dwSize = sizeof(szName)/sizeof(WCHAR);
281         if (RegEnumKeyExW(hKey, dwIndex++, szName, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
282         {
283             pCurrent = CoTaskMemAlloc(sizeof(NetCfgComponentItem));
284             if (!pCurrent)
285                 return E_OUTOFMEMORY;
286 
287             ZeroMemory(pCurrent, sizeof(NetCfgComponentItem));
288             CopyMemory(&pCurrent->ClassGUID, pGuid, sizeof(GUID));
289 
290             if (FAILED(CLSIDFromString(szName, &pCurrent->InstanceId)))
291             {
292                 /// ReactOS tcpip guid is not yet generated
293                 //CoTaskMemFree(pCurrent);
294                 //return E_FAIL;
295             }
296             if (RegOpenKeyExW(hKey, szName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
297             {
298                 /* retrieve Characteristics */
299                 dwSize = sizeof(DWORD);
300 
301                 RegQueryValueExW(hSubKey, L"Characteristics", NULL, &dwType, (LPBYTE)&pCurrent->dwCharacteristics, &dwSize);
302                 if (dwType != REG_DWORD)
303                     pCurrent->dwCharacteristics = 0;
304 
305                 /* retrieve ComponentId */
306                 dwSize = sizeof(szText);
307                 if (RegQueryValueExW(hSubKey, L"ComponentId", NULL, &dwType, (LPBYTE)szText, &dwSize) == ERROR_SUCCESS)
308                 {
309                     if (dwType == REG_SZ)
310                     {
311                         szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
312                         pCurrent->szId = CoTaskMemAlloc((wcslen(szText)+1)* sizeof(WCHAR));
313                         if (pCurrent->szId)
314                             wcscpy(pCurrent->szId, szText);
315                     }
316                 }
317 
318                 /* retrieve Description */
319                 dwSize = sizeof(szText);
320                 if (RegQueryValueExW(hSubKey, L"Description", NULL, &dwType, (LPBYTE)szText, &dwSize) == ERROR_SUCCESS)
321                 {
322                     if (dwType == REG_SZ)
323                     {
324                         szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
325                         pCurrent->szDisplayName = CoTaskMemAlloc((wcslen(szText)+1)* sizeof(WCHAR));
326                         if (pCurrent->szDisplayName)
327                             wcscpy(pCurrent->szDisplayName, szText);
328                     }
329                 }
330 
331                 if (RegOpenKeyExW(hSubKey, L"NDI", 0, KEY_READ, &hNDIKey) == ERROR_SUCCESS)
332                 {
333                     /* retrieve HelpText */
334                     dwSize = sizeof(szText);
335                     if (RegQueryValueExW(hNDIKey, L"HelpText", NULL, &dwType, (LPBYTE)szText, &dwSize) == ERROR_SUCCESS)
336                     {
337                         if (dwType == REG_SZ)
338                         {
339                             szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
340                             pCurrent->szHelpText = CoTaskMemAlloc((wcslen(szText)+1)* sizeof(WCHAR));
341                             if (pCurrent->szHelpText)
342                                 wcscpy(pCurrent->szHelpText, szText);
343                         }
344                     }
345 
346                     /* retrieve Service */
347                     dwSize = sizeof(szText);
348                     if (RegQueryValueExW(hNDIKey, L"Service", NULL, &dwType, (LPBYTE)szText, &dwSize) == ERROR_SUCCESS)
349                     {
350                         if (dwType == REG_SZ)
351                         {
352                             szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
353                             pCurrent->szBindName = CoTaskMemAlloc((wcslen(szText)+1)* sizeof(WCHAR));
354                             if (pCurrent->szBindName)
355                                 wcscpy(pCurrent->szBindName, szText);
356                         }
357                     }
358                     RegCloseKey(hNDIKey);
359                 }
360                 RegCloseKey(hSubKey);
361 
362                 ReadBindingString(pCurrent);
363 
364                 if (!pLast)
365                     *pHead = pCurrent;
366                 else
367                     pLast->pNext = pCurrent;
368 
369                 pLast = pCurrent;
370             }
371         }
372         else
373            break;
374 
375     }while(TRUE);
376     return S_OK;
377 }
378 
379 
380 
381 HRESULT
382 EnumerateNetworkComponent(
383     const GUID *pGuid, NetCfgComponentItem ** pHead)
384 {
385     HKEY hKey;
386     LPOLESTR pszGuid;
387     HRESULT hr;
388     WCHAR szName[150];
389 
390     hr = StringFromCLSID(pGuid, &pszGuid);
391     if (SUCCEEDED(hr))
392     {
393         swprintf(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\%s", pszGuid);
394         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
395         {
396             hr = EnumClientServiceProtocol(hKey, pGuid, pHead);
397             RegCloseKey(hKey);
398         }
399         CoTaskMemFree(pszGuid);
400     }
401     return hr;
402 }
403 
404 HRESULT
405 EnumerateNetworkAdapter(NetCfgComponentItem ** pHead)
406 {
407     DWORD dwSize, dwIndex;
408     HDEVINFO hInfo;
409     SP_DEVINFO_DATA DevInfo;
410     HKEY hKey;
411     WCHAR szNetCfg[50];
412     WCHAR szAdapterNetCfg[MAX_DEVICE_ID_LEN];
413     WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
414     WCHAR szName[130] = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
415     NetCfgComponentItem * pLast = NULL, *pCurrent;
416 
417     hInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
418     if (!hInfo)
419     {
420         return E_FAIL;
421     }
422 
423     dwIndex = 0;
424     do
425     {
426         ZeroMemory(&DevInfo, sizeof(SP_DEVINFO_DATA));
427         DevInfo.cbSize = sizeof(DevInfo);
428 
429         /* get device info */
430         if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, &DevInfo))
431             break;
432 
433         /* get device software registry path */
434         if (!SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
435             break;
436 
437         /* open device registry key */
438         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
439             break;
440 
441         /* query NetCfgInstanceId for current device */
442         dwSize = sizeof(szNetCfg);
443         if (RegQueryValueExW(hKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
444         {
445             RegCloseKey(hKey);
446             break;
447         }
448 
449         /* allocate new INetConnectionItem */
450         pCurrent = CoTaskMemAlloc(sizeof(NetCfgComponentItem));
451         if (!pCurrent)
452             break;
453 
454         ZeroMemory(pCurrent, sizeof(NetCfgComponentItem));
455         CopyMemory(&pCurrent->ClassGUID, &GUID_DEVCLASS_NET, sizeof(GUID));
456         CLSIDFromString(szNetCfg, &pCurrent->InstanceId); //FIXME
457 
458         /* set bind name */
459         pCurrent->szBindName = CoTaskMemAlloc((wcslen(szNetCfg)+1) *sizeof(WCHAR));
460         if (pCurrent->szBindName)
461             wcscpy(pCurrent->szBindName, szNetCfg);
462 
463         /* retrieve ComponentId */
464         dwSize = sizeof(szAdapterNetCfg);
465         if (RegQueryValueExW(hKey, L"ComponentId", NULL, NULL, (LPBYTE)szAdapterNetCfg, &dwSize) == ERROR_SUCCESS)
466         {
467             pCurrent->szId = CoTaskMemAlloc((wcslen(szAdapterNetCfg)+1) * sizeof(WCHAR));
468             if (pCurrent->szId)
469                 wcscpy(pCurrent->szId, szAdapterNetCfg);
470         }
471         /* set INetCfgComponent::GetDisplayName */
472         dwSize = sizeof(szAdapterNetCfg);
473         if (RegQueryValueExW(hKey, L"DriverDesc", NULL, NULL, (LPBYTE)szAdapterNetCfg, &dwSize) == ERROR_SUCCESS)
474         {
475             pCurrent->szDisplayName = CoTaskMemAlloc((wcslen(szAdapterNetCfg)+1) * sizeof(WCHAR));
476             if (pCurrent->szDisplayName)
477                 wcscpy(pCurrent->szDisplayName, szAdapterNetCfg);
478         }
479 
480         RegCloseKey(hKey);
481         /*  open network connections details */
482         wcscpy(&szName[80], szNetCfg);
483         wcscpy(&szName[118], L"\\Connection");
484 
485         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
486         {
487             /* retrieve pnp instance id */
488             dwSize = sizeof(szAdapterNetCfg);
489             if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, NULL, (LPBYTE)szAdapterNetCfg, &dwSize) == ERROR_SUCCESS)
490             {
491                 pCurrent->szNodeId = CoTaskMemAlloc((wcslen(szAdapterNetCfg)+1) * sizeof(WCHAR));
492                 if (pCurrent->szNodeId)
493                     wcscpy(pCurrent->szNodeId, szAdapterNetCfg);
494             }
495             RegCloseKey(hKey);
496         }
497 
498         if (SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DEVICEDESC, NULL, (PBYTE)szNetCfg, sizeof(szNetCfg)/sizeof(WCHAR), &dwSize))
499         {
500             szNetCfg[(sizeof(szNetCfg)/sizeof(WCHAR))-1] = L'\0';
501             pCurrent->szDisplayName = CoTaskMemAlloc((wcslen(szNetCfg)+1) * sizeof(WCHAR));
502             if (pCurrent->szDisplayName)
503                 wcscpy(pCurrent->szDisplayName, szNetCfg);
504         }
505 
506         if (pLast)
507             pLast->pNext = pCurrent;
508         else
509             *pHead = pCurrent;
510 
511         pLast = pCurrent;
512 
513     }while(TRUE);
514 
515     SetupDiDestroyDeviceInfoList(hInfo);
516     return NOERROR;
517 }
518 
519 
520 HRESULT
521 FindNetworkComponent(
522     NetCfgComponentItem * pHead,
523     LPCWSTR pszwComponentId,
524     INetCfgComponent **pComponent,
525     INetCfg * iface)
526 {
527     while(pHead)
528     {
529         if (!_wcsicmp(pHead->szId, pszwComponentId))
530         {
531             return INetCfgComponent_Constructor(NULL, &IID_INetCfgComponent, (LPVOID*)pComponent, pHead, iface);
532         }
533         pHead = pHead->pNext;
534     }
535     return S_FALSE;
536 }
537 
538 
539 
540 HRESULT
541 WINAPI
542 INetCfg_fnQueryInterface(
543     INetCfg * iface,
544     REFIID iid,
545     LPVOID * ppvObj)
546 {
547     INetCfgImpl * This = (INetCfgImpl*)iface;
548     *ppvObj = NULL;
549 
550     if (IsEqualIID (iid, &IID_IUnknown) ||
551         IsEqualIID (iid, &IID_INetCfg))
552     {
553         *ppvObj = This;
554         INetCfg_AddRef(iface);
555         return S_OK;
556     }
557     else if (IsEqualIID (iid, &IID_INetCfgLock))
558     {
559         if (This->bInitialized)
560             return NETCFG_E_ALREADY_INITIALIZED;
561 
562         *ppvObj = (LPVOID)&This->lpVtblLock;
563         This->hMutex = CreateMutexW(NULL, FALSE, L"NetCfgLock");
564 
565         INetCfgLock_AddRef(iface);
566         return S_OK;
567     }
568     else if (IsEqualIID (iid, &IID_INetCfgPnpReconfigCallback))
569     {
570         if (This->bInitialized)
571             return NETCFG_E_ALREADY_INITIALIZED;
572 
573         *ppvObj = (LPVOID)&This->lpVtblPnpReconfigCallback;
574         INetCfgPnpReconfigCallback_AddRef(iface);
575         return S_OK;
576     }
577 
578     return E_NOINTERFACE;
579 }
580 
581 ULONG
582 WINAPI
583 INetCfg_fnAddRef(
584     INetCfg * iface)
585 {
586     INetCfgImpl * This = (INetCfgImpl*)iface;
587     ULONG refCount = InterlockedIncrement(&This->ref);
588 
589     return refCount;
590 }
591 
592 ULONG
593 WINAPI
594 INetCfg_fnRelease(
595     INetCfg * iface)
596 {
597     INetCfgImpl * This = (INetCfgImpl*)iface;
598     ULONG refCount = InterlockedDecrement(&This->ref);
599 
600     if (!refCount)
601     {
602         CoTaskMemFree (This);
603     }
604     return refCount;
605 }
606 
607 HRESULT
608 WINAPI
609 INetCfg_fnInitialize(
610     INetCfg * iface,
611     PVOID pReserved)
612 {
613     HRESULT hr;
614     INetCfgImpl *This = (INetCfgImpl *)iface;
615 
616     if (This->bInitialized)
617         return NETCFG_E_ALREADY_INITIALIZED;
618 
619     hr = EnumerateNetworkAdapter(&This->pNet);
620     if (FAILED(hr))
621         return hr;
622 
623 
624     hr = EnumerateNetworkComponent(&GUID_DEVCLASS_NETCLIENT, &This->pClient);
625     if (FAILED(hr))
626         return hr;
627 
628     hr = EnumerateNetworkComponent(&GUID_DEVCLASS_NETSERVICE, &This->pService);
629     if (FAILED(hr))
630         return hr;
631 
632 
633     hr = EnumerateNetworkComponent(&GUID_DEVCLASS_NETTRANS, &This->pProtocol);
634     if (FAILED(hr))
635         return hr;
636 
637     This->bInitialized = TRUE;
638     return S_OK;
639 }
640 
641 VOID
642 ApplyOrCancelChanges(
643     NetCfgComponentItem *pHead,
644     const CLSID * lpClassGUID,
645     BOOL bApply)
646 {
647     HKEY hKey;
648     WCHAR szName[200];
649     LPOLESTR pszGuid;
650 
651     while(pHead)
652     {
653         if (pHead->bChanged)
654         {
655             if (IsEqualGUID(lpClassGUID, &GUID_DEVCLASS_NET))
656             {
657                 if (bApply)
658                 {
659                     if (StringFromCLSID(&pHead->InstanceId, &pszGuid) == NOERROR)
660                     {
661                         swprintf(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\%s", pszGuid);
662                         CoTaskMemFree(pszGuid);
663 
664                         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
665                         {
666                             RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)pHead->szDisplayName, (wcslen(pHead->szDisplayName)+1) * sizeof(WCHAR));
667                             RegCloseKey(hKey);
668                         }
669                     }
670                 }
671             }
672             else if (pHead->pNCCC)
673             {
674                 if (bApply)
675                 {
676                     INetCfgComponentControl_ApplyRegistryChanges(pHead->pNCCC);
677                     //FIXME
678                     // implement INetCfgPnpReconfigCallback and pass it to
679                     //INetCfgComponentControl_ApplyPnpChanges(pHead->pNCCC, NULL);
680                 }
681                 else
682                 {
683                     INetCfgComponentControl_CancelChanges(pHead->pNCCC);
684                 }
685             }
686         }
687         pHead = pHead->pNext;
688     }
689 }
690 
691 VOID
692 FreeComponentItem(NetCfgComponentItem *pItem)
693 {
694     CoTaskMemFree(pItem->szDisplayName);
695     CoTaskMemFree(pItem->szHelpText);
696     CoTaskMemFree(pItem->szId);
697     CoTaskMemFree(pItem->szBindName);
698     CoTaskMemFree(pItem->szNodeId);
699     CoTaskMemFree(pItem->pszBinding);
700     CoTaskMemFree(pItem);
701 }
702 
703 HRESULT
704 WINAPI
705 INetCfg_fnUninitialize(
706     INetCfg * iface)
707 {
708     INetCfgImpl *This = (INetCfgImpl *)iface;
709     NetCfgComponentItem *pItem;
710 
711     if (!This->bInitialized)
712         return NETCFG_E_NOT_INITIALIZED;
713 
714     /* Free the services */
715     while (This->pService != NULL)
716     {
717         pItem = This->pService;
718         This->pService = pItem->pNext;
719         FreeComponentItem(pItem);
720     }
721 
722     /* Free the clients */
723     while (This->pClient != NULL)
724     {
725         pItem = This->pClient;
726         This->pClient = pItem->pNext;
727         FreeComponentItem(pItem);
728     }
729 
730     /* Free the protocols */
731     while (This->pProtocol != NULL)
732     {
733         pItem = This->pProtocol;
734         This->pProtocol = pItem->pNext;
735         FreeComponentItem(pItem);
736     }
737 
738     /* Free the adapters */
739     while (This->pNet != NULL)
740     {
741         pItem = This->pNet;
742         This->pNet = pItem->pNext;
743         FreeComponentItem(pItem);
744     }
745 
746     This->bInitialized = FALSE;
747 
748     return S_OK;
749 }
750 
751 
752 HRESULT
753 WINAPI
754 INetCfg_fnApply(
755     INetCfg * iface)
756 {
757     INetCfgImpl *This = (INetCfgImpl *)iface;
758 
759     if (!This->bInitialized)
760         return NETCFG_E_NOT_INITIALIZED;
761 
762     ApplyOrCancelChanges(This->pNet, &GUID_DEVCLASS_NET, TRUE);
763     ApplyOrCancelChanges(This->pClient, &GUID_DEVCLASS_NETCLIENT, TRUE);
764     ApplyOrCancelChanges(This->pService, &GUID_DEVCLASS_NETSERVICE, TRUE);
765     ApplyOrCancelChanges(This->pProtocol, &GUID_DEVCLASS_NETTRANS, TRUE);
766 
767     return S_OK;
768 }
769 
770 HRESULT
771 WINAPI
772 INetCfg_fnCancel(
773     INetCfg * iface)
774 {
775     INetCfgImpl *This = (INetCfgImpl *)iface;
776 
777     if (!This->bInitialized)
778         return NETCFG_E_NOT_INITIALIZED;
779 
780     ApplyOrCancelChanges(This->pClient, &GUID_DEVCLASS_NETCLIENT, FALSE);
781     ApplyOrCancelChanges(This->pService, &GUID_DEVCLASS_NETSERVICE, FALSE);
782     ApplyOrCancelChanges(This->pProtocol, &GUID_DEVCLASS_NETTRANS, FALSE);
783 
784     return S_OK;
785 }
786 
787 HRESULT
788 WINAPI
789 INetCfg_fnEnumComponents(
790     INetCfg * iface,
791     const GUID *pguidClass,
792     IEnumNetCfgComponent **ppenumComponent)
793 {
794     INetCfgImpl *This = (INetCfgImpl *)iface;
795 
796     if (!This->bInitialized)
797         return NETCFG_E_NOT_INITIALIZED;
798 
799     if (IsEqualGUID(&GUID_DEVCLASS_NET, pguidClass))
800         return IEnumNetCfgComponent_Constructor (NULL, &IID_IEnumNetCfgComponent, (LPVOID*)ppenumComponent, This->pNet, iface);
801     else if (IsEqualGUID(&GUID_DEVCLASS_NETCLIENT, pguidClass))
802         return IEnumNetCfgComponent_Constructor (NULL, &IID_IEnumNetCfgComponent, (LPVOID*)ppenumComponent, This->pClient, iface);
803     else if (IsEqualGUID(&GUID_DEVCLASS_NETSERVICE, pguidClass))
804         return IEnumNetCfgComponent_Constructor (NULL, &IID_IEnumNetCfgComponent, (LPVOID*)ppenumComponent, This->pService, iface);
805     else if (IsEqualGUID(&GUID_DEVCLASS_NETTRANS, pguidClass))
806         return IEnumNetCfgComponent_Constructor (NULL, &IID_IEnumNetCfgComponent, (LPVOID*)ppenumComponent, This->pProtocol, iface);
807     else
808        return E_NOINTERFACE;
809 }
810 
811 
812 HRESULT
813 WINAPI
814 INetCfg_fnFindComponent(
815     INetCfg * iface,
816     LPCWSTR pszwComponentId,
817     INetCfgComponent **pComponent)
818 {
819     HRESULT hr;
820     INetCfgImpl *This = (INetCfgImpl *)iface;
821 
822     if (!This->bInitialized)
823         return NETCFG_E_NOT_INITIALIZED;
824 
825     hr = FindNetworkComponent(This->pClient, pszwComponentId, pComponent, iface);
826     if (hr == S_OK)
827         return hr;
828 
829     hr = FindNetworkComponent(This->pService, pszwComponentId, pComponent, iface);
830     if (hr == S_OK)
831         return hr;
832 
833     hr = FindNetworkComponent(This->pProtocol, pszwComponentId, pComponent, iface);
834     if (hr == S_OK)
835         return hr;
836 
837     return S_FALSE;
838 }
839 
840 HRESULT
841 WINAPI
842 INetCfg_fnQueryNetCfgClass(
843     INetCfg * iface,
844     const GUID *pguidClass,
845     REFIID riid,
846     void **ppvObject)
847 {
848     return E_FAIL;
849 }
850 
851 static const INetCfgVtbl vt_NetCfg =
852 {
853     INetCfg_fnQueryInterface,
854     INetCfg_fnAddRef,
855     INetCfg_fnRelease,
856     INetCfg_fnInitialize,
857     INetCfg_fnUninitialize,
858     INetCfg_fnApply,
859     INetCfg_fnCancel,
860     INetCfg_fnEnumComponents,
861     INetCfg_fnFindComponent,
862     INetCfg_fnQueryNetCfgClass,
863 };
864 
865 HRESULT WINAPI INetCfg_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
866 {
867     INetCfgImpl *This;
868 
869     if (!ppv)
870         return E_POINTER;
871 
872     This = (INetCfgImpl *) CoTaskMemAlloc(sizeof (INetCfgImpl));
873     if (!This)
874         return E_OUTOFMEMORY;
875 
876     This->ref = 1;
877     This->lpVtbl = (const INetCfg*)&vt_NetCfg;
878     This->lpVtblLock = (const INetCfgLock*)&vt_NetCfgLock;
879     This->lpVtblPnpReconfigCallback = (const INetCfgPnpReconfigCallback*)&vt_NetCfgPnpReconfigCallback;
880     This->hMutex = NULL;
881     This->bInitialized = FALSE;
882     This->pNet = NULL;
883     This->pClient = NULL;
884     This->pService = NULL;
885     This->pProtocol = NULL;
886 
887     if (!SUCCEEDED (INetCfg_QueryInterface ((INetCfg*)This, riid, ppv)))
888     {
889         INetCfg_Release((INetCfg*)This);
890         return E_NOINTERFACE;
891     }
892 
893     INetCfg_Release((INetCfg*)This);
894     return S_OK;
895 }
896