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