1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: System setup 4 * FILE: dll/win32/syssetup/wizard.c 5 * PURPOSE: GUI controls 6 * PROGRAMMERS: Eric Kohl 7 * Pierre Schweitzer <heis_spiter@hotmail.com> 8 * Ismael Ferreras Morezuelas <swyterzone+ros@gmail.com> 9 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 10 * Oleg Dubinskiy <oleg.dubinskij30@gmail.com> 11 */ 12 13 /* INCLUDES *****************************************************************/ 14 15 #include "precomp.h" 16 17 #include <stdlib.h> 18 #include <time.h> 19 #include <winnls.h> 20 #include <windowsx.h> 21 #include <wincon.h> 22 #include <shlobj.h> 23 #include <tzlib.h> 24 #include <strsafe.h> 25 26 #define NDEBUG 27 #include <debug.h> 28 29 #define PM_REGISTRATION_NOTIFY (WM_APP + 1) 30 /* Private Message used to communicate progress from the background 31 registration thread to the main thread. 32 wParam = 0 Registration in progress 33 = 1 Registration completed 34 lParam = Pointer to a REGISTRATIONNOTIFY structure */ 35 36 #define PM_ITEM_START (WM_APP + 2) 37 #define PM_ITEM_END (WM_APP + 3) 38 #define PM_STEP_START (WM_APP + 4) 39 #define PM_STEP_END (WM_APP + 5) 40 #define PM_ITEMS_DONE (WM_APP + 6) 41 42 typedef struct _REGISTRATIONNOTIFY 43 { 44 ULONG Progress; 45 UINT ActivityID; 46 LPCWSTR CurrentItem; 47 LPCWSTR ErrorMessage; 48 UINT MessageID; 49 DWORD LastError; 50 } REGISTRATIONNOTIFY, *PREGISTRATIONNOTIFY; 51 52 typedef struct _ITEMSDATA 53 { 54 HWND hwndDlg; 55 } ITEMSDATA, *PITEMSDATA; 56 57 typedef struct _REGISTRATIONDATA 58 { 59 HWND hwndDlg; 60 ULONG DllCount; 61 ULONG Registered; 62 PVOID DefaultContext; 63 } REGISTRATIONDATA, *PREGISTRATIONDATA; 64 65 typedef struct _TIMEZONE_ENTRY 66 { 67 struct _TIMEZONE_ENTRY *Prev; 68 struct _TIMEZONE_ENTRY *Next; 69 WCHAR Description[128]; /* 'Display' */ 70 WCHAR StandardName[32]; /* 'Std' */ 71 WCHAR DaylightName[32]; /* 'Dlt' */ 72 REG_TZI_FORMAT TimezoneInfo; /* 'TZI' */ 73 ULONG Index; 74 } TIMEZONE_ENTRY, *PTIMEZONE_ENTRY; 75 76 77 /* FUNCTIONS ****************************************************************/ 78 79 extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow); 80 81 82 static VOID 83 CenterWindow(HWND hWnd) 84 { 85 HWND hWndParent; 86 RECT rcParent; 87 RECT rcWindow; 88 89 hWndParent = GetParent(hWnd); 90 if (hWndParent == NULL) 91 hWndParent = GetDesktopWindow(); 92 93 GetWindowRect(hWndParent, &rcParent); 94 GetWindowRect(hWnd, &rcWindow); 95 96 SetWindowPos(hWnd, 97 HWND_TOP, 98 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2, 99 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2, 100 0, 101 0, 102 SWP_NOSIZE); 103 } 104 105 106 static HFONT 107 CreateTitleFont(VOID) 108 { 109 LOGFONTW LogFont = {0}; 110 HDC hdc; 111 HFONT hFont; 112 113 LogFont.lfWeight = FW_BOLD; 114 wcscpy(LogFont.lfFaceName, L"MS Shell Dlg"); 115 116 hdc = GetDC(NULL); 117 LogFont.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72); 118 119 hFont = CreateFontIndirectW(&LogFont); 120 121 ReleaseDC(NULL, hdc); 122 123 return hFont; 124 } 125 126 127 static HFONT 128 CreateBoldFont(VOID) 129 { 130 LOGFONTW tmpFont = {0}; 131 HFONT hBoldFont; 132 HDC hDc; 133 134 /* Grabs the Drawing Context */ 135 hDc = GetDC(NULL); 136 137 tmpFont.lfHeight = -MulDiv(8, GetDeviceCaps(hDc, LOGPIXELSY), 72); 138 tmpFont.lfWeight = FW_BOLD; 139 wcscpy(tmpFont.lfFaceName, L"MS Shell Dlg"); 140 141 hBoldFont = CreateFontIndirectW(&tmpFont); 142 143 ReleaseDC(NULL, hDc); 144 145 return hBoldFont; 146 } 147 148 static INT_PTR CALLBACK 149 GplDlgProc(HWND hwndDlg, 150 UINT uMsg, 151 WPARAM wParam, 152 LPARAM lParam) 153 { 154 HRSRC GplTextResource; 155 HGLOBAL GplTextMem; 156 PVOID GplTextLocked; 157 PCHAR GplText; 158 DWORD Size; 159 160 161 switch (uMsg) 162 { 163 case WM_INITDIALOG: 164 GplTextResource = FindResourceW(hDllInstance, MAKEINTRESOURCE(IDR_GPL), L"RT_TEXT"); 165 if (NULL == GplTextResource) 166 { 167 break; 168 } 169 Size = SizeofResource(hDllInstance, GplTextResource); 170 if (0 == Size) 171 { 172 break; 173 } 174 GplText = HeapAlloc(GetProcessHeap(), 0, Size + 1); 175 if (NULL == GplText) 176 { 177 break; 178 } 179 GplTextMem = LoadResource(hDllInstance, GplTextResource); 180 if (NULL == GplTextMem) 181 { 182 HeapFree(GetProcessHeap(), 0, GplText); 183 break; 184 } 185 GplTextLocked = LockResource(GplTextMem); 186 if (NULL == GplTextLocked) 187 { 188 HeapFree(GetProcessHeap(), 0, GplText); 189 break; 190 } 191 memcpy(GplText, GplTextLocked, Size); 192 GplText[Size] = '\0'; 193 SendMessageA(GetDlgItem(hwndDlg, IDC_GPL_TEXT), WM_SETTEXT, 0, (LPARAM) GplText); 194 HeapFree(GetProcessHeap(), 0, GplText); 195 SetFocus(GetDlgItem(hwndDlg, IDOK)); 196 return FALSE; 197 198 case WM_CLOSE: 199 EndDialog(hwndDlg, IDCANCEL); 200 break; 201 202 case WM_COMMAND: 203 if (HIWORD(wParam) == BN_CLICKED && IDOK == LOWORD(wParam)) 204 { 205 EndDialog(hwndDlg, IDOK); 206 } 207 break; 208 209 default: 210 break; 211 } 212 213 return FALSE; 214 } 215 216 217 static INT_PTR CALLBACK 218 WelcomeDlgProc(HWND hwndDlg, 219 UINT uMsg, 220 WPARAM wParam, 221 LPARAM lParam) 222 { 223 PSETUPDATA pSetupData; 224 225 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 226 227 switch (uMsg) 228 { 229 case WM_INITDIALOG: 230 { 231 HWND hwndControl; 232 DWORD dwStyle; 233 234 /* Get pointer to the global setup data */ 235 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 236 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 237 238 hwndControl = GetParent(hwndDlg); 239 240 /* Center the wizard window */ 241 CenterWindow (hwndControl); 242 243 /* Hide the system menu */ 244 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE); 245 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU); 246 247 /* Hide and disable the 'Cancel' button */ 248 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL); 249 ShowWindow (hwndControl, SW_HIDE); 250 EnableWindow (hwndControl, FALSE); 251 252 /* Set title font */ 253 SendDlgItemMessage(hwndDlg, 254 IDC_WELCOMETITLE, 255 WM_SETFONT, 256 (WPARAM)pSetupData->hTitleFont, 257 (LPARAM)TRUE); 258 } 259 break; 260 261 262 case WM_NOTIFY: 263 { 264 LPNMHDR lpnm = (LPNMHDR)lParam; 265 266 switch (lpnm->code) 267 { 268 case PSN_SETACTIVE: 269 LogItem(L"BEGIN", L"WelcomePage"); 270 /* Enable the Next button */ 271 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 272 if (pSetupData->UnattendSetup) 273 { 274 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_ACKPAGE); 275 return TRUE; 276 } 277 break; 278 279 case PSN_WIZNEXT: 280 LogItem(L"END", L"WelcomePage"); 281 break; 282 283 case PSN_WIZBACK: 284 pSetupData->UnattendSetup = FALSE; 285 break; 286 287 default: 288 break; 289 } 290 } 291 break; 292 293 default: 294 break; 295 } 296 297 return FALSE; 298 } 299 300 301 static INT_PTR CALLBACK 302 AckPageDlgProc(HWND hwndDlg, 303 UINT uMsg, 304 WPARAM wParam, 305 LPARAM lParam) 306 { 307 LPNMHDR lpnm; 308 PWCHAR Projects; 309 PWCHAR End, CurrentProject; 310 INT ProjectsSize, ProjectsCount; 311 PSETUPDATA pSetupData; 312 313 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 314 315 switch (uMsg) 316 { 317 case WM_INITDIALOG: 318 { 319 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 320 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 321 322 Projects = NULL; 323 ProjectsSize = 256; 324 while (TRUE) 325 { 326 Projects = HeapAlloc(GetProcessHeap(), 0, ProjectsSize * sizeof(WCHAR)); 327 if (NULL == Projects) 328 { 329 return FALSE; 330 } 331 ProjectsCount = LoadStringW(hDllInstance, IDS_ACKPROJECTS, Projects, ProjectsSize); 332 if (0 == ProjectsCount) 333 { 334 HeapFree(GetProcessHeap(), 0, Projects); 335 return FALSE; 336 } 337 if (ProjectsCount < ProjectsSize - 1) 338 { 339 break; 340 } 341 HeapFree(GetProcessHeap(), 0, Projects); 342 ProjectsSize *= 2; 343 } 344 345 CurrentProject = Projects; 346 while (*CurrentProject != L'\0') 347 { 348 End = wcschr(CurrentProject, L'\n'); 349 if (NULL != End) 350 { 351 *End = L'\0'; 352 } 353 (void)ListBox_AddString(GetDlgItem(hwndDlg, IDC_PROJECTS), CurrentProject); 354 if (NULL != End) 355 { 356 CurrentProject = End + 1; 357 } 358 else 359 { 360 CurrentProject += wcslen(CurrentProject); 361 } 362 } 363 HeapFree(GetProcessHeap(), 0, Projects); 364 } 365 break; 366 367 case WM_COMMAND: 368 if (HIWORD(wParam) == BN_CLICKED && IDC_VIEWGPL == LOWORD(wParam)) 369 { 370 DialogBox(hDllInstance, MAKEINTRESOURCE(IDD_GPL), NULL, GplDlgProc); 371 SetForegroundWindow(GetParent(hwndDlg)); 372 } 373 break; 374 375 case WM_NOTIFY: 376 { 377 lpnm = (LPNMHDR)lParam; 378 379 switch (lpnm->code) 380 { 381 case PSN_SETACTIVE: 382 /* Enable the Back and Next buttons */ 383 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 384 if (pSetupData->UnattendSetup) 385 { 386 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_PRODUCT); 387 return TRUE; 388 } 389 break; 390 391 case PSN_WIZBACK: 392 pSetupData->UnattendSetup = FALSE; 393 break; 394 395 default: 396 break; 397 } 398 } 399 break; 400 401 default: 402 break; 403 } 404 405 return FALSE; 406 } 407 408 static const WCHAR s_szProductOptions[] = L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions"; 409 static const WCHAR s_szRosVersion[] = L"SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version"; 410 static const WCHAR s_szControlWindows[] = L"SYSTEM\\CurrentControlSet\\Control\\Windows"; 411 static const WCHAR s_szWinlogon[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"; 412 static const WCHAR s_szDefaultSoundEvents[] = L"AppEvents\\Schemes\\Apps\\.Default"; 413 static const WCHAR s_szExplorerSoundEvents[] = L"AppEvents\\Schemes\\Apps\\Explorer"; 414 415 typedef struct _PRODUCT_OPTION_DATA 416 { 417 LPCWSTR ProductSuite; 418 LPCWSTR ProductType; 419 DWORD ReportAsWorkstation; 420 DWORD CSDVersion; 421 DWORD LogonType; 422 } PRODUCT_OPTION_DATA; 423 424 static const PRODUCT_OPTION_DATA s_ProductOptionData[] = 425 { 426 { L"Terminal Server\0", L"ServerNT", 0, 0x200, 0 }, 427 { L"\0", L"WinNT", 1, 0x300, 1 } 428 }; 429 430 static const WCHAR* s_DefaultSoundEvents[][2] = 431 { 432 { L".Default", L"%SystemRoot%\\Media\\ReactOS_Default.wav" }, 433 { L"AppGPFault", L"" }, 434 { L"Close", L"" }, 435 { L"CriticalBatteryAlarm", L"%SystemRoot%\\Media\\ReactOS_Battery_Critical.wav" }, 436 { L"DeviceConnect", L"%SystemRoot%\\Media\\ReactOS_Hardware_Insert.wav" }, 437 { L"DeviceDisconnect", L"%SystemRoot%\\Media\\ReactOS_Hardware_Remove.wav" }, 438 { L"DeviceFail", L"%SystemRoot%\\Media\\ReactOS_Hardware_Fail.wav" }, 439 { L"LowBatteryAlarm", L"%SystemRoot%\\Media\\ReactOS_Battery_Low.wav" }, 440 { L"MailBeep", L"%SystemRoot%\\Media\\ReactOS_Notify.wav" }, 441 { L"Maximize", L"%SystemRoot%\\Media\\ReactOS_Restore.wav" }, 442 { L"MenuCommand", L"%SystemRoot%\\Media\\ReactOS_Menu_Command.wav" }, 443 { L"MenuPopup", L"" }, 444 { L"Minimize", L"%SystemRoot%\\Media\\ReactOS_Minimize.wav" }, 445 { L"Open", L"" }, 446 { L"PrintComplete", L"%SystemRoot%\\Media\\ReactOS_Print_Complete.wav" }, 447 { L"RestoreDown", L"" }, 448 { L"RestoreUp", L"" }, 449 { L"SystemAsterisk", L"%SystemRoot%\\Media\\ReactOS_Ding.wav" }, 450 { L"SystemExclamation", L"%SystemRoot%\\Media\\ReactOS_Exclamation.wav" }, 451 { L"SystemExit", L"%SystemRoot%\\Media\\ReactOS_Shutdown.wav" }, 452 { L"SystemHand", L"%SystemRoot%\\Media\\ReactOS_Critical_Stop.wav" }, 453 { L"SystemNotification", L"%SystemRoot%\\Media\\ReactOS_Balloon.wav" }, 454 { L"SystemQuestion", L"%SystemRoot%\\Media\\ReactOS_Ding.wav" }, 455 { L"SystemStart", L"%SystemRoot%\\Media\\ReactOS_Startup.wav" }, 456 { L"WindowsLogoff", L"%SystemRoot%\\Media\\ReactOS_LogOff.wav" } 457 /* Logon sound is already set by default for both Server and Workstation */ 458 }; 459 460 static const WCHAR* s_ExplorerSoundEvents[][2] = 461 { 462 { L"EmptyRecycleBin", L"%SystemRoot%\\Media\\ReactOS_Recycle.wav" }, 463 { L"Navigating", L"%SystemRoot%\\Media\\ReactOS_Start.wav" } 464 }; 465 466 static BOOL 467 DoWriteSoundEvents(HKEY hKey, 468 LPCWSTR lpSubkey, 469 LPCWSTR lpEventsArray[][2], 470 DWORD dwSize) 471 { 472 HKEY hRootKey, hEventKey, hDefaultKey; 473 LONG error; 474 ULONG i; 475 WCHAR szDest[MAX_PATH]; 476 DWORD dwAttribs; 477 DWORD cbData; 478 479 /* Open the sound events key */ 480 error = RegOpenKeyExW(hKey, lpSubkey, 0, KEY_READ, &hRootKey); 481 if (error) 482 { 483 DPRINT1("RegOpenKeyExW failed\n"); 484 goto Error; 485 } 486 487 /* Set each sound event */ 488 for (i = 0; i < dwSize; i++) 489 { 490 /* 491 * Verify that the sound file exists and is an actual file. 492 */ 493 494 /* Expand the sound file path */ 495 if (!ExpandEnvironmentStringsW(lpEventsArray[i][1], szDest, _countof(szDest))) 496 { 497 /* Failed to expand, continue with the next sound event */ 498 continue; 499 } 500 501 /* Check if the sound file exists and isn't a directory */ 502 dwAttribs = GetFileAttributesW(szDest); 503 if ((dwAttribs == INVALID_FILE_ATTRIBUTES) || 504 (dwAttribs & FILE_ATTRIBUTE_DIRECTORY)) 505 { 506 /* It does not, just continue with the next sound event */ 507 continue; 508 } 509 510 /* 511 * Create the sound event entry. 512 */ 513 514 /* Open the sound event subkey */ 515 error = RegOpenKeyExW(hRootKey, lpEventsArray[i][0], 0, KEY_READ, &hEventKey); 516 if (error) 517 { 518 /* Failed to open, continue with next sound event */ 519 continue; 520 } 521 522 /* Open .Default subkey */ 523 error = RegOpenKeyExW(hEventKey, L".Default", 0, KEY_WRITE, &hDefaultKey); 524 RegCloseKey(hEventKey); 525 if (error) 526 { 527 /* Failed to open, continue with next sound event */ 528 continue; 529 } 530 531 /* Associate the sound file to this sound event */ 532 cbData = (lstrlenW(lpEventsArray[i][1]) + 1) * sizeof(WCHAR); 533 error = RegSetValueExW(hDefaultKey, NULL, 0, REG_EXPAND_SZ, (const BYTE *)lpEventsArray[i][1], cbData); 534 RegCloseKey(hDefaultKey); 535 if (error) 536 { 537 /* Failed to set the value, continue with next sound event */ 538 continue; 539 } 540 } 541 542 Error: 543 if (hRootKey) 544 RegCloseKey(hRootKey); 545 546 return error == ERROR_SUCCESS; 547 } 548 549 static BOOL 550 DoWriteProductOption(PRODUCT_OPTION nOption) 551 { 552 HKEY hKey; 553 LONG error; 554 LPCWSTR pszData; 555 DWORD dwValue, cbData; 556 const PRODUCT_OPTION_DATA *pData = &s_ProductOptionData[nOption]; 557 ASSERT(0 <= nOption && nOption < _countof(s_ProductOptionData)); 558 559 /* open ProductOptions key */ 560 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szProductOptions, 0, KEY_WRITE, &hKey); 561 if (error) 562 { 563 DPRINT1("RegOpenKeyExW failed\n"); 564 goto Error; 565 } 566 567 /* write ProductSuite */ 568 pszData = pData->ProductSuite; 569 cbData = (lstrlenW(pszData) + 2) * sizeof(WCHAR); 570 error = RegSetValueExW(hKey, L"ProductSuite", 0, REG_MULTI_SZ, (const BYTE *)pszData, cbData); 571 if (error) 572 { 573 DPRINT1("RegSetValueExW failed\n"); 574 goto Error; 575 } 576 577 /* write ProductType */ 578 pszData = pData->ProductType; 579 cbData = (lstrlenW(pszData) + 1) * sizeof(WCHAR); 580 error = RegSetValueExW(hKey, L"ProductType", 0, REG_SZ, (const BYTE *)pszData, cbData); 581 if (error) 582 { 583 DPRINT1("RegSetValueExW failed\n"); 584 goto Error; 585 } 586 587 RegCloseKey(hKey); 588 589 /* open ReactOS version key */ 590 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szRosVersion, 0, KEY_WRITE, &hKey); 591 if (error) 592 { 593 DPRINT1("RegOpenKeyExW failed\n"); 594 goto Error; 595 } 596 597 /* write ReportAsWorkstation */ 598 dwValue = pData->ReportAsWorkstation; 599 cbData = sizeof(dwValue); 600 error = RegSetValueExW(hKey, L"ReportAsWorkstation", 0, REG_DWORD, (const BYTE *)&dwValue, cbData); 601 if (error) 602 { 603 DPRINT1("RegSetValueExW failed\n"); 604 goto Error; 605 } 606 607 RegCloseKey(hKey); 608 609 /* open Control Windows key */ 610 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szControlWindows, 0, KEY_WRITE, &hKey); 611 if (error) 612 { 613 DPRINT1("RegOpenKeyExW failed\n"); 614 goto Error; 615 } 616 617 /* write Control Windows CSDVersion */ 618 dwValue = pData->CSDVersion; 619 cbData = sizeof(dwValue); 620 error = RegSetValueExW(hKey, L"CSDVersion", 0, REG_DWORD, (const BYTE *)&dwValue, cbData); 621 if (error) 622 { 623 DPRINT1("RegSetValueExW failed\n"); 624 goto Error; 625 } 626 627 RegCloseKey(hKey); 628 629 /* open Winlogon key */ 630 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szWinlogon, 0, KEY_WRITE, &hKey); 631 if (error) 632 { 633 DPRINT1("RegOpenKeyExW failed\n"); 634 goto Error; 635 } 636 637 /* write LogonType */ 638 dwValue = pData->LogonType; 639 cbData = sizeof(dwValue); 640 error = RegSetValueExW(hKey, L"LogonType", 0, REG_DWORD, (const BYTE *)&dwValue, cbData); 641 if (error) 642 { 643 DPRINT1("RegSetValueExW failed\n"); 644 goto Error; 645 } 646 647 if (nOption == PRODUCT_OPTION_WORKSTATION) 648 { 649 /* Write system sound events values for Workstation */ 650 DoWriteSoundEvents(HKEY_CURRENT_USER, s_szDefaultSoundEvents, s_DefaultSoundEvents, _countof(s_DefaultSoundEvents)); 651 DoWriteSoundEvents(HKEY_CURRENT_USER, s_szExplorerSoundEvents, s_ExplorerSoundEvents, _countof(s_ExplorerSoundEvents)); 652 } 653 654 Error: 655 if (hKey) 656 RegCloseKey(hKey); 657 658 return error == ERROR_SUCCESS; 659 } 660 661 static void 662 OnChooseOption(HWND hwndDlg, PRODUCT_OPTION nOption) 663 { 664 WCHAR szText[256]; 665 ASSERT(0 <= nOption && nOption < _countof(s_ProductOptionData)); 666 667 switch (nOption) 668 { 669 case PRODUCT_OPTION_SERVER: 670 LoadStringW(hDllInstance, IDS_PRODUCTSERVERINFO, szText, _countof(szText)); 671 break; 672 673 case PRODUCT_OPTION_WORKSTATION: 674 LoadStringW(hDllInstance, IDS_PRODUCTWORKSTATIONINFO, szText, _countof(szText)); 675 break; 676 677 default: 678 return; 679 } 680 681 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_DESCRIPTION, szText); 682 } 683 684 static INT_PTR CALLBACK 685 ProductPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 686 { 687 LPNMHDR lpnm; 688 PSETUPDATA pSetupData; 689 INT iItem; 690 WCHAR szText[64], szDefault[64]; 691 HICON hIcon; 692 693 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 694 695 switch (uMsg) 696 { 697 case WM_INITDIALOG: 698 { 699 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 700 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 701 702 LoadStringW(hDllInstance, IDS_DEFAULT, szDefault, _countof(szDefault)); 703 704 LoadStringW(hDllInstance, IDS_PRODUCTSERVERNAME, szText, _countof(szText)); 705 if (PRODUCT_OPTION_DEFAULT == PRODUCT_OPTION_SERVER) 706 { 707 StringCchCatW(szText, _countof(szText), L" "); 708 StringCchCatW(szText, _countof(szText), szDefault); 709 } 710 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_ADDSTRING, 0, (LPARAM)szText); 711 712 LoadStringW(hDllInstance, IDS_PRODUCTWORKSTATIONNAME, szText, _countof(szText)); 713 if (PRODUCT_OPTION_DEFAULT == PRODUCT_OPTION_WORKSTATION) 714 { 715 StringCchCatW(szText, _countof(szText), L" "); 716 StringCchCatW(szText, _countof(szText), szDefault); 717 } 718 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_ADDSTRING, 0, (LPARAM)szText); 719 720 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_SETCURSEL, PRODUCT_OPTION_DEFAULT, 0); 721 OnChooseOption(hwndDlg, PRODUCT_OPTION_DEFAULT); 722 723 hIcon = LoadIcon(NULL, IDI_WINLOGO); 724 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_ICON, STM_SETICON, (WPARAM)hIcon, 0); 725 return TRUE; 726 } 727 728 case WM_COMMAND: 729 if (HIWORD(wParam) == CBN_SELCHANGE && IDC_PRODUCT_OPTIONS == LOWORD(wParam)) 730 { 731 iItem = SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_GETCURSEL, 0, 0); 732 OnChooseOption(hwndDlg, (PRODUCT_OPTION)iItem); 733 } 734 break; 735 736 case WM_NOTIFY: 737 { 738 lpnm = (LPNMHDR)lParam; 739 740 switch (lpnm->code) 741 { 742 case PSN_SETACTIVE: 743 /* Enable the Back and Next buttons */ 744 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 745 if (pSetupData->UnattendSetup) 746 { 747 OnChooseOption(hwndDlg, pSetupData->ProductOption); 748 DoWriteProductOption(pSetupData->ProductOption); 749 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_LOCALEPAGE); 750 return TRUE; 751 } 752 break; 753 754 case PSN_WIZNEXT: 755 iItem = SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_GETCURSEL, 0, 0); 756 pSetupData->ProductOption = (PRODUCT_OPTION)iItem; 757 DoWriteProductOption(pSetupData->ProductOption); 758 break; 759 760 case PSN_WIZBACK: 761 pSetupData->UnattendSetup = FALSE; 762 break; 763 764 default: 765 break; 766 } 767 } 768 break; 769 770 default: 771 break; 772 } 773 774 return FALSE; 775 } 776 777 static 778 BOOL 779 WriteOwnerSettings(WCHAR * OwnerName, 780 WCHAR * OwnerOrganization) 781 { 782 HKEY hKey; 783 LONG res; 784 785 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 786 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 787 0, 788 KEY_ALL_ACCESS, 789 &hKey); 790 791 if (res != ERROR_SUCCESS) 792 { 793 return FALSE; 794 } 795 796 res = RegSetValueExW(hKey, 797 L"RegisteredOwner", 798 0, 799 REG_SZ, 800 (LPBYTE)OwnerName, 801 (wcslen(OwnerName) + 1) * sizeof(WCHAR)); 802 803 if (res != ERROR_SUCCESS) 804 { 805 RegCloseKey(hKey); 806 return FALSE; 807 } 808 809 res = RegSetValueExW(hKey, 810 L"RegisteredOrganization", 811 0, 812 REG_SZ, 813 (LPBYTE)OwnerOrganization, 814 (wcslen(OwnerOrganization) + 1) * sizeof(WCHAR)); 815 816 RegCloseKey(hKey); 817 return (res == ERROR_SUCCESS); 818 } 819 820 static INT_PTR CALLBACK 821 OwnerPageDlgProc(HWND hwndDlg, 822 UINT uMsg, 823 WPARAM wParam, 824 LPARAM lParam) 825 { 826 WCHAR OwnerName[51]; 827 WCHAR OwnerOrganization[51]; 828 WCHAR Title[64]; 829 WCHAR ErrorName[256]; 830 LPNMHDR lpnm; 831 PSETUPDATA pSetupData; 832 833 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 834 835 switch (uMsg) 836 { 837 case WM_INITDIALOG: 838 { 839 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 840 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 841 842 /* set a localized ('Owner') placeholder string as default */ 843 if (LoadStringW(hDllInstance, IDS_MACHINE_OWNER_NAME, OwnerName, _countof(OwnerName))) 844 { 845 SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, WM_SETTEXT, 0, (LPARAM)OwnerName); 846 } 847 848 SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, EM_LIMITTEXT, 50, 0); 849 SendDlgItemMessage(hwndDlg, IDC_OWNERORGANIZATION, EM_LIMITTEXT, 50, 0); 850 851 /* Set focus to owner name */ 852 SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME)); 853 854 /* Select the default text to quickly overwrite it by typing */ 855 SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, EM_SETSEL, 0, -1); 856 } 857 break; 858 859 860 case WM_NOTIFY: 861 { 862 lpnm = (LPNMHDR)lParam; 863 864 switch (lpnm->code) 865 { 866 case PSN_SETACTIVE: 867 /* Enable the Back and Next buttons */ 868 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 869 if (pSetupData->UnattendSetup) 870 { 871 SendMessage(GetDlgItem(hwndDlg, IDC_OWNERNAME), WM_SETTEXT, 0, (LPARAM)pSetupData->OwnerName); 872 SendMessage(GetDlgItem(hwndDlg, IDC_OWNERORGANIZATION), WM_SETTEXT, 0, (LPARAM)pSetupData->OwnerOrganization); 873 if (WriteOwnerSettings(pSetupData->OwnerName, pSetupData->OwnerOrganization)) 874 { 875 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_COMPUTERPAGE); 876 return TRUE; 877 } 878 } 879 break; 880 881 case PSN_WIZNEXT: 882 OwnerName[0] = 0; 883 if (GetDlgItemTextW(hwndDlg, IDC_OWNERNAME, OwnerName, 50) == 0) 884 { 885 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 886 { 887 wcscpy(Title, L"ReactOS Setup"); 888 } 889 if (0 == LoadStringW(hDllInstance, IDS_WZD_NAME, ErrorName, ARRAYSIZE(ErrorName))) 890 { 891 wcscpy(ErrorName, L"Setup cannot continue until you enter your name."); 892 } 893 MessageBoxW(hwndDlg, ErrorName, Title, MB_ICONERROR | MB_OK); 894 895 SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME)); 896 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 897 898 return TRUE; 899 } 900 901 OwnerOrganization[0] = 0; 902 GetDlgItemTextW(hwndDlg, IDC_OWNERORGANIZATION, OwnerOrganization, 50); 903 904 if (!WriteOwnerSettings(OwnerName, OwnerOrganization)) 905 { 906 SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME)); 907 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 908 return TRUE; 909 } 910 911 case PSN_WIZBACK: 912 pSetupData->UnattendSetup = FALSE; 913 break; 914 915 default: 916 break; 917 } 918 } 919 break; 920 921 default: 922 break; 923 } 924 925 return FALSE; 926 } 927 928 static 929 BOOL 930 WriteComputerSettings(WCHAR * ComputerName, HWND hwndDlg) 931 { 932 WCHAR Title[64]; 933 WCHAR ErrorComputerName[256]; 934 LONG lError; 935 HKEY hKey = NULL; 936 937 if (!SetComputerNameW(ComputerName)) 938 { 939 if (hwndDlg != NULL) 940 { 941 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 942 { 943 wcscpy(Title, L"ReactOS Setup"); 944 } 945 if (0 == LoadStringW(hDllInstance, IDS_WZD_SETCOMPUTERNAME, ErrorComputerName, 946 ARRAYSIZE(ErrorComputerName))) 947 { 948 wcscpy(ErrorComputerName, L"Setup failed to set the computer name."); 949 } 950 MessageBoxW(hwndDlg, ErrorComputerName, Title, MB_ICONERROR | MB_OK); 951 } 952 953 return FALSE; 954 } 955 956 /* Set the physical DNS domain */ 957 SetComputerNameExW(ComputerNamePhysicalDnsDomain, L""); 958 959 /* Set the physical DNS hostname */ 960 SetComputerNameExW(ComputerNamePhysicalDnsHostname, ComputerName); 961 962 /* Set the accounts domain name */ 963 SetAccountsDomainSid(NULL, ComputerName); 964 965 /* Now we need to set the Hostname */ 966 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 967 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 968 0, 969 KEY_SET_VALUE, 970 &hKey); 971 if (lError != ERROR_SUCCESS) 972 { 973 DPRINT1("RegOpenKeyExW for Tcpip\\Parameters failed (%08lX)\n", lError); 974 return TRUE; 975 } 976 977 lError = RegSetValueEx(hKey, 978 L"Hostname", 979 0, 980 REG_SZ, 981 (LPBYTE)ComputerName, 982 (wcslen(ComputerName) + 1) * sizeof(WCHAR)); 983 if (lError != ERROR_SUCCESS) 984 { 985 DPRINT1("RegSetValueEx(\"Hostname\") failed (%08lX)\n", lError); 986 } 987 988 RegCloseKey(hKey); 989 990 return TRUE; 991 } 992 993 994 static 995 BOOL 996 WriteDefaultLogonData(LPWSTR Domain) 997 { 998 WCHAR szAdministratorName[256]; 999 HKEY hKey = NULL; 1000 LONG lError; 1001 1002 if (LoadStringW(hDllInstance, 1003 IDS_ADMINISTRATOR_NAME, 1004 szAdministratorName, 1005 ARRAYSIZE(szAdministratorName)) == 0) 1006 { 1007 wcscpy(szAdministratorName, L"Administrator"); 1008 } 1009 1010 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1011 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 1012 0, 1013 KEY_SET_VALUE, 1014 &hKey); 1015 if (lError != ERROR_SUCCESS) 1016 return FALSE; 1017 1018 lError = RegSetValueEx(hKey, 1019 L"DefaultDomainName", 1020 0, 1021 REG_SZ, 1022 (LPBYTE)Domain, 1023 (wcslen(Domain)+ 1) * sizeof(WCHAR)); 1024 if (lError != ERROR_SUCCESS) 1025 { 1026 DPRINT1("RegSetValueEx(\"DefaultDomainName\") failed!\n"); 1027 } 1028 1029 lError = RegSetValueEx(hKey, 1030 L"DefaultUserName", 1031 0, 1032 REG_SZ, 1033 (LPBYTE)szAdministratorName, 1034 (wcslen(szAdministratorName)+ 1) * sizeof(WCHAR)); 1035 if (lError != ERROR_SUCCESS) 1036 { 1037 DPRINT1("RegSetValueEx(\"DefaultUserName\") failed!\n"); 1038 } 1039 1040 RegCloseKey(hKey); 1041 1042 return TRUE; 1043 } 1044 1045 1046 /* lpBuffer will be filled with a 15-char string (plus the null terminator) */ 1047 static void 1048 GenerateComputerName(LPWSTR lpBuffer) 1049 { 1050 static const WCHAR Chars[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1051 static const unsigned cChars = sizeof(Chars) / sizeof(WCHAR) - 1; 1052 unsigned i; 1053 1054 wcscpy(lpBuffer, L"REACTOS-"); 1055 1056 srand(GetTickCount()); 1057 1058 /* fill in 7 characters */ 1059 for (i = 8; i < 15; i++) 1060 lpBuffer[i] = Chars[rand() % cChars]; 1061 1062 lpBuffer[15] = UNICODE_NULL; /* NULL-terminate */ 1063 } 1064 1065 static INT_PTR CALLBACK 1066 ComputerPageDlgProc(HWND hwndDlg, 1067 UINT uMsg, 1068 WPARAM wParam, 1069 LPARAM lParam) 1070 { 1071 WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; 1072 WCHAR Password1[128]; 1073 WCHAR Password2[128]; 1074 PWCHAR Password; 1075 WCHAR Title[64]; 1076 WCHAR EmptyComputerName[256], NotMatchPassword[256], WrongPassword[256]; 1077 LPNMHDR lpnm; 1078 PSETUPDATA pSetupData; 1079 1080 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 1081 1082 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 1083 { 1084 wcscpy(Title, L"ReactOS Setup"); 1085 } 1086 1087 switch (uMsg) 1088 { 1089 case WM_INITDIALOG: 1090 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1091 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 1092 1093 /* Generate a new pseudo-random computer name */ 1094 GenerateComputerName(ComputerName); 1095 1096 /* Display current computer name */ 1097 SetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName); 1098 1099 /* Set text limits */ 1100 SendDlgItemMessage(hwndDlg, IDC_COMPUTERNAME, EM_LIMITTEXT, MAX_COMPUTERNAME_LENGTH, 0); 1101 SendDlgItemMessage(hwndDlg, IDC_ADMINPASSWORD1, EM_LIMITTEXT, 127, 0); 1102 SendDlgItemMessage(hwndDlg, IDC_ADMINPASSWORD2, EM_LIMITTEXT, 127, 0); 1103 1104 /* Set focus to computer name */ 1105 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME)); 1106 if (pSetupData->UnattendSetup) 1107 { 1108 SendMessage(GetDlgItem(hwndDlg, IDC_COMPUTERNAME), WM_SETTEXT, 0, (LPARAM)pSetupData->ComputerName); 1109 SendMessage(GetDlgItem(hwndDlg, IDC_ADMINPASSWORD1), WM_SETTEXT, 0, (LPARAM)pSetupData->AdminPassword); 1110 SendMessage(GetDlgItem(hwndDlg, IDC_ADMINPASSWORD2), WM_SETTEXT, 0, (LPARAM)pSetupData->AdminPassword); 1111 WriteComputerSettings(pSetupData->ComputerName, NULL); 1112 SetAdministratorPassword(pSetupData->AdminPassword); 1113 } 1114 1115 /* Store the administrator account name as the default user name */ 1116 WriteDefaultLogonData(pSetupData->ComputerName); 1117 break; 1118 1119 1120 case WM_NOTIFY: 1121 { 1122 lpnm = (LPNMHDR)lParam; 1123 1124 switch (lpnm->code) 1125 { 1126 case PSN_SETACTIVE: 1127 /* Enable the Back and Next buttons */ 1128 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1129 if (pSetupData->UnattendSetup && WriteComputerSettings(pSetupData->ComputerName, hwndDlg)) 1130 { 1131 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_THEMEPAGE); 1132 return TRUE; 1133 } 1134 break; 1135 1136 case PSN_WIZNEXT: 1137 if (0 == GetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName, MAX_COMPUTERNAME_LENGTH + 1)) 1138 { 1139 if (0 == LoadStringW(hDllInstance, IDS_WZD_COMPUTERNAME, EmptyComputerName, 1140 ARRAYSIZE(EmptyComputerName))) 1141 { 1142 wcscpy(EmptyComputerName, L"Setup cannot continue until you enter the name of your computer."); 1143 } 1144 MessageBoxW(hwndDlg, EmptyComputerName, Title, MB_ICONERROR | MB_OK); 1145 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME)); 1146 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 1147 return TRUE; 1148 } 1149 1150 /* No need to check computer name for invalid characters, 1151 * SetComputerName() will do it for us */ 1152 1153 if (!WriteComputerSettings(ComputerName, hwndDlg)) 1154 { 1155 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME)); 1156 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 1157 return TRUE; 1158 } 1159 1160 #ifdef PASSWORDS_MANDATORY 1161 /* Check if admin passwords have been entered */ 1162 if ((GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD1, Password1, 128) == 0) || 1163 (GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128) == 0)) 1164 { 1165 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDEMPTY, EmptyPassword, 1166 ARRAYSIZE(EmptyPassword))) 1167 { 1168 wcscpy(EmptyPassword, L"You must enter a password !"); 1169 } 1170 MessageBoxW(hwndDlg, EmptyPassword, Title, MB_ICONERROR | MB_OK); 1171 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 1172 return TRUE; 1173 } 1174 #else 1175 GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD1, Password1, 128); 1176 GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128); 1177 #endif 1178 /* Check if passwords match */ 1179 if (wcscmp(Password1, Password2)) 1180 { 1181 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDMATCH, NotMatchPassword, 1182 ARRAYSIZE(NotMatchPassword))) 1183 { 1184 wcscpy(NotMatchPassword, L"The passwords you entered do not match. Please enter the desired password again."); 1185 } 1186 MessageBoxW(hwndDlg, NotMatchPassword, Title, MB_ICONERROR | MB_OK); 1187 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 1188 return TRUE; 1189 } 1190 1191 /* Check password for invalid characters */ 1192 Password = (PWCHAR)Password1; 1193 while (*Password) 1194 { 1195 if (!isprint(*Password)) 1196 { 1197 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDCHAR, WrongPassword, 1198 ARRAYSIZE(WrongPassword))) 1199 { 1200 wcscpy(WrongPassword, L"The password you entered contains invalid characters. Please enter a cleaned password."); 1201 } 1202 MessageBoxW(hwndDlg, WrongPassword, Title, MB_ICONERROR | MB_OK); 1203 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 1204 return TRUE; 1205 } 1206 Password++; 1207 } 1208 1209 /* Set admin password */ 1210 SetAdministratorPassword(Password1); 1211 break; 1212 1213 case PSN_WIZBACK: 1214 pSetupData->UnattendSetup = FALSE; 1215 break; 1216 1217 default: 1218 break; 1219 } 1220 } 1221 break; 1222 1223 default: 1224 break; 1225 } 1226 1227 return FALSE; 1228 } 1229 1230 1231 static VOID 1232 SetUserLocaleName(HWND hwnd) 1233 { 1234 WCHAR CurLocale[256] = L""; 1235 WCHAR CurGeo[256] = L""; 1236 WCHAR ResText[256] = L""; 1237 WCHAR LocaleText[256 * 2]; 1238 1239 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SLANGUAGE, CurLocale, ARRAYSIZE(CurLocale)); 1240 GetGeoInfoW(GetUserGeoID(GEOCLASS_NATION), GEO_FRIENDLYNAME, CurGeo, ARRAYSIZE(CurGeo), GetThreadLocale()); 1241 1242 LoadStringW(hDllInstance, IDS_LOCALETEXT, ResText, ARRAYSIZE(ResText)); 1243 StringCchPrintfW(LocaleText, ARRAYSIZE(LocaleText), ResText, CurLocale, CurGeo); 1244 1245 SetWindowTextW(hwnd, LocaleText); 1246 } 1247 1248 static VOID 1249 SetKeyboardLayoutName(HWND hwnd) 1250 { 1251 HKL hkl; 1252 BOOL LayoutSpecial = FALSE; 1253 WCHAR LayoutPath[256]; 1254 WCHAR LocaleName[32]; 1255 WCHAR SpecialId[5] = L""; 1256 WCHAR ResText[256] = L""; 1257 DWORD dwValueSize; 1258 HKEY hKey; 1259 UINT i; 1260 1261 /* Get the default input language and method */ 1262 if (!SystemParametersInfoW(SPI_GETDEFAULTINPUTLANG, 0, (LPDWORD)&hkl, 0)) 1263 { 1264 hkl = GetKeyboardLayout(0); 1265 } 1266 1267 if ((HIWORD(hkl) & 0xF000) == 0xF000) 1268 { 1269 /* Process keyboard layout with special id */ 1270 StringCchPrintfW(SpecialId, ARRAYSIZE(SpecialId), L"%04x", (HIWORD(hkl) & 0x0FFF)); 1271 LayoutSpecial = TRUE; 1272 } 1273 1274 #define MAX_LAYOUTS_PER_LANGID 0x10000 1275 for (i = 0; i < (LayoutSpecial ? MAX_LAYOUTS_PER_LANGID : 1); i++) 1276 { 1277 /* Generate a hexadecimal identifier for keyboard layout registry key */ 1278 StringCchPrintfW(LocaleName, ARRAYSIZE(LocaleName), L"%08lx", (i << 16) | LOWORD(hkl)); 1279 1280 StringCchCopyW(LayoutPath, ARRAYSIZE(LayoutPath), L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"); 1281 StringCchCatW(LayoutPath, ARRAYSIZE(LayoutPath), LocaleName); 1282 *LocaleName = UNICODE_NULL; 1283 1284 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1285 LayoutPath, 1286 0, 1287 KEY_ALL_ACCESS, 1288 &hKey) == ERROR_SUCCESS) 1289 { 1290 /* Make sure the keyboard layout key we opened is the one we need. 1291 * If the layout has no special id, just pass this check. */ 1292 dwValueSize = sizeof(LocaleName); 1293 if (!LayoutSpecial || 1294 ((RegQueryValueExW(hKey, 1295 L"Layout Id", 1296 NULL, 1297 NULL, 1298 (PVOID)&LocaleName, 1299 &dwValueSize) == ERROR_SUCCESS) && 1300 (wcscmp(LocaleName, SpecialId) == 0))) 1301 { 1302 *LocaleName = UNICODE_NULL; 1303 dwValueSize = sizeof(LocaleName); 1304 RegQueryValueExW(hKey, 1305 L"Layout Text", 1306 NULL, 1307 NULL, 1308 (PVOID)&LocaleName, 1309 &dwValueSize); 1310 /* Let the loop know where to stop */ 1311 i = MAX_LAYOUTS_PER_LANGID; 1312 } 1313 RegCloseKey(hKey); 1314 } 1315 else 1316 { 1317 /* Keyboard layout registry keys are expected to go in order without gaps */ 1318 break; 1319 } 1320 } 1321 #undef MAX_LAYOUTS_PER_LANGID 1322 1323 LoadStringW(hDllInstance, IDS_LAYOUTTEXT, ResText, ARRAYSIZE(ResText)); 1324 StringCchPrintfW(LayoutPath, ARRAYSIZE(LayoutPath), ResText, LocaleName); 1325 1326 SetWindowTextW(hwnd, LayoutPath); 1327 } 1328 1329 1330 static BOOL 1331 RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters) 1332 { 1333 MSG msg; 1334 HWND MainWindow = GetParent(hwnd); 1335 STARTUPINFOW StartupInfo; 1336 PROCESS_INFORMATION ProcessInformation; 1337 WCHAR CmdLine[MAX_PATH] = L"rundll32.exe shell32.dll,Control_RunDLL "; 1338 1339 if (!pwszCPLParameters) 1340 { 1341 MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR); 1342 return FALSE; 1343 } 1344 1345 ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 1346 StartupInfo.cb = sizeof(StartupInfo); 1347 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); 1348 1349 ASSERT(_countof(CmdLine) > wcslen(CmdLine) + wcslen(pwszCPLParameters)); 1350 wcscat(CmdLine, pwszCPLParameters); 1351 1352 if (!CreateProcessW(NULL, 1353 CmdLine, 1354 NULL, 1355 NULL, 1356 FALSE, 1357 0, 1358 NULL, 1359 NULL, 1360 &StartupInfo, 1361 &ProcessInformation)) 1362 { 1363 MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR); 1364 return FALSE; 1365 } 1366 1367 /* Disable the Back and Next buttons and the main window 1368 * while we're interacting with the control panel applet */ 1369 PropSheet_SetWizButtons(MainWindow, 0); 1370 EnableWindow(MainWindow, FALSE); 1371 1372 while ((MsgWaitForMultipleObjects(1, &ProcessInformation.hProcess, FALSE, INFINITE, QS_ALLINPUT|QS_ALLPOSTMESSAGE )) != WAIT_OBJECT_0) 1373 { 1374 /* We still need to process main window messages to avoid freeze */ 1375 while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) 1376 { 1377 TranslateMessage(&msg); 1378 DispatchMessageW(&msg); 1379 } 1380 } 1381 CloseHandle(ProcessInformation.hThread); 1382 CloseHandle(ProcessInformation.hProcess); 1383 1384 /* Enable the Back and Next buttons and the main window again */ 1385 PropSheet_SetWizButtons(MainWindow, PSWIZB_BACK | PSWIZB_NEXT); 1386 EnableWindow(MainWindow, TRUE); 1387 1388 return TRUE; 1389 } 1390 1391 static VOID 1392 WriteUserLocale(VOID) 1393 { 1394 HKEY hKey; 1395 LCID lcid; 1396 WCHAR Locale[12]; 1397 1398 lcid = GetSystemDefaultLCID(); 1399 1400 if (GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Locale, ARRAYSIZE(Locale)) != 0) 1401 { 1402 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel\\International", 1403 0, NULL, REG_OPTION_NON_VOLATILE, 1404 KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) 1405 { 1406 RegSetValueExW(hKey, L"Locale", 0, REG_SZ, (LPBYTE)Locale, (wcslen(Locale) + 1) * sizeof(WCHAR)); 1407 RegCloseKey(hKey); 1408 } 1409 } 1410 } 1411 1412 static INT_PTR CALLBACK 1413 LocalePageDlgProc(HWND hwndDlg, 1414 UINT uMsg, 1415 WPARAM wParam, 1416 LPARAM lParam) 1417 { 1418 PSETUPDATA SetupData; 1419 1420 /* Retrieve pointer to the global setup data */ 1421 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1422 1423 switch (uMsg) 1424 { 1425 case WM_INITDIALOG: 1426 { 1427 /* Save pointer to the global setup data */ 1428 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1429 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1430 WriteUserLocale(); 1431 1432 SetUserLocaleName(GetDlgItem(hwndDlg, IDC_LOCALETEXT)); 1433 SetKeyboardLayoutName(GetDlgItem(hwndDlg, IDC_LAYOUTTEXT)); 1434 } 1435 break; 1436 1437 case WM_COMMAND: 1438 if (HIWORD(wParam) == BN_CLICKED) 1439 { 1440 switch (LOWORD(wParam)) 1441 { 1442 case IDC_CUSTOMLOCALE: 1443 RunControlPanelApplet(hwndDlg, L"intl.cpl,,5"); 1444 SetUserLocaleName(GetDlgItem(hwndDlg, IDC_LOCALETEXT)); 1445 break; 1446 1447 case IDC_CUSTOMLAYOUT: 1448 RunControlPanelApplet(hwndDlg, L"input.dll,@1"); 1449 SetKeyboardLayoutName(GetDlgItem(hwndDlg, IDC_LAYOUTTEXT)); 1450 break; 1451 } 1452 } 1453 break; 1454 1455 case WM_NOTIFY: 1456 { 1457 LPNMHDR lpnm = (LPNMHDR)lParam; 1458 1459 switch (lpnm->code) 1460 { 1461 case PSN_SETACTIVE: 1462 /* Enable the Back and Next buttons */ 1463 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1464 if (SetupData->UnattendSetup) 1465 { 1466 // if (!*SetupData->SourcePath) 1467 { 1468 RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"$winnt$.inf\""); // Should be in System32 1469 } 1470 1471 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_OWNERPAGE); 1472 return TRUE; 1473 } 1474 break; 1475 1476 case PSN_WIZNEXT: 1477 break; 1478 1479 case PSN_WIZBACK: 1480 SetupData->UnattendSetup = FALSE; 1481 break; 1482 1483 default: 1484 break; 1485 } 1486 } 1487 break; 1488 1489 default: 1490 break; 1491 } 1492 1493 return FALSE; 1494 } 1495 1496 1497 static PTIMEZONE_ENTRY 1498 GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD Index) 1499 { 1500 PTIMEZONE_ENTRY Entry; 1501 1502 Entry = SetupData->TimeZoneListHead; 1503 while (Entry != NULL) 1504 { 1505 if (Entry->Index >= Index) 1506 return Entry; 1507 1508 Entry = Entry->Next; 1509 } 1510 1511 return NULL; 1512 } 1513 1514 static LONG 1515 RetrieveTimeZone( 1516 IN HKEY hZoneKey, 1517 IN PVOID Context) 1518 { 1519 LONG lError; 1520 PSETUPDATA SetupData = (PSETUPDATA)Context; 1521 PTIMEZONE_ENTRY Entry; 1522 PTIMEZONE_ENTRY Current; 1523 ULONG DescriptionSize; 1524 ULONG StandardNameSize; 1525 ULONG DaylightNameSize; 1526 1527 Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY)); 1528 if (Entry == NULL) 1529 { 1530 return ERROR_NOT_ENOUGH_MEMORY; 1531 } 1532 1533 DescriptionSize = sizeof(Entry->Description); 1534 StandardNameSize = sizeof(Entry->StandardName); 1535 DaylightNameSize = sizeof(Entry->DaylightName); 1536 1537 lError = QueryTimeZoneData(hZoneKey, 1538 &Entry->Index, 1539 &Entry->TimezoneInfo, 1540 Entry->Description, 1541 &DescriptionSize, 1542 Entry->StandardName, 1543 &StandardNameSize, 1544 Entry->DaylightName, 1545 &DaylightNameSize); 1546 if (lError != ERROR_SUCCESS) 1547 { 1548 HeapFree(GetProcessHeap(), 0, Entry); 1549 return lError; 1550 } 1551 1552 if (SetupData->TimeZoneListHead == NULL && 1553 SetupData->TimeZoneListTail == NULL) 1554 { 1555 Entry->Prev = NULL; 1556 Entry->Next = NULL; 1557 SetupData->TimeZoneListHead = Entry; 1558 SetupData->TimeZoneListTail = Entry; 1559 } 1560 else 1561 { 1562 Current = GetLargerTimeZoneEntry(SetupData, Entry->Index); 1563 if (Current != NULL) 1564 { 1565 if (Current == SetupData->TimeZoneListHead) 1566 { 1567 /* Prepend to head */ 1568 Entry->Prev = NULL; 1569 Entry->Next = SetupData->TimeZoneListHead; 1570 SetupData->TimeZoneListHead->Prev = Entry; 1571 SetupData->TimeZoneListHead = Entry; 1572 } 1573 else 1574 { 1575 /* Insert before current */ 1576 Entry->Prev = Current->Prev; 1577 Entry->Next = Current; 1578 Current->Prev->Next = Entry; 1579 Current->Prev = Entry; 1580 } 1581 } 1582 else 1583 { 1584 /* Append to tail */ 1585 Entry->Prev = SetupData->TimeZoneListTail; 1586 Entry->Next = NULL; 1587 SetupData->TimeZoneListTail->Next = Entry; 1588 SetupData->TimeZoneListTail = Entry; 1589 } 1590 } 1591 1592 return ERROR_SUCCESS; 1593 } 1594 1595 static VOID 1596 CreateTimeZoneList(PSETUPDATA SetupData) 1597 { 1598 EnumerateTimeZoneList(RetrieveTimeZone, SetupData); 1599 } 1600 1601 static VOID 1602 DestroyTimeZoneList(PSETUPDATA SetupData) 1603 { 1604 PTIMEZONE_ENTRY Entry; 1605 1606 while (SetupData->TimeZoneListHead != NULL) 1607 { 1608 Entry = SetupData->TimeZoneListHead; 1609 1610 SetupData->TimeZoneListHead = Entry->Next; 1611 if (SetupData->TimeZoneListHead != NULL) 1612 { 1613 SetupData->TimeZoneListHead->Prev = NULL; 1614 } 1615 1616 HeapFree(GetProcessHeap(), 0, Entry); 1617 } 1618 1619 SetupData->TimeZoneListTail = NULL; 1620 } 1621 1622 1623 static VOID 1624 ShowTimeZoneList(HWND hwnd, PSETUPDATA SetupData, DWORD dwEntryIndex) 1625 { 1626 PTIMEZONE_ENTRY Entry; 1627 DWORD dwIndex = 0; 1628 DWORD dwCount; 1629 1630 GetTimeZoneListIndex(&dwEntryIndex); 1631 1632 Entry = SetupData->TimeZoneListHead; 1633 while (Entry != NULL) 1634 { 1635 dwCount = SendMessage(hwnd, 1636 CB_ADDSTRING, 1637 0, 1638 (LPARAM)Entry->Description); 1639 1640 if (dwEntryIndex != 0 && dwEntryIndex == Entry->Index) 1641 dwIndex = dwCount; 1642 1643 Entry = Entry->Next; 1644 } 1645 1646 SendMessage(hwnd, 1647 CB_SETCURSEL, 1648 (WPARAM)dwIndex, 1649 0); 1650 } 1651 1652 1653 static VOID 1654 SetLocalTimeZone(HWND hwnd, PSETUPDATA SetupData) 1655 { 1656 TIME_ZONE_INFORMATION TimeZoneInformation; 1657 PTIMEZONE_ENTRY Entry; 1658 DWORD dwIndex; 1659 DWORD i; 1660 1661 dwIndex = SendMessage(hwnd, 1662 CB_GETCURSEL, 1663 0, 1664 0); 1665 1666 i = 0; 1667 Entry = SetupData->TimeZoneListHead; 1668 while (i < dwIndex) 1669 { 1670 if (Entry == NULL) 1671 return; 1672 1673 i++; 1674 Entry = Entry->Next; 1675 } 1676 1677 wcscpy(TimeZoneInformation.StandardName, 1678 Entry->StandardName); 1679 wcscpy(TimeZoneInformation.DaylightName, 1680 Entry->DaylightName); 1681 1682 TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias; 1683 TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias; 1684 TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias; 1685 1686 memcpy(&TimeZoneInformation.StandardDate, 1687 &Entry->TimezoneInfo.StandardDate, 1688 sizeof(SYSTEMTIME)); 1689 memcpy(&TimeZoneInformation.DaylightDate, 1690 &Entry->TimezoneInfo.DaylightDate, 1691 sizeof(SYSTEMTIME)); 1692 1693 /* Set time zone information */ 1694 SetTimeZoneInformation(&TimeZoneInformation); 1695 } 1696 1697 1698 static BOOL 1699 GetLocalSystemTime(HWND hwnd, PSETUPDATA SetupData) 1700 { 1701 SYSTEMTIME Date; 1702 SYSTEMTIME Time; 1703 1704 if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), &Date) != GDT_VALID) 1705 { 1706 return FALSE; 1707 } 1708 1709 if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), &Time) != GDT_VALID) 1710 { 1711 return FALSE; 1712 } 1713 1714 SetupData->SystemTime.wYear = Date.wYear; 1715 SetupData->SystemTime.wMonth = Date.wMonth; 1716 SetupData->SystemTime.wDayOfWeek = Date.wDayOfWeek; 1717 SetupData->SystemTime.wDay = Date.wDay; 1718 SetupData->SystemTime.wHour = Time.wHour; 1719 SetupData->SystemTime.wMinute = Time.wMinute; 1720 SetupData->SystemTime.wSecond = Time.wSecond; 1721 SetupData->SystemTime.wMilliseconds = Time.wMilliseconds; 1722 1723 return TRUE; 1724 } 1725 1726 1727 static BOOL 1728 SetSystemLocalTime(HWND hwnd, PSETUPDATA SetupData) 1729 { 1730 BOOL Ret = FALSE; 1731 1732 /* 1733 * Call SetLocalTime twice to ensure correct results 1734 */ 1735 Ret = SetLocalTime(&SetupData->SystemTime) && 1736 SetLocalTime(&SetupData->SystemTime); 1737 1738 return Ret; 1739 } 1740 1741 1742 static VOID 1743 UpdateLocalSystemTime(HWND hwnd, SYSTEMTIME LocalTime) 1744 { 1745 DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), GDT_VALID, &LocalTime); 1746 DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), GDT_VALID, &LocalTime); 1747 } 1748 1749 1750 static BOOL 1751 WriteDateTimeSettings(HWND hwndDlg, PSETUPDATA SetupData) 1752 { 1753 WCHAR Title[64]; 1754 WCHAR ErrorLocalTime[256]; 1755 1756 GetLocalSystemTime(hwndDlg, SetupData); 1757 SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), 1758 SetupData); 1759 1760 SetAutoDaylight(SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, 1761 BM_GETCHECK, 0, 0) != BST_UNCHECKED); 1762 if (!SetSystemLocalTime(hwndDlg, SetupData)) 1763 { 1764 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 1765 { 1766 wcscpy(Title, L"ReactOS Setup"); 1767 } 1768 if (0 == LoadStringW(hDllInstance, IDS_WZD_LOCALTIME, ErrorLocalTime, 1769 ARRAYSIZE(ErrorLocalTime))) 1770 { 1771 wcscpy(ErrorLocalTime, L"Setup was unable to set the local time."); 1772 } 1773 MessageBoxW(hwndDlg, ErrorLocalTime, Title, MB_ICONWARNING | MB_OK); 1774 return FALSE; 1775 } 1776 1777 return TRUE; 1778 } 1779 1780 1781 static INT_PTR CALLBACK 1782 DateTimePageDlgProc(HWND hwndDlg, 1783 UINT uMsg, 1784 WPARAM wParam, 1785 LPARAM lParam) 1786 { 1787 PSETUPDATA SetupData; 1788 1789 /* Retrieve pointer to the global setup data */ 1790 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1791 1792 switch (uMsg) 1793 { 1794 case WM_INITDIALOG: 1795 { 1796 /* Save pointer to the global setup data */ 1797 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1798 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1799 1800 CreateTimeZoneList(SetupData); 1801 1802 if (SetupData->UnattendSetup) 1803 { 1804 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), 1805 SetupData, SetupData->TimeZoneIndex); 1806 1807 if (!SetupData->DisableAutoDaylightTimeSet) 1808 { 1809 SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 1810 } 1811 } 1812 else 1813 { 1814 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), 1815 SetupData, -1); 1816 1817 SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 1818 } 1819 break; 1820 } 1821 1822 case WM_TIMER: 1823 { 1824 SYSTEMTIME LocalTime; 1825 1826 GetLocalTime(&LocalTime); 1827 UpdateLocalSystemTime(hwndDlg, LocalTime); 1828 1829 // Reset timeout. 1830 SetTimer(hwndDlg, 1, 1000 - LocalTime.wMilliseconds, NULL); 1831 break; 1832 } 1833 1834 case WM_NOTIFY: 1835 switch (((LPNMHDR)lParam)->code) 1836 { 1837 case PSN_SETACTIVE: 1838 { 1839 SYSTEMTIME LocalTime; 1840 1841 GetLocalTime(&LocalTime); 1842 UpdateLocalSystemTime(hwndDlg, LocalTime); 1843 1844 /* Enable the Back and Next buttons */ 1845 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1846 1847 if (SetupData->UnattendSetup && WriteDateTimeSettings(hwndDlg, SetupData)) 1848 { 1849 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage); 1850 return TRUE; 1851 } 1852 1853 SetTimer(hwndDlg, 1, 1000 - LocalTime.wMilliseconds, NULL); 1854 break; 1855 } 1856 1857 case PSN_KILLACTIVE: 1858 case DTN_DATETIMECHANGE: 1859 // NB: Not re-set until changing page (PSN_SETACTIVE). 1860 KillTimer(hwndDlg, 1); 1861 break; 1862 1863 case PSN_WIZNEXT: 1864 WriteDateTimeSettings(hwndDlg, SetupData); 1865 break; 1866 1867 case PSN_WIZBACK: 1868 SetupData->UnattendSetup = FALSE; 1869 break; 1870 1871 default: 1872 break; 1873 } 1874 break; 1875 1876 case WM_DESTROY: 1877 DestroyTimeZoneList(SetupData); 1878 break; 1879 1880 default: 1881 break; 1882 } 1883 1884 return FALSE; 1885 } 1886 1887 static struct ThemeInfo 1888 { 1889 LPCWSTR PreviewBitmap; 1890 UINT DisplayName; 1891 LPCWSTR ThemeFile; 1892 1893 } Themes[] = { 1894 { MAKEINTRESOURCE(IDB_CLASSIC), IDS_CLASSIC, NULL }, 1895 { MAKEINTRESOURCE(IDB_LAUTUS), IDS_LAUTUS, L"themes\\lautus\\lautus.msstyles" }, 1896 { MAKEINTRESOURCE(IDB_LUNAR), IDS_LUNAR, L"themes\\lunar\\lunar.msstyles" }, 1897 { MAKEINTRESOURCE(IDB_MIZU), IDS_MIZU, L"themes\\mizu\\mizu.msstyles"}, 1898 }; 1899 1900 static INT_PTR CALLBACK 1901 ThemePageDlgProc(HWND hwndDlg, 1902 UINT uMsg, 1903 WPARAM wParam, 1904 LPARAM lParam) 1905 { 1906 PSETUPDATA SetupData; 1907 LPNMLISTVIEW pnmv; 1908 1909 /* Retrieve pointer to the global setup data */ 1910 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1911 1912 switch (uMsg) 1913 { 1914 case WM_INITDIALOG: 1915 { 1916 HWND hListView; 1917 HIMAGELIST himl; 1918 DWORD n; 1919 LVITEM lvi = {0}; 1920 1921 /* Save pointer to the global setup data */ 1922 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1923 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1924 1925 hListView = GetDlgItem(hwndDlg, IDC_THEMEPICKER); 1926 1927 /* Common */ 1928 himl = ImageList_Create(180, 163, ILC_COLOR32 | ILC_MASK, ARRAYSIZE(Themes), 1); 1929 lvi.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE; 1930 1931 for (n = 0; n < ARRAYSIZE(Themes); ++n) 1932 { 1933 WCHAR DisplayName[100] = {0}; 1934 /* Load the bitmap */ 1935 HANDLE image = LoadImageW(hDllInstance, Themes[n].PreviewBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 1936 ImageList_AddMasked(himl, image, RGB(255,0,255)); 1937 1938 /* Load the string */ 1939 LoadStringW(hDllInstance, Themes[n].DisplayName, DisplayName, ARRAYSIZE(DisplayName)); 1940 DisplayName[ARRAYSIZE(DisplayName)-1] = UNICODE_NULL; 1941 1942 /* Add the listview item */ 1943 lvi.iItem = n; 1944 lvi.iImage = n; 1945 lvi.pszText = DisplayName; 1946 ListView_InsertItem(hListView, &lvi); 1947 } 1948 1949 /* Register the imagelist */ 1950 ListView_SetImageList(hListView, himl, LVSIL_NORMAL); 1951 /* Transparant background */ 1952 ListView_SetBkColor(hListView, CLR_NONE); 1953 ListView_SetTextBkColor(hListView, CLR_NONE); 1954 /* Reduce the size between the items */ 1955 ListView_SetIconSpacing(hListView, 190, 173); 1956 break; 1957 } 1958 case WM_NOTIFY: 1959 switch (((LPNMHDR)lParam)->code) 1960 { 1961 //case LVN_ITEMCHANGING: 1962 case LVN_ITEMCHANGED: 1963 pnmv = (LPNMLISTVIEW)lParam; 1964 if ((pnmv->uChanged & LVIF_STATE) && (pnmv->uNewState & LVIS_SELECTED)) 1965 { 1966 int iTheme = pnmv->iItem; 1967 DPRINT1("Selected theme: %u\n", Themes[iTheme].DisplayName); 1968 1969 if (Themes[iTheme].ThemeFile) 1970 { 1971 WCHAR wszParams[1024]; 1972 WCHAR wszTheme[MAX_PATH]; 1973 WCHAR* format = L"desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:\"%s\""; 1974 1975 SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme); 1976 swprintf(wszParams, format, wszTheme); 1977 RunControlPanelApplet(hwndDlg, wszParams); 1978 } 1979 else 1980 { 1981 RunControlPanelApplet(hwndDlg, L"desk.cpl desk,@Appearance /Action:ActivateMSTheme"); 1982 } 1983 } 1984 break; 1985 case PSN_SETACTIVE: 1986 /* Enable the Back and Next buttons */ 1987 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1988 if (SetupData->UnattendSetup) 1989 { 1990 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage); 1991 return TRUE; 1992 } 1993 break; 1994 1995 case PSN_WIZNEXT: 1996 break; 1997 1998 case PSN_WIZBACK: 1999 SetupData->UnattendSetup = FALSE; 2000 break; 2001 2002 default: 2003 break; 2004 } 2005 break; 2006 2007 default: 2008 break; 2009 } 2010 2011 return FALSE; 2012 } 2013 2014 static UINT CALLBACK 2015 RegistrationNotificationProc(PVOID Context, 2016 UINT Notification, 2017 UINT_PTR Param1, 2018 UINT_PTR Param2) 2019 { 2020 PREGISTRATIONDATA RegistrationData; 2021 REGISTRATIONNOTIFY RegistrationNotify; 2022 PSP_REGISTER_CONTROL_STATUSW StatusInfo; 2023 UINT MessageID; 2024 2025 RegistrationData = (PREGISTRATIONDATA)Context; 2026 2027 if (Notification == SPFILENOTIFY_STARTREGISTRATION || 2028 Notification == SPFILENOTIFY_ENDREGISTRATION) 2029 { 2030 StatusInfo = (PSP_REGISTER_CONTROL_STATUSW) Param1; 2031 RegistrationNotify.CurrentItem = wcsrchr(StatusInfo->FileName, L'\\'); 2032 if (RegistrationNotify.CurrentItem == NULL) 2033 { 2034 RegistrationNotify.CurrentItem = StatusInfo->FileName; 2035 } 2036 else 2037 { 2038 RegistrationNotify.CurrentItem++; 2039 } 2040 2041 if (Notification == SPFILENOTIFY_STARTREGISTRATION) 2042 { 2043 DPRINT("Received SPFILENOTIFY_STARTREGISTRATION notification for %S\n", 2044 StatusInfo->FileName); 2045 RegistrationNotify.ErrorMessage = NULL; 2046 RegistrationNotify.Progress = RegistrationData->Registered; 2047 SendMessage(RegistrationData->hwndDlg, PM_STEP_START, 0, (LPARAM)&RegistrationNotify); 2048 } 2049 else 2050 { 2051 DPRINT("Received SPFILENOTIFY_ENDREGISTRATION notification for %S\n", 2052 StatusInfo->FileName); 2053 DPRINT("Win32Error %u FailureCode %u\n", StatusInfo->Win32Error, 2054 StatusInfo->FailureCode); 2055 if (StatusInfo->FailureCode != SPREG_SUCCESS) 2056 { 2057 switch (StatusInfo->FailureCode) 2058 { 2059 case SPREG_LOADLIBRARY: 2060 MessageID = IDS_LOADLIBRARY_FAILED; 2061 break; 2062 case SPREG_GETPROCADDR: 2063 MessageID = IDS_GETPROCADDR_FAILED; 2064 break; 2065 case SPREG_REGSVR: 2066 MessageID = IDS_REGSVR_FAILED; 2067 break; 2068 case SPREG_DLLINSTALL: 2069 MessageID = IDS_DLLINSTALL_FAILED; 2070 break; 2071 case SPREG_TIMEOUT: 2072 MessageID = IDS_TIMEOUT; 2073 break; 2074 default: 2075 MessageID = IDS_REASON_UNKNOWN; 2076 break; 2077 } 2078 2079 RegistrationNotify.MessageID = MessageID; 2080 RegistrationNotify.LastError = StatusInfo->Win32Error; 2081 } 2082 else 2083 { 2084 RegistrationNotify.MessageID = 0; 2085 RegistrationNotify.LastError = ERROR_SUCCESS; 2086 } 2087 2088 if (RegistrationData->Registered < RegistrationData->DllCount) 2089 { 2090 RegistrationData->Registered++; 2091 } 2092 2093 RegistrationNotify.Progress = RegistrationData->Registered; 2094 SendMessage(RegistrationData->hwndDlg, PM_STEP_END, 0, (LPARAM)&RegistrationNotify); 2095 } 2096 2097 return FILEOP_DOIT; 2098 } 2099 else 2100 { 2101 DPRINT1("Received unexpected notification %u\n", Notification); 2102 return SetupDefaultQueueCallback(RegistrationData->DefaultContext, 2103 Notification, Param1, Param2); 2104 } 2105 } 2106 2107 2108 static 2109 DWORD 2110 RegisterDlls( 2111 PITEMSDATA pItemsData) 2112 { 2113 REGISTRATIONDATA RegistrationData; 2114 WCHAR SectionName[512]; 2115 INFCONTEXT Context; 2116 LONG DllCount = 0; 2117 DWORD LastError = NO_ERROR; 2118 2119 ZeroMemory(&RegistrationData, sizeof(REGISTRATIONDATA)); 2120 RegistrationData.hwndDlg = pItemsData->hwndDlg; 2121 RegistrationData.Registered = 0; 2122 2123 if (!SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2", 2124 L"RegisterDlls", &Context)) 2125 { 2126 DPRINT1("No RegistrationPhase2 section found\n"); 2127 return FALSE; 2128 } 2129 2130 if (!SetupGetStringFieldW(&Context, 1, SectionName, 2131 ARRAYSIZE(SectionName), 2132 NULL)) 2133 { 2134 DPRINT1("Unable to retrieve section name\n"); 2135 return FALSE; 2136 } 2137 2138 DllCount = SetupGetLineCountW(hSysSetupInf, SectionName); 2139 DPRINT1("SectionName %S DllCount %ld\n", SectionName, DllCount); 2140 if (DllCount < 0) 2141 { 2142 SetLastError(STATUS_NOT_FOUND); 2143 return FALSE; 2144 } 2145 2146 RegistrationData.DllCount = (ULONG)DllCount; 2147 RegistrationData.DefaultContext = SetupInitDefaultQueueCallback(RegistrationData.hwndDlg); 2148 2149 SendMessage(pItemsData->hwndDlg, PM_ITEM_START, 0, (LPARAM)RegistrationData.DllCount); 2150 2151 _SEH2_TRY 2152 { 2153 if (!SetupInstallFromInfSectionW(GetParent(RegistrationData.hwndDlg), 2154 hSysSetupInf, 2155 L"RegistrationPhase2", 2156 SPINST_REGISTRY | SPINST_REGISTERCALLBACKAWARE | SPINST_REGSVR, 2157 0, 2158 NULL, 2159 0, 2160 RegistrationNotificationProc, 2161 &RegistrationData, 2162 NULL, 2163 NULL)) 2164 { 2165 LastError = GetLastError(); 2166 } 2167 } 2168 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2169 { 2170 DPRINT("Catching exception\n"); 2171 LastError = RtlNtStatusToDosError(_SEH2_GetExceptionCode()); 2172 } 2173 _SEH2_END; 2174 2175 SetupTermDefaultQueueCallback(RegistrationData.DefaultContext); 2176 2177 SendMessage(pItemsData->hwndDlg, PM_ITEM_END, 0, LastError); 2178 2179 return 0; 2180 } 2181 2182 2183 static 2184 DWORD 2185 CALLBACK 2186 ItemCompletionThread( 2187 LPVOID Parameter) 2188 { 2189 PITEMSDATA pItemsData; 2190 HWND hwndDlg; 2191 2192 pItemsData = (PITEMSDATA)Parameter; 2193 hwndDlg = pItemsData->hwndDlg; 2194 2195 RegisterDlls(pItemsData); 2196 2197 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries"); 2198 2199 /* FIXME: Add completion steps here! */ 2200 2201 // FIXME: Move this call to a separate cleanup page! 2202 RtlCreateBootStatusDataFile(); 2203 2204 /* Free the items data */ 2205 HeapFree(GetProcessHeap(), 0, pItemsData); 2206 2207 /* Tell the wizard page that we are done */ 2208 PostMessage(hwndDlg, PM_ITEMS_DONE, 0, 0); 2209 2210 return 0; 2211 } 2212 2213 2214 static 2215 BOOL 2216 RunItemCompletionThread( 2217 _In_ HWND hwndDlg) 2218 { 2219 HANDLE hCompletionThread; 2220 PITEMSDATA pItemsData; 2221 2222 pItemsData = HeapAlloc(GetProcessHeap(), 0, sizeof(ITEMSDATA)); 2223 if (pItemsData == NULL) 2224 return FALSE; 2225 2226 pItemsData->hwndDlg = hwndDlg; 2227 2228 hCompletionThread = CreateThread(NULL, 2229 0, 2230 ItemCompletionThread, 2231 pItemsData, 2232 0, 2233 NULL); 2234 if (hCompletionThread == NULL) 2235 { 2236 HeapFree(GetProcessHeap(), 0, pItemsData); 2237 } 2238 else 2239 { 2240 CloseHandle(hCompletionThread); 2241 return TRUE; 2242 } 2243 2244 return FALSE; 2245 } 2246 2247 static 2248 VOID 2249 ShowItemError( 2250 HWND hwndDlg, 2251 DWORD LastError) 2252 { 2253 LPWSTR ErrorMessage = NULL; 2254 WCHAR UnknownError[84]; 2255 WCHAR Title[64]; 2256 2257 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 2258 NULL, LastError, 0, ErrorMessage, 0, NULL) == 0) 2259 { 2260 if (LoadStringW(hDllInstance, IDS_UNKNOWN_ERROR, 2261 UnknownError, 2262 ARRAYSIZE(UnknownError) - 20) == 0) 2263 { 2264 wcscpy(UnknownError, L"Unknown error"); 2265 } 2266 wcscat(UnknownError, L" "); 2267 _ultow(LastError, UnknownError + wcslen(UnknownError), 10); 2268 ErrorMessage = UnknownError; 2269 } 2270 2271 if (ErrorMessage != NULL) 2272 { 2273 if (LoadStringW(hDllInstance, IDS_REACTOS_SETUP, 2274 Title, ARRAYSIZE(Title)) == 0) 2275 { 2276 wcscpy(Title, L"ReactOS Setup"); 2277 } 2278 2279 MessageBoxW(hwndDlg, ErrorMessage, Title, MB_ICONERROR | MB_OK); 2280 } 2281 2282 if (ErrorMessage != NULL && 2283 ErrorMessage != UnknownError) 2284 { 2285 LocalFree(ErrorMessage); 2286 } 2287 } 2288 2289 2290 static 2291 VOID 2292 ShowStepError( 2293 HWND hwndDlg, 2294 PREGISTRATIONNOTIFY RegistrationNotify) 2295 { 2296 WCHAR ErrorMessage[128]; 2297 WCHAR Title[64]; 2298 2299 if (LoadStringW(hDllInstance, RegistrationNotify->MessageID, 2300 ErrorMessage, 2301 ARRAYSIZE(ErrorMessage)) == 0) 2302 { 2303 ErrorMessage[0] = L'\0'; 2304 } 2305 2306 if (RegistrationNotify->MessageID != IDS_TIMEOUT) 2307 { 2308 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 2309 RegistrationNotify->LastError, 0, 2310 ErrorMessage + wcslen(ErrorMessage), 2311 ARRAYSIZE(ErrorMessage) - wcslen(ErrorMessage), 2312 NULL); 2313 } 2314 2315 if (ErrorMessage[0] != L'\0') 2316 { 2317 if (LoadStringW(hDllInstance, IDS_REACTOS_SETUP, 2318 Title, ARRAYSIZE(Title)) == 0) 2319 { 2320 wcscpy(Title, L"ReactOS Setup"); 2321 } 2322 2323 MessageBoxW(hwndDlg, ErrorMessage, 2324 Title, MB_ICONERROR | MB_OK); 2325 } 2326 } 2327 2328 2329 static INT_PTR CALLBACK 2330 ProcessPageDlgProc(HWND hwndDlg, 2331 UINT uMsg, 2332 WPARAM wParam, 2333 LPARAM lParam) 2334 { 2335 PSETUPDATA SetupData; 2336 PREGISTRATIONNOTIFY RegistrationNotify; 2337 2338 /* Retrieve pointer to the global setup data */ 2339 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 2340 2341 switch (uMsg) 2342 { 2343 case WM_INITDIALOG: 2344 /* Save pointer to the global setup data */ 2345 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 2346 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 2347 ShowWindow(GetDlgItem(hwndDlg, IDC_TASKTEXT2), SW_HIDE); 2348 ShowWindow(GetDlgItem(hwndDlg, IDC_TASKTEXT3), SW_HIDE); 2349 ShowWindow(GetDlgItem(hwndDlg, IDC_TASKTEXT4), SW_HIDE); 2350 break; 2351 2352 case WM_NOTIFY: 2353 switch (((LPNMHDR)lParam)->code) 2354 { 2355 case PSN_SETACTIVE: 2356 /* Disable the Back and Next buttons */ 2357 PropSheet_SetWizButtons(GetParent(hwndDlg), 0); 2358 RunItemCompletionThread(hwndDlg); 2359 break; 2360 2361 case PSN_WIZNEXT: 2362 break; 2363 2364 case PSN_WIZBACK: 2365 SetupData->UnattendSetup = FALSE; 2366 break; 2367 2368 default: 2369 break; 2370 } 2371 break; 2372 2373 case PM_ITEM_START: 2374 DPRINT("PM_ITEM_START %lu\n", (ULONG)lParam); 2375 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, (ULONG)lParam)); 2376 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS, 0, 0); 2377 SendDlgItemMessage(hwndDlg, IDC_TASKTEXT1 + wParam, WM_SETFONT, (WPARAM)SetupData->hBoldFont, (LPARAM)TRUE); 2378 break; 2379 2380 case PM_ITEM_END: 2381 DPRINT("PM_ITEM_END\n"); 2382 if (lParam == ERROR_SUCCESS) 2383 { 2384 } 2385 else 2386 { 2387 ShowItemError(hwndDlg, (DWORD)lParam); 2388 } 2389 break; 2390 2391 case PM_STEP_START: 2392 DPRINT("PM_STEP_START\n"); 2393 RegistrationNotify = (PREGISTRATIONNOTIFY)lParam; 2394 SendDlgItemMessage(hwndDlg, IDC_ITEM, WM_SETTEXT, 0, 2395 (LPARAM)((RegistrationNotify->CurrentItem != NULL)? RegistrationNotify->CurrentItem : L"")); 2396 break; 2397 2398 case PM_STEP_END: 2399 DPRINT("PM_STEP_END\n"); 2400 RegistrationNotify = (PREGISTRATIONNOTIFY)lParam; 2401 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS, RegistrationNotify->Progress, 0); 2402 if (RegistrationNotify->LastError != ERROR_SUCCESS) 2403 { 2404 ShowStepError(hwndDlg, RegistrationNotify); 2405 } 2406 break; 2407 2408 case PM_ITEMS_DONE: 2409 DPRINT("PM_ITEMS_DONE\n"); 2410 /* Enable the Back and Next buttons */ 2411 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 2412 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_NEXT); 2413 break; 2414 2415 default: 2416 break; 2417 } 2418 2419 return FALSE; 2420 } 2421 2422 2423 static VOID 2424 SetInstallationCompleted(VOID) 2425 { 2426 HKEY hKey = 0; 2427 DWORD InProgress = 0; 2428 DWORD InstallDate; 2429 2430 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, 2431 L"SYSTEM\\Setup", 2432 0, 2433 KEY_WRITE, 2434 &hKey ) == ERROR_SUCCESS) 2435 { 2436 RegSetValueExW( hKey, L"SystemSetupInProgress", 0, REG_DWORD, (LPBYTE)&InProgress, sizeof(InProgress) ); 2437 RegCloseKey( hKey ); 2438 } 2439 2440 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, 2441 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 2442 0, 2443 KEY_WRITE, 2444 &hKey ) == ERROR_SUCCESS) 2445 { 2446 InstallDate = (DWORD)time(NULL); 2447 RegSetValueExW( hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate) ); 2448 RegCloseKey( hKey ); 2449 } 2450 } 2451 2452 static INT_PTR CALLBACK 2453 FinishDlgProc(HWND hwndDlg, 2454 UINT uMsg, 2455 WPARAM wParam, 2456 LPARAM lParam) 2457 { 2458 2459 switch (uMsg) 2460 { 2461 case WM_INITDIALOG: 2462 { 2463 /* Get pointer to the global setup data */ 2464 PSETUPDATA SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 2465 2466 if (!SetupData->UnattendSetup || !SetupData->DisableGeckoInst) 2467 { 2468 /* Run the Wine Gecko prompt */ 2469 Control_RunDLLW(hwndDlg, 0, L"appwiz.cpl install_gecko", SW_SHOW); 2470 } 2471 2472 /* Set title font */ 2473 SendDlgItemMessage(hwndDlg, 2474 IDC_FINISHTITLE, 2475 WM_SETFONT, 2476 (WPARAM)SetupData->hTitleFont, 2477 (LPARAM)TRUE); 2478 if (SetupData->UnattendSetup) 2479 { 2480 KillTimer(hwndDlg, 1); 2481 SetInstallationCompleted(); 2482 PostQuitMessage(0); 2483 } 2484 } 2485 break; 2486 2487 case WM_DESTROY: 2488 { 2489 SetInstallationCompleted(); 2490 PostQuitMessage(0); 2491 return TRUE; 2492 } 2493 2494 case WM_TIMER: 2495 { 2496 INT Position; 2497 HWND hWndProgress; 2498 2499 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS); 2500 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0); 2501 if (Position == 300) 2502 { 2503 KillTimer(hwndDlg, 1); 2504 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH); 2505 } 2506 else 2507 { 2508 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0); 2509 } 2510 } 2511 return TRUE; 2512 2513 case WM_NOTIFY: 2514 { 2515 LPNMHDR lpnm = (LPNMHDR)lParam; 2516 2517 switch (lpnm->code) 2518 { 2519 case PSN_SETACTIVE: 2520 /* Enable the correct buttons on for the active page */ 2521 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); 2522 2523 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, 2524 MAKELPARAM(0, 300)); 2525 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0); 2526 SetTimer(hwndDlg, 1, 50, NULL); 2527 break; 2528 2529 case PSN_WIZFINISH: 2530 DestroyWindow(GetParent(hwndDlg)); 2531 break; 2532 2533 default: 2534 break; 2535 } 2536 } 2537 break; 2538 2539 default: 2540 break; 2541 } 2542 2543 return FALSE; 2544 } 2545 2546 2547 /* 2548 * GetInstallSourceWin32 retrieves the path to the ReactOS installation medium 2549 * in Win32 format, for later use by syssetup and storage in the registry. 2550 */ 2551 static BOOL 2552 GetInstallSourceWin32( 2553 OUT PWSTR pwszPath, 2554 IN DWORD cchPathMax, 2555 IN PCWSTR pwszNTPath) 2556 { 2557 WCHAR wszDrives[512]; 2558 WCHAR wszNTPath[512]; // MAX_PATH ? 2559 DWORD cchDrives; 2560 PWCHAR pwszDrive; 2561 2562 *pwszPath = UNICODE_NULL; 2563 2564 cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives); 2565 if (cchDrives == 0 || cchDrives >= _countof(wszDrives)) 2566 { 2567 /* Buffer too small or failure */ 2568 LogItem(NULL, L"GetLogicalDriveStringsW failed"); 2569 return FALSE; 2570 } 2571 2572 for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1) 2573 { 2574 WCHAR wszBuf[MAX_PATH]; 2575 2576 /* Retrieve the NT path corresponding to the current Win32 DOS path */ 2577 pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash 2578 QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath)); 2579 pwszDrive[2] = L'\\'; // Restore the backslash 2580 2581 wcscat(wszNTPath, L"\\"); // Concat a backslash 2582 2583 /* Logging */ 2584 wsprintf(wszBuf, L"Testing '%s' --> '%s' %s a CD", 2585 pwszDrive, wszNTPath, 2586 (GetDriveTypeW(pwszDrive) == DRIVE_CDROM) ? L"is" : L"is not"); 2587 LogItem(NULL, wszBuf); 2588 2589 /* Check whether the NT path corresponds to the NT installation source path */ 2590 if (!_wcsicmp(wszNTPath, pwszNTPath)) 2591 { 2592 /* Found it! */ 2593 wcscpy(pwszPath, pwszDrive); // cchPathMax 2594 2595 /* Logging */ 2596 wsprintf(wszBuf, L"GetInstallSourceWin32: %s", pwszPath); 2597 LogItem(NULL, wszBuf); 2598 wcscat(wszBuf, L"\n"); 2599 OutputDebugStringW(wszBuf); 2600 2601 return TRUE; 2602 } 2603 } 2604 2605 return FALSE; 2606 } 2607 2608 VOID 2609 ProcessUnattendSection( 2610 IN OUT PSETUPDATA pSetupData) 2611 { 2612 INFCONTEXT InfContext; 2613 WCHAR szName[256]; 2614 WCHAR szValue[MAX_PATH]; 2615 DWORD LineLength; 2616 HKEY hKey; 2617 2618 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2619 L"Unattend", 2620 L"UnattendSetupEnabled", 2621 &InfContext)) 2622 { 2623 DPRINT1("Error: Cannot find UnattendSetupEnabled Key! %d\n", GetLastError()); 2624 return; 2625 } 2626 2627 if (!SetupGetStringFieldW(&InfContext, 2628 1, 2629 szValue, 2630 ARRAYSIZE(szValue), 2631 &LineLength)) 2632 { 2633 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2634 return; 2635 } 2636 2637 if (_wcsicmp(szValue, L"yes") != 0) 2638 { 2639 DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n"); 2640 return; 2641 } 2642 2643 pSetupData->UnattendSetup = TRUE; 2644 2645 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2646 L"Unattend", 2647 NULL, 2648 &InfContext)) 2649 { 2650 DPRINT1("Error: SetupFindFirstLine failed %d\n", GetLastError()); 2651 return; 2652 } 2653 2654 do 2655 { 2656 if (!SetupGetStringFieldW(&InfContext, 2657 0, 2658 szName, 2659 ARRAYSIZE(szName), 2660 &LineLength)) 2661 { 2662 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2663 return; 2664 } 2665 2666 if (!SetupGetStringFieldW(&InfContext, 2667 1, 2668 szValue, 2669 ARRAYSIZE(szValue), 2670 &LineLength)) 2671 { 2672 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2673 return; 2674 } 2675 DPRINT1("Name %S Value %S\n", szName, szValue); 2676 if (!_wcsicmp(szName, L"FullName")) 2677 { 2678 if (ARRAYSIZE(pSetupData->OwnerName) > LineLength) 2679 { 2680 wcscpy(pSetupData->OwnerName, szValue); 2681 } 2682 } 2683 else if (!_wcsicmp(szName, L"OrgName")) 2684 { 2685 if (ARRAYSIZE(pSetupData->OwnerOrganization) > LineLength) 2686 { 2687 wcscpy(pSetupData->OwnerOrganization, szValue); 2688 } 2689 } 2690 else if (!_wcsicmp(szName, L"ComputerName")) 2691 { 2692 if (ARRAYSIZE(pSetupData->ComputerName) > LineLength) 2693 { 2694 wcscpy(pSetupData->ComputerName, szValue); 2695 } 2696 } 2697 else if (!_wcsicmp(szName, L"AdminPassword")) 2698 { 2699 if (ARRAYSIZE(pSetupData->AdminPassword) > LineLength) 2700 { 2701 wcscpy(pSetupData->AdminPassword, szValue); 2702 } 2703 } 2704 else if (!_wcsicmp(szName, L"TimeZoneIndex")) 2705 { 2706 pSetupData->TimeZoneIndex = _wtoi(szValue); 2707 } 2708 else if (!_wcsicmp(szName, L"DisableAutoDaylightTimeSet")) 2709 { 2710 pSetupData->DisableAutoDaylightTimeSet = _wtoi(szValue); 2711 } 2712 else if (!_wcsicmp(szName, L"DisableGeckoInst")) 2713 { 2714 if (!_wcsicmp(szValue, L"yes")) 2715 pSetupData->DisableGeckoInst = TRUE; 2716 else 2717 pSetupData->DisableGeckoInst = FALSE; 2718 } 2719 else if (!_wcsicmp(szName, L"ProductOption")) 2720 { 2721 pSetupData->ProductOption = (PRODUCT_OPTION)_wtoi(szValue); 2722 } 2723 } while (SetupFindNextLine(&InfContext, &InfContext)); 2724 2725 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2726 L"Display", 2727 NULL, 2728 &InfContext)) 2729 { 2730 DEVMODEW dm = { { 0 } }; 2731 dm.dmSize = sizeof(dm); 2732 if (EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dm)) 2733 { 2734 do 2735 { 2736 int iValue; 2737 if (!SetupGetStringFieldW(&InfContext, 2738 0, 2739 szName, 2740 ARRAYSIZE(szName), 2741 &LineLength)) 2742 { 2743 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2744 return; 2745 } 2746 2747 if (!SetupGetStringFieldW(&InfContext, 2748 1, 2749 szValue, 2750 ARRAYSIZE(szValue), 2751 &LineLength)) 2752 { 2753 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2754 return; 2755 } 2756 iValue = _wtoi(szValue); 2757 DPRINT1("Name %S Value %i\n", szName, iValue); 2758 2759 if (!iValue) 2760 continue; 2761 2762 if (!_wcsicmp(szName, L"BitsPerPel")) 2763 { 2764 dm.dmFields |= DM_BITSPERPEL; 2765 dm.dmBitsPerPel = iValue; 2766 } 2767 else if (!_wcsicmp(szName, L"XResolution")) 2768 { 2769 dm.dmFields |= DM_PELSWIDTH; 2770 dm.dmPelsWidth = iValue; 2771 } 2772 else if (!_wcsicmp(szName, L"YResolution")) 2773 { 2774 dm.dmFields |= DM_PELSHEIGHT; 2775 dm.dmPelsHeight = iValue; 2776 } 2777 else if (!_wcsicmp(szName, L"VRefresh")) 2778 { 2779 dm.dmFields |= DM_DISPLAYFREQUENCY; 2780 dm.dmDisplayFrequency = iValue; 2781 } 2782 } while (SetupFindNextLine(&InfContext, &InfContext)); 2783 2784 ChangeDisplaySettingsW(&dm, CDS_UPDATEREGISTRY); 2785 } 2786 } 2787 2788 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2789 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", 2790 0, 2791 KEY_SET_VALUE, 2792 &hKey) != ERROR_SUCCESS) 2793 { 2794 DPRINT1("Error: failed to open HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n"); 2795 return; 2796 } 2797 2798 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2799 L"GuiRunOnce", 2800 NULL, 2801 &InfContext)) 2802 { 2803 int i = 0; 2804 do 2805 { 2806 if (SetupGetStringFieldW(&InfContext, 2807 0, 2808 szValue, 2809 ARRAYSIZE(szValue), 2810 NULL)) 2811 { 2812 WCHAR szPath[MAX_PATH]; 2813 swprintf(szName, L"%d", i); 2814 DPRINT("szName %S szValue %S\n", szName, szValue); 2815 2816 if (ExpandEnvironmentStringsW(szValue, szPath, MAX_PATH)) 2817 { 2818 DPRINT("value %S\n", szPath); 2819 if (RegSetValueExW(hKey, 2820 szName, 2821 0, 2822 REG_SZ, 2823 (const BYTE*)szPath, 2824 (wcslen(szPath) + 1) * sizeof(WCHAR)) == ERROR_SUCCESS) 2825 { 2826 i++; 2827 } 2828 } 2829 } 2830 } while (SetupFindNextLine(&InfContext, &InfContext)); 2831 } 2832 2833 RegCloseKey(hKey); 2834 2835 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2836 L"Env", 2837 NULL, 2838 &InfContext)) 2839 { 2840 if (RegCreateKeyExW( 2841 HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, NULL, 2842 REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &hKey, NULL) != ERROR_SUCCESS) 2843 { 2844 DPRINT1("Error: failed to open HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\n"); 2845 return; 2846 } 2847 do 2848 { 2849 if (!SetupGetStringFieldW(&InfContext, 2850 0, 2851 szName, 2852 ARRAYSIZE(szName), 2853 &LineLength)) 2854 { 2855 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2856 return; 2857 } 2858 2859 if (!SetupGetStringFieldW(&InfContext, 2860 1, 2861 szValue, 2862 ARRAYSIZE(szValue), 2863 &LineLength)) 2864 { 2865 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2866 return; 2867 } 2868 DPRINT1("[ENV] %S=%S\n", szName, szValue); 2869 2870 DWORD dwType = wcschr(szValue, '%') != NULL ? REG_EXPAND_SZ : REG_SZ; 2871 2872 if (RegSetValueExW(hKey, szName, 0, dwType, (const BYTE*)szValue, (DWORD)(wcslen(szValue) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS) 2873 { 2874 DPRINT1(" - Error %d\n", GetLastError()); 2875 } 2876 2877 } while (SetupFindNextLine(&InfContext, &InfContext)); 2878 2879 RegCloseKey(hKey); 2880 } 2881 } 2882 2883 VOID 2884 ProcessSetupInf( 2885 IN OUT PSETUPDATA pSetupData) 2886 { 2887 WCHAR szPath[MAX_PATH]; 2888 WCHAR szValue[MAX_PATH]; 2889 INFCONTEXT InfContext; 2890 DWORD LineLength; 2891 HKEY hKey; 2892 LONG res; 2893 2894 pSetupData->hSetupInf = INVALID_HANDLE_VALUE; 2895 2896 /* Retrieve the path of the setup INF */ 2897 GetSystemDirectoryW(szPath, _countof(szPath)); 2898 wcscat(szPath, L"\\$winnt$.inf"); 2899 2900 /* Open the setup INF */ 2901 pSetupData->hSetupInf = SetupOpenInfFileW(szPath, 2902 NULL, 2903 INF_STYLE_OLDNT, 2904 NULL); 2905 if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE) 2906 { 2907 DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError()); 2908 return; 2909 } 2910 2911 2912 /* Retrieve the NT source path from which the 1st-stage installer was run */ 2913 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2914 L"data", 2915 L"sourcepath", 2916 &InfContext)) 2917 { 2918 DPRINT1("Error: Cannot find sourcepath Key! %d\n", GetLastError()); 2919 return; 2920 } 2921 2922 if (!SetupGetStringFieldW(&InfContext, 2923 1, 2924 szValue, 2925 ARRAYSIZE(szValue), 2926 &LineLength)) 2927 { 2928 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2929 return; 2930 } 2931 2932 *pSetupData->SourcePath = UNICODE_NULL; 2933 2934 /* Close the setup INF as we are going to modify it manually */ 2935 if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE) 2936 SetupCloseInfFile(pSetupData->hSetupInf); 2937 2938 2939 /* Find the installation source path in Win32 format */ 2940 if (!GetInstallSourceWin32(pSetupData->SourcePath, 2941 _countof(pSetupData->SourcePath), 2942 szValue)) 2943 { 2944 *pSetupData->SourcePath = UNICODE_NULL; 2945 } 2946 2947 /* Save the path in Win32 format in the setup INF */ 2948 swprintf(szValue, L"\"%s\"", pSetupData->SourcePath); 2949 WritePrivateProfileStringW(L"data", L"dospath", szValue, szPath); 2950 2951 /* 2952 * Save it also in the registry, in the following keys: 2953 * - HKLM\Software\Microsoft\Windows\CurrentVersion\Setup , 2954 * values "SourcePath" and "ServicePackSourcePath" (REG_SZ); 2955 * - HKLM\Software\Microsoft\Windows NT\CurrentVersion , 2956 * value "SourcePath" (REG_SZ); set to the full path (e.g. D:\I386). 2957 */ 2958 #if 0 2959 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2960 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 2961 0, 2962 KEY_ALL_ACCESS, 2963 &hKey); 2964 2965 if (res != ERROR_SUCCESS) 2966 { 2967 return FALSE; 2968 } 2969 #endif 2970 2971 res = RegCreateKeyExW(HKEY_LOCAL_MACHINE, 2972 L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup", 2973 0, NULL, 2974 REG_OPTION_NON_VOLATILE, 2975 KEY_ALL_ACCESS, // KEY_WRITE 2976 NULL, 2977 &hKey, 2978 NULL); 2979 if (res == ERROR_SUCCESS) 2980 { 2981 res = RegSetValueExW(hKey, 2982 L"SourcePath", 2983 0, 2984 REG_SZ, 2985 (LPBYTE)pSetupData->SourcePath, 2986 (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR)); 2987 2988 res = RegSetValueExW(hKey, 2989 L"ServicePackSourcePath", 2990 0, 2991 REG_SZ, 2992 (LPBYTE)pSetupData->SourcePath, 2993 (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR)); 2994 2995 RegCloseKey(hKey); 2996 } 2997 2998 2999 /* Now, re-open the setup INF (this must succeed) */ 3000 pSetupData->hSetupInf = SetupOpenInfFileW(szPath, 3001 NULL, 3002 INF_STYLE_OLDNT, 3003 NULL); 3004 if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE) 3005 { 3006 DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError()); 3007 return; 3008 } 3009 3010 /* Process the unattended section of the setup file */ 3011 ProcessUnattendSection(pSetupData); 3012 } 3013 3014 typedef DWORD(WINAPI *PFNREQUESTWIZARDPAGES)(PDWORD, HPROPSHEETPAGE *, PSETUPDATA); 3015 3016 VOID 3017 InstallWizard(VOID) 3018 { 3019 PROPSHEETHEADER psh = {0}; 3020 HPROPSHEETPAGE *phpage = NULL; 3021 PROPSHEETPAGE psp = {0}; 3022 UINT nPages = 0; 3023 HWND hWnd; 3024 MSG msg; 3025 PSETUPDATA pSetupData = NULL; 3026 HMODULE hNetShell = NULL; 3027 PFNREQUESTWIZARDPAGES pfn = NULL; 3028 DWORD dwPageCount = 10, dwNetworkPageCount = 0; 3029 3030 LogItem(L"BEGIN_SECTION", L"InstallWizard"); 3031 3032 /* Allocate setup data */ 3033 pSetupData = HeapAlloc(GetProcessHeap(), 3034 HEAP_ZERO_MEMORY, 3035 sizeof(SETUPDATA)); 3036 if (pSetupData == NULL) 3037 { 3038 LogItem(NULL, L"SetupData allocation failed!"); 3039 MessageBoxW(NULL, 3040 L"Setup failed to allocate global data!", 3041 L"ReactOS Setup", 3042 MB_ICONERROR | MB_OK); 3043 goto done; 3044 } 3045 pSetupData->ProductOption = PRODUCT_OPTION_DEFAULT; 3046 3047 hNetShell = LoadLibraryW(L"netshell.dll"); 3048 if (hNetShell != NULL) 3049 { 3050 DPRINT("Netshell.dll loaded!\n"); 3051 3052 pfn = (PFNREQUESTWIZARDPAGES)GetProcAddress(hNetShell, 3053 "NetSetupRequestWizardPages"); 3054 if (pfn != NULL) 3055 { 3056 pfn(&dwNetworkPageCount, NULL, NULL); 3057 dwPageCount += dwNetworkPageCount; 3058 } 3059 } 3060 3061 DPRINT("PageCount: %lu\n", dwPageCount); 3062 3063 phpage = HeapAlloc(GetProcessHeap(), 3064 HEAP_ZERO_MEMORY, 3065 dwPageCount * sizeof(HPROPSHEETPAGE)); 3066 if (phpage == NULL) 3067 { 3068 LogItem(NULL, L"Page array allocation failed!"); 3069 MessageBoxW(NULL, 3070 L"Setup failed to allocate page array!", 3071 L"ReactOS Setup", 3072 MB_ICONERROR | MB_OK); 3073 goto done; 3074 } 3075 3076 /* Process the $winnt$.inf setup file */ 3077 ProcessSetupInf(pSetupData); 3078 3079 /* Create the Welcome page */ 3080 psp.dwSize = sizeof(PROPSHEETPAGE); 3081 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER; 3082 psp.hInstance = hDllInstance; 3083 psp.lParam = (LPARAM)pSetupData; 3084 psp.pfnDlgProc = WelcomeDlgProc; 3085 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE); 3086 phpage[nPages++] = CreatePropertySheetPage(&psp); 3087 3088 /* Create the Acknowledgements page */ 3089 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3090 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ACKTITLE); 3091 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_ACKSUBTITLE); 3092 psp.pszTemplate = MAKEINTRESOURCE(IDD_ACKPAGE); 3093 psp.pfnDlgProc = AckPageDlgProc; 3094 phpage[nPages++] = CreatePropertySheetPage(&psp); 3095 3096 /* Create the Product page */ 3097 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3098 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PRODUCTTITLE); 3099 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PRODUCTSUBTITLE); 3100 psp.pszTemplate = MAKEINTRESOURCE(IDD_PRODUCT); 3101 psp.pfnDlgProc = ProductPageDlgProc; 3102 phpage[nPages++] = CreatePropertySheetPage(&psp); 3103 3104 /* Create the Locale page */ 3105 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3106 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LOCALETITLE); 3107 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LOCALESUBTITLE); 3108 psp.pfnDlgProc = LocalePageDlgProc; 3109 psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE); 3110 phpage[nPages++] = CreatePropertySheetPage(&psp); 3111 3112 /* Create the Owner page */ 3113 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3114 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_OWNERTITLE); 3115 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_OWNERSUBTITLE); 3116 psp.pszTemplate = MAKEINTRESOURCE(IDD_OWNERPAGE); 3117 psp.pfnDlgProc = OwnerPageDlgProc; 3118 phpage[nPages++] = CreatePropertySheetPage(&psp); 3119 3120 /* Create the Computer page */ 3121 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3122 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_COMPUTERTITLE); 3123 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_COMPUTERSUBTITLE); 3124 psp.pfnDlgProc = ComputerPageDlgProc; 3125 psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPUTERPAGE); 3126 phpage[nPages++] = CreatePropertySheetPage(&psp); 3127 3128 /* Create the DateTime page */ 3129 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3130 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE); 3131 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DATETIMESUBTITLE); 3132 psp.pfnDlgProc = DateTimePageDlgProc; 3133 psp.pszTemplate = MAKEINTRESOURCE(IDD_DATETIMEPAGE); 3134 phpage[nPages++] = CreatePropertySheetPage(&psp); 3135 3136 /* Create the theme selection page */ 3137 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3138 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONTITLE); 3139 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONSUBTITLE); 3140 psp.pfnDlgProc = ThemePageDlgProc; 3141 psp.pszTemplate = MAKEINTRESOURCE(IDD_THEMEPAGE); 3142 phpage[nPages++] = CreatePropertySheetPage(&psp); 3143 3144 pSetupData->uFirstNetworkWizardPage = IDD_PROCESSPAGE; 3145 pSetupData->uPostNetworkWizardPage = IDD_PROCESSPAGE; 3146 3147 if (pfn) 3148 { 3149 pfn(&dwNetworkPageCount, &phpage[nPages], pSetupData); 3150 nPages += dwNetworkPageCount; 3151 } 3152 3153 /* Create the Process page */ 3154 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 3155 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE); 3156 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE); 3157 psp.pfnDlgProc = ProcessPageDlgProc; 3158 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE); 3159 phpage[nPages++] = CreatePropertySheetPage(&psp); 3160 3161 /* Create the Finish page */ 3162 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER; 3163 psp.pfnDlgProc = FinishDlgProc; 3164 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE); 3165 phpage[nPages++] = CreatePropertySheetPage(&psp); 3166 3167 ASSERT(nPages == dwPageCount); 3168 3169 /* Create the property sheet */ 3170 psh.dwSize = sizeof(PROPSHEETHEADER); 3171 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_MODELESS; 3172 psh.hInstance = hDllInstance; 3173 psh.hwndParent = NULL; 3174 psh.nPages = nPages; 3175 psh.nStartPage = 0; 3176 psh.phpage = phpage; 3177 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK); 3178 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER); 3179 3180 /* Create title font */ 3181 pSetupData->hTitleFont = CreateTitleFont(); 3182 pSetupData->hBoldFont = CreateBoldFont(); 3183 3184 /* Display the wizard */ 3185 hWnd = (HWND)PropertySheet(&psh); 3186 ShowWindow(hWnd, SW_SHOW); 3187 3188 while (GetMessage(&msg, NULL, 0, 0)) 3189 { 3190 if (!IsDialogMessage(hWnd, &msg)) 3191 { 3192 TranslateMessage(&msg); 3193 DispatchMessage(&msg); 3194 } 3195 } 3196 3197 DeleteObject(pSetupData->hBoldFont); 3198 DeleteObject(pSetupData->hTitleFont); 3199 3200 if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE) 3201 SetupCloseInfFile(pSetupData->hSetupInf); 3202 3203 done: 3204 if (phpage != NULL) 3205 HeapFree(GetProcessHeap(), 0, phpage); 3206 3207 if (hNetShell != NULL) 3208 FreeLibrary(hNetShell); 3209 3210 if (pSetupData != NULL) 3211 HeapFree(GetProcessHeap(), 0, pSetupData); 3212 3213 LogItem(L"END_SECTION", L"InstallWizard"); 3214 } 3215 3216 /* EOF */ 3217