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     hr = INetCfgComponent_GetInstanceGuid(iface, &InstanceGUID);
525     if (FAILED(hr))
526         return hr;
527 
528     hr = StringFromCLSID(&InstanceGUID, &pStr);
529     if (FAILED(hr))
530         return hr;
531 
532     wcscat(szName, pStr);
533     CoTaskMemFree(pStr);
534 
535     wcscat(szName, L"\\NDI");
536 
537     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
538         return E_FAIL;
539 
540     dwSize = sizeof(szName);
541     lRet = RegQueryValueExW(hKey, L"ClsID", NULL, &dwType, (LPBYTE)szName, &dwSize);
542     RegCloseKey(hKey);
543 
544     if (lRet != ERROR_SUCCESS && dwType != REG_SZ)
545         return E_FAIL;
546 
547     hr = CLSIDFromString(szName, &CLSID_NotifyObject);
548     if (FAILED(hr))
549         return E_FAIL;
550 
551     hr = CoCreateInstance(&CLSID_NotifyObject, NULL, CLSCTX_INPROC_SERVER, &IID_INetCfgComponentPropertyUi, (LPVOID*)&pNCCPU);
552     if (FAILED(hr))
553         return E_FAIL;
554 
555     hr = INetCfgComponentPropertyUi_QueryInterface(pNCCPU, &IID_INetCfgComponentControl, (LPVOID*)&pNCCC);
556     if (FAILED(hr))
557     {
558         INetCfgComponentPropertyUi_Release(pNCCPU);
559         return hr;
560     }
561 
562     hr = INetCfgComponentPropertyUi_QueryPropertyUi(pNCCPU, pUnk);
563     if (FAILED(hr))
564     {
565         INetCfgComponentPropertyUi_Release(pNCCPU);
566         return hr;
567     }
568 
569     hr = INetCfgComponentControl_Initialize(pNCCC, iface, This->pNCfg, FALSE);
570     if (FAILED(hr))
571     {
572         INetCfgComponentControl_Release(pNCCC);
573         INetCfgComponentPropertyUi_Release(pNCCPU);
574         return hr;
575     }
576 
577     hr = INetCfgComponentPropertyUi_SetContext(pNCCPU, pUnk);
578     if (FAILED(hr))
579     {
580         INetCfgComponentPropertyUi_Release(pNCCPU);
581         return hr;
582     }
583     This->pProperty = pNCCPU;
584     This->pItem->pNCCC = pNCCC;
585 
586     return S_OK;
587 }
588 
589 static int CALLBACK
590 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
591 {
592     // NOTE: This callback is needed to set large icon correctly.
593     HICON hIcon;
594     switch (uMsg)
595     {
596         case PSCB_INITIALIZED:
597         {
598             hIcon = LoadIconW(netcfgx_hInstance, MAKEINTRESOURCEW(IDI_INTERNET));
599             SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
600             break;
601         }
602     }
603     return 0;
604 }
605 
606 HRESULT
607 WINAPI
608 INetCfgComponent_fnRaisePropertyUi(
609     INetCfgComponent * iface,
610     IN HWND  hwndParent,
611     IN DWORD  dwFlags,
612     IN IUnknown  *pUnk)
613 {
614     HRESULT hr;
615     DWORD dwDefPages;
616     UINT Pages;
617     PROPSHEETHEADERW pinfo;
618     HPROPSHEETPAGE * hppages;
619     INT_PTR iResult;
620     INetCfgComponentImpl * This = (INetCfgComponentImpl*)iface;
621 
622     if (!This->pProperty)
623     {
624          hr = CreateNotificationObject(This,iface, pUnk);
625          if (FAILED(hr))
626              return hr;
627     }
628 
629     if (dwFlags == NCRP_QUERY_PROPERTY_UI)
630         return S_OK;
631 
632     dwDefPages = 0;
633     Pages = 0;
634 
635     hr = INetCfgComponentPropertyUi_MergePropPages(This->pProperty, &dwDefPages, (BYTE**)&hppages, &Pages, hwndParent, NULL);
636     if (FAILED(hr) || !Pages)
637     {
638         return hr;
639     }
640     ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
641     pinfo.dwSize = sizeof(PROPSHEETHEADERW);
642     pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW |
643                     PSH_USEICONID | PSH_USECALLBACK;
644     pinfo.u3.phpage = hppages;
645     pinfo.hwndParent = hwndParent;
646     pinfo.nPages = Pages;
647     pinfo.hInstance = netcfgx_hInstance;
648     pinfo.pszCaption = This->pItem->szDisplayName;
649     pinfo.u.pszIcon = MAKEINTRESOURCEW(IDI_INTERNET);
650     pinfo.pfnCallback = PropSheetProc;
651 
652     iResult = PropertySheetW(&pinfo);
653     CoTaskMemFree(hppages);
654     if (iResult > 0)
655     {
656         /* indicate that settings should be stored */
657         This->pItem->bChanged = TRUE;
658         return S_OK;
659     }
660     return S_FALSE;
661 }
662 static const INetCfgComponentVtbl vt_NetCfgComponent =
663 {
664     INetCfgComponent_fnQueryInterface,
665     INetCfgComponent_fnAddRef,
666     INetCfgComponent_fnRelease,
667     INetCfgComponent_fnGetDisplayName,
668     INetCfgComponent_fnSetDisplayName,
669     INetCfgComponent_fnGetHelpText,
670     INetCfgComponent_fnGetId,
671     INetCfgComponent_fnGetCharacteristics,
672     INetCfgComponent_fnGetInstanceGuid,
673     INetCfgComponent_fnGetPnpDevNodeId,
674     INetCfgComponent_fnGetClassGuid,
675     INetCfgComponent_fnGetBindName,
676     INetCfgComponent_fnGetDeviceStatus,
677     INetCfgComponent_fnOpenParamKey,
678     INetCfgComponent_fnRaisePropertyUi
679 };
680 
681 HRESULT
682 WINAPI
683 INetCfgComponent_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv, NetCfgComponentItem * pItem, INetCfg * pNCfg)
684 {
685     INetCfgComponentImpl *This;
686 
687     if (!ppv)
688         return E_POINTER;
689 
690     This = (INetCfgComponentImpl *) CoTaskMemAlloc(sizeof (INetCfgComponentImpl));
691     if (!This)
692         return E_OUTOFMEMORY;
693 
694     This->ref = 1;
695     This->lpVtbl = (const INetCfgComponent*)&vt_NetCfgComponent;
696     This->lpVtblComponentBindings = (const INetCfgComponentBindings*)&vt_NetCfgComponentBindings;
697     This->pProperty = NULL;
698     This->pItem = pItem;
699     This->pNCfg = pNCfg;
700 
701     if (!SUCCEEDED (INetCfgComponent_QueryInterface ((INetCfgComponent*)This, riid, ppv)))
702     {
703         INetCfgComponent_Release((INetCfg*)This);
704         return E_NOINTERFACE;
705     }
706 
707     INetCfgComponent_Release((INetCfgComponent*)This);
708     return S_OK;
709 }
710 
711 
712 /***************************************************************
713  * IEnumNetCfgComponent
714  */
715 
716 HRESULT
717 WINAPI
718 IEnumNetCfgComponent_fnQueryInterface(
719     IEnumNetCfgComponent * iface,
720     REFIID iid,
721     LPVOID * ppvObj)
722 {
723     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
724     *ppvObj = NULL;
725 
726     if (IsEqualIID (iid, &IID_IUnknown) ||
727         IsEqualIID (iid, &IID_IEnumNetCfgComponent))
728     {
729         *ppvObj = This;
730         INetCfg_AddRef(iface);
731         return S_OK;
732     }
733 
734     return E_NOINTERFACE;
735 }
736 
737 
738 ULONG
739 WINAPI
740 IEnumNetCfgComponent_fnAddRef(
741     IEnumNetCfgComponent * iface)
742 {
743     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
744     ULONG refCount = InterlockedIncrement(&This->ref);
745 
746     return refCount;
747 }
748 
749 ULONG
750 WINAPI
751 IEnumNetCfgComponent_fnRelease(
752     IEnumNetCfgComponent * iface)
753 {
754     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
755     ULONG refCount = InterlockedDecrement(&This->ref);
756 
757     return refCount;
758 }
759 
760 HRESULT
761 WINAPI
762 IEnumNetCfgComponent_fnNext(
763     IEnumNetCfgComponent * iface,
764     ULONG celt,
765     INetCfgComponent **rgelt,
766     ULONG *pceltFetched)
767 {
768     HRESULT hr;
769     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
770 
771     if (!iface || !rgelt)
772         return E_POINTER;
773 
774     if (celt != 1)
775         return E_INVALIDARG;
776 
777     if (!This->pCurrent)
778         return S_FALSE;
779 
780     hr = INetCfgComponent_Constructor (NULL, &IID_INetCfgComponent, (LPVOID*)rgelt, This->pCurrent, This->pNCfg);
781     if (SUCCEEDED(hr))
782     {
783         This->pCurrent = This->pCurrent->pNext;
784         if (pceltFetched)
785             *pceltFetched = 1;
786     }
787     return hr;
788 }
789 
790 HRESULT
791 WINAPI
792 IEnumNetCfgComponent_fnSkip(
793     IEnumNetCfgComponent * iface,
794     ULONG celt)
795 {
796     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
797 
798     if (!This->pCurrent)
799         return S_FALSE;
800 
801     while(celt-- > 0 && This->pCurrent)
802         This->pCurrent = This->pCurrent->pNext;
803 
804     if (!celt)
805         return S_OK;
806     else
807         return S_FALSE;
808 }
809 
810 HRESULT
811 WINAPI
812 IEnumNetCfgComponent_fnReset(
813     IEnumNetCfgComponent * iface)
814 {
815     IEnumNetCfgComponentImpl * This = (IEnumNetCfgComponentImpl*)iface;
816 
817     This->pCurrent = This->pHead;
818     return S_OK;
819 }
820 
821 HRESULT
822 WINAPI
823 IEnumNetCfgComponent_fnClone(
824     IEnumNetCfgComponent * iface,
825     IEnumNetCfgComponent **ppenum)
826 {
827     return E_NOTIMPL;
828 }
829 
830 static const IEnumNetCfgComponentVtbl vt_EnumNetCfgComponent =
831 {
832     IEnumNetCfgComponent_fnQueryInterface,
833     IEnumNetCfgComponent_fnAddRef,
834     IEnumNetCfgComponent_fnRelease,
835     IEnumNetCfgComponent_fnNext,
836     IEnumNetCfgComponent_fnSkip,
837     IEnumNetCfgComponent_fnReset,
838     IEnumNetCfgComponent_fnClone
839 };
840 
841 HRESULT
842 WINAPI
843 IEnumNetCfgComponent_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv, NetCfgComponentItem * pItem, INetCfg * pNCfg)
844 {
845     IEnumNetCfgComponentImpl *This;
846 
847     if (!ppv)
848         return E_POINTER;
849 
850     This = (IEnumNetCfgComponentImpl *) CoTaskMemAlloc(sizeof (IEnumNetCfgComponentImpl));
851     if (!This)
852         return E_OUTOFMEMORY;
853 
854     This->ref = 1;
855     This->lpVtbl = (const IEnumNetCfgComponent*)&vt_EnumNetCfgComponent;
856     This->pCurrent = pItem;
857     This->pHead = pItem;
858     This->pNCfg = pNCfg;
859 
860     if (!SUCCEEDED (IEnumNetCfgComponent_QueryInterface ((INetCfgComponent*)This, riid, ppv)))
861     {
862         IEnumNetCfgComponent_Release((INetCfg*)This);
863         return E_NOINTERFACE;
864     }
865 
866     IEnumNetCfgComponent_Release((IEnumNetCfgComponent*)This);
867     return S_OK;
868 }
869 
870 
871