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