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_BOLD; 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_BOLD; 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_PRODUCT); 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 BOOL 381 DoWriteProductOption(PRODUCT_OPTION nOption) 382 { 383 static const WCHAR s_szProductOptions[] = L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions"; 384 static const WCHAR s_szRosVersion[] = L"SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version"; 385 HKEY hKey; 386 LONG error; 387 LPCWSTR pData; 388 DWORD cbData, dwValue; 389 390 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szProductOptions, 0, KEY_WRITE, &hKey); 391 if (error) 392 return FALSE; 393 394 switch (nOption) 395 { 396 case PRODUCT_OPTION_SERVER: 397 /* write ProductSuite */ 398 pData = L"Terminal Server\0"; 399 cbData = sizeof(L"Terminal Server\0"); 400 error = RegSetValueExW(hKey, L"ProductSuite", 0, REG_MULTI_SZ, (BYTE *)pData, cbData); 401 if (error) 402 break; 403 404 /* write ProductType */ 405 pData = L"ServerNT"; 406 cbData = sizeof(L"ServerNT"); 407 error = RegSetValueExW(hKey, L"ProductType", 0, REG_SZ, (BYTE *)pData, cbData); 408 break; 409 410 case PRODUCT_OPTION_WORKSTATION: 411 /* write ProductSuite */ 412 pData = L"\0"; 413 cbData = sizeof(L"\0"); 414 error = RegSetValueExW(hKey, L"ProductSuite", 0, REG_MULTI_SZ, (BYTE *)pData, cbData); 415 if (error) 416 break; 417 418 /* write ProductType */ 419 pData = L"WinNT"; 420 cbData = sizeof(L"WinNT"); 421 error = RegSetValueExW(hKey, L"ProductType", 0, REG_SZ, (BYTE *)pData, cbData); 422 break; 423 } 424 425 RegCloseKey(hKey); 426 427 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szRosVersion, 0, KEY_WRITE, &hKey); 428 if (error) 429 return FALSE; 430 431 /* write ReportAsWorkstation value */ 432 dwValue = (nOption == PRODUCT_OPTION_WORKSTATION); 433 cbData = sizeof(dwValue); 434 error = RegSetValueExW(hKey, L"ReportAsWorkstation", 0, REG_DWORD, (BYTE *)&dwValue, cbData); 435 436 RegCloseKey(hKey); 437 438 return error == ERROR_SUCCESS; 439 } 440 441 static void 442 OnChooseServer(HWND hwndDlg) 443 { 444 WCHAR szText[256]; 445 446 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_SUITE, L"Terminal Server"); 447 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_TYPE, L"ServerNT"); 448 449 LoadStringW(hDllInstance, IDS_PRODUCTSERVERINFO, szText, _countof(szText)); 450 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_DESCRIPTION, szText); 451 } 452 453 static void 454 OnChooseWorkstation(HWND hwndDlg) 455 { 456 WCHAR szText[256]; 457 458 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_SUITE, L""); 459 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_TYPE, L"WinNT"); 460 461 LoadStringW(hDllInstance, IDS_PRODUCTWORKSTATIONINFO, szText, _countof(szText)); 462 SetDlgItemTextW(hwndDlg, IDC_PRODUCT_DESCRIPTION, szText); 463 } 464 465 static INT_PTR CALLBACK 466 ProductPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 467 { 468 LPNMHDR lpnm; 469 PSETUPDATA pSetupData; 470 INT iItem; 471 WCHAR szText[64]; 472 HICON hIcon; 473 474 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 475 476 switch (uMsg) 477 { 478 case WM_INITDIALOG: 479 { 480 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 481 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 482 483 LoadStringW(hDllInstance, IDS_PRODUCTSERVERNAME, szText, _countof(szText)); 484 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_ADDSTRING, 0, (LPARAM)szText); 485 486 LoadStringW(hDllInstance, IDS_PRODUCTWORKSTATIONNAME, szText, _countof(szText)); 487 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_ADDSTRING, 0, (LPARAM)szText); 488 489 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_SETCURSEL, PRODUCT_OPTION_WORKSTATION, 0); 490 OnChooseWorkstation(hwndDlg); 491 492 hIcon = LoadIcon(NULL, IDI_WINLOGO); 493 SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_ICON, STM_SETICON, (WPARAM)hIcon, 0); 494 return TRUE; 495 } 496 497 case WM_COMMAND: 498 if (HIWORD(wParam) == CBN_SELCHANGE && IDC_PRODUCT_OPTIONS == LOWORD(wParam)) 499 { 500 iItem = SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_GETCURSEL, 0, 0); 501 switch ((PRODUCT_OPTION)iItem) 502 { 503 case PRODUCT_OPTION_SERVER: 504 OnChooseServer(hwndDlg); 505 break; 506 507 case PRODUCT_OPTION_WORKSTATION: 508 OnChooseWorkstation(hwndDlg); 509 break; 510 511 default: 512 break; 513 } 514 } 515 break; 516 517 case WM_NOTIFY: 518 { 519 lpnm = (LPNMHDR)lParam; 520 521 switch (lpnm->code) 522 { 523 case PSN_SETACTIVE: 524 /* Enable the Back and Next buttons */ 525 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 526 if (pSetupData->UnattendSetup) 527 { 528 pSetupData->ProductOption = PRODUCT_OPTION_WORKSTATION; 529 OnChooseWorkstation(hwndDlg); 530 DoWriteProductOption(pSetupData->ProductOption); 531 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_LOCALEPAGE); 532 return TRUE; 533 } 534 break; 535 536 case PSN_WIZNEXT: 537 iItem = SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_GETCURSEL, 0, 0); 538 pSetupData->ProductOption = (PRODUCT_OPTION)iItem; 539 DoWriteProductOption(pSetupData->ProductOption); 540 break; 541 542 case PSN_WIZBACK: 543 pSetupData->UnattendSetup = FALSE; 544 break; 545 546 default: 547 break; 548 } 549 } 550 break; 551 552 default: 553 break; 554 } 555 556 return FALSE; 557 } 558 559 static 560 BOOL 561 WriteOwnerSettings(WCHAR * OwnerName, 562 WCHAR * OwnerOrganization) 563 { 564 HKEY hKey; 565 LONG res; 566 567 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 568 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 569 0, 570 KEY_ALL_ACCESS, 571 &hKey); 572 573 if (res != ERROR_SUCCESS) 574 { 575 return FALSE; 576 } 577 578 res = RegSetValueExW(hKey, 579 L"RegisteredOwner", 580 0, 581 REG_SZ, 582 (LPBYTE)OwnerName, 583 (wcslen(OwnerName) + 1) * sizeof(WCHAR)); 584 585 if (res != ERROR_SUCCESS) 586 { 587 RegCloseKey(hKey); 588 return FALSE; 589 } 590 591 res = RegSetValueExW(hKey, 592 L"RegisteredOrganization", 593 0, 594 REG_SZ, 595 (LPBYTE)OwnerOrganization, 596 (wcslen(OwnerOrganization) + 1) * sizeof(WCHAR)); 597 598 RegCloseKey(hKey); 599 return (res == ERROR_SUCCESS); 600 } 601 602 static INT_PTR CALLBACK 603 OwnerPageDlgProc(HWND hwndDlg, 604 UINT uMsg, 605 WPARAM wParam, 606 LPARAM lParam) 607 { 608 WCHAR OwnerName[51]; 609 WCHAR OwnerOrganization[51]; 610 WCHAR Title[64]; 611 WCHAR ErrorName[256]; 612 LPNMHDR lpnm; 613 PSETUPDATA pSetupData; 614 615 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 616 617 switch (uMsg) 618 { 619 case WM_INITDIALOG: 620 { 621 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 622 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 623 624 /* set a localized ('Owner') placeholder string as default */ 625 if (LoadStringW(hDllInstance, IDS_MACHINE_OWNER_NAME, OwnerName, _countof(OwnerName))) 626 { 627 SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, WM_SETTEXT, 0, (LPARAM)OwnerName); 628 } 629 630 SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, EM_LIMITTEXT, 50, 0); 631 SendDlgItemMessage(hwndDlg, IDC_OWNERORGANIZATION, EM_LIMITTEXT, 50, 0); 632 633 /* Set focus to owner name */ 634 SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME)); 635 636 /* Select the default text to quickly overwrite it by typing */ 637 SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, EM_SETSEL, 0, -1); 638 } 639 break; 640 641 642 case WM_NOTIFY: 643 { 644 lpnm = (LPNMHDR)lParam; 645 646 switch (lpnm->code) 647 { 648 case PSN_SETACTIVE: 649 /* Enable the Back and Next buttons */ 650 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 651 if (pSetupData->UnattendSetup) 652 { 653 SendMessage(GetDlgItem(hwndDlg, IDC_OWNERNAME), WM_SETTEXT, 0, (LPARAM)pSetupData->OwnerName); 654 SendMessage(GetDlgItem(hwndDlg, IDC_OWNERORGANIZATION), WM_SETTEXT, 0, (LPARAM)pSetupData->OwnerOrganization); 655 if (WriteOwnerSettings(pSetupData->OwnerName, pSetupData->OwnerOrganization)) 656 { 657 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_COMPUTERPAGE); 658 return TRUE; 659 } 660 } 661 break; 662 663 case PSN_WIZNEXT: 664 OwnerName[0] = 0; 665 if (GetDlgItemTextW(hwndDlg, IDC_OWNERNAME, OwnerName, 50) == 0) 666 { 667 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 668 { 669 wcscpy(Title, L"ReactOS Setup"); 670 } 671 if (0 == LoadStringW(hDllInstance, IDS_WZD_NAME, ErrorName, ARRAYSIZE(ErrorName))) 672 { 673 wcscpy(ErrorName, L"Setup cannot continue until you enter your name."); 674 } 675 MessageBoxW(hwndDlg, ErrorName, Title, MB_ICONERROR | MB_OK); 676 677 SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME)); 678 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 679 680 return TRUE; 681 } 682 683 OwnerOrganization[0] = 0; 684 GetDlgItemTextW(hwndDlg, IDC_OWNERORGANIZATION, OwnerOrganization, 50); 685 686 if (!WriteOwnerSettings(OwnerName, OwnerOrganization)) 687 { 688 SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME)); 689 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 690 return TRUE; 691 } 692 693 case PSN_WIZBACK: 694 pSetupData->UnattendSetup = FALSE; 695 break; 696 697 default: 698 break; 699 } 700 } 701 break; 702 703 default: 704 break; 705 } 706 707 return FALSE; 708 } 709 710 static 711 BOOL 712 WriteComputerSettings(WCHAR * ComputerName, HWND hwndDlg) 713 { 714 WCHAR Title[64]; 715 WCHAR ErrorComputerName[256]; 716 LONG lError; 717 HKEY hKey = NULL; 718 719 if (!SetComputerNameW(ComputerName)) 720 { 721 if (hwndDlg != NULL) 722 { 723 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 724 { 725 wcscpy(Title, L"ReactOS Setup"); 726 } 727 if (0 == LoadStringW(hDllInstance, IDS_WZD_SETCOMPUTERNAME, ErrorComputerName, 728 ARRAYSIZE(ErrorComputerName))) 729 { 730 wcscpy(ErrorComputerName, L"Setup failed to set the computer name."); 731 } 732 MessageBoxW(hwndDlg, ErrorComputerName, Title, MB_ICONERROR | MB_OK); 733 } 734 735 return FALSE; 736 } 737 738 /* Set the physical DNS domain */ 739 SetComputerNameExW(ComputerNamePhysicalDnsDomain, L""); 740 741 /* Set the physical DNS hostname */ 742 SetComputerNameExW(ComputerNamePhysicalDnsHostname, ComputerName); 743 744 /* Set the accounts domain name */ 745 SetAccountsDomainSid(NULL, ComputerName); 746 747 /* Now we need to set the Hostname */ 748 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 749 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 750 0, 751 KEY_SET_VALUE, 752 &hKey); 753 if (lError != ERROR_SUCCESS) 754 { 755 DPRINT1("RegOpenKeyExW for Tcpip\\Parameters failed (%08lX)\n", lError); 756 return TRUE; 757 } 758 759 lError = RegSetValueEx(hKey, 760 L"Hostname", 761 0, 762 REG_SZ, 763 (LPBYTE)ComputerName, 764 (wcslen(ComputerName) + 1) * sizeof(WCHAR)); 765 if (lError != ERROR_SUCCESS) 766 { 767 DPRINT1("RegSetValueEx(\"Hostname\") failed (%08lX)\n", lError); 768 } 769 770 RegCloseKey(hKey); 771 772 return TRUE; 773 } 774 775 776 static 777 BOOL 778 WriteDefaultLogonData(LPWSTR Domain) 779 { 780 WCHAR szAdministratorName[256]; 781 HKEY hKey = NULL; 782 LONG lError; 783 784 if (LoadStringW(hDllInstance, 785 IDS_ADMINISTRATOR_NAME, 786 szAdministratorName, 787 ARRAYSIZE(szAdministratorName)) == 0) 788 { 789 wcscpy(szAdministratorName, L"Administrator"); 790 } 791 792 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 793 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 794 0, 795 KEY_SET_VALUE, 796 &hKey); 797 if (lError != ERROR_SUCCESS) 798 return FALSE; 799 800 lError = RegSetValueEx(hKey, 801 L"DefaultDomainName", 802 0, 803 REG_SZ, 804 (LPBYTE)Domain, 805 (wcslen(Domain)+ 1) * sizeof(WCHAR)); 806 if (lError != ERROR_SUCCESS) 807 { 808 DPRINT1("RegSetValueEx(\"DefaultDomainName\") failed!\n"); 809 } 810 811 lError = RegSetValueEx(hKey, 812 L"DefaultUserName", 813 0, 814 REG_SZ, 815 (LPBYTE)szAdministratorName, 816 (wcslen(szAdministratorName)+ 1) * sizeof(WCHAR)); 817 if (lError != ERROR_SUCCESS) 818 { 819 DPRINT1("RegSetValueEx(\"DefaultUserName\") failed!\n"); 820 } 821 822 RegCloseKey(hKey); 823 824 return TRUE; 825 } 826 827 828 /* lpBuffer will be filled with a 15-char string (plus the null terminator) */ 829 static void 830 GenerateComputerName(LPWSTR lpBuffer) 831 { 832 static const WCHAR Chars[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 833 static const unsigned cChars = sizeof(Chars) / sizeof(WCHAR) - 1; 834 unsigned i; 835 836 wcscpy(lpBuffer, L"REACTOS-"); 837 838 srand(GetTickCount()); 839 840 /* fill in 7 characters */ 841 for (i = 8; i < 15; i++) 842 lpBuffer[i] = Chars[rand() % cChars]; 843 844 lpBuffer[15] = UNICODE_NULL; /* NULL-terminate */ 845 } 846 847 static INT_PTR CALLBACK 848 ComputerPageDlgProc(HWND hwndDlg, 849 UINT uMsg, 850 WPARAM wParam, 851 LPARAM lParam) 852 { 853 WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; 854 WCHAR Password1[128]; 855 WCHAR Password2[128]; 856 PWCHAR Password; 857 WCHAR Title[64]; 858 WCHAR EmptyComputerName[256], NotMatchPassword[256], WrongPassword[256]; 859 LPNMHDR lpnm; 860 PSETUPDATA pSetupData; 861 862 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 863 864 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 865 { 866 wcscpy(Title, L"ReactOS Setup"); 867 } 868 869 switch (uMsg) 870 { 871 case WM_INITDIALOG: 872 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 873 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData); 874 875 /* Generate a new pseudo-random computer name */ 876 GenerateComputerName(ComputerName); 877 878 /* Display current computer name */ 879 SetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName); 880 881 /* Set text limits */ 882 SendDlgItemMessage(hwndDlg, IDC_COMPUTERNAME, EM_LIMITTEXT, MAX_COMPUTERNAME_LENGTH, 0); 883 SendDlgItemMessage(hwndDlg, IDC_ADMINPASSWORD1, EM_LIMITTEXT, 127, 0); 884 SendDlgItemMessage(hwndDlg, IDC_ADMINPASSWORD2, EM_LIMITTEXT, 127, 0); 885 886 /* Set focus to computer name */ 887 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME)); 888 if (pSetupData->UnattendSetup) 889 { 890 SendMessage(GetDlgItem(hwndDlg, IDC_COMPUTERNAME), WM_SETTEXT, 0, (LPARAM)pSetupData->ComputerName); 891 SendMessage(GetDlgItem(hwndDlg, IDC_ADMINPASSWORD1), WM_SETTEXT, 0, (LPARAM)pSetupData->AdminPassword); 892 SendMessage(GetDlgItem(hwndDlg, IDC_ADMINPASSWORD2), WM_SETTEXT, 0, (LPARAM)pSetupData->AdminPassword); 893 WriteComputerSettings(pSetupData->ComputerName, NULL); 894 SetAdministratorPassword(pSetupData->AdminPassword); 895 } 896 897 /* Store the administrator account name as the default user name */ 898 WriteDefaultLogonData(pSetupData->ComputerName); 899 break; 900 901 902 case WM_NOTIFY: 903 { 904 lpnm = (LPNMHDR)lParam; 905 906 switch (lpnm->code) 907 { 908 case PSN_SETACTIVE: 909 /* Enable the Back and Next buttons */ 910 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 911 if (pSetupData->UnattendSetup && WriteComputerSettings(pSetupData->ComputerName, hwndDlg)) 912 { 913 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_THEMEPAGE); 914 return TRUE; 915 } 916 break; 917 918 case PSN_WIZNEXT: 919 if (0 == GetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName, MAX_COMPUTERNAME_LENGTH + 1)) 920 { 921 if (0 == LoadStringW(hDllInstance, IDS_WZD_COMPUTERNAME, EmptyComputerName, 922 ARRAYSIZE(EmptyComputerName))) 923 { 924 wcscpy(EmptyComputerName, L"Setup cannot continue until you enter the name of your computer."); 925 } 926 MessageBoxW(hwndDlg, EmptyComputerName, Title, MB_ICONERROR | MB_OK); 927 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME)); 928 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 929 return TRUE; 930 } 931 932 /* No need to check computer name for invalid characters, 933 * SetComputerName() will do it for us */ 934 935 if (!WriteComputerSettings(ComputerName, hwndDlg)) 936 { 937 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME)); 938 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 939 return TRUE; 940 } 941 942 #ifdef PASSWORDS_MANDATORY 943 /* Check if admin passwords have been entered */ 944 if ((GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD1, Password1, 128) == 0) || 945 (GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128) == 0)) 946 { 947 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDEMPTY, EmptyPassword, 948 ARRAYSIZE(EmptyPassword))) 949 { 950 wcscpy(EmptyPassword, L"You must enter a password !"); 951 } 952 MessageBoxW(hwndDlg, EmptyPassword, Title, MB_ICONERROR | MB_OK); 953 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 954 return TRUE; 955 } 956 #else 957 GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD1, Password1, 128); 958 GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128); 959 #endif 960 /* Check if passwords match */ 961 if (wcscmp(Password1, Password2)) 962 { 963 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDMATCH, NotMatchPassword, 964 ARRAYSIZE(NotMatchPassword))) 965 { 966 wcscpy(NotMatchPassword, L"The passwords you entered do not match. Please enter the desired password again."); 967 } 968 MessageBoxW(hwndDlg, NotMatchPassword, Title, MB_ICONERROR | MB_OK); 969 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 970 return TRUE; 971 } 972 973 /* Check password for invalid characters */ 974 Password = (PWCHAR)Password1; 975 while (*Password) 976 { 977 if (!isprint(*Password)) 978 { 979 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDCHAR, WrongPassword, 980 ARRAYSIZE(WrongPassword))) 981 { 982 wcscpy(WrongPassword, L"The password you entered contains invalid characters. Please enter a cleaned password."); 983 } 984 MessageBoxW(hwndDlg, WrongPassword, Title, MB_ICONERROR | MB_OK); 985 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); 986 return TRUE; 987 } 988 Password++; 989 } 990 991 /* Set admin password */ 992 SetAdministratorPassword(Password1); 993 break; 994 995 case PSN_WIZBACK: 996 pSetupData->UnattendSetup = FALSE; 997 break; 998 999 default: 1000 break; 1001 } 1002 } 1003 break; 1004 1005 default: 1006 break; 1007 } 1008 1009 return FALSE; 1010 } 1011 1012 1013 static VOID 1014 SetKeyboardLayoutName(HWND hwnd) 1015 { 1016 #if 0 1017 TCHAR szLayoutPath[256]; 1018 TCHAR szLocaleName[32]; 1019 DWORD dwLocaleSize; 1020 HKEY hKey; 1021 1022 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 1023 _T("SYSTEM\\CurrentControlSet\\Control\\NLS\\Locale"), 1024 0, 1025 KEY_ALL_ACCESS, 1026 &hKey)) 1027 return; 1028 1029 dwValueSize = 16 * sizeof(TCHAR); 1030 if (RegQueryValueEx(hKey, 1031 NULL, 1032 NULL, 1033 NULL, 1034 szLocaleName, 1035 &dwLocaleSize)) 1036 { 1037 RegCloseKey(hKey); 1038 return; 1039 } 1040 1041 _tcscpy(szLayoutPath, 1042 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\")); 1043 _tcscat(szLayoutPath, 1044 szLocaleName); 1045 1046 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 1047 szLayoutPath, 1048 0, 1049 KEY_ALL_ACCESS, 1050 &hKey)) 1051 return; 1052 1053 dwValueSize = 32 * sizeof(TCHAR); 1054 if (RegQueryValueEx(hKey, 1055 _T("Layout Text"), 1056 NULL, 1057 NULL, 1058 szLocaleName, 1059 &dwLocaleSize)) 1060 { 1061 RegCloseKey(hKey); 1062 return; 1063 } 1064 1065 RegCloseKey(hKey); 1066 #endif 1067 } 1068 1069 1070 static BOOL 1071 RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters) 1072 { 1073 MSG msg; 1074 STARTUPINFOW StartupInfo; 1075 PROCESS_INFORMATION ProcessInformation; 1076 WCHAR CmdLine[MAX_PATH] = L"rundll32.exe shell32.dll,Control_RunDLL "; 1077 1078 if (!pwszCPLParameters) 1079 { 1080 MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR); 1081 return FALSE; 1082 } 1083 1084 ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 1085 StartupInfo.cb = sizeof(StartupInfo); 1086 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); 1087 1088 ASSERT(_countof(CmdLine) > wcslen(CmdLine) + wcslen(pwszCPLParameters)); 1089 wcscat(CmdLine, pwszCPLParameters); 1090 1091 if (!CreateProcessW(NULL, 1092 CmdLine, 1093 NULL, 1094 NULL, 1095 FALSE, 1096 0, 1097 NULL, 1098 NULL, 1099 &StartupInfo, 1100 &ProcessInformation)) 1101 { 1102 MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR); 1103 return FALSE; 1104 } 1105 1106 while ((MsgWaitForMultipleObjects(1, &ProcessInformation.hProcess, FALSE, INFINITE, QS_ALLINPUT|QS_ALLPOSTMESSAGE )) != WAIT_OBJECT_0) 1107 { 1108 while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) 1109 { 1110 TranslateMessage(&msg); 1111 DispatchMessageW(&msg); 1112 } 1113 } 1114 CloseHandle(ProcessInformation.hThread); 1115 CloseHandle(ProcessInformation.hProcess); 1116 return TRUE; 1117 } 1118 1119 static VOID 1120 WriteUserLocale(VOID) 1121 { 1122 HKEY hKey; 1123 LCID lcid; 1124 WCHAR Locale[12]; 1125 1126 lcid = GetSystemDefaultLCID(); 1127 1128 if (GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Locale, ARRAYSIZE(Locale)) != 0) 1129 { 1130 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel\\International", 1131 0, NULL, REG_OPTION_NON_VOLATILE, 1132 KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) 1133 { 1134 RegSetValueExW(hKey, L"Locale", 0, REG_SZ, (LPBYTE)Locale, (wcslen(Locale) + 1) * sizeof(WCHAR)); 1135 RegCloseKey(hKey); 1136 } 1137 } 1138 } 1139 1140 static INT_PTR CALLBACK 1141 LocalePageDlgProc(HWND hwndDlg, 1142 UINT uMsg, 1143 WPARAM wParam, 1144 LPARAM lParam) 1145 { 1146 PSETUPDATA SetupData; 1147 1148 /* Retrieve pointer to the global setup data */ 1149 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1150 1151 switch (uMsg) 1152 { 1153 case WM_INITDIALOG: 1154 { 1155 /* Save pointer to the global setup data */ 1156 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1157 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1158 WriteUserLocale(); 1159 1160 SetKeyboardLayoutName(GetDlgItem(hwndDlg, IDC_LAYOUTTEXT)); 1161 } 1162 break; 1163 1164 case WM_COMMAND: 1165 if (HIWORD(wParam) == BN_CLICKED) 1166 { 1167 switch (LOWORD(wParam)) 1168 { 1169 case IDC_CUSTOMLOCALE: 1170 RunControlPanelApplet(hwndDlg, L"intl.cpl,,5"); 1171 /* FIXME: Update input locale name */ 1172 break; 1173 1174 case IDC_CUSTOMLAYOUT: 1175 RunControlPanelApplet(hwndDlg, L"input.dll,@1"); 1176 break; 1177 } 1178 } 1179 break; 1180 1181 case WM_NOTIFY: 1182 { 1183 LPNMHDR lpnm = (LPNMHDR)lParam; 1184 1185 switch (lpnm->code) 1186 { 1187 case PSN_SETACTIVE: 1188 /* Enable the Back and Next buttons */ 1189 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1190 if (SetupData->UnattendSetup) 1191 { 1192 // if (!*SetupData->SourcePath) 1193 { 1194 RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"$winnt$.inf\""); // Should be in System32 1195 } 1196 1197 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_OWNERPAGE); 1198 return TRUE; 1199 } 1200 break; 1201 1202 case PSN_WIZNEXT: 1203 break; 1204 1205 case PSN_WIZBACK: 1206 SetupData->UnattendSetup = FALSE; 1207 break; 1208 1209 default: 1210 break; 1211 } 1212 } 1213 break; 1214 1215 default: 1216 break; 1217 } 1218 1219 return FALSE; 1220 } 1221 1222 1223 static PTIMEZONE_ENTRY 1224 GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD Index) 1225 { 1226 PTIMEZONE_ENTRY Entry; 1227 1228 Entry = SetupData->TimeZoneListHead; 1229 while (Entry != NULL) 1230 { 1231 if (Entry->Index >= Index) 1232 return Entry; 1233 1234 Entry = Entry->Next; 1235 } 1236 1237 return NULL; 1238 } 1239 1240 1241 static VOID 1242 CreateTimeZoneList(PSETUPDATA SetupData) 1243 { 1244 WCHAR szKeyName[256]; 1245 DWORD dwIndex; 1246 DWORD dwNameSize; 1247 DWORD dwValueSize; 1248 LONG lError; 1249 HKEY hZonesKey; 1250 HKEY hZoneKey; 1251 1252 PTIMEZONE_ENTRY Entry; 1253 PTIMEZONE_ENTRY Current; 1254 1255 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1256 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", 1257 0, 1258 KEY_ALL_ACCESS, 1259 &hZonesKey)) 1260 return; 1261 1262 dwIndex = 0; 1263 while (TRUE) 1264 { 1265 dwNameSize = 256 * sizeof(WCHAR); 1266 lError = RegEnumKeyExW(hZonesKey, 1267 dwIndex, 1268 szKeyName, 1269 &dwNameSize, 1270 NULL, 1271 NULL, 1272 NULL, 1273 NULL); 1274 if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA) 1275 break; 1276 1277 if (RegOpenKeyExW(hZonesKey, 1278 szKeyName, 1279 0, 1280 KEY_ALL_ACCESS, 1281 &hZoneKey)) 1282 break; 1283 1284 Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY)); 1285 if (Entry == NULL) 1286 { 1287 RegCloseKey(hZoneKey); 1288 break; 1289 } 1290 1291 dwValueSize = 64 * sizeof(WCHAR); 1292 if (RegQueryValueExW(hZoneKey, 1293 L"Display", 1294 NULL, 1295 NULL, 1296 (LPBYTE)&Entry->Description, 1297 &dwValueSize)) 1298 { 1299 RegCloseKey(hZoneKey); 1300 break; 1301 } 1302 1303 dwValueSize = 32 * sizeof(WCHAR); 1304 if (RegQueryValueExW(hZoneKey, 1305 L"Std", 1306 NULL, 1307 NULL, 1308 (LPBYTE)&Entry->StandardName, 1309 &dwValueSize)) 1310 { 1311 RegCloseKey(hZoneKey); 1312 break; 1313 } 1314 1315 dwValueSize = 32 * sizeof(WCHAR); 1316 if (RegQueryValueExW(hZoneKey, 1317 L"Dlt", 1318 NULL, 1319 NULL, 1320 (LPBYTE)&Entry->DaylightName, 1321 &dwValueSize)) 1322 { 1323 RegCloseKey(hZoneKey); 1324 break; 1325 } 1326 1327 dwValueSize = sizeof(DWORD); 1328 if (RegQueryValueExW(hZoneKey, 1329 L"Index", 1330 NULL, 1331 NULL, 1332 (LPBYTE)&Entry->Index, 1333 &dwValueSize)) 1334 { 1335 RegCloseKey(hZoneKey); 1336 break; 1337 } 1338 1339 dwValueSize = sizeof(TZ_INFO); 1340 if (RegQueryValueExW(hZoneKey, 1341 L"TZI", 1342 NULL, 1343 NULL, 1344 (LPBYTE)&Entry->TimezoneInfo, 1345 &dwValueSize)) 1346 { 1347 RegCloseKey(hZoneKey); 1348 break; 1349 } 1350 1351 RegCloseKey(hZoneKey); 1352 1353 if (SetupData->TimeZoneListHead == NULL && 1354 SetupData->TimeZoneListTail == NULL) 1355 { 1356 Entry->Prev = NULL; 1357 Entry->Next = NULL; 1358 SetupData->TimeZoneListHead = Entry; 1359 SetupData->TimeZoneListTail = Entry; 1360 } 1361 else 1362 { 1363 Current = GetLargerTimeZoneEntry(SetupData, Entry->Index); 1364 if (Current != NULL) 1365 { 1366 if (Current == SetupData->TimeZoneListHead) 1367 { 1368 /* Prepend to head */ 1369 Entry->Prev = NULL; 1370 Entry->Next = SetupData->TimeZoneListHead; 1371 SetupData->TimeZoneListHead->Prev = Entry; 1372 SetupData->TimeZoneListHead = Entry; 1373 } 1374 else 1375 { 1376 /* Insert before current */ 1377 Entry->Prev = Current->Prev; 1378 Entry->Next = Current; 1379 Current->Prev->Next = Entry; 1380 Current->Prev = Entry; 1381 } 1382 } 1383 else 1384 { 1385 /* Append to tail */ 1386 Entry->Prev = SetupData->TimeZoneListTail; 1387 Entry->Next = NULL; 1388 SetupData->TimeZoneListTail->Next = Entry; 1389 SetupData->TimeZoneListTail = Entry; 1390 } 1391 } 1392 1393 dwIndex++; 1394 } 1395 1396 RegCloseKey(hZonesKey); 1397 } 1398 1399 1400 static VOID 1401 DestroyTimeZoneList(PSETUPDATA SetupData) 1402 { 1403 PTIMEZONE_ENTRY Entry; 1404 1405 while (SetupData->TimeZoneListHead != NULL) 1406 { 1407 Entry = SetupData->TimeZoneListHead; 1408 1409 SetupData->TimeZoneListHead = Entry->Next; 1410 if (SetupData->TimeZoneListHead != NULL) 1411 { 1412 SetupData->TimeZoneListHead->Prev = NULL; 1413 } 1414 1415 HeapFree(GetProcessHeap(), 0, Entry); 1416 } 1417 1418 SetupData->TimeZoneListTail = NULL; 1419 } 1420 1421 static BOOL 1422 GetTimeZoneListIndex(LPDWORD lpIndex) 1423 { 1424 WCHAR szLanguageIdString[9]; 1425 HKEY hKey; 1426 DWORD dwValueSize; 1427 DWORD Length; 1428 LPWSTR Buffer; 1429 LPWSTR Ptr; 1430 LPWSTR End; 1431 BOOL bFound = FALSE; 1432 unsigned long iLanguageID; 1433 1434 if (*lpIndex == -1) 1435 { 1436 *lpIndex = 85; /* fallback to GMT time zone */ 1437 1438 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1439 L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language", 1440 0, 1441 KEY_ALL_ACCESS, 1442 &hKey)) 1443 return FALSE; 1444 1445 dwValueSize = 9 * sizeof(WCHAR); 1446 if (RegQueryValueExW(hKey, 1447 L"Default", 1448 NULL, 1449 NULL, 1450 (LPBYTE)szLanguageIdString, 1451 &dwValueSize)) 1452 { 1453 RegCloseKey(hKey); 1454 return FALSE; 1455 } 1456 1457 iLanguageID = wcstoul(szLanguageIdString, NULL, 16); 1458 RegCloseKey(hKey); 1459 } 1460 else 1461 { 1462 iLanguageID = *lpIndex; 1463 } 1464 1465 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1466 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", 1467 0, 1468 KEY_ALL_ACCESS, 1469 &hKey)) 1470 return FALSE; 1471 1472 dwValueSize = 0; 1473 if (RegQueryValueExW(hKey, 1474 L"IndexMapping", 1475 NULL, 1476 NULL, 1477 NULL, 1478 &dwValueSize)) 1479 { 1480 RegCloseKey(hKey); 1481 return FALSE; 1482 } 1483 1484 Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize); 1485 if (Buffer == NULL) 1486 { 1487 RegCloseKey(hKey); 1488 return FALSE; 1489 } 1490 1491 if (RegQueryValueExW(hKey, 1492 L"IndexMapping", 1493 NULL, 1494 NULL, 1495 (LPBYTE)Buffer, 1496 &dwValueSize)) 1497 { 1498 HeapFree(GetProcessHeap(), 0, Buffer); 1499 RegCloseKey(hKey); 1500 return FALSE; 1501 } 1502 1503 RegCloseKey(hKey); 1504 1505 Ptr = Buffer; 1506 while (*Ptr != 0) 1507 { 1508 Length = wcslen(Ptr); 1509 if (wcstoul(Ptr, NULL, 16) == iLanguageID) 1510 bFound = TRUE; 1511 1512 Ptr = Ptr + Length + 1; 1513 if (*Ptr == 0) 1514 break; 1515 1516 if (bFound) 1517 { 1518 *lpIndex = wcstoul(Ptr, &End, 10); 1519 HeapFree(GetProcessHeap(), 0, Buffer); 1520 return TRUE; 1521 } 1522 1523 Length = wcslen(Ptr); 1524 Ptr = Ptr + Length + 1; 1525 } 1526 1527 HeapFree(GetProcessHeap(), 0, Buffer); 1528 1529 return FALSE; 1530 } 1531 1532 1533 static VOID 1534 ShowTimeZoneList(HWND hwnd, PSETUPDATA SetupData, DWORD dwEntryIndex) 1535 { 1536 PTIMEZONE_ENTRY Entry; 1537 DWORD dwIndex = 0; 1538 DWORD dwCount; 1539 1540 GetTimeZoneListIndex(&dwEntryIndex); 1541 1542 Entry = SetupData->TimeZoneListHead; 1543 while (Entry != NULL) 1544 { 1545 dwCount = SendMessage(hwnd, 1546 CB_ADDSTRING, 1547 0, 1548 (LPARAM)Entry->Description); 1549 1550 if (dwEntryIndex != 0 && dwEntryIndex == Entry->Index) 1551 dwIndex = dwCount; 1552 1553 Entry = Entry->Next; 1554 } 1555 1556 SendMessage(hwnd, 1557 CB_SETCURSEL, 1558 (WPARAM)dwIndex, 1559 0); 1560 } 1561 1562 1563 static VOID 1564 SetLocalTimeZone(HWND hwnd, PSETUPDATA SetupData) 1565 { 1566 TIME_ZONE_INFORMATION TimeZoneInformation; 1567 PTIMEZONE_ENTRY Entry; 1568 DWORD dwIndex; 1569 DWORD i; 1570 1571 dwIndex = SendMessage(hwnd, 1572 CB_GETCURSEL, 1573 0, 1574 0); 1575 1576 i = 0; 1577 Entry = SetupData->TimeZoneListHead; 1578 while (i < dwIndex) 1579 { 1580 if (Entry == NULL) 1581 return; 1582 1583 i++; 1584 Entry = Entry->Next; 1585 } 1586 1587 wcscpy(TimeZoneInformation.StandardName, 1588 Entry->StandardName); 1589 wcscpy(TimeZoneInformation.DaylightName, 1590 Entry->DaylightName); 1591 1592 TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias; 1593 TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias; 1594 TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias; 1595 1596 memcpy(&TimeZoneInformation.StandardDate, 1597 &Entry->TimezoneInfo.StandardDate, 1598 sizeof(SYSTEMTIME)); 1599 memcpy(&TimeZoneInformation.DaylightDate, 1600 &Entry->TimezoneInfo.DaylightDate, 1601 sizeof(SYSTEMTIME)); 1602 1603 /* Set time zone information */ 1604 SetTimeZoneInformation(&TimeZoneInformation); 1605 } 1606 1607 1608 static BOOL 1609 GetLocalSystemTime(HWND hwnd, PSETUPDATA SetupData) 1610 { 1611 SYSTEMTIME Date; 1612 SYSTEMTIME Time; 1613 1614 if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), &Date) != GDT_VALID) 1615 { 1616 return FALSE; 1617 } 1618 1619 if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), &Time) != GDT_VALID) 1620 { 1621 return FALSE; 1622 } 1623 1624 SetupData->SystemTime.wYear = Date.wYear; 1625 SetupData->SystemTime.wMonth = Date.wMonth; 1626 SetupData->SystemTime.wDayOfWeek = Date.wDayOfWeek; 1627 SetupData->SystemTime.wDay = Date.wDay; 1628 SetupData->SystemTime.wHour = Time.wHour; 1629 SetupData->SystemTime.wMinute = Time.wMinute; 1630 SetupData->SystemTime.wSecond = Time.wSecond; 1631 SetupData->SystemTime.wMilliseconds = Time.wMilliseconds; 1632 1633 return TRUE; 1634 } 1635 1636 1637 static VOID 1638 SetAutoDaylightInfo(HWND hwnd) 1639 { 1640 HKEY hKey; 1641 DWORD dwValue = 1; 1642 1643 if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED) 1644 { 1645 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1646 L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", 1647 0, 1648 KEY_SET_VALUE, 1649 &hKey)) 1650 return; 1651 1652 RegSetValueExW(hKey, 1653 L"DisableAutoDaylightTimeSet", 1654 0, 1655 REG_DWORD, 1656 (LPBYTE)&dwValue, 1657 sizeof(DWORD)); 1658 RegCloseKey(hKey); 1659 } 1660 } 1661 1662 1663 static BOOL 1664 SetSystemLocalTime(HWND hwnd, PSETUPDATA SetupData) 1665 { 1666 BOOL Ret = FALSE; 1667 1668 /* 1669 * Call SetLocalTime twice to ensure correct results 1670 */ 1671 Ret = SetLocalTime(&SetupData->SystemTime) && 1672 SetLocalTime(&SetupData->SystemTime); 1673 1674 return Ret; 1675 } 1676 1677 1678 static VOID 1679 UpdateLocalSystemTime(HWND hwnd) 1680 { 1681 SYSTEMTIME LocalTime; 1682 1683 GetLocalTime(&LocalTime); 1684 DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), GDT_VALID, &LocalTime); 1685 DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), GDT_VALID, &LocalTime); 1686 } 1687 1688 1689 static BOOL 1690 WriteDateTimeSettings(HWND hwndDlg, PSETUPDATA SetupData) 1691 { 1692 WCHAR Title[64]; 1693 WCHAR ErrorLocalTime[256]; 1694 1695 GetLocalSystemTime(hwndDlg, SetupData); 1696 SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), 1697 SetupData); 1698 1699 SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT)); 1700 if (!SetSystemLocalTime(hwndDlg, SetupData)) 1701 { 1702 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title))) 1703 { 1704 wcscpy(Title, L"ReactOS Setup"); 1705 } 1706 if (0 == LoadStringW(hDllInstance, IDS_WZD_LOCALTIME, ErrorLocalTime, 1707 ARRAYSIZE(ErrorLocalTime))) 1708 { 1709 wcscpy(ErrorLocalTime, L"Setup was unable to set the local time."); 1710 } 1711 MessageBoxW(hwndDlg, ErrorLocalTime, Title, MB_ICONWARNING | MB_OK); 1712 return FALSE; 1713 } 1714 1715 return TRUE; 1716 } 1717 1718 1719 static INT_PTR CALLBACK 1720 DateTimePageDlgProc(HWND hwndDlg, 1721 UINT uMsg, 1722 WPARAM wParam, 1723 LPARAM lParam) 1724 { 1725 PSETUPDATA SetupData; 1726 1727 /* Retrieve pointer to the global setup data */ 1728 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1729 1730 switch (uMsg) 1731 { 1732 case WM_INITDIALOG: 1733 /* Save pointer to the global setup data */ 1734 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1735 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1736 1737 CreateTimeZoneList(SetupData); 1738 1739 if (SetupData->UnattendSetup) 1740 { 1741 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), 1742 SetupData, SetupData->TimeZoneIndex); 1743 1744 if (!SetupData->DisableAutoDaylightTimeSet) 1745 { 1746 SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 1747 } 1748 } 1749 else 1750 { 1751 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), 1752 SetupData, -1); 1753 1754 SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 1755 } 1756 break; 1757 1758 case WM_TIMER: 1759 UpdateLocalSystemTime(hwndDlg); 1760 break; 1761 1762 case WM_NOTIFY: 1763 switch (((LPNMHDR)lParam)->code) 1764 { 1765 case PSN_SETACTIVE: 1766 /* Enable the Back and Next buttons */ 1767 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1768 if (SetupData->UnattendSetup && WriteDateTimeSettings(hwndDlg, SetupData)) 1769 { 1770 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage); 1771 return TRUE; 1772 } 1773 SetTimer(hwndDlg, 1, 1000, NULL); 1774 break; 1775 1776 case PSN_KILLACTIVE: 1777 case DTN_DATETIMECHANGE: 1778 KillTimer(hwndDlg, 1); 1779 break; 1780 1781 case PSN_WIZNEXT: 1782 WriteDateTimeSettings(hwndDlg, SetupData); 1783 break; 1784 1785 case PSN_WIZBACK: 1786 SetupData->UnattendSetup = FALSE; 1787 break; 1788 1789 default: 1790 break; 1791 } 1792 break; 1793 1794 case WM_DESTROY: 1795 DestroyTimeZoneList(SetupData); 1796 break; 1797 1798 default: 1799 break; 1800 } 1801 1802 return FALSE; 1803 } 1804 1805 static struct ThemeInfo 1806 { 1807 LPCWSTR PreviewBitmap; 1808 UINT DisplayName; 1809 LPCWSTR ThemeFile; 1810 1811 } Themes[] = { 1812 { MAKEINTRESOURCE(IDB_CLASSIC), IDS_CLASSIC, NULL }, 1813 { MAKEINTRESOURCE(IDB_LAUTUS), IDS_LAUTUS, L"themes\\lautus\\lautus.msstyles" }, 1814 { MAKEINTRESOURCE(IDB_LUNAR), IDS_LUNAR, L"themes\\lunar\\lunar.msstyles" }, 1815 { MAKEINTRESOURCE(IDB_MIZU), IDS_MIZU, L"themes\\mizu\\mizu.msstyles"}, 1816 }; 1817 1818 static INT_PTR CALLBACK 1819 ThemePageDlgProc(HWND hwndDlg, 1820 UINT uMsg, 1821 WPARAM wParam, 1822 LPARAM lParam) 1823 { 1824 PSETUPDATA SetupData; 1825 LPNMLISTVIEW pnmv; 1826 1827 /* Retrieve pointer to the global setup data */ 1828 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1829 1830 switch (uMsg) 1831 { 1832 case WM_INITDIALOG: 1833 { 1834 HWND hListView; 1835 HIMAGELIST himl; 1836 DWORD n; 1837 LVITEM lvi = {0}; 1838 1839 /* Save pointer to the global setup data */ 1840 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1841 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 1842 1843 hListView = GetDlgItem(hwndDlg, IDC_THEMEPICKER); 1844 1845 /* Common */ 1846 himl = ImageList_Create(180, 163, ILC_COLOR32 | ILC_MASK, ARRAYSIZE(Themes), 1); 1847 lvi.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE; 1848 1849 for (n = 0; n < ARRAYSIZE(Themes); ++n) 1850 { 1851 WCHAR DisplayName[100] = {0}; 1852 /* Load the bitmap */ 1853 HANDLE image = LoadImageW(hDllInstance, Themes[n].PreviewBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 1854 ImageList_AddMasked(himl, image, RGB(255,0,255)); 1855 1856 /* Load the string */ 1857 LoadStringW(hDllInstance, Themes[n].DisplayName, DisplayName, ARRAYSIZE(DisplayName)); 1858 DisplayName[ARRAYSIZE(DisplayName)-1] = UNICODE_NULL; 1859 1860 /* Add the listview item */ 1861 lvi.iItem = n; 1862 lvi.iImage = n; 1863 lvi.pszText = DisplayName; 1864 ListView_InsertItem(hListView, &lvi); 1865 } 1866 1867 /* Register the imagelist */ 1868 ListView_SetImageList(hListView, himl, LVSIL_NORMAL); 1869 /* Transparant background */ 1870 ListView_SetBkColor(hListView, CLR_NONE); 1871 ListView_SetTextBkColor(hListView, CLR_NONE); 1872 /* Reduce the size between the items */ 1873 ListView_SetIconSpacing(hListView, 190, 173); 1874 break; 1875 } 1876 case WM_NOTIFY: 1877 switch (((LPNMHDR)lParam)->code) 1878 { 1879 //case LVN_ITEMCHANGING: 1880 case LVN_ITEMCHANGED: 1881 pnmv = (LPNMLISTVIEW)lParam; 1882 if ((pnmv->uChanged & LVIF_STATE) && (pnmv->uNewState & LVIS_SELECTED)) 1883 { 1884 int iTheme = pnmv->iItem; 1885 DPRINT1("Selected theme: %u\n", Themes[iTheme].DisplayName); 1886 1887 if (Themes[iTheme].ThemeFile) 1888 { 1889 WCHAR wszParams[1024]; 1890 WCHAR wszTheme[MAX_PATH]; 1891 WCHAR* format = L"desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:\"%s\""; 1892 1893 SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme); 1894 swprintf(wszParams, format, wszTheme); 1895 RunControlPanelApplet(hwndDlg, wszParams); 1896 } 1897 else 1898 { 1899 RunControlPanelApplet(hwndDlg, L"desk.cpl desk,@Appearance /Action:ActivateMSTheme"); 1900 } 1901 } 1902 break; 1903 case PSN_SETACTIVE: 1904 /* Enable the Back and Next buttons */ 1905 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); 1906 if (SetupData->UnattendSetup) 1907 { 1908 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage); 1909 return TRUE; 1910 } 1911 break; 1912 1913 case PSN_WIZNEXT: 1914 break; 1915 1916 case PSN_WIZBACK: 1917 SetupData->UnattendSetup = FALSE; 1918 break; 1919 1920 default: 1921 break; 1922 } 1923 break; 1924 1925 default: 1926 break; 1927 } 1928 1929 return FALSE; 1930 } 1931 1932 static UINT CALLBACK 1933 RegistrationNotificationProc(PVOID Context, 1934 UINT Notification, 1935 UINT_PTR Param1, 1936 UINT_PTR Param2) 1937 { 1938 PREGISTRATIONDATA RegistrationData; 1939 REGISTRATIONNOTIFY RegistrationNotify; 1940 PSP_REGISTER_CONTROL_STATUSW StatusInfo; 1941 UINT MessageID; 1942 WCHAR ErrorMessage[128]; 1943 1944 RegistrationData = (PREGISTRATIONDATA) Context; 1945 1946 if (SPFILENOTIFY_STARTREGISTRATION == Notification || 1947 SPFILENOTIFY_ENDREGISTRATION == Notification) 1948 { 1949 StatusInfo = (PSP_REGISTER_CONTROL_STATUSW) Param1; 1950 RegistrationNotify.CurrentItem = wcsrchr(StatusInfo->FileName, L'\\'); 1951 if (NULL == RegistrationNotify.CurrentItem) 1952 { 1953 RegistrationNotify.CurrentItem = StatusInfo->FileName; 1954 } 1955 else 1956 { 1957 RegistrationNotify.CurrentItem++; 1958 } 1959 1960 if (SPFILENOTIFY_STARTREGISTRATION == Notification) 1961 { 1962 DPRINT("Received SPFILENOTIFY_STARTREGISTRATION notification for %S\n", 1963 StatusInfo->FileName); 1964 RegistrationNotify.ErrorMessage = NULL; 1965 RegistrationNotify.Progress = RegistrationData->Registered; 1966 } 1967 else 1968 { 1969 DPRINT("Received SPFILENOTIFY_ENDREGISTRATION notification for %S\n", 1970 StatusInfo->FileName); 1971 DPRINT("Win32Error %u FailureCode %u\n", StatusInfo->Win32Error, 1972 StatusInfo->FailureCode); 1973 if (SPREG_SUCCESS != StatusInfo->FailureCode) 1974 { 1975 switch(StatusInfo->FailureCode) 1976 { 1977 case SPREG_LOADLIBRARY: 1978 MessageID = IDS_LOADLIBRARY_FAILED; 1979 break; 1980 case SPREG_GETPROCADDR: 1981 MessageID = IDS_GETPROCADDR_FAILED; 1982 break; 1983 case SPREG_REGSVR: 1984 MessageID = IDS_REGSVR_FAILED; 1985 break; 1986 case SPREG_DLLINSTALL: 1987 MessageID = IDS_DLLINSTALL_FAILED; 1988 break; 1989 case SPREG_TIMEOUT: 1990 MessageID = IDS_TIMEOUT; 1991 break; 1992 default: 1993 MessageID = IDS_REASON_UNKNOWN; 1994 break; 1995 } 1996 if (0 == LoadStringW(hDllInstance, MessageID, 1997 ErrorMessage, 1998 ARRAYSIZE(ErrorMessage))) 1999 { 2000 ErrorMessage[0] = L'\0'; 2001 } 2002 if (SPREG_TIMEOUT != StatusInfo->FailureCode) 2003 { 2004 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 2005 StatusInfo->Win32Error, 0, 2006 ErrorMessage + wcslen(ErrorMessage), 2007 ARRAYSIZE(ErrorMessage) - wcslen(ErrorMessage), 2008 NULL); 2009 } 2010 RegistrationNotify.ErrorMessage = ErrorMessage; 2011 } 2012 else 2013 { 2014 RegistrationNotify.ErrorMessage = NULL; 2015 } 2016 if (RegistrationData->Registered < RegistrationData->DllCount) 2017 { 2018 RegistrationData->Registered++; 2019 } 2020 } 2021 2022 RegistrationNotify.Progress = RegistrationData->Registered; 2023 RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS; 2024 SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY, 2025 0, (LPARAM) &RegistrationNotify); 2026 2027 return FILEOP_DOIT; 2028 } 2029 else 2030 { 2031 DPRINT1("Received unexpected notification %u\n", Notification); 2032 return SetupDefaultQueueCallback(RegistrationData->DefaultContext, 2033 Notification, Param1, Param2); 2034 } 2035 } 2036 2037 2038 static DWORD CALLBACK 2039 RegistrationProc(LPVOID Parameter) 2040 { 2041 PREGISTRATIONDATA RegistrationData; 2042 REGISTRATIONNOTIFY RegistrationNotify; 2043 DWORD LastError = NO_ERROR; 2044 WCHAR UnknownError[84]; 2045 2046 RegistrationData = (PREGISTRATIONDATA) Parameter; 2047 RegistrationData->Registered = 0; 2048 RegistrationData->DefaultContext = SetupInitDefaultQueueCallback(RegistrationData->hwndDlg); 2049 2050 _SEH2_TRY 2051 { 2052 if (!SetupInstallFromInfSectionW(GetParent(RegistrationData->hwndDlg), 2053 hSysSetupInf, 2054 L"RegistrationPhase2", 2055 SPINST_REGISTRY | 2056 SPINST_REGISTERCALLBACKAWARE | 2057 SPINST_REGSVR, 2058 0, 2059 NULL, 2060 0, 2061 RegistrationNotificationProc, 2062 RegistrationData, 2063 NULL, 2064 NULL)) 2065 { 2066 LastError = GetLastError(); 2067 } 2068 } 2069 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2070 { 2071 DPRINT("Catching exception\n"); 2072 LastError = RtlNtStatusToDosError(_SEH2_GetExceptionCode()); 2073 } 2074 _SEH2_END; 2075 2076 if (NO_ERROR == LastError) 2077 { 2078 RegistrationNotify.ErrorMessage = NULL; 2079 } 2080 else 2081 { 2082 DPRINT1("SetupInstallFromInfSection failed with error %u\n", 2083 LastError); 2084 if (0 == FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | 2085 FORMAT_MESSAGE_FROM_SYSTEM, NULL, LastError, 0, 2086 (LPWSTR) &RegistrationNotify.ErrorMessage, 0, 2087 NULL)) 2088 { 2089 if (0 == LoadStringW(hDllInstance, IDS_UNKNOWN_ERROR, 2090 UnknownError, 2091 ARRAYSIZE(UnknownError) - 20)) 2092 { 2093 wcscpy(UnknownError, L"Unknown error"); 2094 } 2095 wcscat(UnknownError, L" "); 2096 _ultow(LastError, UnknownError + wcslen(UnknownError), 10); 2097 RegistrationNotify.ErrorMessage = UnknownError; 2098 } 2099 } 2100 2101 RegistrationNotify.Progress = RegistrationData->DllCount; 2102 RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS; 2103 RegistrationNotify.CurrentItem = NULL; 2104 SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY, 2105 1, (LPARAM) &RegistrationNotify); 2106 if (NULL != RegistrationNotify.ErrorMessage && 2107 UnknownError != RegistrationNotify.ErrorMessage) 2108 { 2109 LocalFree((PVOID) RegistrationNotify.ErrorMessage); 2110 } 2111 2112 SetupTermDefaultQueueCallback(RegistrationData->DefaultContext); 2113 HeapFree(GetProcessHeap(), 0, RegistrationData); 2114 2115 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries"); 2116 2117 // FIXME: Move this call to a separate cleanup page! 2118 RtlCreateBootStatusDataFile(); 2119 2120 return 0; 2121 } 2122 2123 2124 static BOOL 2125 StartComponentRegistration(HWND hwndDlg, PULONG MaxProgress) 2126 { 2127 HANDLE RegistrationThread; 2128 LONG DllCount; 2129 INFCONTEXT Context; 2130 WCHAR SectionName[512]; 2131 PREGISTRATIONDATA RegistrationData; 2132 2133 DllCount = -1; 2134 if (!SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2", 2135 L"RegisterDlls", &Context)) 2136 { 2137 DPRINT1("No RegistrationPhase2 section found\n"); 2138 return FALSE; 2139 } 2140 if (!SetupGetStringFieldW(&Context, 1, SectionName, 2141 ARRAYSIZE(SectionName), 2142 NULL)) 2143 { 2144 DPRINT1("Unable to retrieve section name\n"); 2145 return FALSE; 2146 } 2147 DllCount = SetupGetLineCountW(hSysSetupInf, SectionName); 2148 DPRINT("SectionName %S DllCount %ld\n", SectionName, DllCount); 2149 if (DllCount < 0) 2150 { 2151 SetLastError(STATUS_NOT_FOUND); 2152 return FALSE; 2153 } 2154 2155 *MaxProgress = (ULONG) DllCount; 2156 2157 /* 2158 * Create a background thread to do the actual registrations, so the 2159 * main thread can just run its message loop. 2160 */ 2161 RegistrationThread = NULL; 2162 RegistrationData = HeapAlloc(GetProcessHeap(), 0, 2163 sizeof(REGISTRATIONDATA)); 2164 if (RegistrationData != NULL) 2165 { 2166 RegistrationData->hwndDlg = hwndDlg; 2167 RegistrationData->DllCount = DllCount; 2168 RegistrationThread = CreateThread(NULL, 0, RegistrationProc, 2169 RegistrationData, 0, NULL); 2170 if (RegistrationThread != NULL) 2171 { 2172 CloseHandle(RegistrationThread); 2173 } 2174 else 2175 { 2176 DPRINT1("CreateThread failed, error %u\n", GetLastError()); 2177 HeapFree(GetProcessHeap(), 0, RegistrationData); 2178 return FALSE; 2179 } 2180 } 2181 else 2182 { 2183 DPRINT1("HeapAlloc() failed, error %u\n", GetLastError()); 2184 return FALSE; 2185 } 2186 2187 return TRUE; 2188 } 2189 2190 2191 static INT_PTR CALLBACK 2192 ProcessPageDlgProc(HWND hwndDlg, 2193 UINT uMsg, 2194 WPARAM wParam, 2195 LPARAM lParam) 2196 { 2197 PSETUPDATA SetupData; 2198 PREGISTRATIONNOTIFY RegistrationNotify; 2199 static UINT oldActivityID = -1; 2200 WCHAR Title[64]; 2201 2202 /* Retrieve pointer to the global setup data */ 2203 SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 2204 2205 switch (uMsg) 2206 { 2207 case WM_INITDIALOG: 2208 { 2209 /* Save pointer to the global setup data */ 2210 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 2211 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData); 2212 } 2213 break; 2214 2215 case WM_NOTIFY: 2216 { 2217 LPNMHDR lpnm = (LPNMHDR)lParam; 2218 ULONG MaxProgress = 0; 2219 2220 switch (lpnm->code) 2221 { 2222 case PSN_SETACTIVE: 2223 /* Disable the Back and Next buttons */ 2224 PropSheet_SetWizButtons(GetParent(hwndDlg), 0); 2225 2226 StartComponentRegistration(hwndDlg, &MaxProgress); 2227 2228 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETRANGE, 2229 0, MAKELPARAM(0, MaxProgress)); 2230 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS, 2231 0, 0); 2232 break; 2233 2234 case PSN_WIZNEXT: 2235 break; 2236 2237 case PSN_WIZBACK: 2238 SetupData->UnattendSetup = FALSE; 2239 break; 2240 2241 default: 2242 break; 2243 } 2244 } 2245 break; 2246 2247 case PM_REGISTRATION_NOTIFY: 2248 { 2249 WCHAR Activity[64]; 2250 RegistrationNotify = (PREGISTRATIONNOTIFY) lParam; 2251 // update if necessary only 2252 if (oldActivityID != RegistrationNotify->ActivityID) 2253 { 2254 if (0 != LoadStringW(hDllInstance, RegistrationNotify->ActivityID, 2255 Activity, 2256 ARRAYSIZE(Activity))) 2257 { 2258 SendDlgItemMessageW(hwndDlg, IDC_ACTIVITY, WM_SETTEXT, 2259 0, (LPARAM) Activity); 2260 } 2261 oldActivityID = RegistrationNotify->ActivityID; 2262 } 2263 SendDlgItemMessageW(hwndDlg, IDC_ITEM, WM_SETTEXT, 0, 2264 (LPARAM)(NULL == RegistrationNotify->CurrentItem ? 2265 L"" : RegistrationNotify->CurrentItem)); 2266 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS, 2267 RegistrationNotify->Progress, 0); 2268 if (NULL != RegistrationNotify->ErrorMessage) 2269 { 2270 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, 2271 Title, ARRAYSIZE(Title))) 2272 { 2273 wcscpy(Title, L"ReactOS Setup"); 2274 } 2275 MessageBoxW(hwndDlg, RegistrationNotify->ErrorMessage, 2276 Title, MB_ICONERROR | MB_OK); 2277 2278 } 2279 2280 if (wParam) 2281 { 2282 /* Enable the Back and Next buttons */ 2283 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 2284 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_NEXT); 2285 } 2286 } 2287 return TRUE; 2288 2289 default: 2290 break; 2291 } 2292 2293 return FALSE; 2294 } 2295 2296 2297 static VOID 2298 SetInstallationCompleted(VOID) 2299 { 2300 HKEY hKey = 0; 2301 DWORD InProgress = 0; 2302 DWORD InstallDate; 2303 2304 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, 2305 L"SYSTEM\\Setup", 2306 0, 2307 KEY_WRITE, 2308 &hKey ) == ERROR_SUCCESS) 2309 { 2310 RegSetValueExW( hKey, L"SystemSetupInProgress", 0, REG_DWORD, (LPBYTE)&InProgress, sizeof(InProgress) ); 2311 RegCloseKey( hKey ); 2312 } 2313 2314 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, 2315 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 2316 0, 2317 KEY_WRITE, 2318 &hKey ) == ERROR_SUCCESS) 2319 { 2320 InstallDate = (DWORD)time(NULL); 2321 RegSetValueExW( hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate) ); 2322 RegCloseKey( hKey ); 2323 } 2324 } 2325 2326 static INT_PTR CALLBACK 2327 FinishDlgProc(HWND hwndDlg, 2328 UINT uMsg, 2329 WPARAM wParam, 2330 LPARAM lParam) 2331 { 2332 2333 switch (uMsg) 2334 { 2335 case WM_INITDIALOG: 2336 { 2337 /* Get pointer to the global setup data */ 2338 PSETUPDATA SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; 2339 2340 if (!SetupData->UnattendSetup || !SetupData->DisableGeckoInst) 2341 { 2342 /* Run the Wine Gecko prompt */ 2343 Control_RunDLLW(hwndDlg, 0, L"appwiz.cpl install_gecko", SW_SHOW); 2344 } 2345 2346 /* Set title font */ 2347 SendDlgItemMessage(hwndDlg, 2348 IDC_FINISHTITLE, 2349 WM_SETFONT, 2350 (WPARAM)SetupData->hTitleFont, 2351 (LPARAM)TRUE); 2352 if (SetupData->UnattendSetup) 2353 { 2354 KillTimer(hwndDlg, 1); 2355 SetInstallationCompleted(); 2356 PostQuitMessage(0); 2357 } 2358 } 2359 break; 2360 2361 case WM_DESTROY: 2362 { 2363 SetInstallationCompleted(); 2364 PostQuitMessage(0); 2365 return TRUE; 2366 } 2367 2368 case WM_TIMER: 2369 { 2370 INT Position; 2371 HWND hWndProgress; 2372 2373 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS); 2374 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0); 2375 if (Position == 300) 2376 { 2377 KillTimer(hwndDlg, 1); 2378 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH); 2379 } 2380 else 2381 { 2382 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0); 2383 } 2384 } 2385 return TRUE; 2386 2387 case WM_NOTIFY: 2388 { 2389 LPNMHDR lpnm = (LPNMHDR)lParam; 2390 2391 switch (lpnm->code) 2392 { 2393 case PSN_SETACTIVE: 2394 /* Enable the correct buttons on for the active page */ 2395 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); 2396 2397 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, 2398 MAKELPARAM(0, 300)); 2399 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0); 2400 SetTimer(hwndDlg, 1, 50, NULL); 2401 break; 2402 2403 case PSN_WIZFINISH: 2404 DestroyWindow(GetParent(hwndDlg)); 2405 break; 2406 2407 default: 2408 break; 2409 } 2410 } 2411 break; 2412 2413 default: 2414 break; 2415 } 2416 2417 return FALSE; 2418 } 2419 2420 2421 /* 2422 * GetInstallSourceWin32 retrieves the path to the ReactOS installation medium 2423 * in Win32 format, for later use by syssetup and storage in the registry. 2424 */ 2425 static BOOL 2426 GetInstallSourceWin32( 2427 OUT PWSTR pwszPath, 2428 IN DWORD cchPathMax, 2429 IN PCWSTR pwszNTPath) 2430 { 2431 WCHAR wszDrives[512]; 2432 WCHAR wszNTPath[512]; // MAX_PATH ? 2433 DWORD cchDrives; 2434 PWCHAR pwszDrive; 2435 2436 *pwszPath = UNICODE_NULL; 2437 2438 cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives); 2439 if (cchDrives == 0 || cchDrives >= _countof(wszDrives)) 2440 { 2441 /* Buffer too small or failure */ 2442 LogItem(NULL, L"GetLogicalDriveStringsW failed"); 2443 return FALSE; 2444 } 2445 2446 for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1) 2447 { 2448 WCHAR wszBuf[MAX_PATH]; 2449 2450 /* Retrieve the NT path corresponding to the current Win32 DOS path */ 2451 pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash 2452 QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath)); 2453 pwszDrive[2] = L'\\'; // Restore the backslash 2454 2455 wcscat(wszNTPath, L"\\"); // Concat a backslash 2456 2457 /* Logging */ 2458 wsprintf(wszBuf, L"Testing '%s' --> '%s' %s a CD", 2459 pwszDrive, wszNTPath, 2460 (GetDriveTypeW(pwszDrive) == DRIVE_CDROM) ? L"is" : L"is not"); 2461 LogItem(NULL, wszBuf); 2462 2463 /* Check whether the NT path corresponds to the NT installation source path */ 2464 if (!_wcsicmp(wszNTPath, pwszNTPath)) 2465 { 2466 /* Found it! */ 2467 wcscpy(pwszPath, pwszDrive); // cchPathMax 2468 2469 /* Logging */ 2470 wsprintf(wszBuf, L"GetInstallSourceWin32: %s", pwszPath); 2471 LogItem(NULL, wszBuf); 2472 wcscat(wszBuf, L"\n"); 2473 OutputDebugStringW(wszBuf); 2474 2475 return TRUE; 2476 } 2477 } 2478 2479 return FALSE; 2480 } 2481 2482 VOID 2483 ProcessUnattendSection( 2484 IN OUT PSETUPDATA pSetupData) 2485 { 2486 INFCONTEXT InfContext; 2487 WCHAR szName[256]; 2488 WCHAR szValue[MAX_PATH]; 2489 DWORD LineLength; 2490 HKEY hKey; 2491 2492 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2493 L"Unattend", 2494 L"UnattendSetupEnabled", 2495 &InfContext)) 2496 { 2497 DPRINT1("Error: Cannot find UnattendSetupEnabled Key! %d\n", GetLastError()); 2498 return; 2499 } 2500 2501 if (!SetupGetStringFieldW(&InfContext, 2502 1, 2503 szValue, 2504 ARRAYSIZE(szValue), 2505 &LineLength)) 2506 { 2507 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2508 return; 2509 } 2510 2511 if (_wcsicmp(szValue, L"yes") != 0) 2512 { 2513 DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n"); 2514 return; 2515 } 2516 2517 pSetupData->UnattendSetup = TRUE; 2518 2519 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2520 L"Unattend", 2521 NULL, 2522 &InfContext)) 2523 { 2524 DPRINT1("Error: SetupFindFirstLine failed %d\n", GetLastError()); 2525 return; 2526 } 2527 2528 do 2529 { 2530 if (!SetupGetStringFieldW(&InfContext, 2531 0, 2532 szName, 2533 ARRAYSIZE(szName), 2534 &LineLength)) 2535 { 2536 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2537 return; 2538 } 2539 2540 if (!SetupGetStringFieldW(&InfContext, 2541 1, 2542 szValue, 2543 ARRAYSIZE(szValue), 2544 &LineLength)) 2545 { 2546 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2547 return; 2548 } 2549 DPRINT1("Name %S Value %S\n", szName, szValue); 2550 if (!_wcsicmp(szName, L"FullName")) 2551 { 2552 if (ARRAYSIZE(pSetupData->OwnerName) > LineLength) 2553 { 2554 wcscpy(pSetupData->OwnerName, szValue); 2555 } 2556 } 2557 else if (!_wcsicmp(szName, L"OrgName")) 2558 { 2559 if (ARRAYSIZE(pSetupData->OwnerOrganization) > LineLength) 2560 { 2561 wcscpy(pSetupData->OwnerOrganization, szValue); 2562 } 2563 } 2564 else if (!_wcsicmp(szName, L"ComputerName")) 2565 { 2566 if (ARRAYSIZE(pSetupData->ComputerName) > LineLength) 2567 { 2568 wcscpy(pSetupData->ComputerName, szValue); 2569 } 2570 } 2571 else if (!_wcsicmp(szName, L"AdminPassword")) 2572 { 2573 if (ARRAYSIZE(pSetupData->AdminPassword) > LineLength) 2574 { 2575 wcscpy(pSetupData->AdminPassword, szValue); 2576 } 2577 } 2578 else if (!_wcsicmp(szName, L"TimeZoneIndex")) 2579 { 2580 pSetupData->TimeZoneIndex = _wtoi(szValue); 2581 } 2582 else if (!_wcsicmp(szName, L"DisableAutoDaylightTimeSet")) 2583 { 2584 pSetupData->DisableAutoDaylightTimeSet = _wtoi(szValue); 2585 } 2586 else if (!_wcsicmp(szName, L"DisableGeckoInst")) 2587 { 2588 if (!_wcsicmp(szValue, L"yes")) 2589 pSetupData->DisableGeckoInst = TRUE; 2590 else 2591 pSetupData->DisableGeckoInst = FALSE; 2592 } 2593 2594 } while (SetupFindNextLine(&InfContext, &InfContext)); 2595 2596 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2597 L"Display", 2598 NULL, 2599 &InfContext)) 2600 { 2601 DEVMODEW dm = { { 0 } }; 2602 dm.dmSize = sizeof(dm); 2603 if (EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dm)) 2604 { 2605 do 2606 { 2607 int iValue; 2608 if (!SetupGetStringFieldW(&InfContext, 2609 0, 2610 szName, 2611 ARRAYSIZE(szName), 2612 &LineLength)) 2613 { 2614 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2615 return; 2616 } 2617 2618 if (!SetupGetStringFieldW(&InfContext, 2619 1, 2620 szValue, 2621 ARRAYSIZE(szValue), 2622 &LineLength)) 2623 { 2624 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2625 return; 2626 } 2627 iValue = _wtoi(szValue); 2628 DPRINT1("Name %S Value %i\n", szName, iValue); 2629 2630 if (!iValue) 2631 continue; 2632 2633 if (!_wcsicmp(szName, L"BitsPerPel")) 2634 { 2635 dm.dmFields |= DM_BITSPERPEL; 2636 dm.dmBitsPerPel = iValue; 2637 } 2638 else if (!_wcsicmp(szName, L"XResolution")) 2639 { 2640 dm.dmFields |= DM_PELSWIDTH; 2641 dm.dmPelsWidth = iValue; 2642 } 2643 else if (!_wcsicmp(szName, L"YResolution")) 2644 { 2645 dm.dmFields |= DM_PELSHEIGHT; 2646 dm.dmPelsHeight = iValue; 2647 } 2648 else if (!_wcsicmp(szName, L"VRefresh")) 2649 { 2650 dm.dmFields |= DM_DISPLAYFREQUENCY; 2651 dm.dmDisplayFrequency = iValue; 2652 } 2653 } while (SetupFindNextLine(&InfContext, &InfContext)); 2654 2655 ChangeDisplaySettingsW(&dm, CDS_UPDATEREGISTRY); 2656 } 2657 } 2658 2659 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2660 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", 2661 0, 2662 KEY_SET_VALUE, 2663 &hKey) != ERROR_SUCCESS) 2664 { 2665 DPRINT1("Error: failed to open HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n"); 2666 return; 2667 } 2668 2669 if (SetupFindFirstLineW(pSetupData->hSetupInf, 2670 L"GuiRunOnce", 2671 NULL, 2672 &InfContext)) 2673 { 2674 int i = 0; 2675 do 2676 { 2677 if (SetupGetStringFieldW(&InfContext, 2678 0, 2679 szValue, 2680 ARRAYSIZE(szValue), 2681 NULL)) 2682 { 2683 WCHAR szPath[MAX_PATH]; 2684 swprintf(szName, L"%d", i); 2685 DPRINT("szName %S szValue %S\n", szName, szValue); 2686 2687 if (ExpandEnvironmentStringsW(szValue, szPath, MAX_PATH)) 2688 { 2689 DPRINT("value %S\n", szPath); 2690 if (RegSetValueExW(hKey, 2691 szName, 2692 0, 2693 REG_SZ, 2694 (const BYTE*)szPath, 2695 (wcslen(szPath) + 1) * sizeof(WCHAR)) == ERROR_SUCCESS) 2696 { 2697 i++; 2698 } 2699 } 2700 } 2701 } while (SetupFindNextLine(&InfContext, &InfContext)); 2702 } 2703 2704 RegCloseKey(hKey); 2705 } 2706 2707 VOID 2708 ProcessSetupInf( 2709 IN OUT PSETUPDATA pSetupData) 2710 { 2711 WCHAR szPath[MAX_PATH]; 2712 WCHAR szValue[MAX_PATH]; 2713 INFCONTEXT InfContext; 2714 DWORD LineLength; 2715 HKEY hKey; 2716 LONG res; 2717 2718 pSetupData->hSetupInf = INVALID_HANDLE_VALUE; 2719 2720 /* Retrieve the path of the setup INF */ 2721 GetSystemDirectoryW(szPath, _countof(szPath)); 2722 wcscat(szPath, L"\\$winnt$.inf"); 2723 2724 /* Open the setup INF */ 2725 pSetupData->hSetupInf = SetupOpenInfFileW(szPath, 2726 NULL, 2727 INF_STYLE_OLDNT, 2728 NULL); 2729 if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE) 2730 { 2731 DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError()); 2732 return; 2733 } 2734 2735 2736 /* Retrieve the NT source path from which the 1st-stage installer was run */ 2737 if (!SetupFindFirstLineW(pSetupData->hSetupInf, 2738 L"data", 2739 L"sourcepath", 2740 &InfContext)) 2741 { 2742 DPRINT1("Error: Cannot find sourcepath Key! %d\n", GetLastError()); 2743 return; 2744 } 2745 2746 if (!SetupGetStringFieldW(&InfContext, 2747 1, 2748 szValue, 2749 ARRAYSIZE(szValue), 2750 &LineLength)) 2751 { 2752 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError()); 2753 return; 2754 } 2755 2756 *pSetupData->SourcePath = UNICODE_NULL; 2757 2758 /* Close the setup INF as we are going to modify it manually */ 2759 if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE) 2760 SetupCloseInfFile(pSetupData->hSetupInf); 2761 2762 2763 /* Find the installation source path in Win32 format */ 2764 if (!GetInstallSourceWin32(pSetupData->SourcePath, 2765 _countof(pSetupData->SourcePath), 2766 szValue)) 2767 { 2768 *pSetupData->SourcePath = UNICODE_NULL; 2769 } 2770 2771 /* Save the path in Win32 format in the setup INF */ 2772 swprintf(szValue, L"\"%s\"", pSetupData->SourcePath); 2773 WritePrivateProfileStringW(L"data", L"dospath", szValue, szPath); 2774 2775 /* 2776 * Save it also in the registry, in the following keys: 2777 * - HKLM\Software\Microsoft\Windows\CurrentVersion\Setup , 2778 * values "SourcePath" and "ServicePackSourcePath" (REG_SZ); 2779 * - HKLM\Software\Microsoft\Windows NT\CurrentVersion , 2780 * value "SourcePath" (REG_SZ); set to the full path (e.g. D:\I386). 2781 */ 2782 #if 0 2783 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2784 L"Software\\Microsoft\\Windows NT\\CurrentVersion", 2785 0, 2786 KEY_ALL_ACCESS, 2787 &hKey); 2788 2789 if (res != ERROR_SUCCESS) 2790 { 2791 return FALSE; 2792 } 2793 #endif 2794 2795 res = RegCreateKeyExW(HKEY_LOCAL_MACHINE, 2796 L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup", 2797 0, NULL, 2798 REG_OPTION_NON_VOLATILE, 2799 KEY_ALL_ACCESS, // KEY_WRITE 2800 NULL, 2801 &hKey, 2802 NULL); 2803 if (res == ERROR_SUCCESS) 2804 { 2805 res = RegSetValueExW(hKey, 2806 L"SourcePath", 2807 0, 2808 REG_SZ, 2809 (LPBYTE)pSetupData->SourcePath, 2810 (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR)); 2811 2812 res = RegSetValueExW(hKey, 2813 L"ServicePackSourcePath", 2814 0, 2815 REG_SZ, 2816 (LPBYTE)pSetupData->SourcePath, 2817 (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR)); 2818 2819 RegCloseKey(hKey); 2820 } 2821 2822 2823 /* Now, re-open the setup INF (this must succeed) */ 2824 pSetupData->hSetupInf = SetupOpenInfFileW(szPath, 2825 NULL, 2826 INF_STYLE_OLDNT, 2827 NULL); 2828 if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE) 2829 { 2830 DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError()); 2831 return; 2832 } 2833 2834 /* Process the unattended section of the setup file */ 2835 ProcessUnattendSection(pSetupData); 2836 } 2837 2838 typedef DWORD(WINAPI *PFNREQUESTWIZARDPAGES)(PDWORD, HPROPSHEETPAGE *, PSETUPDATA); 2839 2840 VOID 2841 InstallWizard(VOID) 2842 { 2843 PROPSHEETHEADER psh = {0}; 2844 HPROPSHEETPAGE *phpage = NULL; 2845 PROPSHEETPAGE psp = {0}; 2846 UINT nPages = 0; 2847 HWND hWnd; 2848 MSG msg; 2849 PSETUPDATA pSetupData = NULL; 2850 HMODULE hNetShell = NULL; 2851 PFNREQUESTWIZARDPAGES pfn = NULL; 2852 DWORD dwPageCount = 10, dwNetworkPageCount = 0; 2853 2854 LogItem(L"BEGIN_SECTION", L"InstallWizard"); 2855 2856 /* Allocate setup data */ 2857 pSetupData = HeapAlloc(GetProcessHeap(), 2858 HEAP_ZERO_MEMORY, 2859 sizeof(SETUPDATA)); 2860 if (pSetupData == NULL) 2861 { 2862 LogItem(NULL, L"SetupData allocation failed!"); 2863 MessageBoxW(NULL, 2864 L"Setup failed to allocate global data!", 2865 L"ReactOS Setup", 2866 MB_ICONERROR | MB_OK); 2867 goto done; 2868 } 2869 2870 hNetShell = LoadLibraryW(L"netshell.dll"); 2871 if (hNetShell != NULL) 2872 { 2873 DPRINT("Netshell.dll loaded!\n"); 2874 2875 pfn = (PFNREQUESTWIZARDPAGES)GetProcAddress(hNetShell, 2876 "NetSetupRequestWizardPages"); 2877 if (pfn != NULL) 2878 { 2879 pfn(&dwNetworkPageCount, NULL, NULL); 2880 dwPageCount += dwNetworkPageCount; 2881 } 2882 } 2883 2884 DPRINT("PageCount: %lu\n", dwPageCount); 2885 2886 phpage = HeapAlloc(GetProcessHeap(), 2887 HEAP_ZERO_MEMORY, 2888 dwPageCount * sizeof(HPROPSHEETPAGE)); 2889 if (phpage == NULL) 2890 { 2891 LogItem(NULL, L"Page array allocation failed!"); 2892 MessageBoxW(NULL, 2893 L"Setup failed to allocate page array!", 2894 L"ReactOS Setup", 2895 MB_ICONERROR | MB_OK); 2896 goto done; 2897 } 2898 2899 /* Process the $winnt$.inf setup file */ 2900 ProcessSetupInf(pSetupData); 2901 2902 /* Create the Welcome page */ 2903 psp.dwSize = sizeof(PROPSHEETPAGE); 2904 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER; 2905 psp.hInstance = hDllInstance; 2906 psp.lParam = (LPARAM)pSetupData; 2907 psp.pfnDlgProc = WelcomeDlgProc; 2908 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE); 2909 phpage[nPages++] = CreatePropertySheetPage(&psp); 2910 2911 /* Create the Acknowledgements page */ 2912 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2913 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ACKTITLE); 2914 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_ACKSUBTITLE); 2915 psp.pszTemplate = MAKEINTRESOURCE(IDD_ACKPAGE); 2916 psp.pfnDlgProc = AckPageDlgProc; 2917 phpage[nPages++] = CreatePropertySheetPage(&psp); 2918 2919 /* Create the Product page */ 2920 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2921 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PRODUCTTITLE); 2922 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PRODUCTSUBTITLE); 2923 psp.pszTemplate = MAKEINTRESOURCE(IDD_PRODUCT); 2924 psp.pfnDlgProc = ProductPageDlgProc; 2925 phpage[nPages++] = CreatePropertySheetPage(&psp); 2926 2927 /* Create the Locale page */ 2928 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2929 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LOCALETITLE); 2930 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LOCALESUBTITLE); 2931 psp.pfnDlgProc = LocalePageDlgProc; 2932 psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE); 2933 phpage[nPages++] = CreatePropertySheetPage(&psp); 2934 2935 /* Create the Owner page */ 2936 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2937 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_OWNERTITLE); 2938 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_OWNERSUBTITLE); 2939 psp.pszTemplate = MAKEINTRESOURCE(IDD_OWNERPAGE); 2940 psp.pfnDlgProc = OwnerPageDlgProc; 2941 phpage[nPages++] = CreatePropertySheetPage(&psp); 2942 2943 /* Create the Computer page */ 2944 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2945 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_COMPUTERTITLE); 2946 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_COMPUTERSUBTITLE); 2947 psp.pfnDlgProc = ComputerPageDlgProc; 2948 psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPUTERPAGE); 2949 phpage[nPages++] = CreatePropertySheetPage(&psp); 2950 2951 /* Create the DateTime page */ 2952 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2953 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE); 2954 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DATETIMESUBTITLE); 2955 psp.pfnDlgProc = DateTimePageDlgProc; 2956 psp.pszTemplate = MAKEINTRESOURCE(IDD_DATETIMEPAGE); 2957 phpage[nPages++] = CreatePropertySheetPage(&psp); 2958 2959 /* Create the theme selection page */ 2960 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2961 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONTITLE); 2962 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONSUBTITLE); 2963 psp.pfnDlgProc = ThemePageDlgProc; 2964 psp.pszTemplate = MAKEINTRESOURCE(IDD_THEMEPAGE); 2965 phpage[nPages++] = CreatePropertySheetPage(&psp); 2966 2967 pSetupData->uFirstNetworkWizardPage = IDD_PROCESSPAGE; 2968 pSetupData->uPostNetworkWizardPage = IDD_PROCESSPAGE; 2969 2970 if (pfn) 2971 { 2972 pfn(&dwNetworkPageCount, &phpage[nPages], pSetupData); 2973 nPages += dwNetworkPageCount; 2974 } 2975 2976 /* Create the Process page */ 2977 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; 2978 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE); 2979 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE); 2980 psp.pfnDlgProc = ProcessPageDlgProc; 2981 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE); 2982 phpage[nPages++] = CreatePropertySheetPage(&psp); 2983 2984 /* Create the Finish page */ 2985 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER; 2986 psp.pfnDlgProc = FinishDlgProc; 2987 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE); 2988 phpage[nPages++] = CreatePropertySheetPage(&psp); 2989 2990 ASSERT(nPages == dwPageCount); 2991 2992 /* Create the property sheet */ 2993 psh.dwSize = sizeof(PROPSHEETHEADER); 2994 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_MODELESS; 2995 psh.hInstance = hDllInstance; 2996 psh.hwndParent = NULL; 2997 psh.nPages = nPages; 2998 psh.nStartPage = 0; 2999 psh.phpage = phpage; 3000 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK); 3001 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER); 3002 3003 /* Create title font */ 3004 pSetupData->hTitleFont = CreateTitleFont(); 3005 pSetupData->hBoldFont = CreateBoldFont(); 3006 3007 /* Display the wizard */ 3008 hWnd = (HWND)PropertySheet(&psh); 3009 ShowWindow(hWnd, SW_SHOW); 3010 3011 while (GetMessage(&msg, NULL, 0, 0)) 3012 { 3013 if (!IsDialogMessage(hWnd, &msg)) 3014 { 3015 TranslateMessage(&msg); 3016 DispatchMessage(&msg); 3017 } 3018 } 3019 3020 DeleteObject(pSetupData->hBoldFont); 3021 DeleteObject(pSetupData->hTitleFont); 3022 3023 if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE) 3024 SetupCloseInfFile(pSetupData->hSetupInf); 3025 3026 done: 3027 if (phpage != NULL) 3028 HeapFree(GetProcessHeap(), 0, phpage); 3029 3030 if (hNetShell != NULL) 3031 FreeLibrary(hNetShell); 3032 3033 if (pSetupData != NULL) 3034 HeapFree(GetProcessHeap(), 0, pSetupData); 3035 3036 LogItem(L"END_SECTION", L"InstallWizard"); 3037 } 3038 3039 /* EOF */ 3040