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