sync with trunk r49322
[reactos.git] / dll / win32 / netshell / connectmanager.c
1 #include <precomp.h>
2
3 typedef struct tagINetConnectionItem
4 {
5 struct tagINetConnectionItem * Next;
6 DWORD dwAdapterIndex;
7 NETCON_PROPERTIES Props;
8 }INetConnectionItem, *PINetConnectionItem;
9
10 typedef struct
11 {
12 const INetConnectionManagerVtbl * lpVtbl;
13 const IEnumNetConnectionVtbl * lpVtblNetConnection;
14 LONG ref;
15 PINetConnectionItem pHead;
16 PINetConnectionItem pCurrent;
17
18 } INetConnectionManagerImpl, *LPINetConnectionManagerImpl;
19
20 typedef struct
21 {
22 const INetConnectionVtbl * lpVtbl;
23 LONG ref;
24 NETCON_PROPERTIES Props;
25 DWORD dwAdapterIndex;
26 } INetConnectionImpl, *LPINetConnectionImpl;
27
28
29 static __inline LPINetConnectionManagerImpl impl_from_EnumNetConnection(IEnumNetConnection *iface)
30 {
31 return (LPINetConnectionManagerImpl)((char *)iface - FIELD_OFFSET(INetConnectionManagerImpl, lpVtblNetConnection));
32 }
33
34 VOID NormalizeOperStatus(MIB_IFROW *IfEntry, NETCON_PROPERTIES * Props);
35
36 static
37 HRESULT
38 WINAPI
39 INetConnectionManager_fnQueryInterface(
40 INetConnectionManager * iface,
41 REFIID iid,
42 LPVOID * ppvObj)
43 {
44 INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
45 *ppvObj = NULL;
46
47 if (IsEqualIID (iid, &IID_IUnknown) ||
48 IsEqualIID (iid, &IID_INetConnectionManager))
49 {
50 *ppvObj = This;
51 INetConnectionManager_AddRef(iface);
52 return S_OK;
53 }
54
55 return E_NOINTERFACE;
56 }
57
58 static
59 ULONG
60 WINAPI
61 INetConnectionManager_fnAddRef(
62 INetConnectionManager * iface)
63 {
64 INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
65 ULONG refCount = InterlockedIncrement(&This->ref);
66
67 return refCount;
68 }
69
70 static
71 ULONG
72 WINAPI
73 INetConnectionManager_fnRelease(
74 INetConnectionManager * iface)
75 {
76 INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
77 ULONG refCount = InterlockedDecrement(&This->ref);
78
79 if (!refCount)
80 {
81 CoTaskMemFree (This);
82 }
83 return refCount;
84 }
85
86 static
87 HRESULT
88 WINAPI
89 INetConnectionManager_fnEnumConnections(
90 INetConnectionManager * iface,
91 NETCONMGR_ENUM_FLAGS Flags,
92 IEnumNetConnection **ppEnum)
93 {
94 INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
95
96 if (!ppEnum)
97 return E_POINTER;
98
99 if (Flags != NCME_DEFAULT)
100 return E_FAIL;
101
102 *ppEnum = (IEnumNetConnection *)&This->lpVtblNetConnection;
103 INetConnectionManager_AddRef(iface);
104 return S_OK;
105 }
106
107 static const INetConnectionManagerVtbl vt_NetConnectionManager =
108 {
109 INetConnectionManager_fnQueryInterface,
110 INetConnectionManager_fnAddRef,
111 INetConnectionManager_fnRelease,
112 INetConnectionManager_fnEnumConnections,
113 };
114
115 /***************************************************************
116 * INetConnection Interface
117 */
118
119 static
120 HRESULT
121 WINAPI
122 INetConnection_fnQueryInterface(
123 INetConnection * iface,
124 REFIID iid,
125 LPVOID * ppvObj)
126 {
127 INetConnectionImpl * This = (INetConnectionImpl*)iface;
128 *ppvObj = NULL;
129
130 if (IsEqualIID (iid, &IID_IUnknown) ||
131 IsEqualIID (iid, &IID_INetConnection))
132 {
133 *ppvObj = This;
134 INetConnection_AddRef(iface);
135 return S_OK;
136 }
137
138 return E_NOINTERFACE;
139 }
140
141 static
142 ULONG
143 WINAPI
144 INetConnection_fnAddRef(
145 INetConnection * iface)
146 {
147 INetConnectionImpl * This = (INetConnectionImpl*)iface;
148 ULONG refCount = InterlockedIncrement(&This->ref);
149
150 return refCount;
151 }
152
153 static
154 ULONG
155 WINAPI
156 INetConnection_fnRelease(
157 INetConnection * iface)
158 {
159 INetConnectionImpl * This = (INetConnectionImpl*)iface;
160 ULONG refCount = InterlockedDecrement(&This->ref);
161
162 if (!refCount)
163 {
164 CoTaskMemFree(This->Props.pszwName);
165 CoTaskMemFree(This->Props.pszwDeviceName);
166 CoTaskMemFree(This);
167 }
168 return refCount;
169 }
170
171 static
172 HRESULT
173 WINAPI
174 INetConnection_fnConnect(
175 INetConnection * iface)
176 {
177 return E_NOTIMPL;
178 }
179
180 static
181 HRESULT
182 WINAPI
183 INetConnection_fnDisconnect(
184 INetConnection * iface)
185 {
186 return E_NOTIMPL;
187 }
188
189
190 static
191 HRESULT
192 WINAPI
193 INetConnection_fnDelete(
194 INetConnection * iface)
195 {
196 return E_NOTIMPL;
197 }
198
199 static
200 HRESULT
201 WINAPI
202 INetConnection_fnDuplicate(
203 INetConnection * iface,
204 LPCWSTR pszwDuplicateName,
205 INetConnection **ppCon)
206 {
207 return E_NOTIMPL;
208 }
209
210 static
211 HRESULT
212 WINAPI
213 INetConnection_fnGetProperties(
214 INetConnection * iface,
215 NETCON_PROPERTIES **ppProps)
216 {
217 MIB_IFROW IfEntry;
218 HKEY hKey;
219 LPOLESTR pStr;
220 WCHAR szName[140];
221 DWORD dwShowIcon, dwType, dwSize;
222 NETCON_PROPERTIES * pProperties;
223 HRESULT hr;
224
225 INetConnectionImpl * This = (INetConnectionImpl*)iface;
226
227 if (!ppProps)
228 return E_POINTER;
229
230 pProperties = CoTaskMemAlloc(sizeof(NETCON_PROPERTIES));
231 if (!pProperties)
232 return E_OUTOFMEMORY;
233
234
235 CopyMemory(pProperties, &This->Props, sizeof(NETCON_PROPERTIES));
236 pProperties->pszwName = NULL;
237
238 if (This->Props.pszwDeviceName)
239 {
240 pProperties->pszwDeviceName = CoTaskMemAlloc((wcslen(This->Props.pszwDeviceName)+1)*sizeof(WCHAR));
241 if (pProperties->pszwDeviceName)
242 wcscpy(pProperties->pszwDeviceName, This->Props.pszwDeviceName);
243 }
244
245 *ppProps = pProperties;
246
247 /* get updated adapter characteristics */
248 ZeroMemory(&IfEntry, sizeof(IfEntry));
249 IfEntry.dwIndex = This->dwAdapterIndex;
250 if(GetIfEntry(&IfEntry) != NO_ERROR)
251 return NOERROR;
252
253 NormalizeOperStatus(&IfEntry, pProperties);
254
255
256 hr = StringFromCLSID(&This->Props.guidId, &pStr);
257 if (SUCCEEDED(hr))
258 {
259 wcscpy(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
260 wcscat(szName, pStr);
261 wcscat(szName, L"\\Connection");
262
263 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
264 {
265 dwSize = sizeof(dwShowIcon);
266 if (RegQueryValueExW(hKey, L"ShowIcon", NULL, &dwType, (LPBYTE)&dwShowIcon, &dwSize) == ERROR_SUCCESS && dwType == REG_DWORD)
267 {
268 if (dwShowIcon)
269 pProperties->dwCharacter |= NCCF_SHOW_ICON;
270 else
271 pProperties->dwCharacter &= ~NCCF_SHOW_ICON;
272 }
273 dwSize = sizeof(szName);
274 if (RegQueryValueExW(hKey, L"Name", NULL, &dwType, (LPBYTE)szName, &dwSize) == ERROR_SUCCESS)
275 {
276 /* use updated name */
277 dwSize = wcslen(szName) + 1;
278 pProperties->pszwName = CoTaskMemAlloc(dwSize * sizeof(WCHAR));
279 if (pProperties->pszwName)
280 CopyMemory(pProperties->pszwName, szName, dwSize * sizeof(WCHAR));
281 }
282 else
283 {
284 /* use cached name */
285 if (This->Props.pszwName)
286 {
287 pProperties->pszwName = CoTaskMemAlloc((wcslen(This->Props.pszwName)+1)*sizeof(WCHAR));
288 if (pProperties->pszwName)
289 wcscpy(pProperties->pszwName, This->Props.pszwName);
290 }
291 }
292 RegCloseKey(hKey);
293 }
294 CoTaskMemFree(pStr);
295 }
296
297
298 return NOERROR;
299 }
300
301 static
302 HRESULT
303 WINAPI
304 INetConnection_fnGetUiObjectClassId(
305 INetConnection * iface,
306 CLSID *pclsid)
307 {
308
309 INetConnectionImpl * This = (INetConnectionImpl*)iface;
310
311 if (This->Props.MediaType == NCM_LAN)
312 {
313 CopyMemory(pclsid, &CLSID_LANConnectUI, sizeof(CLSID));
314 return S_OK;
315 }
316
317 return E_NOTIMPL;
318 }
319
320 static
321 HRESULT
322 WINAPI
323 INetConnection_fnRename(
324 INetConnection * iface,
325 LPCWSTR pszwDuplicateName)
326 {
327 return E_NOTIMPL;
328 }
329
330
331 static const INetConnectionVtbl vt_NetConnection =
332 {
333 INetConnection_fnQueryInterface,
334 INetConnection_fnAddRef,
335 INetConnection_fnRelease,
336 INetConnection_fnConnect,
337 INetConnection_fnDisconnect,
338 INetConnection_fnDelete,
339 INetConnection_fnDuplicate,
340 INetConnection_fnGetProperties,
341 INetConnection_fnGetUiObjectClassId,
342 INetConnection_fnRename
343 };
344
345 HRESULT WINAPI IConnection_Constructor (INetConnection **ppv, PINetConnectionItem pItem)
346 {
347 INetConnectionImpl *This;
348
349 if (!ppv)
350 return E_POINTER;
351
352 This = (INetConnectionImpl *) CoTaskMemAlloc(sizeof (INetConnectionImpl));
353 if (!This)
354 return E_OUTOFMEMORY;
355
356 This->ref = 1;
357 This->lpVtbl = &vt_NetConnection;
358 This->dwAdapterIndex = pItem->dwAdapterIndex;
359 CopyMemory(&This->Props, &pItem->Props, sizeof(NETCON_PROPERTIES));
360
361 if (pItem->Props.pszwName)
362 {
363 This->Props.pszwName = CoTaskMemAlloc((wcslen(pItem->Props.pszwName)+1)*sizeof(WCHAR));
364 if (This->Props.pszwName)
365 wcscpy(This->Props.pszwName, pItem->Props.pszwName);
366 }
367
368 if (pItem->Props.pszwDeviceName)
369 {
370 This->Props.pszwDeviceName = CoTaskMemAlloc((wcslen(pItem->Props.pszwDeviceName)+1)*sizeof(WCHAR));
371 if (This->Props.pszwDeviceName)
372 wcscpy(This->Props.pszwDeviceName, pItem->Props.pszwDeviceName);
373 }
374
375 *ppv = (INetConnection *)This;
376
377
378 return S_OK;
379 }
380
381
382 /***************************************************************
383 * IEnumNetConnection Interface
384 */
385
386 static
387 HRESULT
388 WINAPI
389 IEnumNetConnection_fnQueryInterface(
390 IEnumNetConnection * iface,
391 REFIID iid,
392 LPVOID * ppvObj)
393 {
394 INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
395 *ppvObj = NULL;
396
397 if (IsEqualIID (iid, &IID_IUnknown) ||
398 IsEqualIID (iid, &IID_INetConnectionManager))
399 {
400 *ppvObj = This;
401 INetConnectionManager_AddRef(iface);
402 return S_OK;
403 }
404
405 return E_NOINTERFACE;
406 }
407
408 static
409 ULONG
410 WINAPI
411 IEnumNetConnection_fnAddRef(
412 IEnumNetConnection * iface)
413 {
414 INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
415 ULONG refCount = InterlockedIncrement(&This->ref);
416
417 return refCount;
418 }
419
420 static
421 ULONG
422 WINAPI
423 IEnumNetConnection_fnRelease(
424 IEnumNetConnection * iface)
425 {
426 INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
427 ULONG refCount = InterlockedDecrement(&This->ref);
428
429 if (!refCount)
430 {
431 CoTaskMemFree (This);
432 }
433 return refCount;
434 }
435
436 static
437 HRESULT
438 WINAPI
439 IEnumNetConnection_fnNext(
440 IEnumNetConnection * iface,
441 ULONG celt,
442 INetConnection **rgelt,
443 ULONG *pceltFetched)
444 {
445 INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
446 HRESULT hr;
447
448 if (!pceltFetched || !rgelt)
449 return E_POINTER;
450
451 if (celt != 1)
452 return E_FAIL;
453
454 if (!This->pCurrent)
455 return S_FALSE;
456
457 hr = IConnection_Constructor(rgelt, This->pCurrent);
458 This->pCurrent = This->pCurrent->Next;
459
460 return hr;
461 }
462
463 static
464 HRESULT
465 WINAPI
466 IEnumNetConnection_fnSkip(
467 IEnumNetConnection * iface,
468 ULONG celt)
469 {
470 INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
471
472 while(This->pCurrent && celt-- > 0)
473 This->pCurrent = This->pCurrent->Next;
474
475 if (celt)
476 return S_FALSE;
477 else
478 return NOERROR;
479
480 }
481
482 static
483 HRESULT
484 WINAPI
485 IEnumNetConnection_fnReset(
486 IEnumNetConnection * iface)
487 {
488 INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
489
490 This->pCurrent = This->pHead;
491 return NOERROR;
492 }
493
494 static
495 HRESULT
496 WINAPI
497 IEnumNetConnection_fnClone(
498 IEnumNetConnection * iface,
499 IEnumNetConnection **ppenum)
500 {
501 return E_NOTIMPL;
502 }
503
504 static const IEnumNetConnectionVtbl vt_EnumNetConnection =
505 {
506 IEnumNetConnection_fnQueryInterface,
507 IEnumNetConnection_fnAddRef,
508 IEnumNetConnection_fnRelease,
509 IEnumNetConnection_fnNext,
510 IEnumNetConnection_fnSkip,
511 IEnumNetConnection_fnReset,
512 IEnumNetConnection_fnClone
513 };
514
515
516 BOOL
517 GetAdapterIndexFromNetCfgInstanceId(PIP_ADAPTER_INFO pAdapterInfo, LPWSTR szNetCfg, PDWORD pIndex)
518 {
519 WCHAR szBuffer[50];
520 IP_ADAPTER_INFO * pCurrentAdapter;
521
522 pCurrentAdapter = pAdapterInfo;
523 while(pCurrentAdapter)
524 {
525 szBuffer[0] = L'\0';
526 if (MultiByteToWideChar(CP_ACP, 0, pCurrentAdapter->AdapterName, -1, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0])))
527 {
528 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
529 }
530 if (!_wcsicmp(szBuffer, szNetCfg))
531 {
532 *pIndex = pCurrentAdapter->Index;
533 return TRUE;
534 }
535 pCurrentAdapter = pCurrentAdapter->Next;
536 }
537 return FALSE;
538 }
539
540 VOID
541 NormalizeOperStatus(
542 MIB_IFROW *IfEntry,
543 NETCON_PROPERTIES * Props)
544 {
545 switch(IfEntry->dwOperStatus)
546 {
547 case MIB_IF_OPER_STATUS_NON_OPERATIONAL:
548 Props->Status = NCS_HARDWARE_DISABLED;
549 break;
550 case MIB_IF_OPER_STATUS_UNREACHABLE:
551 Props->Status = NCS_DISCONNECTED;
552 break;
553 case MIB_IF_OPER_STATUS_DISCONNECTED:
554 Props->Status = NCS_MEDIA_DISCONNECTED;
555 break;
556 case MIB_IF_OPER_STATUS_CONNECTING:
557 Props->Status = NCS_CONNECTING;
558 break;
559 case MIB_IF_OPER_STATUS_CONNECTED:
560 Props->Status = NCS_CONNECTED;
561 break;
562 case MIB_IF_OPER_STATUS_OPERATIONAL:
563 Props->Status = NCS_CONNECTED;
564 break;
565 default:
566 break;
567 }
568 }
569
570
571 static
572 BOOL
573 EnumerateINetConnections(INetConnectionManagerImpl *This)
574 {
575 DWORD dwSize, dwResult, dwIndex, dwAdapterIndex, dwShowIcon;
576 MIB_IFTABLE *pIfTable;
577 MIB_IFROW IfEntry;
578 IP_ADAPTER_INFO * pAdapterInfo;
579 HDEVINFO hInfo;
580 SP_DEVINFO_DATA DevInfo;
581 HKEY hSubKey;
582 WCHAR szNetCfg[50];
583 WCHAR szAdapterNetCfg[50];
584 WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
585 WCHAR szName[130] = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
586 PINetConnectionItem pNew;
587 PINetConnectionItem pCurrent = NULL;
588
589 /* get the IfTable */
590 dwSize = 0;
591 if (GetIfTable(NULL, &dwSize, TRUE) != ERROR_INSUFFICIENT_BUFFER)
592 return FALSE;
593
594 pIfTable = (PMIB_IFTABLE)CoTaskMemAlloc(dwSize);
595 if (!pIfTable)
596 return FALSE;
597
598 dwResult = GetIfTable(pIfTable, &dwSize, TRUE);
599 if (dwResult != NO_ERROR)
600 {
601 CoTaskMemFree(pIfTable);
602 return FALSE;
603 }
604
605 dwSize = 0;
606 dwResult = GetAdaptersInfo(NULL, &dwSize);
607 if (dwResult!= ERROR_BUFFER_OVERFLOW)
608 {
609 CoTaskMemFree(pIfTable);
610 return FALSE;
611 }
612
613 pAdapterInfo = (PIP_ADAPTER_INFO)CoTaskMemAlloc(dwSize);
614 if (!pAdapterInfo)
615 {
616 CoTaskMemFree(pIfTable);
617 return FALSE;
618 }
619
620 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
621 {
622 CoTaskMemFree(pIfTable);
623 CoTaskMemFree(pAdapterInfo);
624 return FALSE;
625 }
626
627
628 hInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
629 if (!hInfo)
630 {
631 CoTaskMemFree(pIfTable);
632 CoTaskMemFree(pAdapterInfo);
633 return FALSE;
634 }
635
636 dwIndex = 0;
637 do
638 {
639
640 ZeroMemory(&DevInfo, sizeof(SP_DEVINFO_DATA));
641 DevInfo.cbSize = sizeof(DevInfo);
642
643 /* get device info */
644 if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, &DevInfo))
645 break;
646
647 /* get device software registry path */
648 if (!SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
649 break;
650
651 /* open device registry key */
652 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
653 break;
654
655 /* query NetCfgInstanceId for current device */
656 dwSize = sizeof(szNetCfg);
657 if (RegQueryValueExW(hSubKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
658 {
659 RegCloseKey(hSubKey);
660 break;
661 }
662 RegCloseKey(hSubKey);
663
664 /* get the current adapter index from NetCfgInstanceId */
665 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, szNetCfg, &dwAdapterIndex))
666 continue;
667
668 /* get detailed adapter info */
669 ZeroMemory(&IfEntry, sizeof(IfEntry));
670 IfEntry.dwIndex = dwAdapterIndex;
671 if(GetIfEntry(&IfEntry) != NO_ERROR)
672 break;
673
674 /* allocate new INetConnectionItem */
675 pNew = CoTaskMemAlloc(sizeof(INetConnectionItem));
676 if (!pNew)
677 break;
678
679 ZeroMemory(pNew, sizeof(INetConnectionItem));
680 pNew->dwAdapterIndex = dwAdapterIndex;
681 /* store NetCfgInstanceId */
682 CLSIDFromString(szNetCfg, &pNew->Props.guidId);
683 NormalizeOperStatus(&IfEntry, &pNew->Props);
684
685 switch(IfEntry.dwType)
686 {
687 case IF_TYPE_ETHERNET_CSMACD:
688 pNew->Props.MediaType = NCM_LAN;
689 break;
690 case IF_TYPE_IEEE80211:
691 pNew->Props.MediaType = NCM_SHAREDACCESSHOST_RAS;
692 break;
693 default:
694 break;
695 }
696 /* open network connections details */
697 wcscpy(&szName[80], szNetCfg);
698 wcscpy(&szName[118], L"\\Connection");
699
700 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
701 {
702 /* retrieve name of connection */
703 dwSize = sizeof(szAdapterNetCfg);
704 if (RegQueryValueExW(hSubKey, L"Name", NULL, NULL, (LPBYTE)szAdapterNetCfg, &dwSize) == ERROR_SUCCESS)
705 {
706 pNew->Props.pszwName = CoTaskMemAlloc((wcslen(szAdapterNetCfg)+1) * sizeof(WCHAR));
707 if (pNew->Props.pszwName)
708 wcscpy(pNew->Props.pszwName, szAdapterNetCfg);
709 }
710 dwSize = sizeof(dwShowIcon);
711 if (RegQueryValueExW(hSubKey, L"ShowIcon", NULL, NULL, (LPBYTE)&dwShowIcon, &dwSize) == ERROR_SUCCESS)
712 {
713 if (dwShowIcon)
714 pNew->Props.dwCharacter |= NCCF_SHOW_ICON;
715 }
716 RegCloseKey(hSubKey);
717 }
718 if (SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DEVICEDESC, NULL, (PBYTE)szNetCfg, sizeof(szNetCfg)/sizeof(WCHAR), &dwSize))
719 {
720 szNetCfg[(sizeof(szNetCfg)/sizeof(WCHAR))-1] = L'\0';
721 pNew->Props.pszwDeviceName = CoTaskMemAlloc((wcslen(szNetCfg)+1) * sizeof(WCHAR));
722 if (pNew->Props.pszwDeviceName)
723 wcscpy(pNew->Props.pszwDeviceName, szNetCfg);
724 }
725
726 if (pCurrent)
727 pCurrent->Next = pNew;
728 else
729 This->pHead = pNew;
730
731 pCurrent = pNew;
732 }while(TRUE);
733
734 CoTaskMemFree(pIfTable);
735 CoTaskMemFree(pAdapterInfo);
736 SetupDiDestroyDeviceInfoList(hInfo);
737
738 This->pCurrent = This->pHead;
739 return TRUE;
740 }
741
742 HRESULT WINAPI INetConnectionManager_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
743 {
744 INetConnectionManagerImpl *sf;
745
746 if (!ppv)
747 return E_POINTER;
748 if (pUnkOuter)
749 return CLASS_E_NOAGGREGATION;
750
751 sf = (INetConnectionManagerImpl *) CoTaskMemAlloc(sizeof (INetConnectionManagerImpl));
752 if (!sf)
753 return E_OUTOFMEMORY;
754
755 sf->ref = 1;
756 sf->lpVtbl = &vt_NetConnectionManager;
757 sf->lpVtblNetConnection = &vt_EnumNetConnection;
758 sf->pHead = NULL;
759 sf->pCurrent = NULL;
760
761
762 if (!SUCCEEDED (INetConnectionManager_QueryInterface ((INetConnectionManager*)sf, riid, ppv)))
763 {
764 INetConnectionManager_Release((INetConnectionManager*)sf);
765 return E_NOINTERFACE;
766 }
767
768 INetConnectionManager_Release((INetConnectionManager*)sf);
769 EnumerateINetConnections(sf);
770 return S_OK;
771 }
772
773