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