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)
10 VOID
NormalizeOperStatus(MIB_IFROW
*IfEntry
, NETCON_PROPERTIES
* Props
);
12 /***************************************************************
13 * INetConnection Interface
18 CNetConnection::Initialize(PINetConnectionItem pItem
)
20 m_Props
= pItem
->Props
;
21 m_dwAdapterIndex
= pItem
->dwAdapterIndex
;
23 if (pItem
->Props
.pszwName
)
25 m_Props
.pszwName
= static_cast<PWSTR
>(CoTaskMemAlloc((wcslen(pItem
->Props
.pszwName
)+1)*sizeof(WCHAR
)));
27 wcscpy(m_Props
.pszwName
, pItem
->Props
.pszwName
);
30 if (pItem
->Props
.pszwDeviceName
)
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
);
40 CNetConnection::~CNetConnection()
42 CoTaskMemFree(m_Props
.pszwName
);
43 CoTaskMemFree(m_Props
.pszwDeviceName
);
48 CNetConnection::Connect()
54 FindNetworkAdapter(HDEVINFO hInfo
, SP_DEVINFO_DATA
*pDevInfo
, LPWSTR pGuid
)
56 DWORD dwIndex
, dwSize
;
59 WCHAR szDetail
[200] = L
"SYSTEM\\CurrentControlSet\\Control\\Class\\";
64 ZeroMemory(pDevInfo
, sizeof(SP_DEVINFO_DATA
));
65 pDevInfo
->cbSize
= sizeof(SP_DEVINFO_DATA
);
68 if (!SetupDiEnumDeviceInfo(hInfo
, dwIndex
++, pDevInfo
))
71 /* get device software registry path */
72 if (!SetupDiGetDeviceRegistryPropertyW(hInfo
, pDevInfo
, SPDRP_DRIVER
, NULL
, (LPBYTE
)&szDetail
[39], sizeof(szDetail
)/sizeof(WCHAR
) - 40, &dwSize
))
75 /* open device registry key */
76 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szDetail
, 0, KEY_READ
, &hSubKey
) != ERROR_SUCCESS
)
79 /* query NetCfgInstanceId for current device */
80 dwSize
= sizeof(szNetCfg
);
81 if (RegQueryValueExW(hSubKey
, L
"NetCfgInstanceId", NULL
, NULL
, (LPBYTE
)szNetCfg
, &dwSize
) != ERROR_SUCCESS
)
87 if (!_wcsicmp(pGuid
, szNetCfg
))
98 CNetConnection::Disconnect()
101 NETCON_PROPERTIES
* pProperties
;
102 LPOLESTR pDisplayName
;
104 DWORD dwSize
, dwType
;
107 SP_DEVINFO_DATA DevInfo
;
108 SP_PROPCHANGE_PARAMS PropChangeParams
;
111 hr
= GetProperties(&pProperties
);
112 if (FAILED_UNEXPECTEDLY(hr
))
115 hInfo
= SetupDiGetClassDevsW(&GUID_DEVCLASS_NET
, NULL
, NULL
, DIGCF_PRESENT
);
118 NcFreeNetconProperties(pProperties
);
122 if (FAILED(StringFromCLSID((CLSID
)pProperties
->guidId
, &pDisplayName
)))
124 NcFreeNetconProperties(pProperties
);
125 SetupDiDestroyDeviceInfoList(hInfo
);
128 NcFreeNetconProperties(pProperties
);
130 if (FindNetworkAdapter(hInfo
, &DevInfo
, pDisplayName
))
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;
138 if (SetupDiSetClassInstallParams(hInfo
, &DevInfo
, &PropChangeParams
.ClassInstallHeader
, sizeof(SP_PROPCHANGE_PARAMS
)))
140 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
, hInfo
, &DevInfo
);
143 SetupDiDestroyDeviceInfoList(hInfo
);
145 swprintf(szPath
, L
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pDisplayName
);
146 CoTaskMemFree(pDisplayName
);
148 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szPath
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
152 if (RegQueryValueExW(hKey
, L
"PnpInstanceID", NULL
, &dwType
, NULL
, &dwSize
) != ERROR_SUCCESS
|| dwType
!= REG_SZ
)
158 pPnp
= static_cast<PWSTR
>(CoTaskMemAlloc(dwSize
));
165 if (RegQueryValueExW(hKey
, L
"PnpInstanceID", NULL
, &dwType
, (LPBYTE
)pPnp
, &dwSize
) != ERROR_SUCCESS
)
173 swprintf(szPath
, L
"System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Enum\\%s", pPnp
);
176 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szPath
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
179 dwSize
= 1; /* enable = 0, disable = 1 */
180 RegSetValueExW(hKey
, L
"CSConfigFlags", 0, REG_DWORD
, (LPBYTE
)&dwSize
, sizeof(DWORD
));
188 CNetConnection::Delete()
195 CNetConnection::Duplicate(
196 LPCWSTR pszwDuplicateName
,
197 INetConnection
**ppCon
)
204 CNetConnection::GetProperties(NETCON_PROPERTIES
**ppProps
)
210 DWORD dwShowIcon
, dwNotifyDisconnect
, dwType
, dwSize
;
211 NETCON_PROPERTIES
* pProperties
;
217 pProperties
= static_cast<NETCON_PROPERTIES
*>(CoTaskMemAlloc(sizeof(NETCON_PROPERTIES
)));
219 return E_OUTOFMEMORY
;
221 CopyMemory(pProperties
, &m_Props
, sizeof(NETCON_PROPERTIES
));
222 pProperties
->pszwName
= NULL
;
224 if (m_Props
.pszwDeviceName
)
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
);
231 *ppProps
= pProperties
;
233 /* get updated adapter characteristics */
234 ZeroMemory(&IfEntry
, sizeof(IfEntry
));
235 IfEntry
.dwIndex
= m_dwAdapterIndex
;
236 if (GetIfEntry(&IfEntry
) != NO_ERROR
)
239 NormalizeOperStatus(&IfEntry
, pProperties
);
242 hr
= StringFromCLSID((CLSID
)m_Props
.guidId
, &pStr
);
245 wcscpy(szName
, L
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
246 wcscat(szName
, pStr
);
247 wcscat(szName
, L
"\\Connection");
249 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szName
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
251 dwSize
= sizeof(dwShowIcon
);
252 if (RegQueryValueExW(hKey
, L
"ShowIcon", NULL
, &dwType
, (LPBYTE
)&dwShowIcon
, &dwSize
) == ERROR_SUCCESS
&& dwType
== REG_DWORD
)
255 pProperties
->dwCharacter
|= NCCF_SHOW_ICON
;
257 pProperties
->dwCharacter
&= ~NCCF_SHOW_ICON
;
260 dwSize
= sizeof(dwNotifyDisconnect
);
261 if (RegQueryValueExW(hKey
, L
"IpCheckingEnabled", NULL
, &dwType
, (LPBYTE
)&dwNotifyDisconnect
, &dwSize
) == ERROR_SUCCESS
&& dwType
== REG_DWORD
)
263 if (dwNotifyDisconnect
)
264 pProperties
->dwCharacter
|= NCCF_NOTIFY_DISCONNECTED
;
266 pProperties
->dwCharacter
&= ~NCCF_NOTIFY_DISCONNECTED
;
269 dwSize
= sizeof(szName
);
270 if (RegQueryValueExW(hKey
, L
"Name", NULL
, &dwType
, (LPBYTE
)szName
, &dwSize
) == ERROR_SUCCESS
)
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
));
280 /* use cached name */
281 if (m_Props
.pszwName
)
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
);
298 CNetConnection::GetUiObjectClassId(CLSID
*pclsid
)
300 if (m_Props
.MediaType
== NCM_LAN
)
302 CopyMemory(pclsid
, &CLSID_LanConnectionUi
, sizeof(CLSID
));
311 CNetConnection::Rename(LPCWSTR pszwDuplicateName
)
319 if (pszwDuplicateName
== NULL
|| wcslen(pszwDuplicateName
) == 0)
322 if (m_Props
.pszwName
)
324 CoTaskMemFree(m_Props
.pszwName
);
325 m_Props
.pszwName
= NULL
;
328 dwSize
= (wcslen(pszwDuplicateName
) + 1) * sizeof(WCHAR
);
329 m_Props
.pszwName
= static_cast<PWSTR
>(CoTaskMemAlloc(dwSize
));
330 if (m_Props
.pszwName
== NULL
)
331 return E_OUTOFMEMORY
;
333 wcscpy(m_Props
.pszwName
, pszwDuplicateName
);
335 hr
= StringFromCLSID((CLSID
)m_Props
.guidId
, &pStr
);
338 wcscpy(szName
, L
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
339 wcscat(szName
, pStr
);
340 wcscat(szName
, L
"\\Connection");
342 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szName
, 0, KEY_WRITE
, &hKey
) == ERROR_SUCCESS
)
344 RegSetValueExW(hKey
, L
"Name", NULL
, REG_SZ
, (LPBYTE
)m_Props
.pszwName
, dwSize
);
354 HRESULT WINAPI
CNetConnection_CreateInstance(PINetConnectionItem pItem
, REFIID riid
, LPVOID
* ppv
)
356 return ShellObjectCreatorInit
<CNetConnection
>(pItem
, riid
, ppv
);
361 CNetConnectionManager::CNetConnectionManager() :
369 CNetConnectionManager::EnumConnections(
370 NETCONMGR_ENUM_FLAGS Flags
,
371 IEnumNetConnection
**ppEnum
)
373 TRACE("EnumConnections\n");
378 if (Flags
!= NCME_DEFAULT
)
381 *ppEnum
= static_cast<IEnumNetConnection
*>(this);
386 /***************************************************************
387 * IEnumNetConnection Interface
392 CNetConnectionManager::Next(
394 INetConnection
**rgelt
,
399 if (!pceltFetched
|| !rgelt
)
408 hr
= CNetConnection_CreateInstance(m_pCurrent
, IID_PPV_ARG(INetConnection
, rgelt
));
409 m_pCurrent
= m_pCurrent
->Next
;
416 CNetConnectionManager::Skip(ULONG celt
)
418 while (m_pCurrent
&& celt
-- > 0)
419 m_pCurrent
= m_pCurrent
->Next
;
430 CNetConnectionManager::Reset()
432 m_pCurrent
= m_pHead
;
438 CNetConnectionManager::Clone(IEnumNetConnection
**ppenum
)
444 GetAdapterIndexFromNetCfgInstanceId(PIP_ADAPTER_INFO pAdapterInfo
, LPWSTR szNetCfg
, PDWORD pIndex
)
447 IP_ADAPTER_INFO
* pCurrentAdapter
;
449 pCurrentAdapter
= pAdapterInfo
;
450 while (pCurrentAdapter
)
453 if (MultiByteToWideChar(CP_ACP
, 0, pCurrentAdapter
->AdapterName
, -1, szBuffer
, sizeof(szBuffer
)/sizeof(szBuffer
[0])))
455 szBuffer
[(sizeof(szBuffer
)/sizeof(WCHAR
))-1] = L
'\0';
457 if (!_wcsicmp(szBuffer
, szNetCfg
))
459 *pIndex
= pCurrentAdapter
->Index
;
462 pCurrentAdapter
= pCurrentAdapter
->Next
;
470 NETCON_PROPERTIES
* Props
)
472 switch (IfEntry
->dwOperStatus
)
474 case MIB_IF_OPER_STATUS_NON_OPERATIONAL
:
475 Props
->Status
= NCS_HARDWARE_DISABLED
;
477 case MIB_IF_OPER_STATUS_UNREACHABLE
:
478 Props
->Status
= NCS_DISCONNECTED
;
480 case MIB_IF_OPER_STATUS_DISCONNECTED
:
481 Props
->Status
= NCS_MEDIA_DISCONNECTED
;
483 case MIB_IF_OPER_STATUS_CONNECTING
:
484 Props
->Status
= NCS_CONNECTING
;
486 case MIB_IF_OPER_STATUS_CONNECTED
:
487 Props
->Status
= NCS_CONNECTED
;
489 case MIB_IF_OPER_STATUS_OPERATIONAL
:
490 Props
->Status
= NCS_CONNECTED
;
498 CNetConnectionManager::EnumerateINetConnections()
500 DWORD dwSize
, dwResult
, dwIndex
, dwAdapterIndex
, dwShowIcon
, dwNotifyDisconnect
;
501 MIB_IFTABLE
*pIfTable
;
503 IP_ADAPTER_INFO
* pAdapterInfo
;
505 SP_DEVINFO_DATA DevInfo
;
508 WCHAR szAdapterNetCfg
[50];
509 WCHAR szDetail
[200] = L
"SYSTEM\\CurrentControlSet\\Control\\Class\\";
510 WCHAR szName
[130] = L
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
511 PINetConnectionItem pCurrent
= NULL
;
513 /* get the IfTable */
515 if (GetIfTable(NULL
, &dwSize
, TRUE
) != ERROR_INSUFFICIENT_BUFFER
)
518 pIfTable
= static_cast<PMIB_IFTABLE
>(CoTaskMemAlloc(dwSize
));
520 return E_OUTOFMEMORY
;
522 dwResult
= GetIfTable(pIfTable
, &dwSize
, TRUE
);
523 if (dwResult
!= NO_ERROR
)
525 CoTaskMemFree(pIfTable
);
526 return HRESULT_FROM_WIN32(dwResult
);
530 dwResult
= GetAdaptersInfo(NULL
, &dwSize
);
531 if (dwResult
!= ERROR_BUFFER_OVERFLOW
)
533 CoTaskMemFree(pIfTable
);
534 return HRESULT_FROM_WIN32(dwResult
);
537 pAdapterInfo
= static_cast<PIP_ADAPTER_INFO
>(CoTaskMemAlloc(dwSize
));
540 CoTaskMemFree(pIfTable
);
541 return E_OUTOFMEMORY
;
544 dwResult
= GetAdaptersInfo(pAdapterInfo
, &dwSize
);
545 if (dwResult
!= NO_ERROR
)
547 CoTaskMemFree(pIfTable
);
548 CoTaskMemFree(pAdapterInfo
);
549 return HRESULT_FROM_WIN32(dwResult
);
552 hInfo
= SetupDiGetClassDevs(&GUID_DEVCLASS_NET
, NULL
, NULL
, DIGCF_PRESENT
);
555 CoTaskMemFree(pIfTable
);
556 CoTaskMemFree(pAdapterInfo
);
563 ZeroMemory(&DevInfo
, sizeof(SP_DEVINFO_DATA
));
564 DevInfo
.cbSize
= sizeof(DevInfo
);
566 /* get device info */
567 if (!SetupDiEnumDeviceInfo(hInfo
, dwIndex
++, &DevInfo
))
570 /* get device software registry path */
571 if (!SetupDiGetDeviceRegistryPropertyW(hInfo
, &DevInfo
, SPDRP_DRIVER
, NULL
, (LPBYTE
)&szDetail
[39], sizeof(szDetail
)/sizeof(WCHAR
) - 40, &dwSize
))
574 /* open device registry key */
575 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szDetail
, 0, KEY_READ
, &hSubKey
) != ERROR_SUCCESS
)
578 /* query NetCfgInstanceId for current device */
579 dwSize
= sizeof(szNetCfg
);
580 if (RegQueryValueExW(hSubKey
, L
"NetCfgInstanceId", NULL
, NULL
, (LPBYTE
)szNetCfg
, &dwSize
) != ERROR_SUCCESS
)
582 RegCloseKey(hSubKey
);
585 RegCloseKey(hSubKey
);
587 /* get the current adapter index from NetCfgInstanceId */
588 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo
, szNetCfg
, &dwAdapterIndex
))
591 /* get detailed adapter info */
592 ZeroMemory(&IfEntry
, sizeof(IfEntry
));
593 IfEntry
.dwIndex
= dwAdapterIndex
;
594 if (GetIfEntry(&IfEntry
) != NO_ERROR
)
597 /* allocate new INetConnectionItem */
598 PINetConnectionItem pNew
= static_cast<PINetConnectionItem
>(CoTaskMemAlloc(sizeof(INetConnectionItem
)));
602 ZeroMemory(pNew
, sizeof(INetConnectionItem
));
603 pNew
->dwAdapterIndex
= dwAdapterIndex
;
604 /* store NetCfgInstanceId */
605 CLSIDFromString(szNetCfg
, &pNew
->Props
.guidId
);
606 NormalizeOperStatus(&IfEntry
, &pNew
->Props
);
608 switch (IfEntry
.dwType
)
610 case IF_TYPE_ETHERNET_CSMACD
:
611 pNew
->Props
.MediaType
= NCM_LAN
;
613 case IF_TYPE_IEEE80211
:
614 pNew
->Props
.MediaType
= NCM_SHAREDACCESSHOST_RAS
;
619 /* open network connections details */
620 wcscpy(&szName
[80], szNetCfg
);
621 wcscpy(&szName
[118], L
"\\Connection");
623 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szName
, 0, KEY_READ
, &hSubKey
) == ERROR_SUCCESS
)
625 /* retrieve name of connection */
626 dwSize
= sizeof(szAdapterNetCfg
);
627 if (RegQueryValueExW(hSubKey
, L
"Name", NULL
, NULL
, (LPBYTE
)szAdapterNetCfg
, &dwSize
) == ERROR_SUCCESS
)
629 pNew
->Props
.pszwName
= static_cast<PWSTR
>(CoTaskMemAlloc((wcslen(szAdapterNetCfg
)+1) * sizeof(WCHAR
)));
630 if (pNew
->Props
.pszwName
)
631 wcscpy(pNew
->Props
.pszwName
, szAdapterNetCfg
);
633 dwSize
= sizeof(dwShowIcon
);
634 if (RegQueryValueExW(hSubKey
, L
"ShowIcon", NULL
, NULL
, (LPBYTE
)&dwShowIcon
, &dwSize
) == ERROR_SUCCESS
)
637 pNew
->Props
.dwCharacter
|= NCCF_SHOW_ICON
;
639 dwSize
= sizeof(dwNotifyDisconnect
);
640 if (RegQueryValueExW(hSubKey
, L
"IpCheckingEnabled", NULL
, NULL
, (LPBYTE
)&dwNotifyDisconnect
, &dwSize
) == ERROR_SUCCESS
)
642 if (dwNotifyDisconnect
)
643 pNew
->Props
.dwCharacter
|= NCCF_NOTIFY_DISCONNECTED
;
645 RegCloseKey(hSubKey
);
648 /* Get the adapter device description */
650 SetupDiGetDeviceRegistryPropertyW(hInfo
, &DevInfo
, SPDRP_DEVICEDESC
, NULL
, NULL
, 0, &dwSize
);
653 pNew
->Props
.pszwDeviceName
= static_cast<PWSTR
>(CoTaskMemAlloc(dwSize
));
654 if (pNew
->Props
.pszwDeviceName
)
655 SetupDiGetDeviceRegistryPropertyW(hInfo
, &DevInfo
, SPDRP_DEVICEDESC
, NULL
, (PBYTE
)pNew
->Props
.pszwDeviceName
, dwSize
, &dwSize
);
659 pCurrent
->Next
= pNew
;
666 CoTaskMemFree(pIfTable
);
667 CoTaskMemFree(pAdapterInfo
);
668 SetupDiDestroyDeviceInfoList(hInfo
);
670 m_pCurrent
= m_pHead
;
671 return (m_pHead
!= NULL
? S_OK
: S_FALSE
);
674 HRESULT
CNetConnectionManager::Initialize()
676 HRESULT hr
= EnumerateINetConnections();
677 if (FAILED_UNEXPECTEDLY(hr
))
679 /* If something went wrong during the enumeration print an error don't enumerate anything */
680 m_pCurrent
= m_pHead
= NULL
;
686 HRESULT WINAPI
CNetConnectionManager_CreateInstance(REFIID riid
, LPVOID
* ppv
)
688 #if USE_CUSTOM_CONMGR
689 return ShellObjectCreatorInit
<CNetConnectionManager
>(riid
, ppv
);
691 return CoCreateInstance(CLSID_ConnectionManager
, NULL
, CLSCTX_ALL
, riid
, ppv
);