Reactos
at master 634 lines 19 kB view raw
1/* 2 * PROJECT: ReactOS Shell 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: ReactOS Networking Configuration 5 * COPYRIGHT: Copyright 2016 Eric Kohl 6 */ 7 8#include "precomp.h" 9 10#include <syssetup/syssetup.h> 11 12 13#define NETWORK_SETUP_MAGIC 0x50515253 14 15typedef struct _NETWORKSETUPDATA 16{ 17 DWORD dwMagic; 18 PSETUPDATA pSetupData; 19 20 /* settings page data */ 21 BOOL bInitialSetupRun; 22 BOOL bTypicalNetworkSetup; 23 HWND hwndPage; 24} NETWORKSETUPDATA, *PNETWORKSETUPDATA; 25 26extern "C" 27{ 28 29typedef struct _NETWORKCOMPONENT 30{ 31 LPWSTR pszDeviceId; 32 const GUID *pClassGuid; 33} NETWORKCOMPONENT, PNETWORKCOMPONENT; 34 35static NETWORKCOMPONENT NetworkComponents[] = { 36 {(LPWSTR)L"MS_TCPIP", &GUID_DEVCLASS_NETTRANS}, 37 {(LPWSTR)L"MS_NDISUIO", &GUID_DEVCLASS_NETTRANS} 38}; 39 40 41static 42VOID 43SetBoldText( 44 HWND hwndDlg, 45 INT control, 46 PSETUPDATA pSetupData) 47{ 48 SendDlgItemMessageW(hwndDlg, control, WM_SETFONT, (WPARAM)pSetupData->hBoldFont, MAKELPARAM(TRUE, 0)); 49} 50 51 52static 53HRESULT 54InstallNetworkComponent( 55 LPWSTR pszComponentName, 56 const GUID *pClassGuid) 57{ 58 INetCfg *pNetCfg = NULL; 59 INetCfgLock *pNetCfgLock = NULL; 60 INetCfgClassSetup *pNetCfgClassSetup = NULL; 61 INetCfgComponent *pNetCfgComponent = NULL; 62 BOOL fWriteLocked = FALSE, fInitialized = FALSE; 63 OBO_TOKEN OboToken; 64 HRESULT hr; 65 66 TRACE("InstallNetworkComponent(%S)\n", pszComponentName); 67 68 hr = CoInitialize(NULL); 69 if (hr != S_OK) 70 { 71 ERR("CoInitialize failed\n"); 72 goto exit; 73 } 74 75 hr = CoCreateInstance(CLSID_CNetCfg, 76 NULL, 77 CLSCTX_INPROC_SERVER, 78 IID_INetCfg, 79 (PVOID*)&pNetCfg); 80 if (hr != S_OK) 81 { 82 ERR("CoCreateInstance failed\n"); 83 goto exit; 84 } 85 86 /* Acquire the write-lock */ 87 hr = pNetCfg->QueryInterface(IID_INetCfgLock, 88 (PVOID*)&pNetCfgLock); 89 if (hr != S_OK) 90 { 91 ERR("QueryInterface failed\n"); 92 goto exit; 93 } 94 95 hr = pNetCfgLock->AcquireWriteLock(5000, 96 L"SysSetup", 97 NULL); 98 if (hr != S_OK) 99 { 100 ERR("AcquireWriteLock failed\n"); 101 goto exit; 102 } 103 104 fWriteLocked = TRUE; 105 106 /* Initialize the network configuration */ 107 hr = pNetCfg->Initialize(NULL); 108 if (hr != S_OK) 109 { 110 ERR("Initialize failed\n"); 111 goto exit; 112 } 113 114 fInitialized = TRUE; 115 116 hr = pNetCfg->QueryNetCfgClass(pClassGuid, 117 IID_INetCfgClassSetup, 118 (PVOID*)&pNetCfgClassSetup); 119 if (hr != S_OK) 120 { 121 ERR("QueryNetCfgClass failed\n"); 122 goto exit; 123 } 124 125 ZeroMemory(&OboToken, sizeof(OboToken)); 126 OboToken.Type = OBO_USER; 127 128 hr = pNetCfgClassSetup->Install(pszComponentName, 129 &OboToken, 130 0, //NSF_PRIMARYINSTALL, 131 0, 132 NULL, 133 NULL, 134 &pNetCfgComponent); 135 if (hr == S_OK) 136 { 137 if (pNetCfgComponent != NULL) 138 pNetCfgComponent->Release(); 139 } 140 else 141 { 142 ERR("Install failed\n"); 143 goto exit; 144 } 145 146 hr = pNetCfg->Apply(); 147 if (hr != S_OK) 148 { 149 ERR("Apply failed\n"); 150 goto exit; 151 } 152 153exit: 154 if (pNetCfgClassSetup != NULL) 155 pNetCfgClassSetup->Release(); 156 157 if (fInitialized) 158 pNetCfg->Uninitialize(); 159 160 if (fWriteLocked) 161 pNetCfgLock->ReleaseWriteLock(); 162 163 if (pNetCfgLock != NULL) 164 pNetCfgLock->Release(); 165 166 if (pNetCfg != NULL) 167 pNetCfg->Release(); 168 169 CoUninitialize(); 170 171 TRACE("InstallNetworkComponent() done!\n"); 172 173 return hr; 174} 175 176static 177DWORD 178WINAPI 179InstallThreadProc( 180 _In_ LPVOID lpParameter) 181{ 182 PNETWORKSETUPDATA pNetworkSetupData = (PNETWORKSETUPDATA)lpParameter; 183 UINT i, count; 184 185 TRACE("InstallThreadProc()\n"); 186 187 count = sizeof(NetworkComponents) / sizeof(NETWORKCOMPONENT); 188 TRACE("Network Components: %u\n", count); 189 190 SendDlgItemMessage(pNetworkSetupData->hwndPage, IDC_INSTALL_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, count)); 191 SendDlgItemMessage(pNetworkSetupData->hwndPage, IDC_INSTALL_PROGRESS, PBM_SETPOS, 0, 0); 192 193 for (i = 0; i < count; i++) 194 { 195 TRACE("Install Network Component: %S\n", NetworkComponents[i].pszDeviceId); 196 InstallNetworkComponent(NetworkComponents[i].pszDeviceId, NetworkComponents[i].pClassGuid); 197 SendDlgItemMessage(pNetworkSetupData->hwndPage, IDC_INSTALL_PROGRESS, PBM_SETPOS, i, 0); 198 Sleep(500); 199 } 200 201 TRACE("Done\n"); 202 203 /* Done */ 204 pNetworkSetupData->bInitialSetupRun = TRUE; 205 PostMessage(pNetworkSetupData->hwndPage, WM_USER, 0, 0); 206 207 return 0; 208} 209 210static 211INT_PTR 212CALLBACK 213NetworkInitPageDlgProc( 214 HWND hwndDlg, 215 UINT uMsg, 216 WPARAM wParam, 217 LPARAM lParam) 218{ 219 PNETWORKSETUPDATA pNetworkSetupData; 220 PSETUPDATA pSetupData; 221 LPNMHDR lpnm; 222 223 /* Retrieve pointer to the global setup data */ 224 pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 225 if ((pNetworkSetupData != NULL) && 226 (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC)) 227 pSetupData = pNetworkSetupData->pSetupData; 228 229 switch (uMsg) 230 { 231 case WM_INITDIALOG: 232 /* Save pointer to the global setup data */ 233 pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 234 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData); 235 pSetupData = pNetworkSetupData->pSetupData; 236 237 if (pSetupData->UnattendSetup) 238 { 239 //... 240 } 241 break; 242 243 case WM_DESTROY: 244 /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */ 245 //... 246 break; 247 248 case WM_NOTIFY: 249 lpnm = (LPNMHDR)lParam; 250 251 switch (lpnm->code) 252 { 253 case PSN_SETACTIVE: 254 /* Disable the Back and Next buttons */ 255 PropSheet_SetWizButtons(GetParent(hwndDlg), 0); 256 TRACE("Starting install thread!\n"); 257 pNetworkSetupData->hwndPage = hwndDlg; 258 CreateThread(NULL, 0, InstallThreadProc, (LPVOID)pNetworkSetupData, 0, NULL); 259 TRACE("Install thread done!\n"); 260 break; 261 262 case PSN_WIZNEXT: 263 break; 264 265 case PSN_WIZBACK: 266 break; 267 } 268 break; 269 270 case WM_USER: 271 TRACE("WM_USER!\n"); 272 /* Enable the Next button and press it */ 273 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 274 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_NEXT); 275 break; 276 277 default: 278 break; 279 } 280 281 return FALSE; 282} 283 284static 285INT_PTR 286CALLBACK 287NetworkSettingsPageDlgProc( 288 HWND hwndDlg, 289 UINT uMsg, 290 WPARAM wParam, 291 LPARAM lParam) 292{ 293 PNETWORKSETUPDATA pNetworkSetupData; 294 PSETUPDATA pSetupData; 295 LPNMHDR lpnm; 296 297 /* Retrieve pointer to the global setup data */ 298 pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 299 if ((pNetworkSetupData != NULL) && 300 (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC)) 301 pSetupData = pNetworkSetupData->pSetupData; 302 303 switch (uMsg) 304 { 305 case WM_INITDIALOG: 306 /* Save pointer to the global setup data */ 307 pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 308 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData); 309 pSetupData = pNetworkSetupData->pSetupData; 310 311 /* Set the fonts of both the options to bold */ 312 SetBoldText(hwndDlg, IDC_NETWORK_TYPICAL, pSetupData); 313 SetBoldText(hwndDlg, IDC_NETWORK_CUSTOM, pSetupData); 314 315 /* Set the typical settings option as the default */ 316 SendDlgItemMessage(hwndDlg, IDC_NETWORK_TYPICAL, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 317 318 if (pSetupData->UnattendSetup) 319 { 320 //... 321 } 322 break; 323 324 case WM_DESTROY: 325 /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */ 326 //... 327 break; 328 329 case WM_NOTIFY: 330 lpnm = (LPNMHDR)lParam; 331 332 switch (lpnm->code) 333 { 334 case PSN_SETACTIVE: 335 /* Enable the Next button only */ 336 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 337 if (pSetupData->UnattendSetup) 338 { 339 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKCOMPONENTPAGE); 340 return TRUE; 341 } 342 break; 343 344 case PSN_WIZNEXT: 345 pNetworkSetupData->bTypicalNetworkSetup = FALSE; 346 347 /* If the Typical Settings button is chosen, then skip to the Domain Page */ 348 if (IsDlgButtonChecked(hwndDlg, IDC_NETWORK_TYPICAL) == BST_CHECKED) 349 { 350 pNetworkSetupData->bTypicalNetworkSetup = TRUE; 351 352 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKDOMAINPAGE); 353 return TRUE; 354 } 355 break; 356 357 case PSN_WIZBACK: 358 pSetupData->UnattendSetup = FALSE; 359 break; 360 } 361 break; 362 363 default: 364 break; 365 } 366 367 return FALSE; 368} 369 370static 371INT_PTR 372CALLBACK 373NetworkComponentPageDlgProc( 374 HWND hwndDlg, 375 UINT uMsg, 376 WPARAM wParam, 377 LPARAM lParam) 378{ 379 PNETWORKSETUPDATA pNetworkSetupData; 380 PSETUPDATA pSetupData; 381 LPNMHDR lpnm; 382 383 /* Retrieve pointer to the global setup data */ 384 pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 385 if ((pNetworkSetupData != NULL) && 386 (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC)) 387 pSetupData = pNetworkSetupData->pSetupData; 388 389 switch (uMsg) 390 { 391 case WM_INITDIALOG: 392 /* Save pointer to the global setup data */ 393 pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 394 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData); 395 pSetupData = pNetworkSetupData->pSetupData; 396 397 SetBoldText(hwndDlg, IDC_NETWORK_DEVICE, pSetupData); 398 399 if (pSetupData->UnattendSetup) 400 { 401 //... 402 } 403 break; 404 405 case WM_DESTROY: 406 /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */ 407 //... 408 break; 409 410 case WM_NOTIFY: 411 lpnm = (LPNMHDR)lParam; 412 413 switch (lpnm->code) 414 { 415 case PSN_SETACTIVE: 416 /* Enable the Back and Next buttons */ 417 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 418 if (pSetupData->UnattendSetup) 419 { 420 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKDOMAINPAGE); 421 return TRUE; 422 } 423 break; 424 425 case PSN_WIZBACK: 426 pSetupData->UnattendSetup = FALSE; 427 break; 428 } 429 break; 430 431 default: 432 break; 433 } 434 435 return FALSE; 436} 437 438static 439INT_PTR 440CALLBACK 441NetworkDomainPageDlgProc( 442 HWND hwndDlg, 443 UINT uMsg, 444 WPARAM wParam, 445 LPARAM lParam) 446{ 447 PNETWORKSETUPDATA pNetworkSetupData; 448 PSETUPDATA pSetupData; 449 WCHAR DomainName[51]; 450 WCHAR Title[64]; 451 WCHAR ErrorName[256]; 452 LPNMHDR lpnm; 453 454 /* Retrieve pointer to the global setup data */ 455 pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 456 if ((pNetworkSetupData != NULL) && 457 (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC)) 458 pSetupData = pNetworkSetupData->pSetupData; 459 460 switch (uMsg) 461 { 462 case WM_INITDIALOG: 463 /* Save pointer to the global setup data */ 464 pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 465 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData); 466 pSetupData = pNetworkSetupData->pSetupData; 467 468 /* Set the workgroup option as the default */ 469 SendDlgItemMessage(hwndDlg, IDC_SELECT_WORKGROUP, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 470 471 wcscpy(DomainName, L"WORKGROUP"); 472 473 /* Display current computer name */ 474 SetDlgItemTextW(hwndDlg, IDC_DOMAIN_NAME, DomainName); 475 476 /* Set focus to owner name */ 477 SetFocus(GetDlgItem(hwndDlg, IDC_DOMAIN_NAME)); 478 479 if (pSetupData->UnattendSetup) 480 { 481 //... 482 } 483 break; 484 485 case WM_DESTROY: 486 //... 487 /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */ 488 if (pNetworkSetupData != NULL) 489 { 490 if ((!IsBadReadPtr(pNetworkSetupData, sizeof(NETWORKSETUPDATA))) && 491 (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC)) 492 HeapFree(GetProcessHeap(), 0, pNetworkSetupData); 493 494 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)NULL); 495 } 496 break; 497 498 case WM_NOTIFY: 499 lpnm = (LPNMHDR)lParam; 500 501 switch (lpnm->code) 502 { 503 case PSN_SETACTIVE: 504 /* Enable the Back and Next buttons */ 505 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 506 if (pSetupData->UnattendSetup) 507 { 508 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, pSetupData->uPostNetworkWizardPage); 509 return TRUE; 510 } 511 break; 512 513 case PSN_WIZNEXT: 514 DomainName[0] = 0; 515 if (GetDlgItemTextW(hwndDlg, IDC_DOMAIN_NAME, DomainName, 50) == 0) 516 { 517 if (0 == LoadStringW(netshell_hInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0]))) 518 { 519 wcscpy(Title, L"ReactOS Setup"); 520 } 521 if (0 == LoadStringW(netshell_hInstance, IDS_WZD_DOMAIN_NAME, ErrorName, sizeof(ErrorName) / sizeof(ErrorName[0]))) 522 { 523 wcscpy(ErrorName, L"Setup cannot continue until you\nenter the name of your domain/workgroup."); 524 } 525 MessageBoxW(hwndDlg, ErrorName, Title, MB_ICONERROR | MB_OK); 526 527 SetFocus(GetDlgItem(hwndDlg, IDC_DOMAIN_NAME)); 528 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 529 530 //TODO: Implement setting the Domain/Workgroup 531 532 return TRUE; 533 } 534 break; 535 536 case PSN_WIZBACK: 537 pSetupData->UnattendSetup = FALSE; 538 539 /* If the Typical setup chosen, then skip back to the Settings Page */ 540 if (pNetworkSetupData->bTypicalNetworkSetup == TRUE) 541 { 542 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKSETTINGSPAGE); 543 return TRUE; 544 } 545 break; 546 } 547 break; 548 549 default: 550 break; 551 } 552 553 return FALSE; 554} 555 556 557DWORD 558WINAPI 559NetSetupRequestWizardPages( 560 PDWORD pPageCount, 561 HPROPSHEETPAGE *pPages, 562 PSETUPDATA pSetupData) 563{ 564 PNETWORKSETUPDATA pNetworkSetupData; 565 PROPSHEETPAGE psp = {0}; 566 DWORD dwPageCount = 4; 567 INT nPage = 0; 568 569 TRACE("NetSetupRequestWizardPages(%p %p %p)\n", pPageCount, pPages, pSetupData); 570 571 if (pPageCount == NULL) 572 return ERROR_INVALID_PARAMETER; 573 574 if (pPages == NULL) 575 { 576 TRACE("Return %lu pages\n", dwPageCount); 577 *pPageCount = dwPageCount; 578 return ERROR_SUCCESS; 579 } 580 581 if (*pPageCount < dwPageCount) 582 return ERROR_BUFFER_OVERFLOW; 583 584 pSetupData->uFirstNetworkWizardPage = IDD_NETWORKINITPAGE; 585 586 pNetworkSetupData = (PNETWORKSETUPDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NETWORKSETUPDATA)); 587 if (pNetworkSetupData == NULL) 588 return ERROR_OUTOFMEMORY; 589 590 pNetworkSetupData->dwMagic = NETWORK_SETUP_MAGIC; 591 pNetworkSetupData->pSetupData = pSetupData; 592 593 /* Create the Network Settings page */ 594 psp.dwSize = sizeof(PROPSHEETPAGE); 595 psp.hInstance = netshell_hInstance; 596 psp.lParam = (LPARAM)pNetworkSetupData; 597 598 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 599 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKINITTITLE); 600 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKINITSUBTITLE); 601 psp.pfnDlgProc = NetworkInitPageDlgProc; 602 psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKINITPAGE); 603 pPages[nPage++] = CreatePropertySheetPage(&psp); 604 605 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 606 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKSETTINGSTITLE); 607 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKSETTINGSSUBTITLE); 608 psp.pfnDlgProc = NetworkSettingsPageDlgProc; 609 psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKSETTINGSPAGE); 610 pPages[nPage++] = CreatePropertySheetPage(&psp); 611 612 /* Create the Network Components page */ 613 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 614 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKCOMPONENTTITLE); 615 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKCOMPONENTSUBTITLE); 616 psp.pfnDlgProc = NetworkComponentPageDlgProc; 617 psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKCOMPONENTPAGE); 618 pPages[nPage++] = CreatePropertySheetPage(&psp); 619 620 /* Create the Domain/Workgroup page */ 621 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 622 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKDOMAINTITLE); 623 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKDOMAINSUBTITLE); 624 psp.pfnDlgProc = NetworkDomainPageDlgProc; 625 psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKDOMAINPAGE); 626 pPages[nPage++] = CreatePropertySheetPage(&psp); 627 628 TRACE("Return %lu pages\n", dwPageCount); 629 *pPageCount = dwPageCount; 630 631 return ERROR_SUCCESS; 632} 633 634} // extern "C"