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