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