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