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