[SETUP:REACTOS] Adapt the 1st-stage GUI setup to compile with the setuplib.
[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 LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context);
43
44 static VOID
45 CenterWindow(HWND hWnd)
46 {
47 HWND hWndParent;
48 RECT rcParent;
49 RECT rcWindow;
50
51 hWndParent = GetParent(hWnd);
52 if (hWndParent == NULL)
53 hWndParent = GetDesktopWindow();
54
55 GetWindowRect(hWndParent, &rcParent);
56 GetWindowRect(hWnd, &rcWindow);
57
58 SetWindowPos(hWnd,
59 HWND_TOP,
60 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
61 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
62 0,
63 0,
64 SWP_NOSIZE);
65 }
66
67 static HFONT
68 CreateTitleFont(VOID)
69 {
70 NONCLIENTMETRICS ncm;
71 LOGFONT LogFont;
72 HDC hdc;
73 INT FontSize;
74 HFONT hFont;
75
76 ncm.cbSize = sizeof(NONCLIENTMETRICS);
77 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
78
79 LogFont = ncm.lfMessageFont;
80 LogFont.lfWeight = FW_BOLD;
81 _tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
82
83 hdc = GetDC(NULL);
84 FontSize = 12;
85 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
86 hFont = CreateFontIndirect(&LogFont);
87 ReleaseDC(NULL, hdc);
88
89 return hFont;
90 }
91
92 INT DisplayError(
93 IN HWND hParentWnd OPTIONAL,
94 IN UINT uIDTitle,
95 IN UINT uIDMessage)
96 {
97 WCHAR message[512], caption[64];
98
99 LoadStringW(SetupData.hInstance, uIDMessage, message, ARRAYSIZE(message));
100 LoadStringW(SetupData.hInstance, uIDTitle, caption, ARRAYSIZE(caption));
101
102 return MessageBoxW(hParentWnd, message, caption, MB_OK | MB_ICONERROR);
103 }
104
105 static INT_PTR CALLBACK
106 StartDlgProc(HWND hwndDlg,
107 UINT uMsg,
108 WPARAM wParam,
109 LPARAM lParam)
110 {
111 PSETUPDATA pSetupData;
112
113 /* Retrieve pointer to the global setup data */
114 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
115
116 switch (uMsg)
117 {
118 case WM_INITDIALOG:
119 /* Save pointer to the global setup data */
120 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
121 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
122
123 /* Center the wizard window */
124 CenterWindow(GetParent(hwndDlg));
125
126 /* Set title font */
127 SendDlgItemMessage(hwndDlg,
128 IDC_STARTTITLE,
129 WM_SETFONT,
130 (WPARAM)pSetupData->hTitleFont,
131 (LPARAM)TRUE);
132 break;
133
134 case WM_NOTIFY:
135 {
136 LPNMHDR lpnm = (LPNMHDR)lParam;
137
138 switch (lpnm->code)
139 {
140 case PSN_SETACTIVE:
141 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
142 break;
143
144 default:
145 break;
146 }
147 }
148 break;
149
150 default:
151 break;
152
153 }
154
155 return FALSE;
156 }
157
158 static INT_PTR CALLBACK
159 TypeDlgProc(HWND hwndDlg,
160 UINT uMsg,
161 WPARAM wParam,
162 LPARAM lParam)
163 {
164 PSETUPDATA pSetupData;
165
166 /* Retrieve pointer to the global setup data */
167 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
168
169 switch (uMsg)
170 {
171 case WM_INITDIALOG:
172 /* Save pointer to the global setup data */
173 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
174 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
175
176 /* Check the 'install' radio button */
177 CheckDlgButton(hwndDlg, IDC_INSTALL, BST_CHECKED);
178
179 /* Disable the 'update' radio button and text */
180 EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE);
181 EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATETEXT), FALSE);
182 break;
183
184 case WM_NOTIFY:
185 {
186 LPNMHDR lpnm = (LPNMHDR)lParam;
187
188 switch (lpnm->code)
189 {
190 case PSN_SETACTIVE:
191 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
192 break;
193
194 case PSN_QUERYCANCEL:
195 SetWindowLongPtr(hwndDlg,
196 DWLP_MSGRESULT,
197 MessageBox(GetParent(hwndDlg),
198 pSetupData->szAbortMessage,
199 pSetupData->szAbortTitle,
200 MB_YESNO | MB_ICONQUESTION) != IDYES);
201 return TRUE;
202
203 case PSN_WIZNEXT: // set the selected data
204 pSetupData->RepairUpdateFlag = !(SendMessage(GetDlgItem(hwndDlg, IDC_INSTALL),
205 BM_GETCHECK,
206 (WPARAM) 0,
207 (LPARAM) 0) == BST_CHECKED);
208 return TRUE;
209
210 default:
211 break;
212 }
213 }
214 break;
215
216 default:
217 break;
218
219 }
220 return FALSE;
221 }
222
223 static INT_PTR CALLBACK
224 DeviceDlgProc(HWND hwndDlg,
225 UINT uMsg,
226 WPARAM wParam,
227 LPARAM lParam)
228 {
229 PSETUPDATA pSetupData;
230 LONG i;
231 LRESULT tindex;
232 HWND hList;
233
234 /* Retrieve pointer to the global setup data */
235 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
236
237 switch (uMsg)
238 {
239 case WM_INITDIALOG:
240 /* Save pointer to the global setup data */
241 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
242 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
243
244 hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
245
246 for (i=0; i < pSetupData->CompCount; i++)
247 {
248 tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) pSetupData->pComputers[i].Value);
249 SendMessage(hList, CB_SETITEMDATA, tindex, i);
250 }
251 SendMessage(hList, CB_SETCURSEL, 0, 0); // set first as default
252
253 hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
254
255 for (i=0; i < pSetupData->DispCount; i++)
256 {
257 tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) pSetupData->pDisplays[i].Value);
258 SendMessage(hList, CB_SETITEMDATA, tindex, i);
259 }
260 SendMessage(hList, CB_SETCURSEL, 0, 0); // set first as default
261
262 hList = GetDlgItem(hwndDlg, IDC_KEYBOARD);
263
264 for (i=0; i < pSetupData->KeybCount; i++)
265 {
266 tindex = SendMessage(hList,CB_ADDSTRING,(WPARAM)0,(LPARAM)pSetupData->pKeyboards[i].Value);
267 SendMessage(hList,CB_SETITEMDATA,tindex,i);
268 }
269 SendMessage(hList,CB_SETCURSEL,0,0); // set first as default
270 break;
271
272 case WM_NOTIFY:
273 {
274 LPNMHDR lpnm = (LPNMHDR)lParam;
275
276 switch (lpnm->code)
277 {
278 case PSN_SETACTIVE:
279 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
280 break;
281
282 case PSN_QUERYCANCEL:
283 SetWindowLongPtr(hwndDlg,
284 DWLP_MSGRESULT,
285 MessageBox(GetParent(hwndDlg),
286 pSetupData->szAbortMessage,
287 pSetupData->szAbortTitle,
288 MB_YESNO | MB_ICONQUESTION) != IDYES);
289 return TRUE;
290
291 case PSN_WIZNEXT: // set the selected data
292 {
293 hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
294
295 tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
296 if (tindex != CB_ERR)
297 {
298 pSetupData->SelectedComputer = SendMessage(hList,
299 CB_GETITEMDATA,
300 (WPARAM) tindex,
301 (LPARAM) 0);
302 }
303
304 hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
305
306 tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
307 if (tindex != CB_ERR)
308 {
309 pSetupData->SelectedDisplay = SendMessage(hList,
310 CB_GETITEMDATA,
311 (WPARAM) tindex,
312 (LPARAM) 0);
313 }
314
315 hList =GetDlgItem(hwndDlg, IDC_KEYBOARD);
316
317 tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
318 if (tindex != CB_ERR)
319 {
320 pSetupData->SelectedKeyboard = SendMessage(hList,
321 CB_GETITEMDATA,
322 (WPARAM) tindex,
323 (LPARAM) 0);
324 }
325 return TRUE;
326 }
327
328 default:
329 break;
330 }
331 }
332 break;
333
334 default:
335 break;
336
337 }
338 return FALSE;
339 }
340
341 static INT_PTR CALLBACK
342 SummaryDlgProc(HWND hwndDlg,
343 UINT uMsg,
344 WPARAM wParam,
345 LPARAM lParam)
346 {
347 PSETUPDATA pSetupData;
348
349 /* Retrieve pointer to the global setup data */
350 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
351
352 switch (uMsg)
353 {
354 case WM_INITDIALOG:
355 /* Save pointer to the global setup data */
356 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
357 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
358 break;
359
360 case WM_NOTIFY:
361 {
362 LPNMHDR lpnm = (LPNMHDR)lParam;
363
364 switch (lpnm->code)
365 {
366 case PSN_SETACTIVE:
367 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
368 break;
369
370 case PSN_QUERYCANCEL:
371 SetWindowLongPtr(hwndDlg,
372 DWLP_MSGRESULT,
373 MessageBox(GetParent(hwndDlg),
374 pSetupData->szAbortMessage,
375 pSetupData->szAbortTitle,
376 MB_YESNO | MB_ICONQUESTION) != IDYES);
377 return TRUE;
378 default:
379 break;
380 }
381 }
382 break;
383
384 default:
385 break;
386 }
387
388 return FALSE;
389 }
390
391 static INT_PTR CALLBACK
392 ProcessDlgProc(HWND hwndDlg,
393 UINT uMsg,
394 WPARAM wParam,
395 LPARAM lParam)
396 {
397 PSETUPDATA pSetupData;
398
399 /* Retrieve pointer to the global setup data */
400 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
401
402 switch (uMsg)
403 {
404 case WM_INITDIALOG:
405 /* Save pointer to the global setup data */
406 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
407 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
408 break;
409
410 case WM_NOTIFY:
411 {
412 LPNMHDR lpnm = (LPNMHDR)lParam;
413
414 switch (lpnm->code)
415 {
416 case PSN_SETACTIVE:
417 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
418 // disable all buttons during installation process
419 // PropSheet_SetWizButtons(GetParent(hwndDlg), 0 );
420 break;
421 case PSN_QUERYCANCEL:
422 SetWindowLongPtr(hwndDlg,
423 DWLP_MSGRESULT,
424 MessageBox(GetParent(hwndDlg),
425 pSetupData->szAbortMessage,
426 pSetupData->szAbortTitle,
427 MB_YESNO | MB_ICONQUESTION) != IDYES);
428 return TRUE;
429 default:
430 break;
431 }
432 }
433 break;
434
435 default:
436 break;
437
438 }
439
440 return FALSE;
441 }
442
443 static INT_PTR CALLBACK
444 RestartDlgProc(HWND hwndDlg,
445 UINT uMsg,
446 WPARAM wParam,
447 LPARAM lParam)
448 {
449 PSETUPDATA pSetupData;
450
451 /* Retrieve pointer to the global setup data */
452 pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
453
454 switch (uMsg)
455 {
456 case WM_INITDIALOG:
457 /* Save pointer to the global setup data */
458 pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
459 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
460
461 /* Set title font */
462 /*SendDlgItemMessage(hwndDlg,
463 IDC_STARTTITLE,
464 WM_SETFONT,
465 (WPARAM)hTitleFont,
466 (LPARAM)TRUE);*/
467 break;
468
469 case WM_TIMER:
470 {
471 INT Position;
472 HWND hWndProgress;
473
474 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS);
475 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0);
476 if (Position == 300)
477 {
478 KillTimer(hwndDlg, 1);
479 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH);
480 }
481 else
482 {
483 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0);
484 }
485 return TRUE;
486 }
487
488 case WM_DESTROY:
489 return TRUE;
490
491 case WM_NOTIFY:
492 {
493 LPNMHDR lpnm = (LPNMHDR)lParam;
494
495 switch (lpnm->code)
496 {
497 case PSN_SETACTIVE: // Only "Finish" for closing the App
498 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
499 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
500 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0);
501 SetTimer(hwndDlg, 1, 50, NULL);
502 break;
503
504 default:
505 break;
506 }
507 }
508 break;
509
510 default:
511 break;
512
513 }
514
515 return FALSE;
516 }
517
518 BOOL LoadSetupData(
519 PSETUPDATA pSetupData)
520 {
521 BOOL ret = TRUE;
522 INFCONTEXT InfContext;
523 TCHAR tmp[10];
524 //TCHAR szValue[MAX_PATH];
525 DWORD LineLength;
526 LONG Count;
527
528 // get language list
529 pSetupData->LangCount = SetupGetLineCount(pSetupData->SetupInf, _T("Language"));
530 if (pSetupData->LangCount > 0)
531 {
532 pSetupData->pLanguages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LANG) * pSetupData->LangCount);
533 if (pSetupData->pLanguages == NULL)
534 {
535 ret = FALSE;
536 goto done;
537 }
538
539 Count = 0;
540 if (SetupFindFirstLine(pSetupData->SetupInf, _T("Language"), NULL, &InfContext))
541 {
542 do
543 {
544 SetupGetStringField(&InfContext,
545 0,
546 pSetupData->pLanguages[Count].LangId,
547 sizeof(pSetupData->pLanguages[Count].LangId) / sizeof(TCHAR),
548 &LineLength);
549
550 SetupGetStringField(&InfContext,
551 1,
552 pSetupData->pLanguages[Count].LangName,
553 sizeof(pSetupData->pLanguages[Count].LangName) / sizeof(TCHAR),
554 &LineLength);
555 ++Count;
556 }
557 while (SetupFindNextLine(&InfContext, &InfContext) && Count < pSetupData->LangCount);
558 }
559 }
560
561 // get keyboard layout list
562 pSetupData->KbLayoutCount = SetupGetLineCount(pSetupData->SetupInf, _T("KeyboardLayout"));
563 if (pSetupData->KbLayoutCount > 0)
564 {
565 pSetupData->pKbLayouts = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KBLAYOUT) * pSetupData->KbLayoutCount);
566 if (pSetupData->pKbLayouts == NULL)
567 {
568 ret = FALSE;
569 goto done;
570 }
571
572 Count = 0;
573 if (SetupFindFirstLine(pSetupData->SetupInf, _T("KeyboardLayout"), NULL, &InfContext))
574 {
575 do
576 {
577 SetupGetStringField(&InfContext,
578 0,
579 pSetupData->pKbLayouts[Count].LayoutId,
580 sizeof(pSetupData->pKbLayouts[Count].LayoutId) / sizeof(TCHAR),
581 &LineLength);
582
583 SetupGetStringField(&InfContext,
584 1,
585 pSetupData->pKbLayouts[Count].LayoutName,
586 sizeof(pSetupData->pKbLayouts[Count].LayoutName) / sizeof(TCHAR),
587 &LineLength);
588 ++Count;
589 }
590 while (SetupFindNextLine(&InfContext, &InfContext) && Count < pSetupData->KbLayoutCount);
591 }
592 }
593
594 // get default for keyboard and language
595 pSetupData->DefaultKBLayout = -1;
596 pSetupData->DefaultLang = -1;
597
598 // TODO: get defaults from underlaying running system
599 if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLayout"), &InfContext))
600 {
601 SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
602 for (Count = 0; Count < pSetupData->KbLayoutCount; Count++)
603 {
604 if (_tcscmp(tmp, pSetupData->pKbLayouts[Count].LayoutId) == 0)
605 {
606 pSetupData->DefaultKBLayout = Count;
607 break;
608 }
609 }
610 }
611
612 if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLanguage"), &InfContext))
613 {
614 SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
615 for (Count = 0; Count < pSetupData->LangCount; Count++)
616 {
617 if (_tcscmp(tmp, pSetupData->pLanguages[Count].LangId) == 0)
618 {
619 pSetupData->DefaultLang = Count;
620 break;
621 }
622 }
623 }
624
625 // get computers list
626 pSetupData->CompCount = LoadGenentry(pSetupData->SetupInf,_T("Computer"),&pSetupData->pComputers,&InfContext);
627
628 // get display list
629 pSetupData->DispCount = LoadGenentry(pSetupData->SetupInf,_T("Display"),&pSetupData->pDisplays,&InfContext);
630
631 // get keyboard list
632 pSetupData->KeybCount = LoadGenentry(pSetupData->SetupInf, _T("Keyboard"),&pSetupData->pKeyboards,&InfContext);
633
634 // get install directory
635 if (SetupFindFirstLine(pSetupData->SetupInf, _T("SetupData"), _T("DefaultPath"), &InfContext))
636 {
637 SetupGetStringField(&InfContext,
638 1,
639 pSetupData->USetupData.InstallationDirectory,
640 sizeof(pSetupData->USetupData.InstallationDirectory) / sizeof(TCHAR),
641 &LineLength);
642 }
643
644 done:
645 if (ret == FALSE)
646 {
647 if (pSetupData->pKbLayouts != NULL)
648 {
649 HeapFree(GetProcessHeap(), 0, pSetupData->pKbLayouts);
650 pSetupData->pKbLayouts = NULL;
651 }
652
653 if (pSetupData->pLanguages != NULL)
654 {
655 HeapFree(GetProcessHeap(), 0, pSetupData->pLanguages);
656 pSetupData->pLanguages = NULL;
657 }
658 }
659
660 return ret;
661 }
662
663 LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context)
664 {
665 LONG TotalCount;
666 DWORD LineLength;
667
668 TotalCount = SetupGetLineCount(hinf, name);
669 if (TotalCount > 0)
670 {
671 *gen = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * TotalCount);
672 if (*gen != NULL)
673 {
674 if (SetupFindFirstLine(hinf, name, NULL, context))
675 {
676 LONG Count = 0;
677 do
678 {
679 SetupGetStringField(context,
680 0,
681 (*gen)[Count].Id,
682 sizeof((*gen)[Count].Id) / sizeof(TCHAR),
683 &LineLength);
684
685 SetupGetStringField(context,
686 1,
687 (*gen)[Count].Value,
688 sizeof((*gen)[Count].Value) / sizeof(TCHAR),
689 &LineLength);
690 ++Count;
691 }
692 while (SetupFindNextLine(context, context) && Count < TotalCount);
693 }
694 }
695 else return 0;
696 }
697 return TotalCount;
698 }
699
700 /*
701 * Attempts to convert a pure NT file path into a corresponding Win32 path.
702 * Adapted from GetInstallSourceWin32() in dll/win32/syssetup/wizard.c
703 */
704 BOOL
705 ConvertNtPathToWin32Path(
706 OUT PWSTR pwszPath,
707 IN DWORD cchPathMax,
708 IN PCWSTR pwszNTPath)
709 {
710 WCHAR wszDrives[512];
711 WCHAR wszNTPath[512]; // MAX_PATH ?
712 DWORD cchDrives;
713 PWCHAR pwszDrive;
714
715 *pwszPath = UNICODE_NULL;
716
717 cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
718 if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
719 {
720 /* Buffer too small or failure */
721 DPRINT1("GetLogicalDriveStringsW failed\n");
722 return FALSE;
723 }
724
725 for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
726 {
727 /* Retrieve the NT path corresponding to the current Win32 DOS path */
728 pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash
729 QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath));
730 pwszDrive[2] = L'\\'; // Restore the backslash
731
732 wcscat(wszNTPath, L"\\"); // Concat a backslash
733
734 DPRINT1("Testing '%S' --> '%S'\n", pwszDrive, wszNTPath);
735
736 /* Check whether the NT path corresponds to the NT installation source path */
737 if (!_wcsnicmp(wszNTPath, pwszNTPath, wcslen(wszNTPath)))
738 {
739 /* Found it! */
740 wsprintf(pwszPath, L"%s%s", // cchPathMax
741 pwszDrive, pwszNTPath + wcslen(wszNTPath));
742 DPRINT1("ConvertNtPathToWin32Path: %S\n", pwszPath);
743 return TRUE;
744 }
745 }
746
747 return FALSE;
748 }
749
750 /* Used to enable and disable the shutdown privilege */
751 /* static */ BOOL
752 EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
753 {
754 BOOL Success;
755 HANDLE hToken;
756 TOKEN_PRIVILEGES tp;
757
758 Success = OpenProcessToken(GetCurrentProcess(),
759 TOKEN_ADJUST_PRIVILEGES,
760 &hToken);
761 if (!Success) return Success;
762
763 Success = LookupPrivilegeValueW(NULL,
764 lpszPrivilegeName,
765 &tp.Privileges[0].Luid);
766 if (!Success) goto Quit;
767
768 tp.PrivilegeCount = 1;
769 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
770
771 Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
772
773 Quit:
774 CloseHandle(hToken);
775 return Success;
776 }
777
778 int WINAPI
779 _tWinMain(HINSTANCE hInst,
780 HINSTANCE hPrevInstance,
781 LPTSTR lpszCmdLine,
782 int nCmdShow)
783 {
784 NTSTATUS Status;
785 ULONG Error;
786 PROPSHEETHEADER psh;
787 HPROPSHEETPAGE ahpsp[8];
788 PROPSHEETPAGE psp = {0};
789 UINT nPages = 0;
790
791 ProcessHeap = GetProcessHeap();
792
793 /* Initialize global unicode strings */
794 RtlInitUnicodeString(&SetupData.USetupData.SourcePath, NULL);
795 RtlInitUnicodeString(&SetupData.USetupData.SourceRootPath, NULL);
796 RtlInitUnicodeString(&SetupData.USetupData.SourceRootDir, NULL);
797 // RtlInitUnicodeString(&InstallPath, NULL);
798 RtlInitUnicodeString(&SetupData.USetupData.DestinationPath, NULL);
799 RtlInitUnicodeString(&SetupData.USetupData.DestinationArcPath, NULL);
800 RtlInitUnicodeString(&SetupData.USetupData.DestinationRootPath, NULL);
801 RtlInitUnicodeString(&SetupData.USetupData.SystemRootPath, NULL);
802
803 /* Get the source path and source root path */
804 //
805 // NOTE: Sometimes the source path may not be in SystemRoot !!
806 // (and this is the case when using the 1st-stage GUI setup!)
807 //
808 Status = GetSourcePaths(&SetupData.USetupData.SourcePath,
809 &SetupData.USetupData.SourceRootPath,
810 &SetupData.USetupData.SourceRootDir);
811 if (!NT_SUCCESS(Status))
812 {
813 DPRINT1("GetSourcePaths() failed (Status 0x%08lx)", Status);
814 // MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
815 MessageBoxW(NULL, L"GetSourcePaths failed!", L"Error", MB_ICONERROR);
816 goto Quit;
817 }
818 DPRINT1("SourcePath: '%wZ'\n", &SetupData.USetupData.SourcePath);
819 DPRINT1("SourceRootPath: '%wZ'\n", &SetupData.USetupData.SourceRootPath);
820 DPRINT1("SourceRootDir: '%wZ'\n", &SetupData.USetupData.SourceRootDir);
821
822 /* Load 'txtsetup.sif' from the installation media */
823 Error = LoadSetupInf(&SetupData.SetupInf, &SetupData.USetupData);
824 if (Error != ERROR_SUCCESS)
825 {
826 // MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER);
827 DisplayError(NULL, IDS_CAPTION, IDS_NO_TXTSETUP_SIF);
828 goto Quit;
829 }
830 /* Load extra setup data (HW lists etc...) */
831 if (!LoadSetupData(&SetupData))
832 goto Quit;
833
834 SetupData.hInstance = hInst;
835
836 CheckUnattendedSetup(&SetupData.USetupData);
837 SetupData.bUnattend = IsUnattendedSetup;
838
839 LoadStringW(hInst, IDS_ABORTSETUP, SetupData.szAbortMessage, ARRAYSIZE(SetupData.szAbortMessage));
840 LoadStringW(hInst, IDS_ABORTSETUP2, SetupData.szAbortTitle, ARRAYSIZE(SetupData.szAbortTitle));
841
842 /* Create title font */
843 SetupData.hTitleFont = CreateTitleFont();
844
845 if (!SetupData.bUnattend)
846 {
847 /* Create the Start page, until setup is working */
848 // NOTE: What does "until setup is working" mean??
849 psp.dwSize = sizeof(PROPSHEETPAGE);
850 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
851 psp.hInstance = hInst;
852 psp.lParam = (LPARAM)&SetupData;
853 psp.pfnDlgProc = StartDlgProc;
854 psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
855 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
856
857 /* Create install type selection page */
858 psp.dwSize = sizeof(PROPSHEETPAGE);
859 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
860 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
861 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
862 psp.hInstance = hInst;
863 psp.lParam = (LPARAM)&SetupData;
864 psp.pfnDlgProc = TypeDlgProc;
865 psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE);
866 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
867
868 /* Create device settings page */
869 psp.dwSize = sizeof(PROPSHEETPAGE);
870 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
871 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE);
872 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE);
873 psp.hInstance = hInst;
874 psp.lParam = (LPARAM)&SetupData;
875 psp.pfnDlgProc = DeviceDlgProc;
876 psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE);
877 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
878
879 /* Create install device settings page / boot method / install directory */
880 psp.dwSize = sizeof(PROPSHEETPAGE);
881 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
882 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE);
883 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE);
884 psp.hInstance = hInst;
885 psp.lParam = (LPARAM)&SetupData;
886 psp.pfnDlgProc = DriveDlgProc;
887 psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE);
888 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
889
890 /* Create summary page */
891 psp.dwSize = sizeof(PROPSHEETPAGE);
892 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
893 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE);
894 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE);
895 psp.hInstance = hInst;
896 psp.lParam = (LPARAM)&SetupData;
897 psp.pfnDlgProc = SummaryDlgProc;
898 psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE);
899 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
900 }
901
902 /* Create installation progress page */
903 psp.dwSize = sizeof(PROPSHEETPAGE);
904 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
905 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
906 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
907 psp.hInstance = hInst;
908 psp.lParam = (LPARAM)&SetupData;
909 psp.pfnDlgProc = ProcessDlgProc;
910 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
911 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
912
913 /* Create finish to reboot page */
914 psp.dwSize = sizeof(PROPSHEETPAGE);
915 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
916 psp.hInstance = hInst;
917 psp.lParam = (LPARAM)&SetupData;
918 psp.pfnDlgProc = RestartDlgProc;
919 psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE);
920 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
921
922 /* Create the property sheet */
923 psh.dwSize = sizeof(PROPSHEETHEADER);
924 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
925 psh.hInstance = hInst;
926 psh.hwndParent = NULL;
927 psh.nPages = nPages;
928 psh.nStartPage = 0;
929 psh.phpage = ahpsp;
930 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
931 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
932
933 /* Display the wizard */
934 PropertySheet(&psh);
935
936 if (SetupData.hTitleFont)
937 DeleteObject(SetupData.hTitleFont);
938
939 SetupCloseInfFile(SetupData.SetupInf);
940
941 Quit:
942
943 #if 0 // NOTE: Disabled for testing purposes only!
944 EnablePrivilege(SE_SHUTDOWN_NAME, TRUE);
945 ExitWindowsEx(EWX_REBOOT, 0);
946 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
947 #endif
948
949 return 0;
950 }
951
952 /* EOF */