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