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 static struct ThemeInfo 1597 { 1598 LPCWSTR PreviewBitmap; 1599 UINT DisplayName; 1600 LPCWSTR ThemeFile; 1601 1602 } Themes[] = { 1603 { MAKEINTRESOURCE(IDB_CLASSIC), IDS_CLASSIC, NULL }, 1604 { MAKEINTRESOURCE(IDB_LAUTUS), IDS_LAUTUS, L"themes\\lautus\\lautus.msstyles" }, 1605 { MAKEINTRESOURCE(IDB_LUNAR), IDS_LUNAR, L"themes\\lunar\\lunar.msstyles" }, 1606 { MAKEINTRESOURCE(IDB_MIZU), IDS_MIZU, L"themes\\mizu\\mizu.msstyles"}, 1607 }; 1608 1609 static INT_PTR CALLBACK 1610 ThemePageDlgProc(HWND hwndDlg, 1611 UINT uMsg, 1612 WPARAM wParam, 1613 LPARAM lParam) 1614 { 1615 PSETUPDATA SetupData; 1616 LPNMLISTVIEW pnmv; 1617 1618 /* Retrieve pointer to the global setup data */ 1619 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1620 1621 switch (uMsg) 1622 { 1623 case WM_INITDIALOG: 1624 { 1625 HWND hListView; 1626 HIMAGELIST himl; 1627 DWORD n; 1628 LVITEM lvi = {0}; 1629 1630 /* Save pointer to the global setup data */ 1631 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1632 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1633 1634 hListView = GetDlgItem(hwndDlg, IDC_THEMEPICKER); 1635 1636 /* Common */ 1637 himl = ImageList_Create(180, 163, ILC_COLOR32 | ILC_MASK, ARRAYSIZE(Themes), 1); 1638 lvi.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE; 1639 1640 for (n = 0; n < ARRAYSIZE(Themes); ++n) 1641 { 1642 WCHAR DisplayName[100] = {0}; 1643 /* Load the bitmap */ 1644 HANDLE image = LoadImageW(hDllInstance, Themes[n].PreviewBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 1645 ImageList_AddMasked(himl, image, RGB(255,0,255)); 1646 1647 /* Load the string */ 1648 LoadStringW(hDllInstance, Themes[n].DisplayName, DisplayName, ARRAYSIZE(DisplayName)); 1649 DisplayName[ARRAYSIZE(DisplayName)-1] = UNICODE_NULL; 1650 1651 /* Add the listview item */ 1652 lvi.iItem = n; 1653 lvi.iImage = n; 1654 lvi.pszText = DisplayName; 1655 ListView_InsertItem(hListView, &lvi); 1656 } 1657 1658 /* Register the imagelist */ 1659 ListView_SetImageList(hListView, himl, LVSIL_NORMAL); 1660 /* Transparant background */ 1661 ListView_SetBkColor(hListView, CLR_NONE); 1662 ListView_SetTextBkColor(hListView, CLR_NONE); 1663 /* Reduce the size between the items */ 1664 ListView_SetIconSpacing(hListView, 190, 173); 1665 break; 1666 } 1667 case WM_NOTIFY: 1668 switch (((LPNMHDR)lParam)->code) 1669 { 1670 //case LVN_ITEMCHANGING: 1671 case LVN_ITEMCHANGED: 1672 pnmv = (LPNMLISTVIEW)lParam; 1673 if ((pnmv->uChanged & LVIF_STATE) && (pnmv->uNewState & LVIS_SELECTED)) 1674 { 1675 int iTheme = pnmv->iItem; 1676 DPRINT1("Selected theme: %u\n", Themes[iTheme].DisplayName); 1677 1678 if (Themes[iTheme].ThemeFile) 1679 { 1680 WCHAR wszParams[1024]; 1681 WCHAR wszTheme[MAX_PATH]; 1682 WCHAR* format = L"desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:\"%s\""; 1683 1684 SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme); 1685 swprintf(wszParams, format, wszTheme); 1686 RunControlPanelApplet(hwndDlg, wszParams); 1687 } 1688 else 1689 { 1690 RunControlPanelApplet(hwndDlg, L"desk.cpl desk,@Appearance /Action:ActivateMSTheme"); 1691 } 1692 } 1693 break; 1694 case PSN_SETACTIVE: 1695 /* Enable the Back and Next buttons */ 1696 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1697 if (SetupData->UnattendSetup) 1698 { 1699 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage); 1700 return TRUE; 1701 } 1702 break; 1703 1704 case PSN_WIZNEXT: 1705 break; 1706 1707 case PSN_WIZBACK: 1708 SetupData->UnattendSetup = FALSE; 1709 break; 1710 1711 default: 1712 break; 1713 } 1714 break; 1715 1716 default: 1717 break; 1718 } 1719 1720 return FALSE; 1721 } 1722 1723 static UINT CALLBACK 1724 RegistrationNotificationProc(PVOID Context, 1725 UINT Notification, 1726 UINT_PTR Param1, 1727 UINT_PTR Param2) 1728 { 1729 PREGISTRATIONDATA RegistrationData; 1730 REGISTRATIONNOTIFY RegistrationNotify; 1731 PSP_REGISTER_CONTROL_STATUSW StatusInfo; 1732 UINT MessageID; 1733 WCHAR ErrorMessage[128]; 1734 1735 RegistrationData = (PREGISTRATIONDATA) Context; 1736 1737 if (SPFILENOTIFY_STARTREGISTRATION == Notification || 1738 SPFILENOTIFY_ENDREGISTRATION == Notification) 1739 { 1740 StatusInfo = (PSP_REGISTER_CONTROL_STATUSW) Param1; 1741 RegistrationNotify.CurrentItem = wcsrchr(StatusInfo->FileName, L'\\'); 1742 if (NULL == RegistrationNotify.CurrentItem) 1743 { 1744 RegistrationNotify.CurrentItem = StatusInfo->FileName; 1745 } 1746 else 1747 { 1748 RegistrationNotify.CurrentItem++; 1749 } 1750 1751 if (SPFILENOTIFY_STARTREGISTRATION == Notification) 1752 { 1753 DPRINT("Received SPFILENOTIFY_STARTREGISTRATION notification for %S\n", 1754 StatusInfo->FileName); 1755 RegistrationNotify.ErrorMessage = NULL; 1756 RegistrationNotify.Progress = RegistrationData->Registered; 1757 } 1758 else 1759 { 1760 DPRINT("Received SPFILENOTIFY_ENDREGISTRATION notification for %S\n", 1761 StatusInfo->FileName); 1762 DPRINT("Win32Error %u FailureCode %u\n", StatusInfo->Win32Error, 1763 StatusInfo->FailureCode); 1764 if (SPREG_SUCCESS != StatusInfo->FailureCode) 1765 { 1766 switch(StatusInfo->FailureCode) 1767 { 1768 case SPREG_LOADLIBRARY: 1769 MessageID = IDS_LOADLIBRARY_FAILED; 1770 break; 1771 case SPREG_GETPROCADDR: 1772 MessageID = IDS_GETPROCADDR_FAILED; 1773 break; 1774 case SPREG_REGSVR: 1775 MessageID = IDS_REGSVR_FAILED; 1776 break; 1777 case SPREG_DLLINSTALL: 1778 MessageID = IDS_DLLINSTALL_FAILED; 1779 break; 1780 case SPREG_TIMEOUT: 1781 MessageID = IDS_TIMEOUT; 1782 break; 1783 default: 1784 MessageID = IDS_REASON_UNKNOWN; 1785 break; 1786 } 1787 if (0 == LoadStringW(hDllInstance, MessageID, 1788 ErrorMessage, 1789 ARRAYSIZE(ErrorMessage))) 1790 { 1791 ErrorMessage[0] = L'\0'; 1792 } 1793 if (SPREG_TIMEOUT != StatusInfo->FailureCode) 1794 { 1795 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 1796 StatusInfo->Win32Error, 0, 1797 ErrorMessage + wcslen(ErrorMessage), 1798 ARRAYSIZE(ErrorMessage) - wcslen(ErrorMessage), 1799 NULL); 1800 } 1801 RegistrationNotify.ErrorMessage = ErrorMessage; 1802 } 1803 else 1804 { 1805 RegistrationNotify.ErrorMessage = NULL; 1806 } 1807 if (RegistrationData->Registered < RegistrationData->DllCount) 1808 { 1809 RegistrationData->Registered++; 1810 } 1811 } 1812 1813 RegistrationNotify.Progress = RegistrationData->Registered; 1814 RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS; 1815 SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY, 1816 0, (LPARAM) &RegistrationNotify); 1817 1818 return FILEOP_DOIT; 1819 } 1820 else 1821 { 1822 DPRINT1("Received unexpected notification %u\n", Notification); 1823 return SetupDefaultQueueCallback(RegistrationData->DefaultContext, 1824 Notification, Param1, Param2); 1825 } 1826 } 1827 1828 1829 static DWORD CALLBACK 1830 RegistrationProc(LPVOID Parameter) 1831 { 1832 PREGISTRATIONDATA RegistrationData; 1833 REGISTRATIONNOTIFY RegistrationNotify; 1834 DWORD LastError = NO_ERROR; 1835 WCHAR UnknownError[84]; 1836 1837 RegistrationData = (PREGISTRATIONDATA) Parameter; 1838 RegistrationData->Registered = 0; 1839 RegistrationData->DefaultContext = SetupInitDefaultQueueCallback(RegistrationData->hwndDlg); 1840 1841 _SEH2_TRY 1842 { 1843 if (!SetupInstallFromInfSectionW(GetParent(RegistrationData->hwndDlg), 1844 hSysSetupInf, 1845 L"RegistrationPhase2", 1846 SPINST_REGISTRY | 1847 SPINST_REGISTERCALLBACKAWARE | 1848 SPINST_REGSVR, 1849 0, 1850 NULL, 1851 0, 1852 RegistrationNotificationProc, 1853 RegistrationData, 1854 NULL, 1855 NULL)) 1856 { 1857 LastError = GetLastError(); 1858 } 1859 } 1860 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1861 { 1862 DPRINT("Catching exception\n"); 1863 LastError = RtlNtStatusToDosError(_SEH2_GetExceptionCode()); 1864 } 1865 _SEH2_END; 1866 1867 if (NO_ERROR == LastError) 1868 { 1869 RegistrationNotify.ErrorMessage = NULL; 1870 } 1871 else 1872 { 1873 DPRINT1("SetupInstallFromInfSection failed with error %u\n", 1874 LastError); 1875 if (0 == FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | 1876 FORMAT_MESSAGE_FROM_SYSTEM, NULL, LastError, 0, 1877 (LPWSTR) &RegistrationNotify.ErrorMessage, 0, 1878 NULL)) 1879 { 1880 if (0 == LoadStringW(hDllInstance, IDS_UNKNOWN_ERROR, 1881 UnknownError, 1882 ARRAYSIZE(UnknownError) - 20)) 1883 { 1884 wcscpy(UnknownError, L"Unknown error"); 1885 } 1886 wcscat(UnknownError, L" "); 1887 _ultow(LastError, UnknownError + wcslen(UnknownError), 10); 1888 RegistrationNotify.ErrorMessage = UnknownError; 1889 } 1890 } 1891 1892 RegistrationNotify.Progress = RegistrationData->DllCount; 1893 RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS; 1894 RegistrationNotify.CurrentItem = NULL; 1895 SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY, 1896 1, (LPARAM) &RegistrationNotify); 1897 if (NULL != RegistrationNotify.ErrorMessage && 1898 UnknownError != RegistrationNotify.ErrorMessage) 1899 { 1900 LocalFree((PVOID) RegistrationNotify.ErrorMessage); 1901 } 1902 1903 SetupTermDefaultQueueCallback(RegistrationData->DefaultContext); 1904 HeapFree(GetProcessHeap(), 0, RegistrationData); 1905 1906 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries"); 1907 1908 // FIXME: Move this call to a separate cleanup page! 1909 RtlCreateBootStatusDataFile(); 1910 1911 return 0; 1912 } 1913 1914 1915 static BOOL 1916 StartComponentRegistration(HWND hwndDlg, PULONG MaxProgress) 1917 { 1918 HANDLE RegistrationThread; 1919 LONG DllCount; 1920 INFCONTEXT Context; 1921 WCHAR SectionName[512]; 1922 PREGISTRATIONDATA RegistrationData; 1923 1924 DllCount = -1; 1925 if (!SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2", 1926 L"RegisterDlls", &Context)) 1927 { 1928 DPRINT1("No RegistrationPhase2 section found\n"); 1929 return FALSE; 1930 } 1931 if (!SetupGetStringFieldW(&Context, 1, SectionName, 1932 ARRAYSIZE(SectionName), 1933 NULL)) 1934 { 1935 DPRINT1("Unable to retrieve section name\n"); 1936 return FALSE; 1937 } 1938 DllCount = SetupGetLineCountW(hSysSetupInf, SectionName); 1939 DPRINT("SectionName %S DllCount %ld\n", SectionName, DllCount); 1940 if (DllCount < 0) 1941 { 1942 SetLastError(STATUS_NOT_FOUND); 1943 return FALSE; 1944 } 1945 1946 *MaxProgress = (ULONG) DllCount; 1947 1948 /* 1949 * Create a background thread to do the actual registrations, so the 1950 * main thread can just run its message loop. 1951 */ 1952 RegistrationThread = NULL; 1953 RegistrationData = HeapAlloc(GetProcessHeap(), 0, 1954 sizeof(REGISTRATIONDATA)); 1955 if (RegistrationData != NULL) 1956 { 1957 RegistrationData->hwndDlg = hwndDlg; 1958 RegistrationData->DllCount = DllCount; 1959 RegistrationThread = CreateThread(NULL, 0, RegistrationProc, 1960 RegistrationData, 0, NULL); 1961 if (RegistrationThread != NULL) 1962 { 1963 CloseHandle(RegistrationThread); 1964 } 1965 else 1966 { 1967 DPRINT1("CreateThread failed, error %u\n", GetLastError()); 1968 HeapFree(GetProcessHeap(), 0, RegistrationData); 1969 return FALSE; 1970 } 1971 } 1972 else 1973 { 1974 DPRINT1("HeapAlloc() failed, error %u\n", GetLastError()); 1975 return FALSE; 1976 } 1977 1978 return TRUE; 1979 } 1980 1981 1982 static INT_PTR CALLBACK 1983 ProcessPageDlgProc(HWND hwndDlg, 1984 UINT uMsg, 1985 WPARAM wParam, 1986 LPARAM lParam) 1987 { 1988 PSETUPDATA SetupData; 1989 PREGISTRATIONNOTIFY RegistrationNotify; 1990 static UINT oldActivityID = -1; 1991 WCHAR Title[64]; 1992 1993 /* Retrieve pointer to the global setup data */ 1994 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1995 1996 switch (uMsg) 1997 { 1998 case WM_INITDIALOG: 1999 { 2000 /* Save pointer to the global setup data */ 2001 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 2002 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 2003 } 2004 break; 2005 2006 case WM_NOTIFY: 2007 { 2008 LPNMHDR lpnm = (LPNMHDR)lParam; 2009 ULONG MaxProgress = 0; 2010 2011 switch (lpnm->code) 2012 { 2013 case PSN_SETACTIVE: 2014 /* Disable the Back and Next buttons */ 2015 PropSheet_SetWizButtons(GetParent(hwndDlg), 0); 2016 2017 StartComponentRegistration(hwndDlg, &MaxProgress); 2018 2019 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETRANGE, 2020 0, MAKELPARAM(0, MaxProgress)); 2021 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS, 2022 0, 0); 2023 break; 2024 2025 case PSN_WIZNEXT: 2026 break; 2027 2028 case PSN_WIZBACK: 2029 SetupData->UnattendSetup = FALSE; 2030 break; 2031 2032 default: 2033 break; 2034 } 2035 } 2036 break; 2037 2038 case PM_REGISTRATION_NOTIFY: 2039 { 2040 WCHAR Activity[64]; 2041 RegistrationNotify = (PREGISTRATIONNOTIFY) lParam; 2042 // update if necessary only 2043 if (oldActivityID != RegistrationNotify->ActivityID) 2044 { 2045 if (0 != LoadStringW(hDllInstance, RegistrationNotify->ActivityID, 2046 Activity, 2047 ARRAYSIZE(Activity))) 2048 { 2049 SendDlgItemMessageW(hwndDlg, IDC_ACTIVITY, WM_SETTEXT, 2050 0, (LPARAM) Activity); 2051 } 2052 oldActivityID = RegistrationNotify->ActivityID; 2053 } 2054 SendDlgItemMessageW(hwndDlg, IDC_ITEM, WM_SETTEXT, 0, 2055 (LPARAM)(NULL == RegistrationNotify->CurrentItem ? 2056 L"" : RegistrationNotify->CurrentItem)); 2057 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS, 2058 RegistrationNotify->Progress, 0); 2059 if (NULL != RegistrationNotify->ErrorMessage) 2060 { 2061 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, 2062 Title, ARRAYSIZE(Title))) 2063 { 2064 wcscpy(Title, L"ReactOS Setup"); 2065 } 2066 MessageBoxW(hwndDlg, RegistrationNotify->ErrorMessage, 2067 Title, MB_ICONERROR | MB_OK); 2068 2069 } 2070 2071 if (wParam) 2072 { 2073 /* Enable the Back and Next buttons */ 2074 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 2075 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_NEXT); 2076 } 2077 } 2078 return TRUE; 2079 2080 default: 2081 break; 2082 } 2083 2084 return FALSE; 2085 } 2086 2087 2088 static VOID 2089 SetInstallationCompleted(VOID) 2090 { 2091 HKEY hKey = 0; 2092 DWORD InProgress = 0; 2093 DWORD InstallDate; 2094 2095 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, 2096 L"SYSTEM\\Setup", 2097 0, 2098 KEY_WRITE, 2099 &hKey ) == ERROR_SUCCESS) 2100 { 2101 RegSetValueExW( hKey, L"SystemSetupInProgress", 0, REG_DWORD, (LPBYTE)&InProgress, sizeof(InProgress) ); 2102 RegCloseKey( hKey ); 2103 } 2104 2105 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, 2106 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 2107 0, 2108 KEY_WRITE, 2109 &hKey ) == ERROR_SUCCESS) 2110 { 2111 InstallDate = (DWORD)time(NULL); 2112 RegSetValueExW( hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate) ); 2113 RegCloseKey( hKey ); 2114 } 2115 } 2116 2117 static INT_PTR CALLBACK 2118 FinishDlgProc(HWND hwndDlg, 2119 UINT uMsg, 2120 WPARAM wParam, 2121 LPARAM lParam) 2122 { 2123 2124 switch (uMsg) 2125 { 2126 case WM_INITDIALOG: 2127 { 2128 /* Get pointer to the global setup data */ 2129 PSETUPDATA SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 2130 2131 if (!SetupData->UnattendSetup || !SetupData->DisableGeckoInst) 2132 { 2133 /* Run the Wine Gecko prompt */ 2134 Control_RunDLLW(hwndDlg, 0, L"appwiz.cpl install_gecko", SW_SHOW); 2135 } 2136 2137 /* Set title font */ 2138 SendDlgItemMessage(hwndDlg, 2139 IDC_FINISHTITLE, 2140 WM_SETFONT, 2141 (WPARAM)SetupData->hTitleFont, 2142 (LPARAM)TRUE); 2143 if (SetupData->UnattendSetup) 2144 { 2145 KillTimer(hwndDlg, 1); 2146 SetInstallationCompleted(); 2147 PostQuitMessage(0); 2148 } 2149 } 2150 break; 2151 2152 case WM_DESTROY: 2153 { 2154 SetInstallationCompleted(); 2155 PostQuitMessage(0); 2156 return TRUE; 2157 } 2158 2159 case WM_TIMER: 2160 { 2161 INT Position; 2162 HWND hWndProgress; 2163 2164 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS); 2165 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0); 2166 if (Position == 300) 2167 { 2168 KillTimer(hwndDlg, 1); 2169 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH); 2170 } 2171 else 2172 { 2173 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0); 2174 } 2175 } 2176 return TRUE; 2177 2178 case WM_NOTIFY: 2179 { 2180 LPNMHDR lpnm = (LPNMHDR)lParam; 2181 2182 switch (lpnm->code) 2183 { 2184 case PSN_SETACTIVE: 2185 /* Enable the correct buttons on for the active page */ 2186 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); 2187 2188 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, 2189 MAKELPARAM(0, 300)); 2190 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0); 2191 SetTimer(hwndDlg, 1, 50, NULL); 2192 break; 2193 2194 case PSN_WIZFINISH: 2195 DestroyWindow(GetParent(hwndDlg)); 2196 break; 2197 2198 default: 2199 break; 2200 } 2201 } 2202 break; 2203 2204 default: 2205 break; 2206 } 2207 2208 return FALSE; 2209 } 2210 2211 2212 /* 2213 * GetInstallSourceWin32 retrieves the path to the ReactOS installation medium 2214 * in Win32 format, for later use by syssetup and storage in the registry. 2215 */ 2216 static BOOL 2217 GetInstallSourceWin32( 2218 OUT PWSTR pwszPath, 2219 IN DWORD cchPathMax, 2220 IN PCWSTR pwszNTPath) 2221 { 2222 WCHAR wszDrives[512]; 2223 WCHAR wszNTPath[512]; // MAX_PATH ? 2224 DWORD cchDrives; 2225 PWCHAR pwszDrive; 2226 2227 *pwszPath = UNICODE_NULL; 2228 2229 cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives); 2230 if (cchDrives == 0 || cchDrives >= _countof(wszDrives)) 2231 { 2232 /* Buffer too small or failure */ 2233 LogItem(NULL, L"GetLogicalDriveStringsW failed"); 2234 return FALSE; 2235 } 2236 2237 for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1) 2238 { 2239 WCHAR wszBuf[MAX_PATH]; 2240 2241 /* Retrieve the NT path corresponding to the current Win32 DOS path */ 2242 pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash 2243 QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath)); 2244 pwszDrive[2] = L'\\'; // Restore the backslash 2245 2246 wcscat(wszNTPath, L"\\"); // Concat a backslash 2247 2248 /* Logging */ 2249 wsprintf(wszBuf, L"Testing '%s' --> '%s' %s a CD", 2250 pwszDrive, wszNTPath, 2251 (GetDriveTypeW(pwszDrive) == DRIVE_CDROM) ? L"is" : L"is not"); 2252 LogItem(NULL, wszBuf); 2253 2254 /* Check whether the NT path corresponds to the NT installation source path */ 2255 if (!_wcsicmp(wszNTPath, pwszNTPath)) 2256 { 2257 /* Found it! */ 2258 wcscpy(pwszPath, pwszDrive); // cchPathMax 2259 2260 /* Logging */ 2261 wsprintf(wszBuf, L"GetInstallSourceWin32: %s", pwszPath); 2262 LogItem(NULL, wszBuf); 2263 wcscat(wszBuf, L"\n"); 2264 OutputDebugStringW(wszBuf); 2265 2266 return TRUE; 2267 } 2268 } 2269 2270 return FALSE; 2271 } 2272 2273 VOID 2274 ProcessUnattendSection( 2275 IN OUT PSETUPDATA pSetupData) 2276 { 2277 INFCONTEXT InfContext; 2278 WCHAR szName[256]; 2279 WCHAR szValue[MAX_PATH]; 2280 DWORD LineLength; 2281 HKEY hKey; 2282 2283 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2284 L"Unattend", 2285 L"UnattendSetupEnabled", 2286 &InfContext)) 2287 { 2288 DPRINT1("Error: Cannot find UnattendSetupEnabled Key! %d\n", GetLastError()); 2289 return; 2290 } 2291 2292 if (!SetupGetStringFieldW(&InfContext, 2293 1, 2294 szValue, 2295 ARRAYSIZE(szValue), 2296 &LineLength)) 2297 { 2298 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2299 return; 2300 } 2301 2302 if (_wcsicmp(szValue, L"yes") != 0) 2303 { 2304 DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n"); 2305 return; 2306 } 2307 2308 pSetupData->UnattendSetup = TRUE; 2309 2310 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2311 L"Unattend", 2312 NULL, 2313 &InfContext)) 2314 { 2315 DPRINT1("Error: SetupFindFirstLine failed %d\n", GetLastError()); 2316 return; 2317 } 2318 2319 do 2320 { 2321 if (!SetupGetStringFieldW(&InfContext, 2322 0, 2323 szName, 2324 ARRAYSIZE(szName), 2325 &LineLength)) 2326 { 2327 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2328 return; 2329 } 2330 2331 if (!SetupGetStringFieldW(&InfContext, 2332 1, 2333 szValue, 2334 ARRAYSIZE(szValue), 2335 &LineLength)) 2336 { 2337 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2338 return; 2339 } 2340 DPRINT1("Name %S Value %S\n", szName, szValue); 2341 if (!_wcsicmp(szName, L"FullName")) 2342 { 2343 if (ARRAYSIZE(pSetupData->OwnerName) > LineLength) 2344 { 2345 wcscpy(pSetupData->OwnerName, szValue); 2346 } 2347 } 2348 else if (!_wcsicmp(szName, L"OrgName")) 2349 { 2350 if (ARRAYSIZE(pSetupData->OwnerOrganization) > LineLength) 2351 { 2352 wcscpy(pSetupData->OwnerOrganization, szValue); 2353 } 2354 } 2355 else if (!_wcsicmp(szName, L"ComputerName")) 2356 { 2357 if (ARRAYSIZE(pSetupData->ComputerName) > LineLength) 2358 { 2359 wcscpy(pSetupData->ComputerName, szValue); 2360 } 2361 } 2362 else if (!_wcsicmp(szName, L"AdminPassword")) 2363 { 2364 if (ARRAYSIZE(pSetupData->AdminPassword) > LineLength) 2365 { 2366 wcscpy(pSetupData->AdminPassword, szValue); 2367 } 2368 } 2369 else if (!_wcsicmp(szName, L"TimeZoneIndex")) 2370 { 2371 pSetupData->TimeZoneIndex = _wtoi(szValue); 2372 } 2373 else if (!_wcsicmp(szName, L"DisableAutoDaylightTimeSet")) 2374 { 2375 pSetupData->DisableAutoDaylightTimeSet = _wtoi(szValue); 2376 } 2377 else if (!_wcsicmp(szName, L"DisableGeckoInst")) 2378 { 2379 if (!_wcsicmp(szValue, L"yes")) 2380 pSetupData->DisableGeckoInst = TRUE; 2381 else 2382 pSetupData->DisableGeckoInst = FALSE; 2383 } 2384 2385 } while (SetupFindNextLine(&InfContext, &InfContext)); 2386 2387 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2388 L"Display", 2389 NULL, 2390 &InfContext)) 2391 { 2392 DEVMODEW dm = { { 0 } }; 2393 dm.dmSize = sizeof(dm); 2394 if (EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dm)) 2395 { 2396 do 2397 { 2398 int iValue; 2399 if (!SetupGetStringFieldW(&InfContext, 2400 0, 2401 szName, 2402 ARRAYSIZE(szName), 2403 &LineLength)) 2404 { 2405 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2406 return; 2407 } 2408 2409 if (!SetupGetStringFieldW(&InfContext, 2410 1, 2411 szValue, 2412 ARRAYSIZE(szValue), 2413 &LineLength)) 2414 { 2415 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2416 return; 2417 } 2418 iValue = _wtoi(szValue); 2419 DPRINT1("Name %S Value %i\n", szName, iValue); 2420 2421 if (!iValue) 2422 continue; 2423 2424 if (!_wcsicmp(szName, L"BitsPerPel")) 2425 { 2426 dm.dmFields |= DM_BITSPERPEL; 2427 dm.dmBitsPerPel = iValue; 2428 } 2429 else if (!_wcsicmp(szName, L"XResolution")) 2430 { 2431 dm.dmFields |= DM_PELSWIDTH; 2432 dm.dmPelsWidth = iValue; 2433 } 2434 else if (!_wcsicmp(szName, L"YResolution")) 2435 { 2436 dm.dmFields |= DM_PELSHEIGHT; 2437 dm.dmPelsHeight = iValue; 2438 } 2439 else if (!_wcsicmp(szName, L"VRefresh")) 2440 { 2441 dm.dmFields |= DM_DISPLAYFREQUENCY; 2442 dm.dmDisplayFrequency = iValue; 2443 } 2444 } while (SetupFindNextLine(&InfContext, &InfContext)); 2445 2446 ChangeDisplaySettingsW(&dm, CDS_UPDATEREGISTRY); 2447 } 2448 } 2449 2450 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2451 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", 2452 0, 2453 KEY_SET_VALUE, 2454 &hKey) != ERROR_SUCCESS) 2455 { 2456 DPRINT1("Error: failed to open HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n"); 2457 return; 2458 } 2459 2460 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2461 L"GuiRunOnce", 2462 NULL, 2463 &InfContext)) 2464 { 2465 int i = 0; 2466 do 2467 { 2468 if (SetupGetStringFieldW(&InfContext, 2469 0, 2470 szValue, 2471 ARRAYSIZE(szValue), 2472 NULL)) 2473 { 2474 WCHAR szPath[MAX_PATH]; 2475 swprintf(szName, L"%d", i); 2476 DPRINT("szName %S szValue %S\n", szName, szValue); 2477 2478 if (ExpandEnvironmentStringsW(szValue, szPath, MAX_PATH)) 2479 { 2480 DPRINT("value %S\n", szPath); 2481 if (RegSetValueExW(hKey, 2482 szName, 2483 0, 2484 REG_SZ, 2485 (const BYTE*)szPath, 2486 (wcslen(szPath) + 1) * sizeof(WCHAR)) == ERROR_SUCCESS) 2487 { 2488 i++; 2489 } 2490 } 2491 } 2492 } while (SetupFindNextLine(&InfContext, &InfContext)); 2493 } 2494 2495 RegCloseKey(hKey); 2496 } 2497 2498 VOID 2499 ProcessSetupInf( 2500 IN OUT PSETUPDATA pSetupData) 2501 { 2502 WCHAR szPath[MAX_PATH]; 2503 WCHAR szValue[MAX_PATH]; 2504 INFCONTEXT InfContext; 2505 DWORD LineLength; 2506 HKEY hKey; 2507 LONG res; 2508 2509 pSetupData->hSetupInf = INVALID_HANDLE_VALUE; 2510 2511 /* Retrieve the path of the setup INF */ 2512 GetSystemDirectoryW(szPath, _countof(szPath)); 2513 wcscat(szPath, L"\\$winnt$.inf"); 2514 2515 /* Open the setup INF */ 2516 pSetupData->hSetupInf = SetupOpenInfFileW(szPath, 2517 NULL, 2518 INF_STYLE_OLDNT, 2519 NULL); 2520 if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE) 2521 { 2522 DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError()); 2523 return; 2524 } 2525 2526 2527 /* Retrieve the NT source path from which the 1st-stage installer was run */ 2528 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2529 L"data", 2530 L"sourcepath", 2531 &InfContext)) 2532 { 2533 DPRINT1("Error: Cannot find sourcepath Key! %d\n", GetLastError()); 2534 return; 2535 } 2536 2537 if (!SetupGetStringFieldW(&InfContext, 2538 1, 2539 szValue, 2540 ARRAYSIZE(szValue), 2541 &LineLength)) 2542 { 2543 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2544 return; 2545 } 2546 2547 *pSetupData->SourcePath = UNICODE_NULL; 2548 2549 /* Close the setup INF as we are going to modify it manually */ 2550 if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE) 2551 SetupCloseInfFile(pSetupData->hSetupInf); 2552 2553 2554 /* Find the installation source path in Win32 format */ 2555 if (!GetInstallSourceWin32(pSetupData->SourcePath, 2556 _countof(pSetupData->SourcePath), 2557 szValue)) 2558 { 2559 *pSetupData->SourcePath = UNICODE_NULL; 2560 } 2561 2562 /* Save the path in Win32 format in the setup INF */ 2563 swprintf(szValue, L"\"%s\"", pSetupData->SourcePath); 2564 WritePrivateProfileStringW(L"data", L"dospath", szValue, szPath); 2565 2566 /* 2567 * Save it also in the registry, in the following keys: 2568 * - HKLM\Software\Microsoft\Windows\CurrentVersion\Setup , 2569 * values "SourcePath" and "ServicePackSourcePath" (REG_SZ); 2570 * - HKLM\Software\Microsoft\Windows NT\CurrentVersion , 2571 * value "SourcePath" (REG_SZ); set to the full path (e.g. D:\I386). 2572 */ 2573 #if 0 2574 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2575 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 2576 0, 2577 KEY_ALL_ACCESS, 2578 &hKey); 2579 2580 if (res != ERROR_SUCCESS) 2581 { 2582 return FALSE; 2583 } 2584 #endif 2585 2586 res = RegCreateKeyExW(HKEY_LOCAL_MACHINE, 2587 L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup", 2588 0, NULL, 2589 REG_OPTION_NON_VOLATILE, 2590 KEY_ALL_ACCESS, // KEY_WRITE 2591 NULL, 2592 &hKey, 2593 NULL); 2594 if (res == ERROR_SUCCESS) 2595 { 2596 res = RegSetValueExW(hKey, 2597 L"SourcePath", 2598 0, 2599 REG_SZ, 2600 (LPBYTE)pSetupData->SourcePath, 2601 (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR)); 2602 2603 res = RegSetValueExW(hKey, 2604 L"ServicePackSourcePath", 2605 0, 2606 REG_SZ, 2607 (LPBYTE)pSetupData->SourcePath, 2608 (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR)); 2609 2610 RegCloseKey(hKey); 2611 } 2612 2613 2614 /* Now, re-open the setup INF (this must succeed) */ 2615 pSetupData->hSetupInf = SetupOpenInfFileW(szPath, 2616 NULL, 2617 INF_STYLE_OLDNT, 2618 NULL); 2619 if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE) 2620 { 2621 DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError()); 2622 return; 2623 } 2624 2625 /* Process the unattended section of the setup file */ 2626 ProcessUnattendSection(pSetupData); 2627 } 2628 2629 typedef DWORD(WINAPI *PFNREQUESTWIZARDPAGES)(PDWORD, HPROPSHEETPAGE *, PSETUPDATA); 2630 2631 VOID 2632 InstallWizard(VOID) 2633 { 2634 PROPSHEETHEADER psh; 2635 HPROPSHEETPAGE *phpage = NULL; 2636 PROPSHEETPAGE psp = {0}; 2637 UINT nPages = 0; 2638 HWND hWnd; 2639 MSG msg; 2640 PSETUPDATA pSetupData = NULL; 2641 HMODULE hNetShell = NULL; 2642 PFNREQUESTWIZARDPAGES pfn = NULL; 2643 DWORD dwPageCount = 9, dwNetworkPageCount = 0; 2644 2645 LogItem(L"BEGIN_SECTION", L"InstallWizard"); 2646 2647 /* Allocate setup data */ 2648 pSetupData = HeapAlloc(GetProcessHeap(), 2649 HEAP_ZERO_MEMORY, 2650 sizeof(SETUPDATA)); 2651 if (pSetupData == NULL) 2652 { 2653 LogItem(NULL, L"SetupData allocation failed!"); 2654 MessageBoxW(NULL, 2655 L"Setup failed to allocate global data!", 2656 L"ReactOS Setup", 2657 MB_ICONERROR | MB_OK); 2658 goto done; 2659 } 2660 2661 hNetShell = LoadLibraryW(L"netshell.dll"); 2662 if (hNetShell != NULL) 2663 { 2664 DPRINT("Netshell.dll loaded!\n"); 2665 2666 pfn = (PFNREQUESTWIZARDPAGES)GetProcAddress(hNetShell, 2667 "NetSetupRequestWizardPages"); 2668 if (pfn != NULL) 2669 { 2670 pfn(&dwNetworkPageCount, NULL, NULL); 2671 dwPageCount += dwNetworkPageCount; 2672 } 2673 } 2674 2675 DPRINT("PageCount: %lu\n", dwPageCount); 2676 2677 phpage = HeapAlloc(GetProcessHeap(), 2678 HEAP_ZERO_MEMORY, 2679 dwPageCount * sizeof(HPROPSHEETPAGE)); 2680 if (phpage == NULL) 2681 { 2682 LogItem(NULL, L"Page array allocation failed!"); 2683 MessageBoxW(NULL, 2684 L"Setup failed to allocate page array!", 2685 L"ReactOS Setup", 2686 MB_ICONERROR | MB_OK); 2687 goto done; 2688 } 2689 2690 /* Process the $winnt$.inf setup file */ 2691 ProcessSetupInf(pSetupData); 2692 2693 /* Create the Welcome page */ 2694 psp.dwSize = sizeof(PROPSHEETPAGE); 2695 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER; 2696 psp.hInstance = hDllInstance; 2697 psp.lParam = (LPARAM)pSetupData; 2698 psp.pfnDlgProc = WelcomeDlgProc; 2699 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE); 2700 phpage[nPages++] = CreatePropertySheetPage(&psp); 2701 2702 /* Create the Acknowledgements page */ 2703 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2704 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ACKTITLE); 2705 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_ACKSUBTITLE); 2706 psp.pszTemplate = MAKEINTRESOURCE(IDD_ACKPAGE); 2707 psp.pfnDlgProc = AckPageDlgProc; 2708 phpage[nPages++] = CreatePropertySheetPage(&psp); 2709 2710 /* Create the Locale page */ 2711 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2712 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LOCALETITLE); 2713 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LOCALESUBTITLE); 2714 psp.pfnDlgProc = LocalePageDlgProc; 2715 psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE); 2716 phpage[nPages++] = CreatePropertySheetPage(&psp); 2717 2718 /* Create the Owner page */ 2719 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2720 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_OWNERTITLE); 2721 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_OWNERSUBTITLE); 2722 psp.pszTemplate = MAKEINTRESOURCE(IDD_OWNERPAGE); 2723 psp.pfnDlgProc = OwnerPageDlgProc; 2724 phpage[nPages++] = CreatePropertySheetPage(&psp); 2725 2726 /* Create the Computer page */ 2727 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2728 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_COMPUTERTITLE); 2729 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_COMPUTERSUBTITLE); 2730 psp.pfnDlgProc = ComputerPageDlgProc; 2731 psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPUTERPAGE); 2732 phpage[nPages++] = CreatePropertySheetPage(&psp); 2733 2734 /* Create the DateTime page */ 2735 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2736 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE); 2737 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DATETIMESUBTITLE); 2738 psp.pfnDlgProc = DateTimePageDlgProc; 2739 psp.pszTemplate = MAKEINTRESOURCE(IDD_DATETIMEPAGE); 2740 phpage[nPages++] = CreatePropertySheetPage(&psp); 2741 2742 /* Create the theme selection page */ 2743 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2744 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONTITLE); 2745 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONSUBTITLE); 2746 psp.pfnDlgProc = ThemePageDlgProc; 2747 psp.pszTemplate = MAKEINTRESOURCE(IDD_THEMEPAGE); 2748 phpage[nPages++] = CreatePropertySheetPage(&psp); 2749 2750 pSetupData->uFirstNetworkWizardPage = IDD_PROCESSPAGE; 2751 pSetupData->uPostNetworkWizardPage = IDD_PROCESSPAGE; 2752 2753 if (pfn) 2754 { 2755 pfn(&dwNetworkPageCount, &phpage[nPages], pSetupData); 2756 nPages += dwNetworkPageCount; 2757 } 2758 2759 /* Create the Process page */ 2760 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2761 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE); 2762 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE); 2763 psp.pfnDlgProc = ProcessPageDlgProc; 2764 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE); 2765 phpage[nPages++] = CreatePropertySheetPage(&psp); 2766 2767 /* Create the Finish page */ 2768 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER; 2769 psp.pfnDlgProc = FinishDlgProc; 2770 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE); 2771 phpage[nPages++] = CreatePropertySheetPage(&psp); 2772 2773 ASSERT(nPages == dwPageCount); 2774 2775 /* Create the property sheet */ 2776 psh.dwSize = sizeof(PROPSHEETHEADER); 2777 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_MODELESS; 2778 psh.hInstance = hDllInstance; 2779 psh.hwndParent = NULL; 2780 psh.nPages = nPages; 2781 psh.nStartPage = 0; 2782 psh.phpage = phpage; 2783 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK); 2784 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER); 2785 2786 /* Create title font */ 2787 pSetupData->hTitleFont = CreateTitleFont(); 2788 pSetupData->hBoldFont = CreateBoldFont(); 2789 2790 /* Display the wizard */ 2791 hWnd = (HWND)PropertySheet(&psh); 2792 ShowWindow(hWnd, SW_SHOW); 2793 2794 while (GetMessage(&msg, NULL, 0, 0)) 2795 { 2796 if (!IsDialogMessage(hWnd, &msg)) 2797 { 2798 TranslateMessage(&msg); 2799 DispatchMessage(&msg); 2800 } 2801 } 2802 2803 DeleteObject(pSetupData->hBoldFont); 2804 DeleteObject(pSetupData->hTitleFont); 2805 2806 if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE) 2807 SetupCloseInfFile(pSetupData->hSetupInf); 2808 2809 done: 2810 if (phpage != NULL) 2811 HeapFree(GetProcessHeap(), 0, phpage); 2812 2813 if (hNetShell != NULL) 2814 FreeLibrary(hNetShell); 2815 2816 if (pSetupData != NULL) 2817 HeapFree(GetProcessHeap(), 0, pSetupData); 2818 2819 LogItem(L"END_SECTION", L"InstallWizard"); 2820 } 2821 2822 /* EOF */ 2823