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