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