1 #include "precomp.h"
2 
3 typedef struct
4 {
5     const INetCfgComponent *lpVtbl;
6     const INetCfgComponentBindings *lpVtblComponentBindings;
7     LONG  ref;
8     NetCfgComponentItem * pItem;
9     INetCfgComponentPropertyUi * pProperty;
10     INetCfg * pNCfg;
11 } INetCfgComponentImpl;
12 
13 typedef struct
14 {
15     const IEnumNetCfgComponent * lpVtbl;
16     LONG  ref;
17     NetCfgComponentItem * pCurrent;
18     NetCfgComponentItem * pHead;
19     INetCfg * pNCfg;
20 } IEnumNetCfgComponentImpl;
21 
22 static __inline INetCfgComponentImpl* impl_from_INetCfgComponentBindings(INetCfgComponentBindings *iface)
23 {
24     return (INetCfgComponentImpl*)((char *)iface - FIELD_OFFSET(INetCfgComponentImpl, lpVtblComponentBindings));
25 }
26 
27 
28 /***************************************************************
29  * INetCfgComponentBindings
30  */
31 
32 HRESULT
33 WINAPI
34 INetCfgComponentBindings_fnQueryInterface(
35     INetCfgComponentBindings *iface,
36     REFIID iid,
37     LPVOID *ppvObj)
38 {
39     INetCfgComponentImpl *This = impl_from_INetCfgComponentBindings(iface);
40     return INetCfgComponent_QueryInterface((INetCfgComponent*)This, iid, ppvObj);
41 }
42 
43 ULONG
44 WINAPI
45 INetCfgComponentBindings_fnAddRef(
46     INetCfgComponentBindings *iface)
47 {
48     INetCfgComponentImpl *This = impl_from_INetCfgComponentBindings(iface);
49     return INetCfgComponent_AddRef((INetCfgComponent*)This);
50 }
51 
52 ULONG
53 WINAPI
54 INetCfgComponentBindings_fnRelease(
55     INetCfgComponentBindings *iface)
56 {
57     INetCfgComponentImpl *This = impl_from_INetCfgComponentBindings(iface);
58     return INetCfgComponent_Release((INetCfgComponent*)This);
59 }
60 
61 HRESULT
62 WINAPI
63 INetCfgComponentBindings_fnBindTo(
64     INetCfgComponentBindings *iface,
65     INetCfgComponent *pnccItem)
66 {
67     return E_NOTIMPL;
68 }
69 
70 HRESULT
71 WINAPI
72 INetCfgComponentBindings_fnUnbindFrom(
73     INetCfgComponentBindings *iface,
74     INetCfgComponent *pnccItem)
75 {
76     return E_NOTIMPL;
77 }
78 
79 HRESULT
80 WINAPI
81 INetCfgComponentBindings_fnSupportsBindingInterface(
82     INetCfgComponentBindings *iface,
83     DWORD dwFlags,
84     LPCWSTR pszwInterfaceName)
85 {
86     return E_NOTIMPL;
87 }
88 
89 HRESULT
90 WINAPI
91 INetCfgComponentBindings_fnIsBoundTo(
92     INetCfgComponentBindings *iface,
93     INetCfgComponent *pnccItem)
94 {
95     INetCfgComponentImpl *pComponent;
96     PWSTR pszBindName, ptr;
97     INT len;
98 
99     pComponent = impl_from_INetCfgComponentBindings(iface);
100     if (pComponent == NULL ||
101         pComponent->pItem == NULL ||
102         pComponent->pItem->pszBinding == NULL)
103         return E_POINTER;
104 
105     if (pnccItem == NULL ||
106         ((INetCfgComponentImpl*)pnccItem)->pItem == NULL ||
107         ((INetCfgComponentImpl*)pnccItem)->pItem->szBindName == NULL)
108         return E_POINTER;
109 
110     pszBindName = ((INetCfgComponentImpl*)pnccItem)->pItem->szBindName;
111 
112     ptr = pComponent->pItem->pszBinding;
113     while (*ptr != UNICODE_NULL)
114     {
115         len = wcslen(ptr);
116 
117         if (len > 8 && _wcsicmp(&ptr[8], pszBindName) == 0)
118             return S_OK;
119 
120         ptr = ptr + len + 1;
121     }
122 
123     return S_FALSE;
124 }
125 
126 HRESULT
127 WINAPI
128 INetCfgComponentBindings_fnIsBindableTo(
129     INetCfgComponentBindings *iface,
130     INetCfgComponent *pnccItem)
131 {
132     return E_NOTIMPL;
133 }
134 
135 HRESULT
136 WINAPI
137 INetCfgComponentBindings_fnEnumBindingPaths(
138     INetCfgComponentBindings *iface,
139     DWORD dwFlags,
140     IEnumNetCfgBindingPath **ppIEnum)
141 {
142     return IEnumNetCfgBindingPath_Constructor(NULL, &IID_IEnumNetCfgBindingPath, (LPVOID *)ppIEnum, dwFlags);
143 }
144 
145 HRESULT
146 WINAPI
147 INetCfgComponentBindings_fnMoveBefore(
148     INetCfgComponentBindings *iface,
149     DWORD dwFlags,
150     INetCfgBindingPath *pncbItemSrc,
151     INetCfgBindingPath *pncbItemDest)
152 {
153     return E_NOTIMPL;
154 }
155 
156 HRESULT
157 WINAPI
158 INetCfgComponentBindings_fnMoveAfter(
159     INetCfgComponentBindings *iface,
160     DWORD dwFlags,
161     INetCfgBindingPath *pncbItemSrc,
162     INetCfgBindingPath *pncbItemDest)
163 {
164     return E_NOTIMPL;
165 }
166 
167 static const INetCfgComponentBindingsVtbl vt_NetCfgComponentBindings =
168 {
169     INetCfgComponentBindings_fnQueryInterface,
170     INetCfgComponentBindings_fnAddRef,
171     INetCfgComponentBindings_fnRelease,
172     INetCfgComponentBindings_fnBindTo,
173     INetCfgComponentBindings_fnUnbindFrom,
174     INetCfgComponentBindings_fnSupportsBindingInterface,
175     INetCfgComponentBindings_fnIsBoundTo,
176     INetCfgComponentBindings_fnIsBindableTo,
177     INetCfgComponentBindings_fnEnumBindingPaths,
178     INetCfgComponentBindings_fnMoveBefore,
179     INetCfgComponentBindings_fnMoveAfter,
180 };
181 
182 /***************************************************************
183  * INetCfgComponent
184  */
185 
186 HRESULT
187 WINAPI
188 INetCfgComponent_fnQueryInterface(
189     INetCfgComponent * iface,
190     REFIID iid,
191     LPVOID * ppvObj)
192 {
193     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
194     *ppvObj = NULL;
195 
196     if (IsEqualIID (iid, &IID_IUnknown) ||
197         IsEqualIID (iid, &IID_INetCfgComponent))
198     {
199         *ppvObj = This;
200         INetCfg_AddRef(iface);
201         return S_OK;
202     }
203     else if (IsEqualIID (iid, &IID_INetCfgComponentBindings))
204     {
205         *ppvObj = (LPVOID)&This->lpVtblComponentBindings;
206         INetCfgComponentBindings_AddRef(iface);
207         return S_OK;
208     }
209 
210     return E_NOINTERFACE;
211 }
212 
213 ULONG
214 WINAPI
215 INetCfgComponent_fnAddRef(
216     INetCfgComponent * iface)
217 {
218     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
219     ULONG refCount = InterlockedIncrement(&This->ref);
220 
221     return refCount;
222 }
223 
224 ULONG
225 WINAPI
226 INetCfgComponent_fnRelease(
227     INetCfgComponent * iface)
228 {
229     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
230     ULONG refCount = InterlockedDecrement(&This->ref);
231 
232     if (!refCount)
233     {
234        CoTaskMemFree(This);
235     }
236     return refCount;
237 }
238 
239 HRESULT
240 WINAPI
241 INetCfgComponent_fnGetDisplayName(
242     INetCfgComponent * iface,
243     LPWSTR * ppszwDisplayName)
244 {
245     LPWSTR szName;
246     UINT Length;
247     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
248 
249     if (This == NULL || ppszwDisplayName == NULL)
250         return E_POINTER;
251 
252     if (This->pItem->szDisplayName)
253         Length = wcslen(This->pItem->szDisplayName)+1;
254     else
255         Length = 1;
256 
257     szName = CoTaskMemAlloc(Length * sizeof(WCHAR));
258     if (!szName)
259         return E_OUTOFMEMORY;
260 
261     if (Length > 1)
262         wcscpy(szName, This->pItem->szDisplayName);
263     else
264         szName[0] = L'\0';
265 
266     *ppszwDisplayName = szName;
267 
268     return S_OK;
269 }
270 
271 HRESULT
272 WINAPI
273 INetCfgComponent_fnSetDisplayName(
274     INetCfgComponent * iface,
275     LPCWSTR ppszwDisplayName)
276 {
277     LPWSTR szName;
278     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
279 
280     if (This == NULL || ppszwDisplayName == NULL)
281         return E_POINTER;
282 
283     /* setting name is only supported for network cards */
284     if (!IsEqualGUID(&This->pItem->ClassGUID, &GUID_DEVCLASS_NET))
285         return E_NOTIMPL;
286 
287     /// FIXME
288     /// check for invalid characters
289     /// check for write lock
290 
291     szName = CoTaskMemAlloc((wcslen(ppszwDisplayName)+1) * sizeof(WCHAR));
292     if (!szName)
293         return E_OUTOFMEMORY;
294 
295     wcscpy(szName, ppszwDisplayName);
296     CoTaskMemFree(This->pItem->szDisplayName);
297     This->pItem->szDisplayName = szName;
298     This->pItem->bChanged = TRUE;
299 
300     return S_OK;
301 }
302 
303 HRESULT
304 WINAPI
305 INetCfgComponent_fnGetHelpText(
306     INetCfgComponent * iface,
307     LPWSTR * ppszwHelpText)
308 {
309     LPWSTR szHelp;
310     UINT Length;
311     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
312 
313     if (This == NULL || ppszwHelpText == NULL)
314         return E_POINTER;
315 
316     if (This->pItem->szHelpText)
317         Length = wcslen(This->pItem->szHelpText)+1;
318     else
319         Length = 1;
320 
321     szHelp = CoTaskMemAlloc(Length * sizeof(WCHAR));
322     if (!szHelp)
323         return E_OUTOFMEMORY;
324 
325     if (Length > 1)
326         wcscpy(szHelp, This->pItem->szHelpText);
327     else
328         szHelp[0] = L'\0';
329 
330     *ppszwHelpText = szHelp;
331 
332     return S_OK;
333 }
334 
335 HRESULT
336 WINAPI
337 INetCfgComponent_fnGetId(
338     INetCfgComponent * iface,
339     LPWSTR * ppszwId)
340 {
341     LPWSTR szId;
342     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
343 
344     if (This == NULL || ppszwId == NULL)
345         return E_POINTER;
346 
347     szId = CoTaskMemAlloc((wcslen(This->pItem->szId)+1) * sizeof(WCHAR));
348     if (!szId)
349         return E_OUTOFMEMORY;
350 
351      wcscpy(szId, This->pItem->szId);
352     *ppszwId = szId;
353 
354     return S_OK;
355 }
356 
357 HRESULT
358 WINAPI
359 INetCfgComponent_fnGetCharacteristics(
360     INetCfgComponent * iface,
361     DWORD * pdwCharacteristics)
362 {
363     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
364 
365     if (This == NULL || pdwCharacteristics == NULL)
366         return E_POINTER;
367 
368     *pdwCharacteristics = This->pItem->dwCharacteristics;
369 
370     return S_OK;
371 }
372 
373 HRESULT
374 WINAPI
375 INetCfgComponent_fnGetInstanceGuid(
376     INetCfgComponent * iface,
377     GUID * pGuid)
378 {
379     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
380 
381     if (This == NULL || pGuid == NULL)
382         return E_POINTER;
383 
384     CopyMemory(pGuid, &This->pItem->InstanceId, sizeof(GUID));
385     return S_OK;
386 }
387 
388 HRESULT
389 WINAPI
390 INetCfgComponent_fnGetPnpDevNodeId(
391     INetCfgComponent * iface,
392     LPWSTR * ppszwDevNodeId)
393 {
394     LPWSTR szNode;
395     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
396 
397     if (This == NULL || ppszwDevNodeId == NULL)
398         return E_POINTER;
399 
400     if (!IsEqualGUID(&GUID_DEVCLASS_NET, &This->pItem->ClassGUID))
401         return E_NOTIMPL;
402 
403     szNode = CoTaskMemAlloc((wcslen(This->pItem->szNodeId)+1) * sizeof(WCHAR));
404     if (!szNode)
405         return E_OUTOFMEMORY;
406 
407     wcscpy(szNode, This->pItem->szNodeId);
408     *ppszwDevNodeId = szNode;
409     return S_OK;
410 }
411 
412 HRESULT
413 WINAPI
414 INetCfgComponent_fnGetClassGuid(
415     INetCfgComponent * iface,
416     GUID * pGuid)
417 {
418     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
419 
420     if (This == NULL || pGuid == NULL)
421         return E_POINTER;
422 
423     CopyMemory(pGuid, &This->pItem->ClassGUID, sizeof(GUID));
424     return S_OK;
425 }
426 
427 HRESULT
428 WINAPI
429 INetCfgComponent_fnGetBindName(
430     INetCfgComponent * iface,
431     LPWSTR * ppszwBindName)
432 {
433     LPWSTR szBind;
434     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
435 
436     if (This == NULL || ppszwBindName == NULL)
437         return E_POINTER;
438 
439     szBind = CoTaskMemAlloc((wcslen(This->pItem->szBindName)+1) * sizeof(WCHAR));
440     if (!szBind)
441         return E_OUTOFMEMORY;
442 
443      wcscpy(szBind, This->pItem->szBindName);
444     *ppszwBindName = szBind;
445 
446     return S_OK;
447 }
448 
449 HRESULT
450 WINAPI
451 INetCfgComponent_fnGetDeviceStatus(
452     INetCfgComponent * iface,
453     ULONG * pStatus)
454 {
455     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
456 
457     if (This == NULL || pStatus == NULL)
458         return E_POINTER;
459 
460     if (!IsEqualGUID(&GUID_DEVCLASS_NET, &This->pItem->ClassGUID))
461         return E_UNEXPECTED;
462 
463     *pStatus = This->pItem->Status;
464 
465     return S_OK;
466 }
467 
468 HRESULT
469 WINAPI
470 INetCfgComponent_fnOpenParamKey(
471     INetCfgComponent * iface,
472     HKEY * phkey)
473 {
474     WCHAR szBuffer[200] = L"SYSTEM\\CurrentControlSet\\Services\\";
475     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
476 
477     if (This == NULL || phkey == NULL)
478         return E_POINTER;
479 
480     wcscat(szBuffer, This->pItem->szBindName);
481     wcscat(szBuffer, L"\\Parameters");
482 
483     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ | KEY_WRITE, phkey) == ERROR_SUCCESS)
484         return S_OK;
485     else
486         return E_FAIL;
487 }
488 
489 
490 HRESULT
491 CreateNotificationObject(
492     INetCfgComponentImpl * This,
493     INetCfgComponent * iface,
494     IUnknown  *pUnk)
495 {
496     WCHAR szName[150];
497     HKEY hKey;
498     DWORD dwSize, dwType;
499     GUID CLSID_NotifyObject;
500     LPOLESTR pStr;
501     INetCfgComponentPropertyUi * pNCCPU;
502     INetCfgComponentControl * pNCCC;
503     HRESULT hr;
504     LONG lRet;
505     CLSID ClassGUID;
506     //CLSID InstanceGUID;
507 
508     wcscpy(szName,L"SYSTEM\\CurrentControlSet\\Control\\Network\\");
509 
510     /* get the Class GUID */
511     hr = INetCfgComponent_GetClassGuid(iface, &ClassGUID);
512     if (FAILED(hr))
513         return hr;
514 
515     hr = StringFromCLSID(&ClassGUID, &pStr);
516     if (FAILED(hr))
517         return hr;
518 
519     wcscat(szName, pStr);
520     CoTaskMemFree(pStr);
521     wcscat(szName, L"\\");
522 
523     /* get the Instance GUID */
524 #if 0
525     hr = INetCfgComponent_GetInstanceGuid(iface, &InstanceGUID);
526     if (FAILED(hr))
527         return hr;
528 
529     hr = StringFromCLSID(&InstanceGUID, &pStr);
530     if (FAILED(hr))
531         return hr;
532 
533     wcscat(szName, pStr);
534     CoTaskMemFree(pStr);
535 #else
536     // HACK HACK HACK HACK HACK
537     wcscat(szName, L"{RandomProtocolGUID_TCPIP}");
538 #endif
539 
540     wcscat(szName, L"\\NDI");
541 
542     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
543         return E_FAIL;
544 
545     dwSize = sizeof(szName);
546     lRet = RegQueryValueExW(hKey, L"ClsID", NULL, &dwType, (LPBYTE)szName, &dwSize);
547     RegCloseKey(hKey);
548 
549     if (lRet != ERROR_SUCCESS && dwType != REG_SZ)
550         return E_FAIL;
551 
552     hr = CLSIDFromString(szName, &CLSID_NotifyObject);
553     if (FAILED(hr))
554         return E_FAIL;
555 
556     hr = CoCreateInstance(&CLSID_NotifyObject, NULL, CLSCTX_INPROC_SERVER, &IID_INetCfgComponentPropertyUi, (LPVOID*)&pNCCPU);
557     if (FAILED(hr))
558         return E_FAIL;
559 
560     hr = INetCfgComponentPropertyUi_QueryInterface(pNCCPU, &IID_INetCfgComponentControl, (LPVOID*)&pNCCC);
561     if (FAILED(hr))
562     {
563         INetCfgComponentPropertyUi_Release(pNCCPU);
564         return hr;
565     }
566 
567     hr = INetCfgComponentPropertyUi_QueryPropertyUi(pNCCPU, pUnk);
568     if (FAILED(hr))
569     {
570         INetCfgComponentPropertyUi_Release(pNCCPU);
571         return hr;
572     }
573 
574     hr = INetCfgComponentControl_Initialize(pNCCC, iface, This->pNCfg, FALSE);
575     if (FAILED(hr))
576     {
577         INetCfgComponentControl_Release(pNCCC);
578         INetCfgComponentPropertyUi_Release(pNCCPU);
579         return hr;
580     }
581 
582     hr = INetCfgComponentPropertyUi_SetContext(pNCCPU, pUnk);
583     if (FAILED(hr))
584     {
585         INetCfgComponentPropertyUi_Release(pNCCPU);
586         return hr;
587     }
588     This->pProperty = pNCCPU;
589     This->pItem->pNCCC = pNCCC;
590 
591     return S_OK;
592 }
593 
594 static int CALLBACK
595 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
596 {
597     // NOTE: This callback is needed to set large icon correctly.
598     HICON hIcon;
599     switch (uMsg)
600     {
601         case PSCB_INITIALIZED:
602         {
603             hIcon = LoadIconW(netcfgx_hInstance, MAKEINTRESOURCEW(IDI_INTERNET));
604             SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
605             break;
606         }
607     }
608     return 0;
609 }
610 
611 HRESULT
612 WINAPI
613 INetCfgComponent_fnRaisePropertyUi(
614     INetCfgComponent * iface,
615     IN HWND  hwndParent,
616     IN DWORD  dwFlags,
617     IN IUnknown  *pUnk)
618 {
619     HRESULT hr;
620     DWORD dwDefPages;
621     UINT Pages;
622     PROPSHEETHEADERW pinfo;
623     HPROPSHEETPAGE * hppages;
624     INT_PTR iResult;
625     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
626 
627     if (!This->pProperty)
628     {
629          hr = CreateNotificationObject(This,iface, pUnk);
630          if (FAILED(hr))
631              return hr;
632     }
633 
634     if (dwFlags == NCRP_QUERY_PROPERTY_UI)
635         return S_OK;
636 
637     dwDefPages = 0;
638     Pages = 0;
639 
640     hr = INetCfgComponentPropertyUi_MergePropPages(This->pProperty, &dwDefPages, (BYTE**)&hppages, &Pages, hwndParent, NULL);
641     if (FAILED(hr) || !Pages)
642     {
643         return hr;
644     }
645     ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
646     pinfo.dwSize = sizeof(PROPSHEETHEADERW);
647     pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW |
648                     PSH_USEICONID | PSH_USECALLBACK;
649     pinfo.u3.phpage = hppages;
650     pinfo.hwndParent = hwndParent;
651     pinfo.nPages = Pages;
652     pinfo.hInstance = netcfgx_hInstance;
653     pinfo.pszCaption = This->pItem->szDisplayName;
654     pinfo.u.pszIcon = MAKEINTRESOURCEW(IDI_INTERNET);
655     pinfo.pfnCallback = PropSheetProc;
656 
657     iResult = PropertySheetW(&pinfo);
658     CoTaskMemFree(hppages);
659     if (iResult > 0)
660     {
661         /* indicate that settings should be stored */
662         This->pItem->bChanged = TRUE;
663         return S_OK;
664     }
665     return S_FALSE;
666 }
667 static const INetCfgComponentVtbl vt_NetCfgComponent =
668 {
669     INetCfgComponent_fnQueryInterface,
670     INetCfgComponent_fnAddRef,
671     INetCfgComponent_fnRelease,
672     INetCfgComponent_fnGetDisplayName,
673     INetCfgComponent_fnSetDisplayName,
674     INetCfgComponent_fnGetHelpText,
675     INetCfgComponent_fnGetId,
676     INetCfgComponent_fnGetCharacteristics,
677     INetCfgComponent_fnGetInstanceGuid,
678     INetCfgComponent_fnGetPnpDevNodeId,
679     INetCfgComponent_fnGetClassGuid,
680     INetCfgComponent_fnGetBindName,
681     INetCfgComponent_fnGetDeviceStatus,
682     INetCfgComponent_fnOpenParamKey,
683     INetCfgComponent_fnRaisePropertyUi
684 };
685 
686 HRESULT
687 WINAPI
688 INetCfgComponent_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv, NetCfgComponentItem * pItem, INetCfg * pNCfg)
689 {
690     INetCfgComponentImpl *This;
691 
692     if (!ppv)
693         return E_POINTER;
694 
695     This = (INetCfgComponentImpl *) CoTaskMemAlloc(sizeof (INetCfgComponentImpl));
696     if (!This)
697         return E_OUTOFMEMORY;
698 
699     This->ref = 1;
700     This->lpVtbl = (const INetCfgComponent*)&vt_NetCfgComponent;
701     This->lpVtblComponentBindings = (const INetCfgComponentBindings*)&vt_NetCfgComponentBindings;
702     This->pProperty = NULL;
703     This->pItem = pItem;
704     This->pNCfg = pNCfg;
705 
706     if (!SUCCEEDED (INetCfgComponent_QueryInterface ((INetCfgComponent*)This, riid, ppv)))
707     {
708         INetCfgComponent_Release((INetCfg*)This);
709         return E_NOINTERFACE;
710     }
711 
712     INetCfgComponent_Release((INetCfgComponent*)This);
713     return S_OK;
714 }
715 
716 
717 /***************************************************************
718  * IEnumNetCfgComponent
719  */
720 
721 HRESULT
722 WINAPI
723 IEnumNetCfgComponent_fnQueryInterface(
724     IEnumNetCfgComponent * iface,
725     REFIID iid,
726     LPVOID * ppvObj)
727 {
728     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
729     *ppvObj = NULL;
730 
731     if (IsEqualIID (iid, &IID_IUnknown) ||
732         IsEqualIID (iid, &IID_IEnumNetCfgComponent))
733     {
734         *ppvObj = This;
735         INetCfg_AddRef(iface);
736         return S_OK;
737     }
738 
739     return E_NOINTERFACE;
740 }
741 
742 
743 ULONG
744 WINAPI
745 IEnumNetCfgComponent_fnAddRef(
746     IEnumNetCfgComponent * iface)
747 {
748     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
749     ULONG refCount = InterlockedIncrement(&This->ref);
750 
751     return refCount;
752 }
753 
754 ULONG
755 WINAPI
756 IEnumNetCfgComponent_fnRelease(
757     IEnumNetCfgComponent * iface)
758 {
759     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
760     ULONG refCount = InterlockedDecrement(&This->ref);
761 
762     return refCount;
763 }
764 
765 HRESULT
766 WINAPI
767 IEnumNetCfgComponent_fnNext(
768     IEnumNetCfgComponent * iface,
769     ULONG celt,
770     INetCfgComponent **rgelt,
771     ULONG *pceltFetched)
772 {
773     HRESULT hr;
774     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
775 
776     if (!iface || !rgelt)
777         return E_POINTER;
778 
779     if (celt != 1)
780         return E_INVALIDARG;
781 
782     if (!This->pCurrent)
783         return S_FALSE;
784 
785     hr = INetCfgComponent_Constructor (NULL, &IID_INetCfgComponent, (LPVOID*)rgelt, This->pCurrent, This->pNCfg);
786     if (SUCCEEDED(hr))
787     {
788         This->pCurrent = This->pCurrent->pNext;
789         if (pceltFetched)
790             *pceltFetched = 1;
791     }
792     return hr;
793 }
794 
795 HRESULT
796 WINAPI
797 IEnumNetCfgComponent_fnSkip(
798     IEnumNetCfgComponent * iface,
799     ULONG celt)
800 {
801     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
802 
803     if (!This->pCurrent)
804         return S_FALSE;
805 
806     while(celt-- > 0 && This->pCurrent)
807         This->pCurrent = This->pCurrent->pNext;
808 
809     if (!celt)
810         return S_OK;
811     else
812         return S_FALSE;
813 }
814 
815 HRESULT
816 WINAPI
817 IEnumNetCfgComponent_fnReset(
818     IEnumNetCfgComponent * iface)
819 {
820     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
821 
822     This->pCurrent = This->pHead;
823     return S_OK;
824 }
825 
826 HRESULT
827 WINAPI
828 IEnumNetCfgComponent_fnClone(
829     IEnumNetCfgComponent * iface,
830     IEnumNetCfgComponent **ppenum)
831 {
832     return E_NOTIMPL;
833 }
834 
835 static const IEnumNetCfgComponentVtbl vt_EnumNetCfgComponent =
836 {
837     IEnumNetCfgComponent_fnQueryInterface,
838     IEnumNetCfgComponent_fnAddRef,
839     IEnumNetCfgComponent_fnRelease,
840     IEnumNetCfgComponent_fnNext,
841     IEnumNetCfgComponent_fnSkip,
842     IEnumNetCfgComponent_fnReset,
843     IEnumNetCfgComponent_fnClone
844 };
845 
846 HRESULT
847 WINAPI
848 IEnumNetCfgComponent_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv, NetCfgComponentItem * pItem, INetCfg * pNCfg)
849 {
850     IEnumNetCfgComponentImpl *This;
851 
852     if (!ppv)
853         return E_POINTER;
854 
855     This = (IEnumNetCfgComponentImpl *) CoTaskMemAlloc(sizeof (IEnumNetCfgComponentImpl));
856     if (!This)
857         return E_OUTOFMEMORY;
858 
859     This->ref = 1;
860     This->lpVtbl = (const IEnumNetCfgComponent*)&vt_EnumNetCfgComponent;
861     This->pCurrent = pItem;
862     This->pHead = pItem;
863     This->pNCfg = pNCfg;
864 
865     if (!SUCCEEDED (IEnumNetCfgComponent_QueryInterface ((INetCfgComponent*)This, riid, ppv)))
866     {
867         IEnumNetCfgComponent_Release((INetCfg*)This);
868         return E_NOINTERFACE;
869     }
870 
871     IEnumNetCfgComponent_Release((IEnumNetCfgComponent*)This);
872     return S_OK;
873 }
874 
875 
876