1 /*
2  * PROJECT:     ReactOS Shell
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     CNetConnectionManager class
5  * COPYRIGHT:   Copyright 2008 Johannes Anderwald (johannes.anderwald@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 VOID NormalizeOperStatus(MIB_IFROW *IfEntry, NETCON_PROPERTIES * Props);
11 
12 /***************************************************************
13  * INetConnection Interface
14  */
15 
16 HRESULT
17 WINAPI
18 CNetConnection::Initialize(PINetConnectionItem pItem)
19 {
20     m_Props = pItem->Props;
21     m_dwAdapterIndex = pItem->dwAdapterIndex;
22 
23     if (pItem->Props.pszwName)
24     {
25         m_Props.pszwName = static_cast<PWSTR>(CoTaskMemAlloc((wcslen(pItem->Props.pszwName)+1)*sizeof(WCHAR)));
26         if (m_Props.pszwName)
27             wcscpy(m_Props.pszwName, pItem->Props.pszwName);
28     }
29 
30     if (pItem->Props.pszwDeviceName)
31     {
32         m_Props.pszwDeviceName = static_cast<PWSTR>(CoTaskMemAlloc((wcslen(pItem->Props.pszwDeviceName)+1)*sizeof(WCHAR)));
33         if (m_Props.pszwDeviceName)
34             wcscpy(m_Props.pszwDeviceName, pItem->Props.pszwDeviceName);
35     }
36 
37     return S_OK;
38 }
39 
40 CNetConnection::~CNetConnection()
41 {
42     CoTaskMemFree(m_Props.pszwName);
43     CoTaskMemFree(m_Props.pszwDeviceName);
44 }
45 
46 HRESULT
47 WINAPI
48 CNetConnection::Connect()
49 {
50     return E_NOTIMPL;
51 }
52 
53 BOOL
54 FindNetworkAdapter(HDEVINFO hInfo, SP_DEVINFO_DATA *pDevInfo, LPWSTR pGuid)
55 {
56     DWORD dwIndex, dwSize;
57     HKEY hSubKey;
58     WCHAR szNetCfg[50];
59     WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
60 
61     dwIndex = 0;
62     do
63     {
64         ZeroMemory(pDevInfo, sizeof(SP_DEVINFO_DATA));
65         pDevInfo->cbSize = sizeof(SP_DEVINFO_DATA);
66 
67         /* get device info */
68         if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, pDevInfo))
69             break;
70 
71         /* get device software registry path */
72         if (!SetupDiGetDeviceRegistryPropertyW(hInfo, pDevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
73             break;
74 
75         /* open device registry key */
76         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
77             break;
78 
79         /* query NetCfgInstanceId for current device */
80         dwSize = sizeof(szNetCfg);
81         if (RegQueryValueExW(hSubKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
82         {
83             RegCloseKey(hSubKey);
84             break;
85         }
86         RegCloseKey(hSubKey);
87         if (!_wcsicmp(pGuid, szNetCfg))
88         {
89             return TRUE;
90         }
91     } while (TRUE);
92 
93     return FALSE;
94 }
95 
96 HRESULT
97 WINAPI
98 CNetConnection::Disconnect()
99 {
100     HKEY hKey;
101     NETCON_PROPERTIES * pProperties;
102     LPOLESTR pDisplayName;
103     WCHAR szPath[200];
104     DWORD dwSize, dwType;
105     LPWSTR pPnp;
106     HDEVINFO hInfo;
107     SP_DEVINFO_DATA DevInfo;
108     SP_PROPCHANGE_PARAMS PropChangeParams;
109     HRESULT hr;
110 
111     hr = GetProperties(&pProperties);
112     if (FAILED_UNEXPECTEDLY(hr))
113         return hr;
114 
115     hInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
116     if (!hInfo)
117     {
118         NcFreeNetconProperties(pProperties);
119         return E_FAIL;
120     }
121 
122     if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pDisplayName)))
123     {
124         NcFreeNetconProperties(pProperties);
125         SetupDiDestroyDeviceInfoList(hInfo);
126         return E_FAIL;
127     }
128     NcFreeNetconProperties(pProperties);
129 
130     if (FindNetworkAdapter(hInfo, &DevInfo, pDisplayName))
131     {
132         PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
133         PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; //;
134         PropChangeParams.StateChange = DICS_DISABLE;
135         PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
136         PropChangeParams.HwProfile = 0;
137 
138         if (SetupDiSetClassInstallParams(hInfo, &DevInfo, &PropChangeParams.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS)))
139         {
140             SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hInfo, &DevInfo);
141         }
142     }
143     SetupDiDestroyDeviceInfoList(hInfo);
144 
145     swprintf(szPath, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pDisplayName);
146     CoTaskMemFree(pDisplayName);
147 
148     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
149         return E_FAIL;
150 
151     dwSize = 0;
152     if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_SZ)
153     {
154         RegCloseKey(hKey);
155         return E_FAIL;
156     }
157 
158     pPnp = static_cast<PWSTR>(CoTaskMemAlloc(dwSize));
159     if (!pPnp)
160     {
161         RegCloseKey(hKey);
162         return E_FAIL;
163     }
164 
165     if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, (LPBYTE)pPnp, &dwSize) != ERROR_SUCCESS)
166     {
167         CoTaskMemFree(pPnp);
168         RegCloseKey(hKey);
169         return E_FAIL;
170     }
171     RegCloseKey(hKey);
172 
173     swprintf(szPath, L"System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Enum\\%s", pPnp);
174     CoTaskMemFree(pPnp);
175 
176     if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
177         return E_FAIL;
178 
179     dwSize = 1; /* enable = 0, disable = 1 */
180     RegSetValueExW(hKey, L"CSConfigFlags", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
181     RegCloseKey(hKey);
182 
183     return S_OK;
184 }
185 
186 HRESULT
187 WINAPI
188 CNetConnection::Delete()
189 {
190     return E_NOTIMPL;
191 }
192 
193 HRESULT
194 WINAPI
195 CNetConnection::Duplicate(
196     LPCWSTR pszwDuplicateName,
197     INetConnection **ppCon)
198 {
199     return E_NOTIMPL;
200 }
201 
202 HRESULT
203 WINAPI
204 CNetConnection::GetProperties(NETCON_PROPERTIES **ppProps)
205 {
206     MIB_IFROW IfEntry;
207     HKEY hKey;
208     LPOLESTR pStr;
209     WCHAR szName[140];
210     DWORD dwShowIcon, dwNotifyDisconnect, dwType, dwSize;
211     NETCON_PROPERTIES * pProperties;
212     HRESULT hr;
213 
214     if (!ppProps)
215         return E_POINTER;
216 
217     pProperties = static_cast<NETCON_PROPERTIES*>(CoTaskMemAlloc(sizeof(NETCON_PROPERTIES)));
218     if (!pProperties)
219         return E_OUTOFMEMORY;
220 
221     CopyMemory(pProperties, &m_Props, sizeof(NETCON_PROPERTIES));
222     pProperties->pszwName = NULL;
223 
224     if (m_Props.pszwDeviceName)
225     {
226         pProperties->pszwDeviceName = static_cast<LPWSTR>(CoTaskMemAlloc((wcslen(m_Props.pszwDeviceName)+1)*sizeof(WCHAR)));
227         if (pProperties->pszwDeviceName)
228             wcscpy(pProperties->pszwDeviceName, m_Props.pszwDeviceName);
229     }
230 
231     *ppProps = pProperties;
232 
233     /* get updated adapter characteristics */
234     ZeroMemory(&IfEntry, sizeof(IfEntry));
235     IfEntry.dwIndex = m_dwAdapterIndex;
236     if (GetIfEntry(&IfEntry) != NO_ERROR)
237         return NOERROR;
238 
239     NormalizeOperStatus(&IfEntry, pProperties);
240 
241 
242     hr = StringFromCLSID((CLSID)m_Props.guidId, &pStr);
243     if (SUCCEEDED(hr))
244     {
245         wcscpy(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
246         wcscat(szName, pStr);
247         wcscat(szName, L"\\Connection");
248 
249         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
250         {
251             dwSize = sizeof(dwShowIcon);
252             if (RegQueryValueExW(hKey, L"ShowIcon", NULL, &dwType, (LPBYTE)&dwShowIcon, &dwSize) == ERROR_SUCCESS && dwType == REG_DWORD)
253             {
254                 if (dwShowIcon)
255                     pProperties->dwCharacter |= NCCF_SHOW_ICON;
256                 else
257                     pProperties->dwCharacter &= ~NCCF_SHOW_ICON;
258             }
259 
260             dwSize = sizeof(dwNotifyDisconnect);
261             if (RegQueryValueExW(hKey, L"IpCheckingEnabled", NULL, &dwType, (LPBYTE)&dwNotifyDisconnect, &dwSize) == ERROR_SUCCESS && dwType == REG_DWORD)
262             {
263                 if (dwNotifyDisconnect)
264                     pProperties->dwCharacter |= NCCF_NOTIFY_DISCONNECTED;
265                 else
266                     pProperties->dwCharacter &= ~NCCF_NOTIFY_DISCONNECTED;
267             }
268 
269             dwSize = sizeof(szName);
270             if (RegQueryValueExW(hKey, L"Name", NULL, &dwType, (LPBYTE)szName, &dwSize) == ERROR_SUCCESS)
271             {
272                 /* use updated name */
273                 dwSize = wcslen(szName) + 1;
274                 pProperties->pszwName = static_cast<PWSTR>(CoTaskMemAlloc(dwSize * sizeof(WCHAR)));
275                 if (pProperties->pszwName)
276                     CopyMemory(pProperties->pszwName, szName, dwSize * sizeof(WCHAR));
277             }
278             else
279             {
280                 /* use cached name */
281                 if (m_Props.pszwName)
282                 {
283                     pProperties->pszwName = static_cast<PWSTR>(CoTaskMemAlloc((wcslen(m_Props.pszwName)+1)*sizeof(WCHAR)));
284                     if (pProperties->pszwName)
285                         wcscpy(pProperties->pszwName, m_Props.pszwName);
286                 }
287             }
288             RegCloseKey(hKey);
289         }
290         CoTaskMemFree(pStr);
291     }
292 
293     /* Enable 'Rename' and 'Delete' for Adminstrators only */
294     if (IsUserAdmin())
295     {
296         pProperties->dwCharacter |= NCCF_ALLOW_RENAME;
297 
298         /* Virtual network interfaces can be deleted */
299         if (IfEntry.dwType == IF_TYPE_TUNNEL)
300         {
301             pProperties->dwCharacter |= NCCF_ALLOW_REMOVAL;
302         }
303     }
304     else
305     {
306         pProperties->dwCharacter &= ~(NCCF_ALLOW_RENAME | NCCF_ALLOW_REMOVAL);
307     }
308 
309     return S_OK;
310 }
311 
312 HRESULT
313 WINAPI
314 CNetConnection::GetUiObjectClassId(CLSID *pclsid)
315 {
316     if (m_Props.MediaType == NCM_LAN)
317     {
318         CopyMemory(pclsid, &CLSID_LanConnectionUi, sizeof(CLSID));
319         return S_OK;
320     }
321 
322     return E_NOTIMPL;
323 }
324 
325 HRESULT
326 WINAPI
327 CNetConnection::Rename(LPCWSTR pszwDuplicateName)
328 {
329     WCHAR szName[140];
330     LPOLESTR pStr;
331     DWORD dwSize;
332     HKEY hKey;
333     HRESULT hr;
334 
335     if (pszwDuplicateName == NULL || wcslen(pszwDuplicateName) == 0)
336         return S_OK;
337 
338     if (m_Props.pszwName)
339     {
340         CoTaskMemFree(m_Props.pszwName);
341         m_Props.pszwName = NULL;
342     }
343 
344     dwSize = (wcslen(pszwDuplicateName) + 1) * sizeof(WCHAR);
345     m_Props.pszwName = static_cast<PWSTR>(CoTaskMemAlloc(dwSize));
346     if (m_Props.pszwName == NULL)
347         return E_OUTOFMEMORY;
348 
349     wcscpy(m_Props.pszwName, pszwDuplicateName);
350 
351     hr = StringFromCLSID((CLSID)m_Props.guidId, &pStr);
352     if (SUCCEEDED(hr))
353     {
354         wcscpy(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
355         wcscat(szName, pStr);
356         wcscat(szName, L"\\Connection");
357 
358         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
359         {
360             RegSetValueExW(hKey, L"Name", NULL, REG_SZ, (LPBYTE)m_Props.pszwName, dwSize);
361             RegCloseKey(hKey);
362         }
363 
364         CoTaskMemFree(pStr);
365     }
366 
367     return hr;
368 }
369 
370 HRESULT WINAPI CNetConnection_CreateInstance(PINetConnectionItem pItem, REFIID riid, LPVOID * ppv)
371 {
372     return ShellObjectCreatorInit<CNetConnection>(pItem, riid, ppv);
373 }
374 
375 
376 
377 CNetConnectionManager::CNetConnectionManager() :
378     m_pHead(NULL),
379     m_pCurrent(NULL)
380 {
381 }
382 
383 HRESULT
384 WINAPI
385 CNetConnectionManager::EnumConnections(
386     NETCONMGR_ENUM_FLAGS Flags,
387     IEnumNetConnection **ppEnum)
388 {
389     TRACE("EnumConnections\n");
390 
391     if (!ppEnum)
392         return E_POINTER;
393 
394     if (Flags != NCME_DEFAULT)
395         return E_FAIL;
396 
397     *ppEnum = static_cast<IEnumNetConnection*>(this);
398     AddRef();
399     return S_OK;
400 }
401 
402 /***************************************************************
403  * IEnumNetConnection Interface
404  */
405 
406 HRESULT
407 WINAPI
408 CNetConnectionManager::Next(
409     ULONG celt,
410     INetConnection **rgelt,
411     ULONG *pceltFetched)
412 {
413     HRESULT hr;
414 
415     if (!pceltFetched || !rgelt)
416         return E_POINTER;
417 
418     if (celt != 1)
419         return E_FAIL;
420 
421     if (!m_pCurrent)
422         return S_FALSE;
423 
424     hr = CNetConnection_CreateInstance(m_pCurrent, IID_PPV_ARG(INetConnection, rgelt));
425     m_pCurrent = m_pCurrent->Next;
426 
427     return hr;
428 }
429 
430 HRESULT
431 WINAPI
432 CNetConnectionManager::Skip(ULONG celt)
433 {
434     while (m_pCurrent && celt-- > 0)
435         m_pCurrent = m_pCurrent->Next;
436 
437     if (celt)
438        return S_FALSE;
439     else
440        return S_OK;
441 
442 }
443 
444 HRESULT
445 WINAPI
446 CNetConnectionManager::Reset()
447 {
448     m_pCurrent = m_pHead;
449     return S_OK;
450 }
451 
452 HRESULT
453 WINAPI
454 CNetConnectionManager::Clone(IEnumNetConnection **ppenum)
455 {
456     return E_NOTIMPL;
457 }
458 
459 BOOL
460 GetAdapterIndexFromNetCfgInstanceId(PIP_ADAPTER_INFO pAdapterInfo, LPWSTR szNetCfg, PDWORD pIndex)
461 {
462     WCHAR szBuffer[50];
463     IP_ADAPTER_INFO * pCurrentAdapter;
464 
465     pCurrentAdapter = pAdapterInfo;
466     while (pCurrentAdapter)
467     {
468         szBuffer[0] = L'\0';
469         if (MultiByteToWideChar(CP_ACP, 0, pCurrentAdapter->AdapterName, -1, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0])))
470         {
471             szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
472         }
473         if (!_wcsicmp(szBuffer, szNetCfg))
474         {
475             *pIndex = pCurrentAdapter->Index;
476             return TRUE;
477         }
478         pCurrentAdapter = pCurrentAdapter->Next;
479     }
480     return FALSE;
481 }
482 
483 VOID
484 NormalizeOperStatus(
485     MIB_IFROW *IfEntry,
486     NETCON_PROPERTIES    * Props)
487 {
488     switch (IfEntry->dwOperStatus)
489     {
490         case MIB_IF_OPER_STATUS_NON_OPERATIONAL:
491             Props->Status = NCS_HARDWARE_DISABLED;
492             break;
493         case MIB_IF_OPER_STATUS_UNREACHABLE:
494             Props->Status = NCS_DISCONNECTED;
495             break;
496         case MIB_IF_OPER_STATUS_DISCONNECTED:
497             Props->Status = NCS_MEDIA_DISCONNECTED;
498             break;
499         case MIB_IF_OPER_STATUS_CONNECTING:
500             Props->Status = NCS_CONNECTING;
501             break;
502         case MIB_IF_OPER_STATUS_CONNECTED:
503             Props->Status = NCS_CONNECTED;
504             break;
505         case MIB_IF_OPER_STATUS_OPERATIONAL:
506             Props->Status = NCS_CONNECTED;
507             break;
508         default:
509             break;
510     }
511 }
512 
513 HRESULT
514 CNetConnectionManager::EnumerateINetConnections()
515 {
516     DWORD dwSize, dwResult, dwIndex, dwAdapterIndex, dwShowIcon, dwNotifyDisconnect;
517     MIB_IFTABLE *pIfTable;
518     MIB_IFROW IfEntry;
519     IP_ADAPTER_INFO * pAdapterInfo;
520     HDEVINFO hInfo;
521     SP_DEVINFO_DATA DevInfo;
522     HKEY hSubKey;
523     WCHAR szNetCfg[50];
524     WCHAR szAdapterNetCfg[50];
525     WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
526     WCHAR szName[130] = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
527     PINetConnectionItem pCurrent = NULL;
528 
529     /* get the IfTable */
530     dwSize = 0;
531     if (GetIfTable(NULL, &dwSize, TRUE) != ERROR_INSUFFICIENT_BUFFER)
532         return E_FAIL;
533 
534     pIfTable = static_cast<PMIB_IFTABLE>(CoTaskMemAlloc(dwSize));
535     if (!pIfTable)
536         return E_OUTOFMEMORY;
537 
538     dwResult = GetIfTable(pIfTable, &dwSize, TRUE);
539     if (dwResult != NO_ERROR)
540     {
541         CoTaskMemFree(pIfTable);
542         return HRESULT_FROM_WIN32(dwResult);
543     }
544 
545     dwSize = 0;
546     dwResult = GetAdaptersInfo(NULL, &dwSize);
547     if (dwResult!= ERROR_BUFFER_OVERFLOW)
548     {
549         CoTaskMemFree(pIfTable);
550         return HRESULT_FROM_WIN32(dwResult);
551     }
552 
553     pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
554     if (!pAdapterInfo)
555     {
556         CoTaskMemFree(pIfTable);
557         return E_OUTOFMEMORY;
558     }
559 
560     dwResult = GetAdaptersInfo(pAdapterInfo, &dwSize);
561     if (dwResult != NO_ERROR)
562     {
563         CoTaskMemFree(pIfTable);
564         CoTaskMemFree(pAdapterInfo);
565         return HRESULT_FROM_WIN32(dwResult);
566     }
567 
568     hInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
569     if (!hInfo)
570     {
571         CoTaskMemFree(pIfTable);
572         CoTaskMemFree(pAdapterInfo);
573         return E_FAIL;
574     }
575 
576     dwIndex = 0;
577     do
578     {
579         ZeroMemory(&DevInfo, sizeof(SP_DEVINFO_DATA));
580         DevInfo.cbSize = sizeof(DevInfo);
581 
582         /* get device info */
583         if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, &DevInfo))
584             break;
585 
586         /* get device software registry path */
587         if (!SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
588             break;
589 
590         /* open device registry key */
591         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
592             break;
593 
594         /* query NetCfgInstanceId for current device */
595         dwSize = sizeof(szNetCfg);
596         if (RegQueryValueExW(hSubKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
597         {
598             RegCloseKey(hSubKey);
599             break;
600         }
601         RegCloseKey(hSubKey);
602 
603         /* get the current adapter index from NetCfgInstanceId */
604         if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, szNetCfg, &dwAdapterIndex))
605             continue;
606 
607         /* get detailed adapter info */
608         ZeroMemory(&IfEntry, sizeof(IfEntry));
609         IfEntry.dwIndex = dwAdapterIndex;
610         if (GetIfEntry(&IfEntry) != NO_ERROR)
611             break;
612 
613         /* allocate new INetConnectionItem */
614         PINetConnectionItem pNew = static_cast<PINetConnectionItem>(CoTaskMemAlloc(sizeof(INetConnectionItem)));
615         if (!pNew)
616             break;
617 
618         ZeroMemory(pNew, sizeof(INetConnectionItem));
619         pNew->dwAdapterIndex = dwAdapterIndex;
620         /* store NetCfgInstanceId */
621         CLSIDFromString(szNetCfg, &pNew->Props.guidId);
622         NormalizeOperStatus(&IfEntry, &pNew->Props);
623 
624         switch (IfEntry.dwType)
625         {
626             case IF_TYPE_ETHERNET_CSMACD:
627                 pNew->Props.MediaType = NCM_LAN;
628                 break;
629             case IF_TYPE_IEEE80211:
630                 pNew->Props.MediaType = NCM_SHAREDACCESSHOST_RAS;
631                 break;
632             default:
633                 break;
634         }
635         /*  open network connections details */
636         wcscpy(&szName[80], szNetCfg);
637         wcscpy(&szName[118], L"\\Connection");
638 
639         if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
640         {
641             /* retrieve name of connection */
642             dwSize = sizeof(szAdapterNetCfg);
643             if (RegQueryValueExW(hSubKey, L"Name", NULL, NULL, (LPBYTE)szAdapterNetCfg, &dwSize) == ERROR_SUCCESS)
644             {
645                 pNew->Props.pszwName = static_cast<PWSTR>(CoTaskMemAlloc((wcslen(szAdapterNetCfg)+1) * sizeof(WCHAR)));
646                 if (pNew->Props.pszwName)
647                     wcscpy(pNew->Props.pszwName, szAdapterNetCfg);
648             }
649             dwSize = sizeof(dwShowIcon);
650             if (RegQueryValueExW(hSubKey, L"ShowIcon", NULL, NULL, (LPBYTE)&dwShowIcon, &dwSize) == ERROR_SUCCESS)
651             {
652                 if (dwShowIcon)
653                     pNew->Props.dwCharacter |= NCCF_SHOW_ICON;
654             }
655             dwSize = sizeof(dwNotifyDisconnect);
656             if (RegQueryValueExW(hSubKey, L"IpCheckingEnabled", NULL, NULL, (LPBYTE)&dwNotifyDisconnect, &dwSize) == ERROR_SUCCESS)
657             {
658                 if (dwNotifyDisconnect)
659                     pNew->Props.dwCharacter |= NCCF_NOTIFY_DISCONNECTED;
660             }
661             RegCloseKey(hSubKey);
662         }
663 
664         /* Get the adapter device description */
665         dwSize = 0;
666         SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DEVICEDESC, NULL, NULL, 0, &dwSize);
667         if (dwSize != 0)
668         {
669             pNew->Props.pszwDeviceName = static_cast<PWSTR>(CoTaskMemAlloc(dwSize));
670             if (pNew->Props.pszwDeviceName)
671                 SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DEVICEDESC, NULL, (PBYTE)pNew->Props.pszwDeviceName, dwSize, &dwSize);
672         }
673 
674         if (pCurrent)
675             pCurrent->Next = pNew;
676         else
677             m_pHead = pNew;
678 
679         pCurrent = pNew;
680     } while (TRUE);
681 
682     CoTaskMemFree(pIfTable);
683     CoTaskMemFree(pAdapterInfo);
684     SetupDiDestroyDeviceInfoList(hInfo);
685 
686     m_pCurrent = m_pHead;
687     return (m_pHead != NULL ? S_OK : S_FALSE);
688 }
689 
690 HRESULT CNetConnectionManager::Initialize()
691 {
692     HRESULT hr = EnumerateINetConnections();
693     if (FAILED_UNEXPECTEDLY(hr))
694     {
695         /* If something went wrong during the enumeration print an error don't enumerate anything */
696         m_pCurrent = m_pHead = NULL;
697         return S_FALSE;
698     }
699     return S_OK;
700 }
701 
702 HRESULT WINAPI CNetConnectionManager_CreateInstance(REFIID riid, LPVOID * ppv)
703 {
704 #if USE_CUSTOM_CONMGR
705     return ShellObjectCreatorInit<CNetConnectionManager>(riid, ppv);
706 #else
707     return CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_ALL, riid, ppv);
708 #endif
709 }
710