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