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