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