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