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