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