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