e24643119a8a52790b5dbf52261aae05b0c4cf07
[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 }
621
622 }
623 break;
624
625
626 case WM_NOTIFY:
627 {
628 lpnm = (LPNMHDR)lParam;
629
630 switch (lpnm->code)
631 {
632 case PSN_SETACTIVE:
633 /* Enable the Back and Next buttons */
634 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
635 if (SetupData.UnattendSetup && WriteComputerSettings(SetupData.ComputerName, hwndDlg))
636 {
637 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_DATETIMEPAGE);
638 return TRUE;
639 }
640 break;
641
642 case PSN_WIZNEXT:
643 if (0 == GetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName, MAX_COMPUTERNAME_LENGTH + 1))
644 {
645 if (0 == LoadStringW(hDllInstance, IDS_WZD_COMPUTERNAME, EmptyComputerName,
646 sizeof(EmptyComputerName) / sizeof(EmptyComputerName[0])))
647 {
648 wcscpy(EmptyComputerName, L"Setup cannot continue until you enter the name of your computer.");
649 }
650 MessageBoxW(hwndDlg, EmptyComputerName, Title, MB_ICONERROR | MB_OK);
651 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME));
652 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, -1);
653 return TRUE;
654 }
655
656 /* No need to check computer name for invalid characters,
657 * SetComputerName() will do it for us */
658
659 if (!WriteComputerSettings(ComputerName, hwndDlg))
660 {
661 SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME));
662 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, -1);
663 return TRUE;
664 }
665
666 #if 0
667 /* Check if admin passwords have been entered */
668 if ((GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD1, Password1, 15) == 0) ||
669 (GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD2, Password2, 15) == 0))
670 {
671 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDEMPTY, EmptyPassword,
672 sizeof(EmptyPassword) / sizeof(EmptyPassword[0])))
673 {
674 wcscpy(EmptyPassword, L"You must enter a password !");
675 }
676 MessageBoxW(hwndDlg, EmptyPassword, Title, MB_ICONERROR | MB_OK);
677 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, -1);
678 return TRUE;
679 }
680 #else
681 GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD1, Password1, 15);
682 GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD2, Password2, 15);
683 #endif
684 /* Check if passwords match */
685 if (wcscmp(Password1, Password2))
686 {
687 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDMATCH, NotMatchPassword,
688 sizeof(NotMatchPassword) / sizeof(NotMatchPassword[0])))
689 {
690 wcscpy(NotMatchPassword, L"The passwords you entered do not match. Please enter the desired password again.");
691 }
692 MessageBoxW(hwndDlg, NotMatchPassword, Title, MB_ICONERROR | MB_OK);
693 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, -1);
694 return TRUE;
695 }
696
697 /* Check password for invalid characters */
698 Password = (PWCHAR)Password1;
699 while (*Password)
700 {
701 if (!isprint(*Password))
702 {
703 if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDCHAR, WrongPassword,
704 sizeof(WrongPassword) / sizeof(WrongPassword[0])))
705 {
706 wcscpy(WrongPassword, L"The password you entered contains invalid characters. Please enter a cleaned password.");
707 }
708 MessageBoxW(hwndDlg, WrongPassword, Title, MB_ICONERROR | MB_OK);
709 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, -1);
710 return TRUE;
711 }
712 Password++;
713 }
714
715 /* Set admin password */
716 SetAdministratorPassword(Password1);
717 break;
718
719 case PSN_WIZBACK:
720 SetupData.UnattendSetup = FALSE;
721 break;
722
723 default:
724 break;
725 }
726 }
727 break;
728
729 default:
730 break;
731 }
732
733 return FALSE;
734 }
735
736
737 static VOID
738 SetKeyboardLayoutName(HWND hwnd)
739 {
740 #if 0
741 TCHAR szLayoutPath[256];
742 TCHAR szLocaleName[32];
743 DWORD dwLocaleSize;
744 HKEY hKey;
745
746 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
747 _T("SYSTEM\\CurrentControlSet\\Control\\NLS\\Locale"),
748 0,
749 KEY_ALL_ACCESS,
750 &hKey))
751 return;
752
753 dwValueSize = 16 * sizeof(TCHAR);
754 if (RegQueryValueEx(hKey,
755 NULL,
756 NULL,
757 NULL,
758 szLocaleName,
759 &dwLocaleSize))
760 {
761 RegCloseKey(hKey);
762 return;
763 }
764
765 _tcscpy(szLayoutPath,
766 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"));
767 _tcscat(szLayoutPath,
768 szLocaleName);
769
770 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
771 szLayoutPath,
772 0,
773 KEY_ALL_ACCESS,
774 &hKey))
775 return;
776
777 dwValueSize = 32 * sizeof(TCHAR);
778 if (RegQueryValueEx(hKey,
779 _T("Layout Text"),
780 NULL,
781 NULL,
782 szLocaleName,
783 &dwLocaleSize))
784 {
785 RegCloseKey(hKey);
786 return;
787 }
788
789 RegCloseKey(hKey);
790 #endif
791 }
792
793
794 static BOOL
795 RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters)
796 {
797 if (pwszCPLParameters)
798 {
799 STARTUPINFOW StartupInfo;
800 PROCESS_INFORMATION ProcessInformation;
801 WCHAR CmdLine[MAX_PATH] = L"rundll32.exe shell32.dll,Control_RunDLL ";
802
803 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
804 StartupInfo.cb = sizeof(StartupInfo);
805
806 ASSERT(_countof(CmdLine) > wcslen(CmdLine) + wcslen(pwszCPLParameters));
807 wcscat(CmdLine, pwszCPLParameters);
808
809 if (!CreateProcessW(NULL,
810 CmdLine,
811 NULL,
812 NULL,
813 FALSE,
814 0,
815 NULL,
816 NULL,
817 &StartupInfo,
818 &ProcessInformation))
819 {
820 MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
821 return FALSE;
822 }
823
824 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
825 CloseHandle(ProcessInformation.hThread);
826 CloseHandle(ProcessInformation.hProcess);
827 return TRUE;
828 }
829 else
830 {
831 MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
832 return FALSE;
833 }
834 }
835
836 static VOID
837 WriteUserLocale(VOID)
838 {
839 HKEY hKey;
840 LCID lcid;
841 WCHAR Locale[12];
842
843 lcid = GetSystemDefaultLCID();
844
845 if (GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Locale, sizeof(Locale) / sizeof(Locale[0])) != 0)
846 {
847 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel\\International",
848 0, NULL, REG_OPTION_NON_VOLATILE,
849 KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
850 {
851 RegSetValueExW(hKey, L"Locale", 0, REG_SZ, (LPBYTE)Locale, (wcslen(Locale) + 1) * sizeof(WCHAR));
852 RegCloseKey(hKey);
853 }
854 }
855 }
856
857 static INT_PTR CALLBACK
858 LocalePageDlgProc(HWND hwndDlg,
859 UINT uMsg,
860 WPARAM wParam,
861 LPARAM lParam)
862 {
863 PSETUPDATA SetupData;
864
865 /* Retrieve pointer to the global setup data */
866 SetupData = (PSETUPDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
867
868 switch (uMsg)
869 {
870 case WM_INITDIALOG:
871 {
872 /* Save pointer to the global setup data */
873 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
874 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)SetupData);
875 WriteUserLocale();
876
877 SetKeyboardLayoutName(GetDlgItem(hwndDlg, IDC_LAYOUTTEXT));
878 }
879 break;
880
881 case WM_COMMAND:
882 if (HIWORD(wParam) == BN_CLICKED)
883 {
884 switch (LOWORD(wParam))
885 {
886 case IDC_CUSTOMLOCALE:
887 RunControlPanelApplet(hwndDlg, L"intl.cpl,,5");
888 /* FIXME: Update input locale name */
889 break;
890
891 case IDC_CUSTOMLAYOUT:
892 RunControlPanelApplet(hwndDlg, L"input.dll,@1");
893 break;
894 }
895 }
896 break;
897
898 case WM_NOTIFY:
899 {
900 LPNMHDR lpnm = (LPNMHDR)lParam;
901
902 switch (lpnm->code)
903 {
904 case PSN_SETACTIVE:
905 /* Enable the Back and Next buttons */
906 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
907 if (SetupData->UnattendSetup)
908 {
909 WCHAR wszPath[MAX_PATH];
910 if (GetRosInstallCD(wszPath, _countof(wszPath)))
911 {
912 WCHAR wszParams[1024];
913 swprintf(wszParams, L"intl.cpl,,/f:\"%sreactos\\unattend.inf\"", wszPath);
914 RunControlPanelApplet(hwndDlg, wszParams);
915 }
916 else
917 {
918 RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"unattend.inf\"");
919 }
920
921 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_OWNERPAGE);
922 return TRUE;
923 }
924 break;
925
926 case PSN_WIZNEXT:
927 break;
928
929 case PSN_WIZBACK:
930 SetupData->UnattendSetup = FALSE;
931 break;
932
933 default:
934 break;
935 }
936 }
937 break;
938
939 default:
940 break;
941 }
942
943 return FALSE;
944 }
945
946
947 static PTIMEZONE_ENTRY
948 GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD Index)
949 {
950 PTIMEZONE_ENTRY Entry;
951
952 Entry = SetupData->TimeZoneListHead;
953 while (Entry != NULL)
954 {
955 if (Entry->Index >= Index)
956 return Entry;
957
958 Entry = Entry->Next;
959 }
960
961 return NULL;
962 }
963
964
965 static VOID
966 CreateTimeZoneList(PSETUPDATA SetupData)
967 {
968 WCHAR szKeyName[256];
969 DWORD dwIndex;
970 DWORD dwNameSize;
971 DWORD dwValueSize;
972 LONG lError;
973 HKEY hZonesKey;
974 HKEY hZoneKey;
975
976 PTIMEZONE_ENTRY Entry;
977 PTIMEZONE_ENTRY Current;
978
979 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
980 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
981 0,
982 KEY_ALL_ACCESS,
983 &hZonesKey))
984 return;
985
986 dwIndex = 0;
987 while (TRUE)
988 {
989 dwNameSize = 256 * sizeof(WCHAR);
990 lError = RegEnumKeyExW(hZonesKey,
991 dwIndex,
992 szKeyName,
993 &dwNameSize,
994 NULL,
995 NULL,
996 NULL,
997 NULL);
998 if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
999 break;
1000
1001 if (RegOpenKeyExW(hZonesKey,
1002 szKeyName,
1003 0,
1004 KEY_ALL_ACCESS,
1005 &hZoneKey))
1006 break;
1007
1008 Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
1009 if (Entry == NULL)
1010 {
1011 RegCloseKey(hZoneKey);
1012 break;
1013 }
1014
1015 dwValueSize = 64 * sizeof(WCHAR);
1016 if (RegQueryValueExW(hZoneKey,
1017 L"Display",
1018 NULL,
1019 NULL,
1020 (LPBYTE)&Entry->Description,
1021 &dwValueSize))
1022 {
1023 RegCloseKey(hZoneKey);
1024 break;
1025 }
1026
1027 dwValueSize = 32 * sizeof(WCHAR);
1028 if (RegQueryValueExW(hZoneKey,
1029 L"Std",
1030 NULL,
1031 NULL,
1032 (LPBYTE)&Entry->StandardName,
1033 &dwValueSize))
1034 {
1035 RegCloseKey(hZoneKey);
1036 break;
1037 }
1038
1039 dwValueSize = 32 * sizeof(WCHAR);
1040 if (RegQueryValueExW(hZoneKey,
1041 L"Dlt",
1042 NULL,
1043 NULL,
1044 (LPBYTE)&Entry->DaylightName,
1045 &dwValueSize))
1046 {
1047 RegCloseKey(hZoneKey);
1048 break;
1049 }
1050
1051 dwValueSize = sizeof(DWORD);
1052 if (RegQueryValueExW(hZoneKey,
1053 L"Index",
1054 NULL,
1055 NULL,
1056 (LPBYTE)&Entry->Index,
1057 &dwValueSize))
1058 {
1059 RegCloseKey(hZoneKey);
1060 break;
1061 }
1062
1063 dwValueSize = sizeof(TZ_INFO);
1064 if (RegQueryValueExW(hZoneKey,
1065 L"TZI",
1066 NULL,
1067 NULL,
1068 (LPBYTE)&Entry->TimezoneInfo,
1069 &dwValueSize))
1070 {
1071 RegCloseKey(hZoneKey);
1072 break;
1073 }
1074
1075 RegCloseKey(hZoneKey);
1076
1077 if (SetupData->TimeZoneListHead == NULL &&
1078 SetupData->TimeZoneListTail == NULL)
1079 {
1080 Entry->Prev = NULL;
1081 Entry->Next = NULL;
1082 SetupData->TimeZoneListHead = Entry;
1083 SetupData->TimeZoneListTail = Entry;
1084 }
1085 else
1086 {
1087 Current = GetLargerTimeZoneEntry(SetupData, Entry->Index);
1088 if (Current != NULL)
1089 {
1090 if (Current == SetupData->TimeZoneListHead)
1091 {
1092 /* Prepend to head */
1093 Entry->Prev = NULL;
1094 Entry->Next = SetupData->TimeZoneListHead;
1095 SetupData->TimeZoneListHead->Prev = Entry;
1096 SetupData->TimeZoneListHead = Entry;
1097 }
1098 else
1099 {
1100 /* Insert before current */
1101 Entry->Prev = Current->Prev;
1102 Entry->Next = Current;
1103 Current->Prev->Next = Entry;
1104 Current->Prev = Entry;
1105 }
1106 }
1107 else
1108 {
1109 /* Append to tail */
1110 Entry->Prev = SetupData->TimeZoneListTail;
1111 Entry->Next = NULL;
1112 SetupData->TimeZoneListTail->Next = Entry;
1113 SetupData->TimeZoneListTail = Entry;
1114 }
1115 }
1116
1117 dwIndex++;
1118 }
1119
1120 RegCloseKey(hZonesKey);
1121 }
1122
1123
1124 static VOID
1125 DestroyTimeZoneList(PSETUPDATA SetupData)
1126 {
1127 PTIMEZONE_ENTRY Entry;
1128
1129 while (SetupData->TimeZoneListHead != NULL)
1130 {
1131 Entry = SetupData->TimeZoneListHead;
1132
1133 SetupData->TimeZoneListHead = Entry->Next;
1134 if (SetupData->TimeZoneListHead != NULL)
1135 {
1136 SetupData->TimeZoneListHead->Prev = NULL;
1137 }
1138
1139 HeapFree(GetProcessHeap(), 0, Entry);
1140 }
1141
1142 SetupData->TimeZoneListTail = NULL;
1143 }
1144
1145 static BOOL
1146 GetTimeZoneListIndex(LPDWORD lpIndex)
1147 {
1148 WCHAR szLanguageIdString[9];
1149 HKEY hKey;
1150 DWORD dwValueSize;
1151 DWORD Length;
1152 LPWSTR Buffer;
1153 LPWSTR Ptr;
1154 LPWSTR End;
1155 BOOL bFound = FALSE;
1156 unsigned long iLanguageID;
1157
1158 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1159 L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
1160 0,
1161 KEY_ALL_ACCESS,
1162 &hKey))
1163 return FALSE;
1164
1165 dwValueSize = 9 * sizeof(WCHAR);
1166 if (RegQueryValueExW(hKey,
1167 L"Default",
1168 NULL,
1169 NULL,
1170 (LPBYTE)szLanguageIdString,
1171 &dwValueSize))
1172 {
1173 RegCloseKey(hKey);
1174 return FALSE;
1175 }
1176
1177 iLanguageID = wcstoul(szLanguageIdString, NULL, 16);
1178 RegCloseKey(hKey);
1179
1180 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1181 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
1182 0,
1183 KEY_ALL_ACCESS,
1184 &hKey))
1185 return FALSE;
1186
1187 dwValueSize = 0;
1188 if (RegQueryValueExW(hKey,
1189 L"IndexMapping",
1190 NULL,
1191 NULL,
1192 NULL,
1193 &dwValueSize))
1194 {
1195 RegCloseKey(hKey);
1196 return FALSE;
1197 }
1198
1199 Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
1200 if (Buffer == NULL)
1201 {
1202 RegCloseKey(hKey);
1203 return FALSE;
1204 }
1205
1206 if (RegQueryValueExW(hKey,
1207 L"IndexMapping",
1208 NULL,
1209 NULL,
1210 (LPBYTE)Buffer,
1211 &dwValueSize))
1212 {
1213 HeapFree(GetProcessHeap(), 0, Buffer);
1214 RegCloseKey(hKey);
1215 return FALSE;
1216 }
1217
1218 RegCloseKey(hKey);
1219
1220 Ptr = Buffer;
1221 while (*Ptr != 0)
1222 {
1223 Length = wcslen(Ptr);
1224 if (wcstoul(Ptr, NULL, 16) == iLanguageID)
1225 bFound = TRUE;
1226
1227 Ptr = Ptr + Length + 1;
1228 if (*Ptr == 0)
1229 break;
1230
1231 if (bFound)
1232 {
1233 *lpIndex = wcstoul(Ptr, &End, 10);
1234 HeapFree(GetProcessHeap(), 0, Buffer);
1235 return TRUE;
1236 }
1237
1238 Length = wcslen(Ptr);
1239 Ptr = Ptr + Length + 1;
1240 }
1241
1242 HeapFree(GetProcessHeap(), 0, Buffer);
1243
1244 return FALSE;
1245 }
1246
1247
1248 static VOID
1249 ShowTimeZoneList(HWND hwnd, PSETUPDATA SetupData, DWORD dwEntryIndex)
1250 {
1251 PTIMEZONE_ENTRY Entry;
1252 DWORD dwIndex = 0;
1253 DWORD dwCount;
1254
1255 GetTimeZoneListIndex(&dwEntryIndex);
1256
1257 Entry = SetupData->TimeZoneListHead;
1258 while (Entry != NULL)
1259 {
1260 dwCount = SendMessage(hwnd,
1261 CB_ADDSTRING,
1262 0,
1263 (LPARAM)Entry->Description);
1264
1265 if (dwEntryIndex != 0 && dwEntryIndex == Entry->Index)
1266 dwIndex = dwCount;
1267
1268 Entry = Entry->Next;
1269 }
1270
1271 SendMessage(hwnd,
1272 CB_SETCURSEL,
1273 (WPARAM)dwIndex,
1274 0);
1275 }
1276
1277
1278 static VOID
1279 SetLocalTimeZone(HWND hwnd, PSETUPDATA SetupData)
1280 {
1281 TIME_ZONE_INFORMATION TimeZoneInformation;
1282 PTIMEZONE_ENTRY Entry;
1283 DWORD dwIndex;
1284 DWORD i;
1285
1286 dwIndex = SendMessage(hwnd,
1287 CB_GETCURSEL,
1288 0,
1289 0);
1290
1291 i = 0;
1292 Entry = SetupData->TimeZoneListHead;
1293 while (i < dwIndex)
1294 {
1295 if (Entry == NULL)
1296 return;
1297
1298 i++;
1299 Entry = Entry->Next;
1300 }
1301
1302 wcscpy(TimeZoneInformation.StandardName,
1303 Entry->StandardName);
1304 wcscpy(TimeZoneInformation.DaylightName,
1305 Entry->DaylightName);
1306
1307 TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias;
1308 TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias;
1309 TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias;
1310
1311 memcpy(&TimeZoneInformation.StandardDate,
1312 &Entry->TimezoneInfo.StandardDate,
1313 sizeof(SYSTEMTIME));
1314 memcpy(&TimeZoneInformation.DaylightDate,
1315 &Entry->TimezoneInfo.DaylightDate,
1316 sizeof(SYSTEMTIME));
1317
1318 /* Set time zone information */
1319 SetTimeZoneInformation(&TimeZoneInformation);
1320 }
1321
1322
1323 static BOOL
1324 GetLocalSystemTime(HWND hwnd, PSETUPDATA SetupData)
1325 {
1326 SYSTEMTIME Date;
1327 SYSTEMTIME Time;
1328
1329 if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), &Date) != GDT_VALID)
1330 {
1331 return FALSE;
1332 }
1333
1334 if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), &Time) != GDT_VALID)
1335 {
1336 return FALSE;
1337 }
1338
1339 SetupData->SystemTime.wYear = Date.wYear;
1340 SetupData->SystemTime.wMonth = Date.wMonth;
1341 SetupData->SystemTime.wDayOfWeek = Date.wDayOfWeek;
1342 SetupData->SystemTime.wDay = Date.wDay;
1343 SetupData->SystemTime.wHour = Time.wHour;
1344 SetupData->SystemTime.wMinute = Time.wMinute;
1345 SetupData->SystemTime.wSecond = Time.wSecond;
1346 SetupData->SystemTime.wMilliseconds = Time.wMilliseconds;
1347
1348 return TRUE;
1349 }
1350
1351
1352 static VOID
1353 SetAutoDaylightInfo(HWND hwnd)
1354 {
1355 HKEY hKey;
1356 DWORD dwValue = 1;
1357
1358 if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
1359 {
1360 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1361 L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
1362 0,
1363 KEY_SET_VALUE,
1364 &hKey))
1365 return;
1366
1367 RegSetValueExW(hKey,
1368 L"DisableAutoDaylightTimeSet",
1369 0,
1370 REG_DWORD,
1371 (LPBYTE)&dwValue,
1372 sizeof(DWORD));
1373 RegCloseKey(hKey);
1374 }
1375 }
1376
1377
1378 static BOOL
1379 SetSystemLocalTime(HWND hwnd, PSETUPDATA SetupData)
1380 {
1381 BOOL Ret = FALSE;
1382
1383 /*
1384 * Call SetLocalTime twice to ensure correct results
1385 */
1386 Ret = SetLocalTime(&SetupData->SystemTime) &&
1387 SetLocalTime(&SetupData->SystemTime);
1388
1389 return Ret;
1390 }
1391
1392 static BOOL
1393 WriteDateTimeSettings(HWND hwndDlg, PSETUPDATA SetupData)
1394 {
1395 WCHAR Title[64];
1396 WCHAR ErrorLocalTime[256];
1397 GetLocalSystemTime(hwndDlg, SetupData);
1398 SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
1399 SetupData);
1400
1401 SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
1402 if(!SetSystemLocalTime(hwndDlg, SetupData))
1403 {
1404 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0])))
1405 {
1406 wcscpy(Title, L"ReactOS Setup");
1407 }
1408 if (0 == LoadStringW(hDllInstance, IDS_WZD_LOCALTIME, ErrorLocalTime,
1409 sizeof(ErrorLocalTime) / sizeof(ErrorLocalTime[0])))
1410 {
1411 wcscpy(ErrorLocalTime, L"Setup was unable to set the local time.");
1412 }
1413 MessageBoxW(hwndDlg, ErrorLocalTime, Title, MB_ICONWARNING | MB_OK);
1414 return FALSE;
1415 }
1416
1417 return TRUE;
1418 }
1419
1420 static INT_PTR CALLBACK
1421 DateTimePageDlgProc(HWND hwndDlg,
1422 UINT uMsg,
1423 WPARAM wParam,
1424 LPARAM lParam)
1425 {
1426 PSETUPDATA SetupData;
1427
1428 /* Retrieve pointer to the global setup data */
1429 SetupData = (PSETUPDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
1430
1431 switch (uMsg)
1432 {
1433 case WM_INITDIALOG:
1434 {
1435 /* Save pointer to the global setup data */
1436 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
1437 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)SetupData);
1438
1439 CreateTimeZoneList(SetupData);
1440
1441 if (SetupData->UnattendSetup)
1442 {
1443 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
1444 SetupData, SetupData->TimeZoneIndex);
1445
1446 if (!SetupData->DisableAutoDaylightTimeSet)
1447 {
1448 SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
1449 }
1450 }
1451 else
1452 {
1453 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
1454 SetupData, 85 /* GMT time zone */);
1455
1456 SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
1457 }
1458
1459 }
1460 break;
1461
1462
1463 case WM_NOTIFY:
1464 {
1465 LPNMHDR lpnm = (LPNMHDR)lParam;
1466
1467 switch (lpnm->code)
1468 {
1469 case PSN_SETACTIVE:
1470 /* Enable the Back and Next buttons */
1471 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
1472 if (SetupData->UnattendSetup && WriteDateTimeSettings(hwndDlg, SetupData))
1473 {
1474 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_PROCESSPAGE);
1475 return TRUE;
1476 }
1477 break;
1478
1479 case PSN_WIZNEXT:
1480 {
1481 WriteDateTimeSettings(hwndDlg, SetupData);
1482 }
1483 break;
1484
1485 case PSN_WIZBACK:
1486 SetupData->UnattendSetup = FALSE;
1487 break;
1488
1489 default:
1490 break;
1491 }
1492 }
1493 break;
1494
1495 case WM_DESTROY:
1496 DestroyTimeZoneList(SetupData);
1497 break;
1498
1499 default:
1500 break;
1501 }
1502
1503 return FALSE;
1504 }
1505
1506
1507 static UINT CALLBACK
1508 RegistrationNotificationProc(PVOID Context,
1509 UINT Notification,
1510 UINT_PTR Param1,
1511 UINT_PTR Param2)
1512 {
1513 PREGISTRATIONDATA RegistrationData;
1514 REGISTRATIONNOTIFY RegistrationNotify;
1515 PSP_REGISTER_CONTROL_STATUSW StatusInfo;
1516 UINT MessageID;
1517 WCHAR ErrorMessage[128];
1518
1519 RegistrationData = (PREGISTRATIONDATA) Context;
1520
1521 if (SPFILENOTIFY_STARTREGISTRATION == Notification ||
1522 SPFILENOTIFY_ENDREGISTRATION == Notification)
1523 {
1524 StatusInfo = (PSP_REGISTER_CONTROL_STATUSW) Param1;
1525 RegistrationNotify.CurrentItem = wcsrchr(StatusInfo->FileName, L'\\');
1526 if (NULL == RegistrationNotify.CurrentItem)
1527 {
1528 RegistrationNotify.CurrentItem = StatusInfo->FileName;
1529 }
1530 else
1531 {
1532 RegistrationNotify.CurrentItem++;
1533 }
1534
1535 if (SPFILENOTIFY_STARTREGISTRATION == Notification)
1536 {
1537 DPRINT("Received SPFILENOTIFY_STARTREGISTRATION notification for %S\n",
1538 StatusInfo->FileName);
1539 RegistrationNotify.ErrorMessage = NULL;
1540 RegistrationNotify.Progress = RegistrationData->Registered;
1541 }
1542 else
1543 {
1544 DPRINT("Received SPFILENOTIFY_ENDREGISTRATION notification for %S\n",
1545 StatusInfo->FileName);
1546 DPRINT("Win32Error %u FailureCode %u\n", StatusInfo->Win32Error,
1547 StatusInfo->FailureCode);
1548 if (SPREG_SUCCESS != StatusInfo->FailureCode)
1549 {
1550 switch(StatusInfo->FailureCode)
1551 {
1552 case SPREG_LOADLIBRARY:
1553 MessageID = IDS_LOADLIBRARY_FAILED;
1554 break;
1555 case SPREG_GETPROCADDR:
1556 MessageID = IDS_GETPROCADDR_FAILED;
1557 break;
1558 case SPREG_REGSVR:
1559 MessageID = IDS_REGSVR_FAILED;
1560 break;
1561 case SPREG_DLLINSTALL:
1562 MessageID = IDS_DLLINSTALL_FAILED;
1563 break;
1564 case SPREG_TIMEOUT:
1565 MessageID = IDS_TIMEOUT;
1566 break;
1567 default:
1568 MessageID = IDS_REASON_UNKNOWN;
1569 break;
1570 }
1571 if (0 == LoadStringW(hDllInstance, MessageID,
1572 ErrorMessage,
1573 sizeof(ErrorMessage) /
1574 sizeof(ErrorMessage[0])))
1575 {
1576 ErrorMessage[0] = L'\0';
1577 }
1578 if (SPREG_TIMEOUT != StatusInfo->FailureCode)
1579 {
1580 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
1581 StatusInfo->Win32Error, 0,
1582 ErrorMessage + wcslen(ErrorMessage),
1583 sizeof(ErrorMessage) / sizeof(ErrorMessage[0]) -
1584 wcslen(ErrorMessage), NULL);
1585 }
1586 RegistrationNotify.ErrorMessage = ErrorMessage;
1587 }
1588 else
1589 {
1590 RegistrationNotify.ErrorMessage = NULL;
1591 }
1592 if (RegistrationData->Registered < RegistrationData->DllCount)
1593 {
1594 RegistrationData->Registered++;
1595 }
1596 }
1597
1598 RegistrationNotify.Progress = RegistrationData->Registered;
1599 RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS;
1600 SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY,
1601 0, (LPARAM) &RegistrationNotify);
1602
1603 return FILEOP_DOIT;
1604 }
1605 else
1606 {
1607 DPRINT1("Received unexpected notification %u\n", Notification);
1608 return SetupDefaultQueueCallback(RegistrationData->DefaultContext,
1609 Notification, Param1, Param2);
1610 }
1611 }
1612
1613
1614 static DWORD CALLBACK
1615 RegistrationProc(LPVOID Parameter)
1616 {
1617 PREGISTRATIONDATA RegistrationData;
1618 REGISTRATIONNOTIFY RegistrationNotify;
1619 DWORD LastError = NO_ERROR;
1620 WCHAR UnknownError[84];
1621
1622 RegistrationData = (PREGISTRATIONDATA) Parameter;
1623 RegistrationData->Registered = 0;
1624 RegistrationData->DefaultContext = SetupInitDefaultQueueCallback(RegistrationData->hwndDlg);
1625
1626 _SEH2_TRY
1627 {
1628 if (!SetupInstallFromInfSectionW(GetParent(RegistrationData->hwndDlg),
1629 hSysSetupInf,
1630 L"RegistrationPhase2",
1631 SPINST_REGISTRY |
1632 SPINST_REGISTERCALLBACKAWARE |
1633 SPINST_REGSVR,
1634 0,
1635 NULL,
1636 0,
1637 RegistrationNotificationProc,
1638 RegistrationData,
1639 NULL,
1640 NULL))
1641 {
1642 LastError = GetLastError();
1643 }
1644 }
1645 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1646 {
1647 DPRINT("Catching exception\n");
1648 LastError = RtlNtStatusToDosError(_SEH2_GetExceptionCode());
1649 }
1650 _SEH2_END;
1651
1652 if (NO_ERROR == LastError)
1653 {
1654 RegistrationNotify.ErrorMessage = NULL;
1655 }
1656 else
1657 {
1658 DPRINT1("SetupInstallFromInfSection failed with error %u\n",
1659 LastError);
1660 if (0 == FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1661 FORMAT_MESSAGE_FROM_SYSTEM, NULL, LastError, 0,
1662 (LPWSTR) &RegistrationNotify.ErrorMessage, 0,
1663 NULL))
1664 {
1665 if (0 == LoadStringW(hDllInstance, IDS_UNKNOWN_ERROR,
1666 UnknownError,
1667 sizeof(UnknownError) / sizeof(UnknownError[0]) -
1668 20))
1669 {
1670 wcscpy(UnknownError, L"Unknown error");
1671 }
1672 wcscat(UnknownError, L" ");
1673 _ultow(LastError, UnknownError + wcslen(UnknownError), 10);
1674 RegistrationNotify.ErrorMessage = UnknownError;
1675 }
1676 }
1677
1678 RegistrationNotify.Progress = RegistrationData->DllCount;
1679 RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS;
1680 RegistrationNotify.CurrentItem = NULL;
1681 SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY,
1682 1, (LPARAM) &RegistrationNotify);
1683 if (NULL != RegistrationNotify.ErrorMessage &&
1684 UnknownError != RegistrationNotify.ErrorMessage)
1685 {
1686 LocalFree((PVOID) RegistrationNotify.ErrorMessage);
1687 }
1688
1689 SetupTermDefaultQueueCallback(RegistrationData->DefaultContext);
1690 HeapFree(GetProcessHeap(), 0, RegistrationData);
1691
1692 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries");
1693
1694 // FIXME: Move this call to a separate cleanup page!
1695 RtlCreateBootStatusDataFile();
1696
1697 return 0;
1698 }
1699
1700
1701 static BOOL
1702 StartComponentRegistration(HWND hwndDlg, PULONG MaxProgress)
1703 {
1704 HANDLE RegistrationThread;
1705 LONG DllCount;
1706 INFCONTEXT Context;
1707 WCHAR SectionName[512];
1708 PREGISTRATIONDATA RegistrationData;
1709
1710 DllCount = -1;
1711 if (! SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2",
1712 L"RegisterDlls", &Context))
1713 {
1714 DPRINT1("No RegistrationPhase2 section found\n");
1715 return FALSE;
1716 }
1717 if (! SetupGetStringFieldW(&Context, 1, SectionName,
1718 sizeof(SectionName) / sizeof(SectionName[0]),
1719 NULL))
1720 {
1721 DPRINT1("Unable to retrieve section name\n");
1722 return FALSE;
1723 }
1724 DllCount = SetupGetLineCountW(hSysSetupInf, SectionName);
1725 DPRINT("SectionName %S DllCount %ld\n", SectionName, DllCount);
1726 if (DllCount < 0)
1727 {
1728 SetLastError(STATUS_NOT_FOUND);
1729 return FALSE;
1730 }
1731
1732 *MaxProgress = (ULONG) DllCount;
1733
1734 /*
1735 * Create a background thread to do the actual registrations, so the
1736 * main thread can just run its message loop.
1737 */
1738 RegistrationThread = NULL;
1739 RegistrationData = HeapAlloc(GetProcessHeap(), 0,
1740 sizeof(REGISTRATIONDATA));
1741 if (RegistrationData != NULL)
1742 {
1743 RegistrationData->hwndDlg = hwndDlg;
1744 RegistrationData->DllCount = DllCount;
1745 RegistrationThread = CreateThread(NULL, 0, RegistrationProc,
1746 (LPVOID) RegistrationData, 0, NULL);
1747 if (RegistrationThread != NULL)
1748 {
1749 CloseHandle(RegistrationThread);
1750 }
1751 else
1752 {
1753 DPRINT1("CreateThread failed, error %u\n", GetLastError());
1754 HeapFree(GetProcessHeap(), 0, RegistrationData);
1755 return FALSE;
1756 }
1757 }
1758 else
1759 {
1760 DPRINT1("HeapAlloc() failed, error %u\n", GetLastError());
1761 return FALSE;
1762 }
1763
1764 return TRUE;
1765 }
1766
1767
1768 static INT_PTR CALLBACK
1769 ProcessPageDlgProc(HWND hwndDlg,
1770 UINT uMsg,
1771 WPARAM wParam,
1772 LPARAM lParam)
1773 {
1774 PSETUPDATA SetupData;
1775 PREGISTRATIONNOTIFY RegistrationNotify;
1776 static UINT oldActivityID = -1;
1777 WCHAR Title[64];
1778
1779 /* Retrieve pointer to the global setup data */
1780 SetupData = (PSETUPDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
1781
1782 switch (uMsg)
1783 {
1784 case WM_INITDIALOG:
1785 {
1786 /* Save pointer to the global setup data */
1787 SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
1788 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)SetupData);
1789 }
1790 break;
1791
1792 case WM_NOTIFY:
1793 {
1794 LPNMHDR lpnm = (LPNMHDR)lParam;
1795 ULONG MaxProgress = 0;
1796
1797 switch (lpnm->code)
1798 {
1799 case PSN_SETACTIVE:
1800 /* Disable the Back and Next buttons */
1801 PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
1802
1803 StartComponentRegistration(hwndDlg, &MaxProgress);
1804
1805 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETRANGE,
1806 0, MAKELPARAM(0, MaxProgress));
1807 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS,
1808 0, 0);
1809 break;
1810
1811 case PSN_WIZNEXT:
1812 break;
1813
1814 case PSN_WIZBACK:
1815 SetupData->UnattendSetup = FALSE;
1816 break;
1817
1818 default:
1819 break;
1820 }
1821 }
1822 break;
1823
1824 case PM_REGISTRATION_NOTIFY:
1825 {
1826 WCHAR Activity[64];
1827 RegistrationNotify = (PREGISTRATIONNOTIFY) lParam;
1828 // update if necessary only
1829 if (oldActivityID != RegistrationNotify->ActivityID)
1830 {
1831 if (0 != LoadStringW(hDllInstance, RegistrationNotify->ActivityID,
1832 Activity,
1833 sizeof(Activity) / sizeof(Activity[0])))
1834 {
1835 SendDlgItemMessageW(hwndDlg, IDC_ACTIVITY, WM_SETTEXT,
1836 0, (LPARAM) Activity);
1837 }
1838 oldActivityID = RegistrationNotify->ActivityID;
1839 }
1840 SendDlgItemMessageW(hwndDlg, IDC_ITEM, WM_SETTEXT, 0,
1841 (LPARAM)(NULL == RegistrationNotify->CurrentItem ?
1842 L"" : RegistrationNotify->CurrentItem));
1843 SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS,
1844 RegistrationNotify->Progress, 0);
1845 if (NULL != RegistrationNotify->ErrorMessage)
1846 {
1847 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP,
1848 Title, sizeof(Title) / sizeof(Title[0])))
1849 {
1850 wcscpy(Title, L"ReactOS Setup");
1851 }
1852 MessageBoxW(hwndDlg, RegistrationNotify->ErrorMessage,
1853 Title, MB_ICONERROR | MB_OK);
1854
1855 }
1856
1857 if (wParam)
1858 {
1859 #ifdef VMWINST
1860 if(!SetupData->UnattendSetup && !SetupData->DisableVmwInst)
1861 RunVMWInstall(GetParent(hwndDlg));
1862 #endif
1863
1864 /* Enable the Back and Next buttons */
1865 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
1866 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_NEXT);
1867 }
1868 }
1869 return TRUE;
1870
1871 default:
1872 break;
1873 }
1874
1875 return FALSE;
1876 }
1877
1878
1879 static VOID
1880 SetInstallationCompleted(VOID)
1881 {
1882 HKEY hKey = 0;
1883 DWORD InProgress = 0;
1884 DWORD InstallDate;
1885
1886 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE,
1887 L"SYSTEM\\Setup",
1888 0,
1889 KEY_WRITE,
1890 &hKey ) == ERROR_SUCCESS)
1891 {
1892 RegSetValueExW( hKey, L"SystemSetupInProgress", 0, REG_DWORD, (LPBYTE)&InProgress, sizeof(InProgress) );
1893 RegCloseKey( hKey );
1894 }
1895
1896 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE,
1897 L"Software\\Microsoft\\Windows NT\\CurrentVersion",
1898 0,
1899 KEY_WRITE,
1900 &hKey ) == ERROR_SUCCESS)
1901 {
1902 InstallDate = (DWORD)time(NULL);
1903 RegSetValueExW( hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate) );
1904 RegCloseKey( hKey );
1905 }
1906 }
1907
1908 static INT_PTR CALLBACK
1909 FinishDlgProc(HWND hwndDlg,
1910 UINT uMsg,
1911 WPARAM wParam,
1912 LPARAM lParam)
1913 {
1914
1915 switch (uMsg)
1916 {
1917 case WM_INITDIALOG:
1918 {
1919 /* Get pointer to the global setup data */
1920 PSETUPDATA SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
1921
1922 /* Run the Wine Gecko prompt */
1923 Control_RunDLLW(GetDesktopWindow(), 0, L"appwiz.cpl install_gecko", SW_SHOW);
1924
1925 /* Set title font */
1926 SendDlgItemMessage(hwndDlg,
1927 IDC_FINISHTITLE,
1928 WM_SETFONT,
1929 (WPARAM)SetupData->hTitleFont,
1930 (LPARAM)TRUE);
1931 if (SetupData->UnattendSetup)
1932 {
1933 KillTimer(hwndDlg, 1);
1934 SetInstallationCompleted();
1935 PostQuitMessage(0);
1936 }
1937 }
1938 break;
1939
1940 case WM_DESTROY:
1941 {
1942 SetInstallationCompleted();
1943 PostQuitMessage(0);
1944 return TRUE;
1945 }
1946
1947 case WM_TIMER:
1948 {
1949 INT Position;
1950 HWND hWndProgress;
1951
1952 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS);
1953 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0);
1954 if (Position == 300)
1955 {
1956 KillTimer(hwndDlg, 1);
1957 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH);
1958 }
1959 else
1960 {
1961 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0);
1962 }
1963 }
1964 return TRUE;
1965
1966 case WM_NOTIFY:
1967 {
1968 LPNMHDR lpnm = (LPNMHDR)lParam;
1969
1970 switch (lpnm->code)
1971 {
1972 case PSN_SETACTIVE:
1973 /* Enable the correct buttons on for the active page */
1974 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
1975
1976 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0,
1977 MAKELPARAM(0, 300));
1978 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0);
1979 SetTimer(hwndDlg, 1, 50, NULL);
1980 break;
1981
1982 case PSN_WIZFINISH:
1983 DestroyWindow(GetParent(hwndDlg));
1984 break;
1985
1986 default:
1987 break;
1988 }
1989 }
1990 break;
1991
1992 default:
1993 break;
1994 }
1995
1996 return FALSE;
1997 }
1998
1999
2000 BOOL
2001 ProcessUnattendInf(HINF hUnattendedInf)
2002 {
2003 INFCONTEXT InfContext;
2004 WCHAR szName[256];
2005 WCHAR szValue[MAX_PATH];
2006 DWORD LineLength;
2007 HKEY hKey;
2008
2009 if (!SetupFindFirstLineW(hUnattendedInf,
2010 L"Unattend",
2011 L"UnattendSetupEnabled",
2012 &InfContext))
2013 {
2014 DPRINT1("Error: Cant find UnattendSetupEnabled Key! %d\n", GetLastError());
2015 return FALSE;
2016 }
2017
2018 if (!SetupGetStringFieldW(&InfContext,
2019 1,
2020 szValue,
2021 sizeof(szValue) / sizeof(WCHAR),
2022 &LineLength))
2023 {
2024 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2025 return FALSE;
2026 }
2027
2028 if (wcscmp(szValue, L"yes") != 0)
2029 {
2030 DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n");
2031 return FALSE;
2032 }
2033
2034 if (!SetupFindFirstLineW(hUnattendedInf,
2035 L"Unattend",
2036 NULL,
2037 &InfContext))
2038 {
2039 DPRINT1("Error: SetupFindFirstLine failed %d\n", GetLastError());
2040 return FALSE;
2041 }
2042
2043
2044 do
2045 {
2046 if (!SetupGetStringFieldW(&InfContext,
2047 0,
2048 szName,
2049 sizeof(szName) / sizeof(WCHAR),
2050 &LineLength))
2051 {
2052 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2053 return FALSE;
2054 }
2055
2056 if (!SetupGetStringFieldW(&InfContext,
2057 1,
2058 szValue,
2059 sizeof(szValue) / sizeof(WCHAR),
2060 &LineLength))
2061 {
2062 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2063 return FALSE;
2064 }
2065 DPRINT1("Name %S Value %S\n", szName, szValue);
2066 if (!wcscmp(szName, L"FullName"))
2067 {
2068 if ((sizeof(SetupData.OwnerName) / sizeof(TCHAR)) > LineLength)
2069 {
2070 wcscpy(SetupData.OwnerName, szValue);
2071 }
2072 }
2073 else if (!wcscmp(szName, L"OrgName"))
2074 {
2075 if ((sizeof(SetupData.OwnerOrganization) / sizeof(WCHAR)) > LineLength)
2076 {
2077 wcscpy(SetupData.OwnerOrganization, szValue);
2078 }
2079 }
2080 else if (!wcscmp(szName, L"ComputerName"))
2081 {
2082 if ((sizeof(SetupData.ComputerName) / sizeof(WCHAR)) > LineLength)
2083 {
2084 wcscpy(SetupData.ComputerName, szValue);
2085 }
2086 }
2087 else if (!wcscmp(szName, L"AdminPassword"))
2088 {
2089 if ((sizeof(SetupData.AdminPassword) / sizeof(WCHAR)) > LineLength)
2090 {
2091 wcscpy(SetupData.AdminPassword, szValue);
2092 }
2093 }
2094 else if (!wcscmp(szName, L"TimeZoneIndex"))
2095 {
2096 SetupData.TimeZoneIndex = _wtoi(szValue);
2097 }
2098 else if (!wcscmp(szName, L"DisableAutoDaylightTimeSet"))
2099 {
2100 SetupData.DisableAutoDaylightTimeSet = _wtoi(szValue);
2101 }
2102 else if (!wcscmp(szName, L"DisableVmwInst"))
2103 {
2104 if(!wcscmp(szValue, L"yes"))
2105 SetupData.DisableVmwInst = 1;
2106 else
2107 SetupData.DisableVmwInst = 0;
2108 }
2109
2110 }
2111 while (SetupFindNextLine(&InfContext, &InfContext));
2112
2113 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2114 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
2115 0,
2116 KEY_SET_VALUE,
2117 &hKey) != ERROR_SUCCESS)
2118 {
2119 DPRINT1("Error: failed to open HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n");
2120 return TRUE;
2121 }
2122
2123
2124 if (SetupFindFirstLineW(hUnattendedInf,
2125 L"GuiRunOnce",
2126 NULL,
2127 &InfContext))
2128 {
2129
2130 int i = 0;
2131 do
2132 {
2133 if(SetupGetStringFieldW(&InfContext,
2134 0,
2135 szValue,
2136 sizeof(szValue) / sizeof(WCHAR),
2137 NULL))
2138 {
2139 WCHAR szPath[MAX_PATH];
2140 swprintf(szName, L"%d", i);
2141 DPRINT("szName %S szValue %S\n", szName, szValue);
2142
2143 if (ExpandEnvironmentStringsW(szValue, szPath, MAX_PATH))
2144 {
2145 DPRINT("value %S\n", szPath);
2146 if (RegSetValueExW(hKey,
2147 szName,
2148 0,
2149 REG_SZ,
2150 (const BYTE*)szPath,
2151 (wcslen(szPath) + 1) * sizeof(WCHAR)) == ERROR_SUCCESS)
2152 {
2153 i++;
2154 }
2155 }
2156 }
2157 } while(SetupFindNextLine(&InfContext, &InfContext));
2158 }
2159
2160 RegCloseKey(hKey);
2161 return TRUE;
2162 }
2163
2164 /*
2165 * GetRosInstallCD should find the path to ros installation medium
2166 * BUG 1
2167 * If there are more than one CDDrive in it containing a ReactOS
2168 * installation cd, then it will pick the first one regardless if
2169 * it is really the installation cd
2170 *
2171 * The best way to implement this is to set the key
2172 * HKLM\Software\Microsoft\Windows NT\CurrentVersion\SourcePath (REG_SZ)
2173 */
2174
2175 BOOL
2176 GetRosInstallCD(WCHAR *pwszPath, DWORD cchPathMax)
2177 {
2178 WCHAR wszDrives[512];
2179 DWORD cchDrives;
2180 WCHAR *pwszDrive;
2181
2182 cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
2183 if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
2184 {
2185 /* buffer too small or failure */
2186 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"GetLogicalDriveStringsW failed");
2187 return FALSE;
2188 }
2189
2190 for (pwszDrive = wszDrives; pwszDrive[0]; pwszDrive += wcslen(pwszDrive) + 1)
2191 {
2192 if (GetDriveTypeW(pwszDrive) == DRIVE_CDROM)
2193 {
2194 WCHAR wszBuf[MAX_PATH];
2195 wsprintf(wszBuf, L"%sreactos\\system32\\ntoskrnl.exe", pwszDrive);
2196 LogItem(SYSSETUP_SEVERITY_INFORMATION, wszBuf);
2197 if (GetFileAttributesW(wszBuf) != INVALID_FILE_ATTRIBUTES)
2198 {
2199 /* the file exists, so this is the right drive */
2200 wcsncpy(pwszPath, pwszDrive, cchPathMax);
2201 OutputDebugStringW(L"GetRosInstallCD: ");OutputDebugStringW(pwszPath);OutputDebugStringW(L"\n");
2202 return TRUE;
2203 }
2204 }
2205 }
2206 return FALSE;
2207 }
2208
2209
2210 VOID
2211 ProcessUnattendSetup(VOID)
2212 {
2213 WCHAR szPath[MAX_PATH];
2214 HINF hUnattendedInf;
2215 DWORD dwLength;
2216
2217 if (!GetRosInstallCD(szPath, MAX_PATH))
2218 {
2219 /* no cd drive found */
2220 return;
2221 }
2222
2223 dwLength = wcslen(szPath);
2224 if (dwLength + 21 > MAX_PATH)
2225 {
2226 /* FIXME
2227 * allocate bigger buffer
2228 */
2229 return;
2230 }
2231
2232 wcscat(szPath, L"reactos\\unattend.inf");
2233
2234 hUnattendedInf = SetupOpenInfFileW(szPath,
2235 NULL,
2236 INF_STYLE_OLDNT,
2237 NULL);
2238
2239 if (hUnattendedInf != INVALID_HANDLE_VALUE)
2240 {
2241 SetupData.UnattendSetup = ProcessUnattendInf(hUnattendedInf);
2242 SetupCloseInfFile(hUnattendedInf);
2243 }
2244 }
2245
2246
2247 VOID
2248 InstallWizard(VOID)
2249 {
2250 PROPSHEETHEADER psh;
2251 HPROPSHEETPAGE ahpsp[8];
2252 PROPSHEETPAGE psp = {0};
2253 UINT nPages = 0;
2254 HWND hWnd;
2255 MSG msg;
2256
2257 /* Clear setup data */
2258 ZeroMemory(&SetupData, sizeof(SETUPDATA));
2259
2260 ProcessUnattendSetup();
2261
2262 /* Create the Welcome page */
2263 psp.dwSize = sizeof(PROPSHEETPAGE);
2264 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
2265 psp.hInstance = hDllInstance;
2266 psp.lParam = (LPARAM)&SetupData;
2267 psp.pfnDlgProc = WelcomeDlgProc;
2268 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE);
2269 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2270
2271 /* Create the Acknowledgements page */
2272 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
2273 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ACKTITLE);
2274 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_ACKSUBTITLE);
2275 psp.pszTemplate = MAKEINTRESOURCE(IDD_ACKPAGE);
2276 psp.pfnDlgProc = AckPageDlgProc;
2277 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2278
2279 /* Create the Locale page */
2280 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
2281 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LOCALETITLE);
2282 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LOCALESUBTITLE);
2283 psp.pfnDlgProc = LocalePageDlgProc;
2284 psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE);
2285 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2286
2287
2288 /* Create the Owner page */
2289 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
2290 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_OWNERTITLE);
2291 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_OWNERSUBTITLE);
2292 psp.pszTemplate = MAKEINTRESOURCE(IDD_OWNERPAGE);
2293 psp.pfnDlgProc = OwnerPageDlgProc;
2294 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2295
2296 /* Create the Computer page */
2297 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
2298 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_COMPUTERTITLE);
2299 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_COMPUTERSUBTITLE);
2300 psp.pfnDlgProc = ComputerPageDlgProc;
2301 psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPUTERPAGE);
2302 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2303
2304
2305 /* Create the DateTime page */
2306 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
2307 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE);
2308 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DATETIMESUBTITLE);
2309 psp.pfnDlgProc = DateTimePageDlgProc;
2310 psp.pszTemplate = MAKEINTRESOURCE(IDD_DATETIMEPAGE);
2311 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2312
2313
2314 /* Create the Process page */
2315 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
2316 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
2317 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
2318 psp.pfnDlgProc = ProcessPageDlgProc;
2319 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
2320 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2321
2322
2323 /* Create the Finish page */
2324 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
2325 psp.pfnDlgProc = FinishDlgProc;
2326 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
2327 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
2328
2329 /* Create the property sheet */
2330 psh.dwSize = sizeof(PROPSHEETHEADER);
2331 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_MODELESS;
2332 psh.hInstance = hDllInstance;
2333 psh.hwndParent = NULL;
2334 psh.nPages = nPages;
2335 psh.nStartPage = 0;
2336 psh.phpage = ahpsp;
2337 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
2338 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
2339
2340 /* Create title font */
2341 SetupData.hTitleFont = CreateTitleFont();
2342
2343 /* Display the wizard */
2344 hWnd = (HWND)PropertySheet(&psh);
2345 ShowWindow(hWnd, SW_SHOW);
2346
2347 while (GetMessage(&msg, NULL, 0, 0))
2348 {
2349 if(!IsDialogMessage(hWnd, &msg))
2350 {
2351 TranslateMessage(&msg);
2352 DispatchMessage(&msg);
2353 }
2354 }
2355
2356 DeleteObject(SetupData.hTitleFont);
2357 }
2358
2359 /* EOF */