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