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