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