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