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