1 /* 2 * PROJECT: ReactOS Shell 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: CNetConnectionPropertyUi: Network connection configuration dialog 5 * COPYRIGHT: Copyright 2008 Johannes Anderwald (johannes.anderwald@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 CNetConnectionPropertyUi::CNetConnectionPropertyUi() : 11 m_pProperties(NULL) 12 { 13 } 14 15 CNetConnectionPropertyUi::~CNetConnectionPropertyUi() 16 { 17 if (m_pNCfg) 18 m_pNCfg->Uninitialize(); 19 20 if (m_pProperties) 21 NcFreeNetconProperties(m_pProperties); 22 } 23 24 VOID 25 AddItemToListView(HWND hDlgCtrl, PNET_ITEM pItem, LPWSTR szName, BOOL bChecked) 26 { 27 LVITEMW lvItem; 28 29 ZeroMemory(&lvItem, sizeof(lvItem)); 30 lvItem.mask = LVIF_TEXT | LVIF_PARAM; 31 lvItem.pszText = szName; 32 lvItem.lParam = (LPARAM)pItem; 33 lvItem.iItem = ListView_GetItemCount(hDlgCtrl); 34 lvItem.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem); 35 ListView_SetCheckState(hDlgCtrl, lvItem.iItem, bChecked); 36 } 37 38 BOOL 39 CNetConnectionPropertyUi::GetINetCfgComponent(INetCfg *pNCfg, INetCfgComponent ** pOut) 40 { 41 LPWSTR pName; 42 HRESULT hr; 43 ULONG Fetched; 44 CComPtr<IEnumNetCfgComponent> pEnumCfg; 45 46 hr = pNCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumCfg); 47 if (FAILED_UNEXPECTEDLY(hr)) 48 return FALSE; 49 50 while (TRUE) 51 { 52 CComPtr<INetCfgComponent> pNCg; 53 hr = pEnumCfg->Next(1, &pNCg, &Fetched); 54 if (hr != S_OK) 55 break; 56 57 hr = pNCg->GetDisplayName(&pName); 58 if (SUCCEEDED(hr)) 59 { 60 if (!_wcsicmp(pName, m_pProperties->pszwDeviceName)) 61 { 62 *pOut = pNCg.Detach(); 63 return TRUE; 64 } 65 CoTaskMemFree(pName); 66 } 67 } 68 return FALSE; 69 } 70 71 VOID 72 CNetConnectionPropertyUi::EnumComponents(HWND hDlgCtrl, INetCfg *pNCfg, const GUID *CompGuid, UINT Type) 73 { 74 HRESULT hr; 75 CComPtr<IEnumNetCfgComponent> pENetCfg; 76 ULONG Num; 77 DWORD dwCharacteristics; 78 LPOLESTR pDisplayName, pHelpText; 79 PNET_ITEM pItem; 80 BOOL bChecked; 81 82 hr = pNCfg->EnumComponents(CompGuid, &pENetCfg); 83 if (FAILED_UNEXPECTEDLY(hr)) 84 return; 85 86 while (TRUE) 87 { 88 CComPtr<INetCfgComponent> pNCfgComp; 89 CComPtr<INetCfgComponentBindings> pCompBind; 90 CComPtr<INetCfgComponent> pAdapterCfgComp; 91 92 hr = pENetCfg->Next(1, &pNCfgComp, &Num); 93 if (hr != S_OK) 94 break; 95 96 hr = pNCfgComp->GetCharacteristics(&dwCharacteristics); 97 if (SUCCEEDED(hr) && (dwCharacteristics & NCF_HIDDEN)) 98 continue; 99 100 pDisplayName = NULL; 101 pHelpText = NULL; 102 hr = pNCfgComp->GetDisplayName(&pDisplayName); 103 hr = pNCfgComp->GetHelpText(&pHelpText); 104 bChecked = TRUE; //ReactOS hack 105 hr = pNCfgComp->QueryInterface(IID_PPV_ARG(INetCfgComponentBindings, &pCompBind)); 106 if (SUCCEEDED(hr)) 107 { 108 if (GetINetCfgComponent(pNCfg, &pAdapterCfgComp)) 109 { 110 hr = pCompBind->IsBoundTo(pAdapterCfgComp); 111 if (hr == S_OK) 112 bChecked = TRUE; 113 else 114 bChecked = FALSE; 115 } 116 } 117 118 pItem = static_cast<NET_ITEM*>(CoTaskMemAlloc(sizeof(NET_ITEM))); 119 if (!pItem) 120 continue; 121 122 pItem->dwCharacteristics = dwCharacteristics; 123 pItem->szHelp = pHelpText; 124 pItem->Type = (NET_TYPE)Type; 125 pItem->pNCfgComp = pNCfgComp.Detach(); 126 pItem->NumPropDialogOpen = 0; 127 128 AddItemToListView(hDlgCtrl, pItem, pDisplayName, bChecked); 129 CoTaskMemFree(pDisplayName); 130 } 131 } 132 133 VOID 134 CNetConnectionPropertyUi::InitializeLANPropertiesUIDlg(HWND hwndDlg) 135 { 136 HRESULT hr; 137 CComPtr<INetCfg> pNCfg; 138 CComPtr<INetCfgLock> pNCfgLock; 139 HWND hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMPONENTSLIST); 140 LVCOLUMNW lc; 141 RECT rc; 142 DWORD dwStyle; 143 LPWSTR pDisplayName; 144 LVITEMW li; 145 146 SendDlgItemMessageW(hwndDlg, IDC_NETCARDNAME, WM_SETTEXT, 0, (LPARAM)m_pProperties->pszwDeviceName); 147 if (m_pProperties->dwCharacter & NCCF_SHOW_ICON) 148 { 149 /* check show item on taskbar*/ 150 SendDlgItemMessageW(hwndDlg, IDC_SHOWTASKBAR, BM_SETCHECK, BST_CHECKED, 0); 151 } 152 if (m_pProperties->dwCharacter & NCCF_NOTIFY_DISCONNECTED) 153 { 154 /* check notify item */ 155 SendDlgItemMessageW(hwndDlg, IDC_NOTIFYNOCONNECTION, BM_SETCHECK, BST_CHECKED, 0); 156 } 157 158 memset(&lc, 0, sizeof(LV_COLUMN)); 159 lc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT; 160 lc.fmt = LVCFMT_FIXED_WIDTH; 161 if (GetClientRect(hDlgCtrl, &rc)) 162 { 163 lc.mask |= LVCF_WIDTH; 164 lc.cx = rc.right - rc.left; 165 } 166 lc.pszText = (LPWSTR)L""; 167 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&lc); 168 dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 169 dwStyle = dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES; 170 SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); 171 172 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(INetCfg, &pNCfg)); 173 if (FAILED(hr)) 174 return; 175 176 hr = pNCfg->QueryInterface(IID_PPV_ARG(INetCfgLock, &pNCfgLock)); 177 hr = pNCfgLock->AcquireWriteLock(100, L"", &pDisplayName); 178 if (hr == S_FALSE) 179 { 180 CoTaskMemFree(pDisplayName); 181 return; 182 } 183 184 hr = pNCfg->Initialize(NULL); 185 if (FAILED_UNEXPECTEDLY(hr)) 186 return; 187 188 m_pNCfg = pNCfg; 189 m_NCfgLock = pNCfgLock; 190 191 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETCLIENT, NET_TYPE_CLIENT); 192 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETSERVICE, NET_TYPE_SERVICE); 193 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETTRANS, NET_TYPE_PROTOCOL); 194 195 ZeroMemory(&li, sizeof(li)); 196 li.mask = LVIF_STATE; 197 li.stateMask = (UINT)-1; 198 li.state = LVIS_FOCUSED|LVIS_SELECTED; 199 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 200 } 201 202 VOID 203 CNetConnectionPropertyUi::ShowNetworkComponentProperties(HWND hwndDlg) 204 { 205 LVITEMW lvItem; 206 HWND hDlgCtrl; 207 UINT Index, Count; 208 HRESULT hr; 209 INetCfgComponent *pNCfgComp; 210 PNET_ITEM pItem; 211 212 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMPONENTSLIST); 213 Count = ListView_GetItemCount(hDlgCtrl); 214 if (!Count) 215 return; 216 217 ZeroMemory(&lvItem, sizeof(LVITEMW)); 218 lvItem.mask = LVIF_PARAM | LVIF_STATE; 219 lvItem.stateMask = (UINT)-1; 220 for (Index = 0; Index < Count; Index++) 221 { 222 lvItem.iItem = Index; 223 if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&lvItem)) 224 { 225 if (lvItem.state & LVIS_SELECTED) 226 break; 227 } 228 } 229 230 if (!(lvItem.state & LVIS_SELECTED)) 231 { 232 return; 233 } 234 235 pItem = (PNET_ITEM)lvItem.lParam; 236 pNCfgComp = (INetCfgComponent*)pItem->pNCfgComp; 237 hr = pNCfgComp->RaisePropertyUi(GetParent(hwndDlg), NCRP_QUERY_PROPERTY_UI, (INetConnectionConnectUi*)this); 238 if (SUCCEEDED(hr)) 239 { 240 hr = pNCfgComp->RaisePropertyUi(GetParent(hwndDlg), NCRP_SHOW_PROPERTY_UI, (INetConnectionConnectUi*)this); 241 } 242 } 243 244 INT_PTR 245 CALLBACK 246 CNetConnectionPropertyUi::LANPropertiesUIDlg( 247 HWND hwndDlg, 248 UINT uMsg, 249 WPARAM wParam, 250 LPARAM lParam) 251 { 252 PROPSHEETPAGE *page; 253 LPNMLISTVIEW lppl; 254 LVITEMW li; 255 PNET_ITEM pItem; 256 CNetConnectionPropertyUi * This; 257 LPPSHNOTIFY lppsn; 258 DWORD dwShowIcon, dwNotifyDisconnect; 259 HRESULT hr; 260 WCHAR szKey[200]; 261 LPOLESTR pStr; 262 HKEY hKey; 263 264 switch (uMsg) 265 { 266 case WM_INITDIALOG: 267 page = (PROPSHEETPAGE*)lParam; 268 This = (CNetConnectionPropertyUi*)page->lParam; 269 This->InitializeLANPropertiesUIDlg(hwndDlg); 270 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This); 271 return TRUE; 272 case WM_NOTIFY: 273 lppl = (LPNMLISTVIEW) lParam; 274 lppsn = (LPPSHNOTIFY) lParam; 275 if (lppsn->hdr.code == PSN_APPLY) 276 { 277 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER); 278 if (This->m_pNCfg) 279 { 280 hr = This->m_pNCfg->Apply(); 281 if (FAILED(hr)) 282 return PSNRET_INVALID; 283 } 284 285 if (SendDlgItemMessageW(hwndDlg, IDC_SHOWTASKBAR, BM_GETCHECK, 0, 0) == BST_CHECKED) 286 dwShowIcon = 1; 287 else 288 dwShowIcon = 0; 289 290 if (SendDlgItemMessageW(hwndDlg, IDC_NOTIFYNOCONNECTION, BM_GETCHECK, 0, 0) == BST_CHECKED) 291 dwNotifyDisconnect = 1; 292 else 293 dwNotifyDisconnect = 0; 294 295 //NOTE: Windows write these setting with the undocumented INetLanConnection::SetInfo 296 if (StringFromCLSID((CLSID)This->m_pProperties->guidId, &pStr) == ERROR_SUCCESS) 297 { 298 swprintf(szKey, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pStr); 299 CoTaskMemFree(pStr); 300 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKey, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) 301 { 302 RegSetValueExW(hKey, L"ShowIcon", 0, REG_DWORD, (LPBYTE)&dwShowIcon, sizeof(DWORD)); 303 RegSetValueExW(hKey, L"IpCheckingEnabled", 0, REG_DWORD, (LPBYTE)&dwNotifyDisconnect, sizeof(DWORD)); 304 RegCloseKey(hKey); 305 } 306 } 307 308 return PSNRET_NOERROR; 309 } 310 #if 0 311 else if (lppsn->hdr.code == PSN_CANCEL) 312 { 313 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER); 314 if (This->m_pNCfg) 315 { 316 hr = This->m_pNCfg->Cancel(); 317 if (SUCCEEDED(hr)) 318 return PSNRET_NOERROR; 319 else 320 return PSNRET_INVALID; 321 } 322 return PSNRET_NOERROR; 323 } 324 #endif 325 if (lppl->hdr.code == LVN_ITEMCHANGING) 326 { 327 ZeroMemory(&li, sizeof(li)); 328 li.mask = LVIF_PARAM; 329 li.iItem = lppl->iItem; 330 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&li)) 331 return TRUE; 332 333 pItem = (PNET_ITEM)li.lParam; 334 if (!pItem) 335 return TRUE; 336 337 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED)) 338 { 339 /* new focused item */ 340 if (pItem->dwCharacteristics & NCF_NOT_USER_REMOVABLE) 341 EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALL), FALSE); 342 else 343 EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALL), TRUE); 344 345 if (pItem->dwCharacteristics & NCF_HAS_UI) 346 EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), TRUE); 347 else 348 EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), FALSE); 349 350 SendDlgItemMessageW(hwndDlg, IDC_DESCRIPTION, WM_SETTEXT, 0, (LPARAM)pItem->szHelp); 351 } 352 } 353 break; 354 case WM_COMMAND: 355 if (LOWORD(wParam) == IDC_PROPERTIES) 356 { 357 This = (CNetConnectionPropertyUi*) GetWindowLongPtr(hwndDlg, DWLP_USER); 358 This->ShowNetworkComponentProperties(hwndDlg); 359 return FALSE; 360 } 361 else if (LOWORD(wParam) == IDC_CONFIGURE) 362 { 363 LPOLESTR DeviceInstanceID; 364 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER); 365 366 if (This->GetDeviceInstanceID(&DeviceInstanceID)) 367 { 368 WCHAR wszCmd[2*MAX_PATH]; 369 StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32.exe devmgr.dll,DeviceProperties_RunDLL /DeviceID %s", DeviceInstanceID); 370 CoTaskMemFree(DeviceInstanceID); 371 372 STARTUPINFOW si; 373 PROCESS_INFORMATION pi; 374 ZeroMemory(&si, sizeof(si)); 375 si.cb = sizeof(si); 376 if (!CreateProcessW(NULL, wszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 377 break; 378 379 CloseHandle(pi.hProcess); 380 CloseHandle(pi.hThread); 381 } 382 } 383 break; 384 } 385 return FALSE; 386 } 387 388 BOOL 389 CNetConnectionPropertyUi::GetDeviceInstanceID( 390 OUT LPOLESTR *DeviceInstanceID) 391 { 392 LPOLESTR pStr, pResult; 393 HKEY hKey; 394 DWORD dwInstanceID; 395 WCHAR szKeyName[2*MAX_PATH]; 396 WCHAR szInstanceID[2*MAX_PATH]; 397 398 if (StringFromCLSID(m_pProperties->guidId, &pStr) != ERROR_SUCCESS) 399 { 400 // failed to convert guid to string 401 return FALSE; 402 } 403 404 StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pStr); 405 CoTaskMemFree(pStr); 406 407 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 408 { 409 // failed to open key 410 return FALSE; 411 } 412 413 dwInstanceID = sizeof(szInstanceID); 414 if (RegGetValueW(hKey, NULL, L"PnpInstanceId", RRF_RT_REG_SZ, NULL, (PVOID)szInstanceID, &dwInstanceID) == ERROR_SUCCESS) 415 { 416 szInstanceID[MAX_PATH-1] = L'\0'; 417 pResult = static_cast<LPOLESTR>(CoTaskMemAlloc((wcslen(szInstanceID) + 1) * sizeof(WCHAR))); 418 if (pResult != 0) 419 { 420 wcscpy(pResult, szInstanceID); 421 *DeviceInstanceID = pResult; 422 RegCloseKey(hKey); 423 return TRUE; 424 } 425 } 426 RegCloseKey(hKey); 427 return FALSE; 428 } 429 430 HRESULT 431 WINAPI 432 CNetConnectionPropertyUi::AddPages( 433 HWND hwndParent, 434 LPFNADDPROPSHEETPAGE pfnAddPage, 435 LPARAM lParam) 436 { 437 HPROPSHEETPAGE hProp; 438 BOOL ret; 439 HRESULT hr = E_FAIL; 440 INITCOMMONCONTROLSEX initEx; 441 442 initEx.dwSize = sizeof(initEx); 443 initEx.dwICC = ICC_LISTVIEW_CLASSES; 444 if (!InitCommonControlsEx(&initEx)) 445 return E_FAIL; 446 447 hr = m_pCon->GetProperties(&m_pProperties); 448 if (FAILED_UNEXPECTEDLY(hr)) 449 return hr; 450 451 hProp = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_NETPROPERTIES), LANPropertiesUIDlg, reinterpret_cast<LPARAM>(this), NULL); 452 if (hProp) 453 { 454 ret = (*pfnAddPage)(hProp, lParam); 455 if (ret) 456 { 457 hr = NOERROR; 458 } 459 else 460 { 461 DestroyPropertySheetPage(hProp); 462 } 463 } 464 return hr; 465 } 466 467 HRESULT 468 WINAPI 469 CNetConnectionPropertyUi::GetIcon( 470 DWORD dwSize, 471 HICON *phIcon) 472 { 473 return E_NOTIMPL; 474 } 475 476 HRESULT 477 WINAPI 478 CNetConnectionPropertyUi::GetDeviceGuid(GUID *pGuid) 479 { 480 CopyMemory(pGuid, &m_pProperties->guidId, sizeof(GUID)); 481 return S_OK; 482 } 483 484 HRESULT 485 WINAPI 486 CNetConnectionPropertyUi::SetConnection(INetConnection* pCon) 487 { 488 if (!pCon) 489 return E_POINTER; 490 491 m_pCon = pCon; 492 return S_OK; 493 } 494 495 HRESULT 496 WINAPI 497 CNetConnectionPropertyUi::Connect( 498 HWND hwndParent, 499 DWORD dwFlags) 500 { 501 if (!m_pCon) 502 return E_POINTER; //FIXME 503 504 if (dwFlags & NCUC_NO_UI) 505 return m_pCon->Connect(); 506 507 return E_FAIL; 508 } 509 510 HRESULT 511 WINAPI 512 CNetConnectionPropertyUi::Disconnect( 513 HWND hwndParent, 514 DWORD dwFlags) 515 { 516 WCHAR szBuffer[100]; 517 swprintf(szBuffer, L"INetConnectionConnectUi_fnDisconnect flags %x\n", dwFlags); 518 MessageBoxW(NULL, szBuffer, NULL, MB_OK); 519 520 return S_OK; 521 } 522