7bc0581b9c7191f028c51d6d84903da15247a893
[reactos.git] / base / setup / reactos / reactos.c
1 /*
2 * ReactOS applications
3 * Copyright (C) 2004-2008 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS GUI first stage setup application
22 * FILE: base/setup/reactos/reactos.c
23 * PROGRAMMERS: Matthias Kupfer
24 * Dmitry Chapyshev (dmitry@reactos.org)
25 */
26
27 #include "reactos.h"
28 #include "resource.h"
29
30 #define NDEBUG
31 #include <debug.h>
32
33 /* GLOBALS ******************************************************************/
34
35 HANDLE ProcessHeap;
36 BOOLEAN IsUnattendedSetup = FALSE;
37 SETUPDATA SetupData;
38
39
40 /* FUNCTIONS ****************************************************************/
41
42 static VOID
43 CenterWindow(HWND hWnd)
44 {
45 HWND hWndParent;
46 RECT rcParent;
47 RECT rcWindow;
48
49 hWndParent = GetParent(hWnd);
50 if (hWndParent == NULL)
51 hWndParent = GetDesktopWindow();
52
53 GetWindowRect(hWndParent, &rcParent);
54 GetWindowRect(hWnd, &rcWindow);
55
56 SetWindowPos(hWnd,
57 HWND_TOP,
58 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
59 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
60 0,
61 0,
62 SWP_NOSIZE);
63 }
64
65 static HFONT
66 CreateTitleFont(VOID)
67 {
68 NONCLIENTMETRICS ncm;
69 LOGFONT LogFont;
70 HDC hdc;
71 INT FontSize;
72 HFONT hFont;
73
74 ncm.cbSize = sizeof(NONCLIENTMETRICS);
75 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
76
77 LogFont = ncm.lfMessageFont;
78 LogFont.lfWeight = FW_BOLD;
79 _tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
80
81 hdc = GetDC(NULL);
82 FontSize = 12;
83 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
84 hFont = CreateFontIndirect(&LogFont);
85 ReleaseDC(NULL, hdc);
86
87 return hFont;
88 }
89
90 INT DisplayError(
91 IN HWND hParentWnd OPTIONAL,
92 IN UINT uIDTitle,
93 IN UINT uIDMessage)
94 {
95 WCHAR message[512], caption[64];
96
97 LoadStringW(SetupData.hInstance, uIDMessage, message, ARRAYSIZE(message));
98 LoadStringW(SetupData.hInstance, uIDTitle, caption, ARRAYSIZE(caption));
99
100 return MessageBoxW(hParentWnd, message, caption, MB_OK | MB_ICONERROR);
101 }
102
103 static INT_PTR CALLBACK
104 StartDlgProc(
105 IN HWND hwndDlg,
106 IN UINT uMsg,
107 IN WPARAM wParam,
108 IN LPARAM lParam)
109 {
110 PSETUPDATA pSetupData;
111
112 /* Retrieve pointer to the global setup data */
113 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
114
115 switch (uMsg)
116 {
117 case WM_INITDIALOG:
118 /* Save pointer to the global setup data */
119 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
120 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
121
122 /* Center the wizard window */
123 CenterWindow(GetParent(hwndDlg));
124
125 /* Set title font */
126 SendDlgItemMessage(hwndDlg,
127 IDC_STARTTITLE,
128 WM_SETFONT,
129 (WPARAM)pSetupData->hTitleFont,
130 (LPARAM)TRUE);
131 break;
132
133 case WM_NOTIFY:
134 {
135 LPNMHDR lpnm = (LPNMHDR)lParam;
136
137 switch (lpnm->code)
138 {
139 case PSN_SETACTIVE:
140 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
141 break;
142
143 default:
144 break;
145 }
146 }
147 break;
148
149 default:
150 break;
151
152 }
153
154 return FALSE;
155 }
156
157 static INT_PTR CALLBACK
158 TypeDlgProc(
159 IN HWND hwndDlg,
160 IN UINT uMsg,
161 IN WPARAM wParam,
162 IN LPARAM lParam)
163 {
164 PSETUPDATA pSetupData;
165
166 /* Retrieve pointer to the global setup data */
167 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
168
169 switch (uMsg)
170 {
171 case WM_INITDIALOG:
172 {
173 /* Save pointer to the global setup data */
174 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
175 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
176
177 /* Check the 'install' radio button */
178 CheckDlgButton(hwndDlg, IDC_INSTALL, BST_CHECKED);
179
180 /*
181 * Enable the 'update' radio button and text only if we have
182 * available NT installations, otherwise disable them.
183 */
184 if (pSetupData->NtOsInstallsList &&
185 GetNumberOfListEntries(pSetupData->NtOsInstallsList) != 0)
186 {
187 EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), TRUE);
188 EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATETEXT), TRUE);
189 }
190 else
191 {
192 EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE);
193 EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATETEXT), FALSE);
194 }
195
196 break;
197 }
198
199 case WM_NOTIFY:
200 {
201 LPNMHDR lpnm = (LPNMHDR)lParam;
202
203 switch (lpnm->code)
204 {
205 case PSN_SETACTIVE:
206 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
207 break;
208
209 case PSN_QUERYCANCEL:
210 SetWindowLongPtrW(hwndDlg,
211 DWLP_MSGRESULT,
212 MessageBoxW(GetParent(hwndDlg),
213 pSetupData->szAbortMessage,
214 pSetupData->szAbortTitle,
215 MB_YESNO | MB_ICONQUESTION) != IDYES);
216 return TRUE;
217
218 case PSN_WIZNEXT: /* Set the selected data */
219 {
220 pSetupData->RepairUpdateFlag =
221 !(SendMessageW(GetDlgItem(hwndDlg, IDC_INSTALL),
222 BM_GETCHECK,
223 0, 0) == BST_CHECKED);
224
225 /*
226 * Display the existing NT installations page only
227 * if we have more than one available NT installations.
228 */
229 if (pSetupData->NtOsInstallsList &&
230 GetNumberOfListEntries(pSetupData->NtOsInstallsList) > 1)
231 {
232 /* Actually the best would be to dynamically insert the page only when needed */
233 SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, IDD_UPDATEREPAIRPAGE);
234 }
235 else
236 {
237 SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, IDD_DEVICEPAGE);
238 }
239
240 return TRUE;
241 }
242
243 default:
244 break;
245 }
246 }
247 break;
248
249 default:
250 break;
251
252 }
253 return FALSE;
254 }
255
256
257
258 typedef VOID
259 (NTAPI *PGET_ENTRY_DESCRIPTION)(
260 IN PGENERIC_LIST_ENTRY Entry,
261 OUT PWSTR Buffer,
262 IN SIZE_T cchBufferSize);
263
264 VOID
265 InitGenericComboList(
266 IN HWND hWndList,
267 IN PGENERIC_LIST List,
268 IN PGET_ENTRY_DESCRIPTION GetEntryDescriptionProc)
269 {
270 INT Index, CurrentEntryIndex = 0;
271 PGENERIC_LIST_ENTRY ListEntry;
272 PLIST_ENTRY Entry;
273 WCHAR CurrentItemText[256];
274
275 for (Entry = List->ListHead.Flink;
276 Entry != &List->ListHead;
277 Entry = Entry->Flink)
278 {
279 ListEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
280
281 if (GetEntryDescriptionProc)
282 {
283 GetEntryDescriptionProc(ListEntry,
284 CurrentItemText,
285 ARRAYSIZE(CurrentItemText));
286 Index = SendMessageW(hWndList, CB_ADDSTRING, 0, (LPARAM)CurrentItemText);
287 }
288 else
289 {
290 Index = SendMessageW(hWndList, CB_ADDSTRING, 0, (LPARAM)L"n/a");
291 }
292
293 if (ListEntry == List->CurrentEntry)
294 CurrentEntryIndex = Index;
295
296 SendMessageW(hWndList, CB_SETITEMDATA, Index, (LPARAM)ListEntry);
297 }
298
299 SendMessageW(hWndList, CB_SETCURSEL, CurrentEntryIndex, 0);
300 }
301
302 INT
303 GetSelectedComboListItem(
304 IN HWND hWndList)
305 {
306 LRESULT Index;
307
308 Index = SendMessageW(hWndList, CB_GETCURSEL, 0, 0);
309 if (Index == CB_ERR)
310 return CB_ERR;
311
312 // TODO: Update List->CurrentEntry?
313 // return SendMessageW(hWndList, CB_GETITEMDATA, (WPARAM)Index, 0);
314 return Index;
315 }
316
317 typedef VOID
318 (NTAPI *PADD_ENTRY_ITEM)(
319 IN HWND hWndList,
320 IN LVITEM* plvItem,
321 IN PGENERIC_LIST_ENTRY Entry,
322 IN OUT PWSTR Buffer,
323 IN SIZE_T cchBufferSize);
324
325 VOID
326 InitGenericListView(
327 IN HWND hWndList,
328 IN PGENERIC_LIST List,
329 IN PADD_ENTRY_ITEM AddEntryItemProc)
330 {
331 INT CurrentEntryIndex = 0;
332 LVITEM lvItem;
333 PGENERIC_LIST_ENTRY ListEntry;
334 PLIST_ENTRY Entry;
335 WCHAR CurrentItemText[256];
336
337 for (Entry = List->ListHead.Flink;
338 Entry != &List->ListHead;
339 Entry = Entry->Flink)
340 {
341 ListEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
342
343 if (!AddEntryItemProc)
344 continue;
345
346 AddEntryItemProc(hWndList,
347 &lvItem,
348 ListEntry,
349 CurrentItemText,
350 ARRAYSIZE(CurrentItemText));
351
352 if (ListEntry == List->CurrentEntry)
353 CurrentEntryIndex = lvItem.iItem;
354 }
355
356 SendMessageW(hWndList, LVM_ENSUREVISIBLE, CurrentEntryIndex, FALSE);
357 ListView_SetItemState(hWndList, CurrentEntryIndex, LVIS_SELECTED, LVIS_SELECTED);
358 ListView_SetItemState(hWndList, CurrentEntryIndex, LVIS_FOCUSED, LVIS_FOCUSED);
359 }
360
361
362 static VOID
363 NTAPI
364 GetSettingDescription(
365 IN PGENERIC_LIST_ENTRY Entry,
366 OUT PWSTR Buffer,
367 IN SIZE_T cchBufferSize)
368 {
369 StringCchCopyW(Buffer, cchBufferSize,
370 ((PGENENTRY)GetListEntryData(Entry))->Value);
371 }
372
373 static VOID
374 NTAPI
375 AddNTOSInstallationItem(
376 IN HWND hWndList,
377 IN LVITEM* plvItem,
378 IN PGENERIC_LIST_ENTRY Entry,
379 IN OUT PWSTR Buffer, // SystemRootPath
380 IN SIZE_T cchBufferSize)
381 {
382 PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
383 PPARTENTRY PartEntry = NtOsInstall->PartEntry;
384
385 if (PartEntry && PartEntry->DriveLetter)
386 {
387 /* We have retrieved a partition that is mounted */
388 StringCchPrintfW(Buffer, cchBufferSize,
389 L"%C:%s",
390 PartEntry->DriveLetter,
391 NtOsInstall->PathComponent);
392 }
393 else
394 {
395 /* We failed somewhere, just show the NT path */
396 StringCchPrintfW(Buffer, cchBufferSize,
397 L"%wZ",
398 &NtOsInstall->SystemNtPath);
399 }
400
401 plvItem->mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
402 plvItem->iItem = 0;
403 plvItem->iSubItem = 0;
404 plvItem->lParam = (LPARAM)Entry;
405 plvItem->pszText = NtOsInstall->InstallationName;
406
407 /* Associate vendor icon */
408 if (FindSubStrI(NtOsInstall->VendorName, VENDOR_REACTOS))
409 {
410 plvItem->mask |= LVIF_IMAGE;
411 plvItem->iImage = 0;
412 }
413 else if (FindSubStrI(NtOsInstall->VendorName, VENDOR_MICROSOFT))
414 {
415 plvItem->mask |= LVIF_IMAGE;
416 plvItem->iImage = 1;
417 }
418
419 plvItem->iItem = SendMessageW(hWndList, LVM_INSERTITEMW, 0, (LPARAM)plvItem);
420
421 plvItem->iSubItem = 1;
422 plvItem->pszText = Buffer; // SystemRootPath;
423 SendMessageW(hWndList, LVM_SETITEMTEXTW, plvItem->iItem, (LPARAM)plvItem);
424
425 plvItem->iSubItem = 2;
426 plvItem->pszText = NtOsInstall->VendorName;
427 SendMessageW(hWndList, LVM_SETITEMTEXTW, plvItem->iItem, (LPARAM)plvItem);
428 }
429
430
431 #define IDS_LIST_COLUMN_FIRST IDS_INSTALLATION_NAME
432 #define IDS_LIST_COLUMN_LAST IDS_INSTALLATION_VENDOR
433
434 #define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1)
435 static const UINT column_ids[MAX_LIST_COLUMNS] = {IDS_LIST_COLUMN_FIRST, IDS_LIST_COLUMN_FIRST + 1, IDS_LIST_COLUMN_FIRST + 2};
436 static const INT column_widths[MAX_LIST_COLUMNS] = {200, 150, 100};
437 static const INT column_alignment[MAX_LIST_COLUMNS] = {LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT};
438
439 static INT_PTR CALLBACK
440 UpgradeRepairDlgProc(
441 IN HWND hwndDlg,
442 IN UINT uMsg,
443 IN WPARAM wParam,
444 IN LPARAM lParam)
445 {
446 PSETUPDATA pSetupData;
447 HWND hList;
448 HIMAGELIST hSmall;
449
450 /* Retrieve pointer to the global setup data */
451 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
452
453 switch (uMsg)
454 {
455 case WM_INITDIALOG:
456 {
457 /* Save pointer to the global setup data */
458 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
459 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
460
461 hList = GetDlgItem(hwndDlg, IDC_NTOSLIST);
462
463 CreateListViewColumns(pSetupData->hInstance,
464 hList,
465 column_ids,
466 column_widths,
467 column_alignment,
468 MAX_LIST_COLUMNS);
469
470 /* Create the ImageList */
471 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
472 GetSystemMetrics(SM_CYSMICON),
473 ILC_COLOR32 | ILC_MASK, // ILC_COLOR24
474 1, 1);
475
476 /* Add event type icons to the ImageList */
477 ImageList_AddIcon(hSmall, LoadIconW(pSetupData->hInstance, MAKEINTRESOURCEW(IDI_ROSICON)));
478 ImageList_AddIcon(hSmall, LoadIconW(pSetupData->hInstance, MAKEINTRESOURCEW(IDI_WINICON)));
479
480 /* Assign the ImageList to the List View */
481 ListView_SetImageList(hList, hSmall, LVSIL_SMALL);
482
483 InitGenericListView(hList, pSetupData->NtOsInstallsList, AddNTOSInstallationItem);
484
485 break;
486 }
487
488 case WM_DESTROY:
489 {
490 hList = GetDlgItem(hwndDlg, IDC_NTOSLIST);
491 hSmall = ListView_GetImageList(hList, LVSIL_SMALL);
492 ListView_SetImageList(hList, NULL, LVSIL_SMALL);
493 ImageList_Destroy(hSmall);
494 return TRUE;
495 }
496
497 case WM_NOTIFY:
498 {
499 LPNMHDR lpnm = (LPNMHDR)lParam;
500
501 switch (lpnm->code)
502 {
503 case PSN_SETACTIVE:
504 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
505 break;
506
507 case PSN_QUERYCANCEL:
508 SetWindowLongPtrW(hwndDlg,
509 DWLP_MSGRESULT,
510 MessageBoxW(GetParent(hwndDlg),
511 pSetupData->szAbortMessage,
512 pSetupData->szAbortTitle,
513 MB_YESNO | MB_ICONQUESTION) != IDYES);
514 return TRUE;
515
516 case PSN_WIZNEXT: /* Set the selected data */
517 pSetupData->RepairUpdateFlag =
518 !(SendMessageW(GetDlgItem(hwndDlg, IDC_INSTALL),
519 BM_GETCHECK,
520 0, 0) == BST_CHECKED);
521 return TRUE;
522
523 default:
524 break;
525 }
526 }
527 break;
528
529 default:
530 break;
531
532 }
533 return FALSE;
534 }
535
536 static INT_PTR CALLBACK
537 DeviceDlgProc(
538 IN HWND hwndDlg,
539 IN UINT uMsg,
540 IN WPARAM wParam,
541 IN LPARAM lParam)
542 {
543 PSETUPDATA pSetupData;
544 HWND hList;
545
546 /* Retrieve pointer to the global setup data */
547 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
548
549 switch (uMsg)
550 {
551 case WM_INITDIALOG:
552 {
553 /* Save pointer to the global setup data */
554 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
555 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
556
557 hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
558 InitGenericComboList(hList, pSetupData->ComputerList, GetSettingDescription);
559
560 hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
561 InitGenericComboList(hList, pSetupData->DisplayList, GetSettingDescription);
562
563 hList = GetDlgItem(hwndDlg, IDC_KEYBOARD);
564 InitGenericComboList(hList, pSetupData->KeyboardList, GetSettingDescription);
565
566 // hList = GetDlgItem(hwndDlg, IDC_KEYBOARD_LAYOUT);
567 // InitGenericComboList(hList, pSetupData->LayoutList, GetSettingDescription);
568
569 break;
570 }
571
572 case WM_NOTIFY:
573 {
574 LPNMHDR lpnm = (LPNMHDR)lParam;
575
576 switch (lpnm->code)
577 {
578 case PSN_SETACTIVE:
579 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
580 break;
581
582 case PSN_QUERYCANCEL:
583 SetWindowLongPtrW(hwndDlg,
584 DWLP_MSGRESULT,
585 MessageBoxW(GetParent(hwndDlg),
586 pSetupData->szAbortMessage,
587 pSetupData->szAbortTitle,
588 MB_YESNO | MB_ICONQUESTION) != IDYES);
589 return TRUE;
590
591 case PSN_WIZNEXT: /* Set the selected data */
592 {
593 hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
594 pSetupData->SelectedComputer = GetSelectedComboListItem(hList);
595
596 hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
597 pSetupData->SelectedDisplay = GetSelectedComboListItem(hList);
598
599 hList = GetDlgItem(hwndDlg, IDC_KEYBOARD);
600 pSetupData->SelectedKeyboard = GetSelectedComboListItem(hList);
601
602 return TRUE;
603 }
604
605 default:
606 break;
607 }
608 }
609 break;
610
611 default:
612 break;
613
614 }
615 return FALSE;
616 }
617
618 static INT_PTR CALLBACK
619 SummaryDlgProc(
620 IN HWND hwndDlg,
621 IN UINT uMsg,
622 IN WPARAM wParam,
623 IN LPARAM lParam)
624 {
625 PSETUPDATA pSetupData;
626
627 /* Retrieve pointer to the global setup data */
628 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
629
630 switch (uMsg)
631 {
632 case WM_INITDIALOG:
633 /* Save pointer to the global setup data */
634 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
635 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
636 break;
637
638 case WM_NOTIFY:
639 {
640 LPNMHDR lpnm = (LPNMHDR)lParam;
641
642 switch (lpnm->code)
643 {
644 case PSN_SETACTIVE:
645 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
646 break;
647
648 case PSN_QUERYCANCEL:
649 SetWindowLongPtrW(hwndDlg,
650 DWLP_MSGRESULT,
651 MessageBoxW(GetParent(hwndDlg),
652 pSetupData->szAbortMessage,
653 pSetupData->szAbortTitle,
654 MB_YESNO | MB_ICONQUESTION) != IDYES);
655 return TRUE;
656
657 default:
658 break;
659 }
660 }
661 break;
662
663 default:
664 break;
665 }
666
667 return FALSE;
668 }
669
670 static INT_PTR CALLBACK
671 ProcessDlgProc(
672 IN HWND hwndDlg,
673 IN UINT uMsg,
674 IN WPARAM wParam,
675 IN LPARAM lParam)
676 {
677 PSETUPDATA pSetupData;
678
679 /* Retrieve pointer to the global setup data */
680 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
681
682 switch (uMsg)
683 {
684 case WM_INITDIALOG:
685 /* Save pointer to the global setup data */
686 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
687 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
688 break;
689
690 case WM_NOTIFY:
691 {
692 LPNMHDR lpnm = (LPNMHDR)lParam;
693
694 switch (lpnm->code)
695 {
696 case PSN_SETACTIVE:
697 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
698 // disable all buttons during installation process
699 // PropSheet_SetWizButtons(GetParent(hwndDlg), 0 );
700 break;
701 case PSN_QUERYCANCEL:
702 SetWindowLongPtrW(hwndDlg,
703 DWLP_MSGRESULT,
704 MessageBoxW(GetParent(hwndDlg),
705 pSetupData->szAbortMessage,
706 pSetupData->szAbortTitle,
707 MB_YESNO | MB_ICONQUESTION) != IDYES);
708 return TRUE;
709
710 default:
711 break;
712 }
713 }
714 break;
715
716 default:
717 break;
718
719 }
720
721 return FALSE;
722 }
723
724 static INT_PTR CALLBACK
725 RestartDlgProc(
726 IN HWND hwndDlg,
727 IN UINT uMsg,
728 IN WPARAM wParam,
729 IN LPARAM lParam)
730 {
731 PSETUPDATA pSetupData;
732
733 /* Retrieve pointer to the global setup data */
734 pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
735
736 switch (uMsg)
737 {
738 case WM_INITDIALOG:
739 /* Save pointer to the global setup data */
740 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
741 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
742
743 /* Set title font */
744 /*SendDlgItemMessage(hwndDlg,
745 IDC_STARTTITLE,
746 WM_SETFONT,
747 (WPARAM)hTitleFont,
748 (LPARAM)TRUE);*/
749 break;
750
751 case WM_TIMER:
752 {
753 INT Position;
754 HWND hWndProgress;
755
756 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS);
757 Position = SendMessageW(hWndProgress, PBM_GETPOS, 0, 0);
758 if (Position == 300)
759 {
760 KillTimer(hwndDlg, 1);
761 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH);
762 }
763 else
764 {
765 SendMessageW(hWndProgress, PBM_SETPOS, Position + 1, 0);
766 }
767 return TRUE;
768 }
769
770 case WM_DESTROY:
771 return TRUE;
772
773 case WM_NOTIFY:
774 {
775 LPNMHDR lpnm = (LPNMHDR)lParam;
776
777 switch (lpnm->code)
778 {
779 case PSN_SETACTIVE: // Only "Finish" for closing the App
780 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
781 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
782 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0);
783 SetTimer(hwndDlg, 1, 50, NULL);
784 break;
785
786 default:
787 break;
788 }
789 }
790 break;
791
792 default:
793 break;
794
795 }
796
797 return FALSE;
798 }
799
800 BOOL LoadSetupData(
801 IN OUT PSETUPDATA pSetupData)
802 {
803 BOOL ret = TRUE;
804 // INFCONTEXT InfContext;
805 // TCHAR tmp[10];
806 // DWORD LineLength;
807 // LONG Count;
808
809 /* Load the hardware, language and keyboard layout lists */
810
811 pSetupData->ComputerList = CreateComputerTypeList(pSetupData->SetupInf);
812 pSetupData->DisplayList = CreateDisplayDriverList(pSetupData->SetupInf);
813 pSetupData->KeyboardList = CreateKeyboardDriverList(pSetupData->SetupInf);
814
815 pSetupData->LanguageList = CreateLanguageList(pSetupData->SetupInf, pSetupData->DefaultLanguage);
816
817 pSetupData->PartitionList = CreatePartitionList();
818
819 pSetupData->NtOsInstallsList = CreateNTOSInstallationsList(pSetupData->PartitionList);
820 if (!pSetupData->NtOsInstallsList)
821 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
822
823
824 /* new part */
825 pSetupData->SelectedLanguageId = pSetupData->DefaultLanguage;
826 wcscpy(pSetupData->DefaultLanguage, pSetupData->USetupData.LocaleID);
827 pSetupData->USetupData.LanguageId = (LANGID)(wcstol(pSetupData->SelectedLanguageId, NULL, 16) & 0xFFFF);
828
829 pSetupData->LayoutList = CreateKeyboardLayoutList(pSetupData->SetupInf, pSetupData->SelectedLanguageId, pSetupData->DefaultKBLayout);
830
831 #if 0
832 // get default for keyboard and language
833 pSetupData->DefaultKBLayout = -1;
834 pSetupData->DefaultLang = -1;
835
836 // TODO: get defaults from underlaying running system
837 if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLayout"), &InfContext))
838 {
839 SetupGetStringField(&InfContext, 1, tmp, ARRAYSIZE(tmp), &LineLength);
840 for (Count = 0; Count < pSetupData->KbLayoutCount; Count++)
841 {
842 if (_tcscmp(tmp, pSetupData->pKbLayouts[Count].LayoutId) == 0)
843 {
844 pSetupData->DefaultKBLayout = Count;
845 break;
846 }
847 }
848 }
849
850 if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLanguage"), &InfContext))
851 {
852 SetupGetStringField(&InfContext, 1, tmp, ARRAYSIZE(tmp), &LineLength);
853 for (Count = 0; Count < pSetupData->LangCount; Count++)
854 {
855 if (_tcscmp(tmp, pSetupData->pLanguages[Count].LangId) == 0)
856 {
857 pSetupData->DefaultLang = Count;
858 break;
859 }
860 }
861 }
862 #endif
863
864 return ret;
865 }
866
867 /*
868 * Attempts to convert a pure NT file path into a corresponding Win32 path.
869 * Adapted from GetInstallSourceWin32() in dll/win32/syssetup/wizard.c
870 */
871 BOOL
872 ConvertNtPathToWin32Path(
873 OUT PWSTR pwszPath,
874 IN DWORD cchPathMax,
875 IN PCWSTR pwszNTPath)
876 {
877 WCHAR wszDrives[512];
878 WCHAR wszNTPath[512]; // MAX_PATH ?
879 DWORD cchDrives;
880 PWCHAR pwszDrive;
881
882 *pwszPath = UNICODE_NULL;
883
884 cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
885 if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
886 {
887 /* Buffer too small or failure */
888 DPRINT1("GetLogicalDriveStringsW failed\n");
889 return FALSE;
890 }
891
892 for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
893 {
894 /* Retrieve the NT path corresponding to the current Win32 DOS path */
895 pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash
896 QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath));
897 pwszDrive[2] = L'\\'; // Restore the backslash
898
899 wcscat(wszNTPath, L"\\"); // Concat a backslash
900
901 DPRINT1("Testing '%S' --> '%S'\n", pwszDrive, wszNTPath);
902
903 /* Check whether the NT path corresponds to the NT installation source path */
904 if (!_wcsnicmp(wszNTPath, pwszNTPath, wcslen(wszNTPath)))
905 {
906 /* Found it! */
907 wsprintf(pwszPath, L"%s%s", // cchPathMax
908 pwszDrive, pwszNTPath + wcslen(wszNTPath));
909 DPRINT1("ConvertNtPathToWin32Path: %S\n", pwszPath);
910 return TRUE;
911 }
912 }
913
914 return FALSE;
915 }
916
917 /* Used to enable and disable the shutdown privilege */
918 /* static */ BOOL
919 EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
920 {
921 BOOL Success;
922 HANDLE hToken;
923 TOKEN_PRIVILEGES tp;
924
925 Success = OpenProcessToken(GetCurrentProcess(),
926 TOKEN_ADJUST_PRIVILEGES,
927 &hToken);
928 if (!Success) return Success;
929
930 Success = LookupPrivilegeValueW(NULL,
931 lpszPrivilegeName,
932 &tp.Privileges[0].Luid);
933 if (!Success) goto Quit;
934
935 tp.PrivilegeCount = 1;
936 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
937
938 Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
939
940 Quit:
941 CloseHandle(hToken);
942 return Success;
943 }
944
945 int WINAPI
946 _tWinMain(HINSTANCE hInst,
947 HINSTANCE hPrevInstance,
948 LPTSTR lpszCmdLine,
949 int nCmdShow)
950 {
951 NTSTATUS Status;
952 ULONG Error;
953 INITCOMMONCONTROLSEX iccx;
954 PROPSHEETHEADER psh;
955 HPROPSHEETPAGE ahpsp[8];
956 PROPSHEETPAGE psp = {0};
957 UINT nPages = 0;
958
959 ProcessHeap = GetProcessHeap();
960
961 /* Initialize global unicode strings */
962 RtlInitUnicodeString(&SetupData.USetupData.SourcePath, NULL);
963 RtlInitUnicodeString(&SetupData.USetupData.SourceRootPath, NULL);
964 RtlInitUnicodeString(&SetupData.USetupData.SourceRootDir, NULL);
965 // RtlInitUnicodeString(&InstallPath, NULL);
966 RtlInitUnicodeString(&SetupData.USetupData.DestinationPath, NULL);
967 RtlInitUnicodeString(&SetupData.USetupData.DestinationArcPath, NULL);
968 RtlInitUnicodeString(&SetupData.USetupData.DestinationRootPath, NULL);
969 RtlInitUnicodeString(&SetupData.USetupData.SystemRootPath, NULL);
970
971 /* Get the source path and source root path */
972 //
973 // NOTE: Sometimes the source path may not be in SystemRoot !!
974 // (and this is the case when using the 1st-stage GUI setup!)
975 //
976 Status = GetSourcePaths(&SetupData.USetupData.SourcePath,
977 &SetupData.USetupData.SourceRootPath,
978 &SetupData.USetupData.SourceRootDir);
979 if (!NT_SUCCESS(Status))
980 {
981 DPRINT1("GetSourcePaths() failed (Status 0x%08lx)", Status);
982 // MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
983 MessageBoxW(NULL, L"GetSourcePaths failed!", L"Error", MB_ICONERROR);
984 goto Quit;
985 }
986 DPRINT1("SourcePath: '%wZ'\n", &SetupData.USetupData.SourcePath);
987 DPRINT1("SourceRootPath: '%wZ'\n", &SetupData.USetupData.SourceRootPath);
988 DPRINT1("SourceRootDir: '%wZ'\n", &SetupData.USetupData.SourceRootDir);
989
990 /* Load 'txtsetup.sif' from the installation media */
991 Error = LoadSetupInf(&SetupData.SetupInf, &SetupData.USetupData);
992 if (Error != ERROR_SUCCESS)
993 {
994 // MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER);
995 DisplayError(NULL, IDS_CAPTION, IDS_NO_TXTSETUP_SIF);
996 goto Quit;
997 }
998
999 /* Load extra setup data (HW lists etc...) */
1000 if (!LoadSetupData(&SetupData))
1001 goto Quit;
1002
1003 SetupData.hInstance = hInst;
1004
1005 CheckUnattendedSetup(&SetupData.USetupData);
1006 SetupData.bUnattend = IsUnattendedSetup;
1007
1008 /* Cache commonly-used strings */
1009 LoadStringW(hInst, IDS_ABORTSETUP, SetupData.szAbortMessage, ARRAYSIZE(SetupData.szAbortMessage));
1010 LoadStringW(hInst, IDS_ABORTSETUP2, SetupData.szAbortTitle, ARRAYSIZE(SetupData.szAbortTitle));
1011
1012 /* Whenever any of the common controls are used in your app,
1013 * you must call InitCommonControlsEx() to register the classes
1014 * for those controls. */
1015 iccx.dwSize = sizeof(iccx);
1016 iccx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES /* | ICC_PROGRESS_CLASS */;
1017 InitCommonControlsEx(&iccx);
1018
1019 /* Create title font */
1020 SetupData.hTitleFont = CreateTitleFont();
1021
1022 if (!SetupData.bUnattend)
1023 {
1024 /* Create the Start page, until setup is working */
1025 // NOTE: What does "until setup is working" mean??
1026 psp.dwSize = sizeof(PROPSHEETPAGE);
1027 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
1028 psp.hInstance = hInst;
1029 psp.lParam = (LPARAM)&SetupData;
1030 psp.pfnDlgProc = StartDlgProc;
1031 psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
1032 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1033
1034 /* Create the install type selection page */
1035 psp.dwSize = sizeof(PROPSHEETPAGE);
1036 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1037 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
1038 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
1039 psp.hInstance = hInst;
1040 psp.lParam = (LPARAM)&SetupData;
1041 psp.pfnDlgProc = TypeDlgProc;
1042 psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE);
1043 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1044
1045 /* Create the upgrade/repair selection page */
1046 psp.dwSize = sizeof(PROPSHEETPAGE);
1047 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1048 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
1049 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
1050 psp.hInstance = hInst;
1051 psp.lParam = (LPARAM)&SetupData;
1052 psp.pfnDlgProc = UpgradeRepairDlgProc;
1053 psp.pszTemplate = MAKEINTRESOURCE(IDD_UPDATEREPAIRPAGE);
1054 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1055
1056 /* Create the device settings page */
1057 psp.dwSize = sizeof(PROPSHEETPAGE);
1058 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1059 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE);
1060 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE);
1061 psp.hInstance = hInst;
1062 psp.lParam = (LPARAM)&SetupData;
1063 psp.pfnDlgProc = DeviceDlgProc;
1064 psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE);
1065 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1066
1067 /* Create the install device settings page / boot method / install directory */
1068 psp.dwSize = sizeof(PROPSHEETPAGE);
1069 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1070 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE);
1071 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE);
1072 psp.hInstance = hInst;
1073 psp.lParam = (LPARAM)&SetupData;
1074 psp.pfnDlgProc = DriveDlgProc;
1075 psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE);
1076 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1077
1078 /* Create the summary page */
1079 psp.dwSize = sizeof(PROPSHEETPAGE);
1080 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1081 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE);
1082 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE);
1083 psp.hInstance = hInst;
1084 psp.lParam = (LPARAM)&SetupData;
1085 psp.pfnDlgProc = SummaryDlgProc;
1086 psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE);
1087 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1088 }
1089
1090 /* Create the installation progress page */
1091 psp.dwSize = sizeof(PROPSHEETPAGE);
1092 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1093 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
1094 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
1095 psp.hInstance = hInst;
1096 psp.lParam = (LPARAM)&SetupData;
1097 psp.pfnDlgProc = ProcessDlgProc;
1098 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
1099 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1100
1101 /* Create the finish-and-reboot page */
1102 psp.dwSize = sizeof(PROPSHEETPAGE);
1103 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
1104 psp.hInstance = hInst;
1105 psp.lParam = (LPARAM)&SetupData;
1106 psp.pfnDlgProc = RestartDlgProc;
1107 psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE);
1108 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1109
1110 /* Create the property sheet */
1111 psh.dwSize = sizeof(PROPSHEETHEADER);
1112 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
1113 psh.hInstance = hInst;
1114 psh.hwndParent = NULL;
1115 psh.nPages = nPages;
1116 psh.nStartPage = 0;
1117 psh.phpage = ahpsp;
1118 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
1119 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
1120
1121 /* Display the wizard */
1122 PropertySheet(&psh);
1123
1124 if (SetupData.hTitleFont)
1125 DeleteObject(SetupData.hTitleFont);
1126
1127 SetupCloseInfFile(SetupData.SetupInf);
1128
1129 Quit:
1130
1131 #if 0 // NOTE: Disabled for testing purposes only!
1132 EnablePrivilege(SE_SHUTDOWN_NAME, TRUE);
1133 ExitWindowsEx(EWX_REBOOT, 0);
1134 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
1135 #endif
1136
1137 return 0;
1138 }
1139
1140 /* EOF */