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