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