SXS Support Part 2 of 2.
[reactos.git] / reactos / 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 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS GUI first stage setup application
23 * FILE: subsys/system/reactos/reactos.c
24 * PROGRAMMERS: Eric Kohl
25 * Matthias Kupfer
26 * Dmitry Chapyshev (dmitry@reactos.org)
27 */
28
29 #include <windows.h>
30 #include <commctrl.h>
31 #include <tchar.h>
32 #include <setupapi.h>
33 #include <initguid.h>
34 #include <devguid.h>
35 #include <wine/unicode.h>
36
37 #include "resource.h"
38
39 /* GLOBALS ******************************************************************/
40
41 HFONT hTitleFont;
42
43 typedef struct _LANG
44 {
45 TCHAR LangId[9];
46 TCHAR LangName[128];
47 } LANG, *PLANG;
48
49 typedef struct _KBLAYOUT
50 {
51 TCHAR LayoutId[9];
52 TCHAR LayoutName[128];
53 TCHAR DllName[128];
54 } KBLAYOUT, *PKBLAYOUT;
55
56
57 // generic entries with simple 1:1 mapping
58 typedef struct _GENENTRY
59 {
60 TCHAR Id[24];
61 TCHAR Value[128];
62 } GENENTRY, *PGENENTRY;
63
64 struct
65 {
66 // Settings
67 LONG DestDiskNumber; // physical disk
68 LONG DestPartNumber; // partition on disk
69 LONG DestPartSize; // if partition doesn't exist, size of partition
70 LONG FSType; // file system type on partition
71 LONG MBRInstallType; // install bootloader
72 LONG FormatPart; // type of format the partition
73 LONG SelectedLangId; // selected language (table index)
74 LONG SelectedKBLayout; // selected keyboard layout (table index)
75 TCHAR InstallDir[MAX_PATH]; // installation directory on hdd
76 LONG SelectedComputer; // selected computer type (table index)
77 LONG SelectedDisplay; // selected display type (table index)
78 LONG SelectedKeyboard; // selected keyboard type (table index)
79 BOOLEAN RepairUpdateFlag; // flag for update/repair an installed reactos
80 // txtsetup.sif data
81 LONG DefaultLang; // default language (table index)
82 PLANG pLanguages;
83 LONG LangCount;
84 LONG DefaultKBLayout; // default keyboard layout (table index)
85 PKBLAYOUT pKbLayouts;
86 LONG KbLayoutCount;
87 PGENENTRY pComputers;
88 LONG CompCount;
89 PGENENTRY pDisplays;
90 LONG DispCount;
91 PGENENTRY pKeyboards;
92 LONG KeybCount;
93 } SetupData;
94
95 typedef struct _IMGINFO
96 {
97 HBITMAP hBitmap;
98 INT cxSource;
99 INT cySource;
100 } IMGINFO, *PIMGINFO;
101
102 TCHAR abort_msg[512], abort_title[64];
103 HINSTANCE hInstance;
104 BOOL isUnattend;
105
106 LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY gen,PINFCONTEXT context);
107
108 /* FUNCTIONS ****************************************************************/
109
110 static VOID
111 CenterWindow(HWND hWnd)
112 {
113 HWND hWndParent;
114 RECT rcParent;
115 RECT rcWindow;
116
117 hWndParent = GetParent(hWnd);
118 if (hWndParent == NULL)
119 hWndParent = GetDesktopWindow();
120
121 GetWindowRect(hWndParent, &rcParent);
122 GetWindowRect(hWnd, &rcWindow);
123
124 SetWindowPos(hWnd,
125 HWND_TOP,
126 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
127 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
128 0,
129 0,
130 SWP_NOSIZE);
131 }
132
133 static HFONT
134 CreateTitleFont(VOID)
135 {
136 NONCLIENTMETRICS ncm;
137 LOGFONT LogFont;
138 HDC hdc;
139 INT FontSize;
140 HFONT hFont;
141
142 ncm.cbSize = sizeof(NONCLIENTMETRICS);
143 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
144
145 LogFont = ncm.lfMessageFont;
146 LogFont.lfWeight = FW_BOLD;
147 _tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
148
149 hdc = GetDC(NULL);
150 FontSize = 12;
151 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
152 hFont = CreateFontIndirect(&LogFont);
153 ReleaseDC(NULL, hdc);
154
155 return hFont;
156 }
157
158 static VOID
159 InitImageInfo(PIMGINFO ImgInfo)
160 {
161 BITMAP bitmap;
162
163 ZeroMemory(ImgInfo, sizeof(*ImgInfo));
164
165 ImgInfo->hBitmap = LoadImage(hInstance,
166 MAKEINTRESOURCE(IDB_ROSLOGO),
167 IMAGE_BITMAP,
168 0,
169 0,
170 LR_DEFAULTCOLOR);
171
172 if (ImgInfo->hBitmap != NULL)
173 {
174 GetObject(ImgInfo->hBitmap, sizeof(BITMAP), &bitmap);
175
176 ImgInfo->cxSource = bitmap.bmWidth;
177 ImgInfo->cySource = bitmap.bmHeight;
178 }
179 }
180
181 static INT_PTR CALLBACK
182 StartDlgProc(HWND hwndDlg,
183 UINT uMsg,
184 WPARAM wParam,
185 LPARAM lParam)
186 {
187 switch (uMsg)
188 {
189 case WM_INITDIALOG:
190 {
191 HWND hwndControl;
192 DWORD dwStyle;
193
194 hwndControl = GetParent(hwndDlg);
195
196 /* Center the wizard window */
197 CenterWindow (hwndControl);
198
199 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
200 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
201
202 /* Hide and disable the 'Cancel' button at the moment,
203 * we use this button to cancel the setup process
204 * like F3 in usetup
205 */
206 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
207 ShowWindow (hwndControl, SW_HIDE);
208 EnableWindow (hwndControl, FALSE);
209
210 /* Set title font */
211 SendDlgItemMessage(hwndDlg,
212 IDC_STARTTITLE,
213 WM_SETFONT,
214 (WPARAM)hTitleFont,
215 (LPARAM)TRUE);
216 }
217 break;
218
219 case WM_NOTIFY:
220 {
221 LPNMHDR lpnm = (LPNMHDR)lParam;
222
223 switch (lpnm->code)
224 {
225 case PSN_SETACTIVE:
226 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
227 break;
228 default:
229 break;
230 }
231 }
232 break;
233
234 default:
235 break;
236
237 }
238
239 return FALSE;
240 }
241
242 static INT_PTR CALLBACK
243 LangSelDlgProc(HWND hwndDlg,
244 UINT uMsg,
245 WPARAM wParam,
246 LPARAM lParam)
247 {
248 PIMGINFO pImgInfo;
249 LONG i;
250 LRESULT tindex;
251 HWND hList;
252
253 pImgInfo = (PIMGINFO)GetWindowLongPtr(hwndDlg, DWLP_USER);
254
255 switch (uMsg)
256 {
257 case WM_INITDIALOG:
258 {
259 HWND hwndControl;
260 DWORD dwStyle;
261
262 hwndControl = GetParent(hwndDlg);
263
264 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
265 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
266
267 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
268 ShowWindow (hwndControl, SW_SHOW);
269 EnableWindow (hwndControl, TRUE);
270
271 pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO));
272 if (pImgInfo == NULL)
273 {
274 EndDialog(hwndDlg, 0);
275 return FALSE;
276 }
277
278 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pImgInfo);
279
280 InitImageInfo(pImgInfo);
281
282 /* Set title font */
283 /*SendDlgItemMessage(hwndDlg,
284 IDC_STARTTITLE,
285 WM_SETFONT,
286 (WPARAM)hTitleFont,
287 (LPARAM)TRUE);*/
288
289 hList = GetDlgItem(hwndDlg, IDC_LANGUAGES);
290
291 for (i=0; i < SetupData.LangCount; i++)
292 {
293 tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SetupData.pLanguages[i].LangName);
294 SendMessage(hList, CB_SETITEMDATA, tindex, i);
295 if (SetupData.DefaultLang == i)
296 SendMessage(hList, CB_SETCURSEL, (WPARAM) tindex,(LPARAM) 0);
297 }
298
299 hList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT);
300
301 for (i=0; i < SetupData.KbLayoutCount; i++)
302 {
303 tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM)SetupData.pKbLayouts[i].LayoutName);
304 SendMessage(hList, CB_SETITEMDATA, tindex, i);
305 if (SetupData.DefaultKBLayout == i)
306 SendMessage(hList,CB_SETCURSEL,(WPARAM)tindex,(LPARAM)0);
307 }
308 }
309 break;
310
311 case WM_DRAWITEM:
312 {
313 LPDRAWITEMSTRUCT lpDrawItem;
314 lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
315
316 if (lpDrawItem->CtlID == IDB_ROSLOGO)
317 {
318 HDC hdcMem;
319 LONG left;
320
321 /* position image in centre of dialog */
322 left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2;
323
324 hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
325 if (hdcMem != NULL)
326 {
327 SelectObject(hdcMem, pImgInfo->hBitmap);
328 BitBlt(lpDrawItem->hDC,
329 left,
330 lpDrawItem->rcItem.top,
331 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
332 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
333 hdcMem,
334 0,
335 0,
336 SRCCOPY);
337 DeleteDC(hdcMem);
338 }
339 }
340 return TRUE;
341 }
342
343 case WM_NOTIFY:
344 {
345 LPNMHDR lpnm = (LPNMHDR)lParam;
346
347 switch (lpnm->code)
348 {
349 case PSN_SETACTIVE:
350 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
351 break;
352
353 case PSN_QUERYCANCEL:
354 SetWindowLongPtr(hwndDlg,
355 DWL_MSGRESULT,
356 MessageBox(GetParent(hwndDlg),
357 abort_msg,
358 abort_title,
359 MB_YESNO | MB_ICONQUESTION) != IDYES);
360 return TRUE;
361
362 case PSN_WIZNEXT: // set the selected data
363 {
364 hList =GetDlgItem(hwndDlg, IDC_LANGUAGES);
365 tindex = SendMessage(hList,CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
366
367 if (tindex != CB_ERR)
368 {
369 WORD LangID;
370 SetupData.SelectedLangId = SendMessage(hList, CB_GETITEMDATA, (WPARAM) tindex, (LPARAM) 0);
371 LangID = _tcstol(SetupData.pLanguages[SetupData.SelectedLangId].LangId, NULL, 16);
372 SetThreadLocale(MAKELCID(LangID, SORT_DEFAULT));
373 // FIXME: need to reload all resource to force
374 // the new language setting
375 }
376
377 hList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT);
378 tindex = SendMessage(hList,CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
379 if (tindex != CB_ERR)
380 {
381 SetupData.SelectedKBLayout = SendMessage(hList, CB_GETITEMDATA, (WPARAM) tindex, (LPARAM) 0);
382 }
383 return TRUE;
384 }
385
386 default:
387 break;
388 }
389 }
390 break;
391
392 default:
393 break;
394
395 }
396 return FALSE;
397 }
398
399 static INT_PTR CALLBACK
400 TypeDlgProc(HWND hwndDlg,
401 UINT uMsg,
402 WPARAM wParam,
403 LPARAM lParam)
404 {
405 switch (uMsg)
406 {
407 case WM_INITDIALOG:
408 {
409 HWND hwndControl;
410 DWORD dwStyle;
411
412 hwndControl = GetParent(hwndDlg);
413
414 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
415 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
416
417 CheckDlgButton(hwndDlg, IDC_INSTALL, BST_CHECKED);
418
419 /* Set title font */
420 /*SendDlgItemMessage(hwndDlg,
421 IDC_STARTTITLE,
422 WM_SETFONT,
423 (WPARAM)hTitleFont,
424 (LPARAM)TRUE);*/
425 }
426 break;
427
428 case WM_NOTIFY:
429 {
430 LPNMHDR lpnm = (LPNMHDR)lParam;
431
432 switch (lpnm->code)
433 {
434 case PSN_SETACTIVE:
435 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
436 break;
437
438 case PSN_QUERYCANCEL:
439 SetWindowLongPtr(hwndDlg,
440 DWL_MSGRESULT,
441 MessageBox(GetParent(hwndDlg),
442 abort_msg,
443 abort_title,
444 MB_YESNO | MB_ICONQUESTION) != IDYES);
445 return TRUE;
446
447 case PSN_WIZNEXT: // set the selected data
448 SetupData.RepairUpdateFlag = !(SendMessage(GetDlgItem(hwndDlg, IDC_INSTALL),
449 BM_GETCHECK,
450 (WPARAM) 0,
451 (LPARAM) 0) == BST_CHECKED);
452 return TRUE;
453
454 default:
455 break;
456 }
457 }
458 break;
459
460 default:
461 break;
462
463 }
464 return FALSE;
465 }
466
467 static INT_PTR CALLBACK
468 DeviceDlgProc(HWND hwndDlg,
469 UINT uMsg,
470 WPARAM wParam,
471 LPARAM lParam)
472 {
473 LONG i;
474 LRESULT tindex;
475 HWND hList;
476
477 switch (uMsg)
478 {
479 case WM_INITDIALOG:
480 {
481 HWND hwndControl;
482 DWORD dwStyle;
483
484 hwndControl = GetParent(hwndDlg);
485
486 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
487 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
488
489 /* Set title font */
490 /*SendDlgItemMessage(hwndDlg,
491 IDC_STARTTITLE,
492 WM_SETFONT,
493 (WPARAM)hTitleFont,
494 (LPARAM)TRUE);*/
495
496 hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
497
498 for (i=0; i < SetupData.CompCount; i++)
499 {
500 tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SetupData.pComputers[i].Value);
501 SendMessage(hList, CB_SETITEMDATA, tindex, i);
502 }
503 SendMessage(hList, CB_SETCURSEL, 0, 0); // set first as default
504
505 hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
506
507 for (i=0; i < SetupData.DispCount; i++)
508 {
509 tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SetupData.pDisplays[i].Value);
510 SendMessage(hList, CB_SETITEMDATA, tindex, i);
511 }
512 SendMessage(hList, CB_SETCURSEL, 0, 0); // set first as default
513
514 hList = GetDlgItem(hwndDlg, IDC_KEYBOARD);
515
516 for (i=0; i < SetupData.KeybCount; i++)
517 {
518 tindex = SendMessage(hList,CB_ADDSTRING,(WPARAM)0,(LPARAM)SetupData.pKeyboards[i].Value);
519 SendMessage(hList,CB_SETITEMDATA,tindex,i);
520 }
521 SendMessage(hList,CB_SETCURSEL,0,0); // set first as default
522 }
523 break;
524
525 case WM_NOTIFY:
526 {
527 LPNMHDR lpnm = (LPNMHDR)lParam;
528
529 switch (lpnm->code)
530 {
531 case PSN_SETACTIVE:
532 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
533 break;
534
535 case PSN_QUERYCANCEL:
536 SetWindowLongPtr(hwndDlg,
537 DWL_MSGRESULT,
538 MessageBox(GetParent(hwndDlg),
539 abort_msg,
540 abort_title,
541 MB_YESNO | MB_ICONQUESTION) != IDYES);
542 return TRUE;
543
544 case PSN_WIZNEXT: // set the selected data
545 {
546 hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
547
548 tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
549 if (tindex != CB_ERR)
550 {
551 SetupData.SelectedComputer = SendMessage(hList,
552 CB_GETITEMDATA,
553 (WPARAM) tindex,
554 (LPARAM) 0);
555 }
556
557 hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
558
559 tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
560 if (tindex != CB_ERR)
561 {
562 SetupData.SelectedDisplay = SendMessage(hList,
563 CB_GETITEMDATA,
564 (WPARAM) tindex,
565 (LPARAM) 0);
566 }
567
568 hList =GetDlgItem(hwndDlg, IDC_KEYBOARD);
569
570 tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
571 if (tindex != CB_ERR)
572 {
573 SetupData.SelectedKeyboard = SendMessage(hList,
574 CB_GETITEMDATA,
575 (WPARAM) tindex,
576 (LPARAM) 0);
577 }
578 return TRUE;
579 }
580
581 default:
582 break;
583 }
584 }
585 break;
586
587 default:
588 break;
589
590 }
591 return FALSE;
592 }
593
594 static INT_PTR CALLBACK
595 MoreOptDlgProc(HWND hwndDlg,
596 UINT uMsg,
597 WPARAM wParam,
598 LPARAM lParam)
599 {
600 switch (uMsg)
601 {
602 case WM_INITDIALOG:
603 {
604 CheckDlgButton(hwndDlg, IDC_INSTFREELDR, BST_CHECKED);
605 SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
606 WM_SETTEXT,
607 (WPARAM) 0,
608 (LPARAM) SetupData.InstallDir);
609 }
610 break;
611
612 case WM_COMMAND:
613 {
614 switch(LOWORD(wParam))
615 {
616 case IDOK:
617 {
618 SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
619 WM_GETTEXT,
620 (WPARAM) sizeof(SetupData.InstallDir) / sizeof(TCHAR),
621 (LPARAM) SetupData.InstallDir);
622
623 EndDialog(hwndDlg, IDOK);
624 return TRUE;
625 }
626
627 case IDCANCEL:
628 {
629 EndDialog(hwndDlg, IDCANCEL);
630 return TRUE;
631 }
632 }
633 }
634 }
635
636 return FALSE;
637 }
638
639 static INT_PTR CALLBACK
640 PartitionDlgProc(HWND hwndDlg,
641 UINT uMsg,
642 WPARAM wParam,
643 LPARAM lParam)
644 {
645 switch (uMsg)
646 {
647 case WM_INITDIALOG:
648 break;
649 case WM_COMMAND:
650 {
651 switch(LOWORD(wParam))
652 {
653 case IDOK:
654 EndDialog(hwndDlg, IDOK);
655 return TRUE;
656 case IDCANCEL:
657 EndDialog(hwndDlg, IDCANCEL);
658 return TRUE;
659 }
660 }
661 }
662 return FALSE;
663 }
664
665 static INT_PTR CALLBACK
666 DriveDlgProc(HWND hwndDlg,
667 UINT uMsg,
668 WPARAM wParam,
669 LPARAM lParam)
670 {
671 #if 0
672 HDEVINFO h;
673 HWND hList;
674 SP_DEVINFO_DATA DevInfoData;
675 DWORD i;
676 #endif
677 switch (uMsg)
678 {
679 case WM_INITDIALOG:
680 {
681 HWND hwndControl;
682 DWORD dwStyle;
683
684 hwndControl = GetParent(hwndDlg);
685
686 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
687 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
688
689 /* Set title font */
690 /*SendDlgItemMessage(hwndDlg,
691 IDC_STARTTITLE,
692 WM_SETFONT,
693 (WPARAM)hTitleFont,
694 (LPARAM)TRUE);*/
695 #if 0
696 h = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT);
697 if (h != INVALID_HANDLE_VALUE)
698 {
699 hList =GetDlgItem(hwndDlg, IDC_PARTITION);
700 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
701 for (i=0; SetupDiEnumDeviceInfo(h, i, &DevInfoData); i++)
702 {
703 DWORD DataT;
704 LPTSTR buffer = NULL;
705 DWORD buffersize = 0;
706
707 while (!SetupDiGetDeviceRegistryProperty(h,
708 &DevInfoData,
709 SPDRP_DEVICEDESC,
710 &DataT,
711 (PBYTE)buffer,
712 buffersize,
713 &buffersize))
714 {
715 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
716 {
717 if (buffer) LocalFree(buffer);
718 buffer = LocalAlloc(LPTR, buffersize * 2);
719 }
720 else
721 break;
722 }
723 if (buffer)
724 {
725 SendMessage(hList, LB_ADDSTRING, (WPARAM) 0, (LPARAM) buffer);
726 LocalFree(buffer);
727 }
728 }
729 SetupDiDestroyDeviceInfoList(h);
730 }
731 #endif
732 }
733 break;
734
735 case WM_COMMAND:
736 {
737 switch(LOWORD(wParam))
738 {
739 case IDC_PARTMOREOPTS:
740 DialogBox(hInstance,
741 MAKEINTRESOURCE(IDD_BOOTOPTIONS),
742 hwndDlg,
743 (DLGPROC) MoreOptDlgProc);
744 break;
745 case IDC_PARTCREATE:
746 DialogBox(hInstance,
747 MAKEINTRESOURCE(IDD_PARTITION),
748 hwndDlg,
749 (DLGPROC) PartitionDlgProc);
750 break;
751 case IDC_PARTDELETE:
752 break;
753 }
754 break;
755 }
756
757 case WM_NOTIFY:
758 {
759 LPNMHDR lpnm = (LPNMHDR)lParam;
760
761 switch (lpnm->code)
762 {
763 case PSN_SETACTIVE:
764 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
765 break;
766
767 case PSN_QUERYCANCEL:
768 SetWindowLongPtr(hwndDlg,
769 DWL_MSGRESULT,
770 MessageBox(GetParent(hwndDlg),
771 abort_msg,
772 abort_title,
773 MB_YESNO | MB_ICONQUESTION) != IDYES);
774 return TRUE;
775
776 default:
777 break;
778 }
779 }
780 break;
781
782 default:
783 break;
784
785 }
786
787 return FALSE;
788 }
789
790 static INT_PTR CALLBACK
791 SummaryDlgProc(HWND hwndDlg,
792 UINT uMsg,
793 WPARAM wParam,
794 LPARAM lParam)
795 {
796 switch (uMsg)
797 {
798 case WM_INITDIALOG:
799 {
800 HWND hwndControl;
801 DWORD dwStyle;
802
803 hwndControl = GetParent(hwndDlg);
804
805 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
806 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
807
808 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
809 ShowWindow(hwndControl, SW_HIDE);
810 EnableWindow(hwndControl, FALSE);
811
812 /* Set title font */
813 /*SendDlgItemMessage(hwndDlg,
814 IDC_STARTTITLE,
815 WM_SETFONT,
816 (WPARAM)hTitleFont,
817 (LPARAM)TRUE);*/
818 }
819 break;
820
821 case WM_NOTIFY:
822 {
823 LPNMHDR lpnm = (LPNMHDR)lParam;
824
825 switch (lpnm->code)
826 {
827 case PSN_SETACTIVE:
828 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
829 break;
830
831 default:
832 break;
833 }
834 }
835 break;
836
837 default:
838 break;
839 }
840
841 return FALSE;
842 }
843
844 static INT_PTR CALLBACK
845 ProcessDlgProc(HWND hwndDlg,
846 UINT uMsg,
847 WPARAM wParam,
848 LPARAM lParam)
849 {
850 switch (uMsg)
851 {
852 case WM_INITDIALOG:
853 {
854 HWND hwndControl;
855 DWORD dwStyle;
856
857 hwndControl = GetParent(hwndDlg);
858
859 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
860 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
861
862 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
863 ShowWindow(hwndControl, SW_HIDE);
864 EnableWindow(hwndControl, FALSE);
865
866 /* Set title font */
867 /*SendDlgItemMessage(hwndDlg,
868 IDC_STARTTITLE,
869 WM_SETFONT,
870 (WPARAM)hTitleFont,
871 (LPARAM)TRUE);*/
872 }
873 break;
874
875 case WM_NOTIFY:
876 {
877 LPNMHDR lpnm = (LPNMHDR)lParam;
878
879 switch (lpnm->code)
880 {
881 case PSN_SETACTIVE:
882 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
883 // disable all buttons during installation process
884 // PropSheet_SetWizButtons(GetParent(hwndDlg), 0 );
885 break;
886
887 default:
888 break;
889 }
890 }
891 break;
892
893 default:
894 break;
895
896 }
897
898 return FALSE;
899 }
900
901 static INT_PTR CALLBACK
902 RestartDlgProc(HWND hwndDlg,
903 UINT uMsg,
904 WPARAM wParam,
905 LPARAM lParam)
906 {
907 switch (uMsg)
908 {
909 case WM_INITDIALOG:
910 {
911 HWND hwndControl;
912 DWORD dwStyle;
913
914 hwndControl = GetParent(hwndDlg);
915
916 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
917 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
918
919 /* Set title font */
920 /*SendDlgItemMessage(hwndDlg,
921 IDC_STARTTITLE,
922 WM_SETFONT,
923 (WPARAM)hTitleFont,
924 (LPARAM)TRUE);*/
925 }
926 break;
927
928 case WM_TIMER:
929 {
930 INT Position;
931 HWND hWndProgress;
932
933 hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS);
934 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0);
935 if (Position == 300)
936 {
937 KillTimer(hwndDlg, 1);
938 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH);
939 }
940 else
941 {
942 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0);
943 }
944 return TRUE;
945 }
946
947 case WM_DESTROY:
948 return TRUE;
949
950 case WM_NOTIFY:
951 {
952 LPNMHDR lpnm = (LPNMHDR)lParam;
953
954 switch (lpnm->code)
955 {
956 case PSN_SETACTIVE: // Only "Finish" for closing the App
957 {
958 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
959 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
960 SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0);
961 SetTimer(hwndDlg, 1, 50, NULL);
962 }
963 break;
964
965 default:
966 break;
967 }
968 }
969 break;
970
971 default:
972 break;
973
974 }
975
976 return FALSE;
977 }
978
979 void LoadSetupData()
980 {
981 WCHAR szPath[MAX_PATH];
982 TCHAR tmp[10];
983 WCHAR *ch;
984 HINF hTxtsetupSif;
985 INFCONTEXT InfContext;
986 //TCHAR szValue[MAX_PATH];
987 DWORD LineLength;
988 LONG Count;
989
990 GetModuleFileNameW(NULL,szPath,MAX_PATH);
991 ch = strrchrW(szPath,L'\\');
992 if (ch != NULL)
993 *ch = L'\0';
994
995 wcscat(szPath, L"\\txtsetup.sif");
996 hTxtsetupSif = SetupOpenInfFileW(szPath, NULL, INF_STYLE_OLDNT, NULL);
997 if (hTxtsetupSif != INVALID_HANDLE_VALUE)
998 {
999 // get language list
1000 SetupData.LangCount = SetupGetLineCount(hTxtsetupSif, _T("Language"));
1001 if (SetupData.LangCount > 0)
1002 {
1003 SetupData.pLanguages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LANG) * SetupData.LangCount);
1004 if (SetupData.pLanguages != NULL)
1005 {
1006 Count = 0;
1007 if (SetupFindFirstLine(hTxtsetupSif, _T("Language"), NULL, &InfContext))
1008 {
1009 do
1010 {
1011 SetupGetStringField(&InfContext,
1012 0,
1013 SetupData.pLanguages[Count].LangId,
1014 sizeof(SetupData.pLanguages[Count].LangId) / sizeof(TCHAR),
1015 &LineLength);
1016
1017 SetupGetStringField(&InfContext,
1018 1,
1019 SetupData.pLanguages[Count].LangName,
1020 sizeof(SetupData.pLanguages[Count].LangName) / sizeof(TCHAR),
1021 &LineLength);
1022 ++Count;
1023 }
1024 while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.LangCount);
1025 }
1026 }
1027 }
1028
1029 // get keyboard layout list
1030 SetupData.KbLayoutCount = SetupGetLineCount(hTxtsetupSif, _T("KeyboardLayout"));
1031 if (SetupData.KbLayoutCount > 0)
1032 {
1033 SetupData.pKbLayouts = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KBLAYOUT) * SetupData.KbLayoutCount);
1034 if (SetupData.pKbLayouts != NULL)
1035 {
1036 Count = 0;
1037 if (SetupFindFirstLine(hTxtsetupSif, _T("KeyboardLayout"), NULL, &InfContext))
1038 {
1039 do
1040 {
1041 SetupGetStringField(&InfContext,
1042 0,
1043 SetupData.pKbLayouts[Count].LayoutId,
1044 sizeof(SetupData.pKbLayouts[Count].LayoutId) / sizeof(TCHAR),
1045 &LineLength);
1046
1047 SetupGetStringField(&InfContext,
1048 1,
1049 SetupData.pKbLayouts[Count].LayoutName,
1050 sizeof(SetupData.pKbLayouts[Count].LayoutName) / sizeof(TCHAR),
1051 &LineLength);
1052 ++Count;
1053 }
1054 while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.KbLayoutCount);
1055 }
1056 }
1057 }
1058
1059 // get default for keyboard and language
1060 SetupData.DefaultKBLayout = -1;
1061 SetupData.DefaultLang = -1;
1062
1063 // TODO: get defaults from underlaying running system
1064 if (SetupFindFirstLine(hTxtsetupSif, _T("NLS"), _T("DefaultLayout"), &InfContext))
1065 {
1066 SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
1067 for (Count = 0; Count < SetupData.KbLayoutCount; Count++)
1068 if (_tcscmp(tmp, SetupData.pKbLayouts[Count].LayoutId) == 0)
1069 {
1070 SetupData.DefaultKBLayout = Count;
1071 break;
1072 }
1073 }
1074
1075 if (SetupFindFirstLine(hTxtsetupSif, _T("NLS"), _T("DefaultLanguage"), &InfContext))
1076 {
1077 SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
1078 for (Count = 0; Count < SetupData.LangCount; Count++)
1079 if (_tcscmp(tmp, SetupData.pLanguages[Count].LangId) == 0)
1080 {
1081 SetupData.DefaultLang = Count;
1082 break;
1083 }
1084 }
1085
1086 // get computers list
1087 SetupData.CompCount = LoadGenentry(hTxtsetupSif,_T("Computer"),SetupData.pComputers,&InfContext);
1088
1089 // get display list
1090 SetupData.DispCount = LoadGenentry(hTxtsetupSif,_T("Display"),SetupData.pDisplays,&InfContext);
1091
1092 // get keyboard list
1093 SetupData.KeybCount = LoadGenentry(hTxtsetupSif, _T("Keyboard"),SetupData.pKeyboards,&InfContext);
1094
1095 // get install directory
1096 if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
1097 {
1098 SetupGetStringField(&InfContext,
1099 1,
1100 SetupData.InstallDir,
1101 sizeof(SetupData.InstallDir) / sizeof(TCHAR),
1102 &LineLength);
1103 }
1104 SetupCloseInfFile(hTxtsetupSif);
1105 }
1106 }
1107
1108 LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY gen,PINFCONTEXT context)
1109 {
1110 LONG TotalCount;
1111
1112 TotalCount = SetupGetLineCount(hinf, name);
1113 if (TotalCount > 0)
1114 {
1115 gen = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * TotalCount);
1116 if (gen != NULL)
1117 {
1118 if (SetupFindFirstLine(hinf, name, NULL, context))
1119 {
1120 LONG Count = 0;
1121 do
1122 {
1123 SetupGetStringField(context,
1124 0,
1125 gen[Count].Id,
1126 sizeof(gen[Count].Id) / sizeof(TCHAR),
1127 NULL);
1128
1129 SetupGetStringField(context,
1130 1,
1131 gen[Count].Value,
1132 sizeof(gen[Count].Value) / sizeof(TCHAR),
1133 NULL);
1134 Count++;
1135 }
1136 while (SetupFindNextLine(context, context) && Count < TotalCount);
1137 }
1138 }
1139 }
1140
1141 return TotalCount;
1142 }
1143
1144 BOOL isUnattendSetup()
1145 {
1146 WCHAR szPath[MAX_PATH];
1147 WCHAR *ch;
1148 HINF hUnattendedInf;
1149 INFCONTEXT InfContext;
1150 TCHAR szValue[MAX_PATH];
1151 DWORD LineLength;
1152 //HKEY hKey;
1153 BOOL result = 0;
1154
1155 GetModuleFileNameW(NULL, szPath, MAX_PATH);
1156 ch = strrchrW(szPath, L'\\');
1157 if (ch != NULL)
1158 *ch = L'\0';
1159
1160 wcscat(szPath, L"\\unattend.inf");
1161 hUnattendedInf = SetupOpenInfFileW(szPath, NULL, INF_STYLE_OLDNT, NULL);
1162
1163 if (hUnattendedInf != INVALID_HANDLE_VALUE)
1164 {
1165 if (SetupFindFirstLine(hUnattendedInf, _T("Unattend"), _T("UnattendSetupEnabled"),&InfContext))
1166 {
1167 if (SetupGetStringField(&InfContext,
1168 1,
1169 szValue,
1170 sizeof(szValue) / sizeof(TCHAR),
1171 &LineLength) && (_tcsicmp(szValue, _T("yes")) == 0))
1172 {
1173 result = 1; // unattendSetup enabled
1174 // read values and store in SetupData
1175 }
1176 }
1177 SetupCloseInfFile(hUnattendedInf);
1178 }
1179
1180 return result;
1181 }
1182
1183 int WINAPI
1184 _tWinMain(HINSTANCE hInst,
1185 HINSTANCE hPrevInstance,
1186 LPTSTR lpszCmdLine,
1187 int nCmdShow)
1188 {
1189 PROPSHEETHEADER psh;
1190 HPROPSHEETPAGE ahpsp[8];
1191 PROPSHEETPAGE psp = {0};
1192 UINT nPages = 0;
1193 hInstance = hInst;
1194 isUnattend = isUnattendSetup();
1195
1196 if (!isUnattend)
1197 {
1198 LoadString(hInst,IDS_ABORTSETUP, abort_msg, sizeof(abort_msg)/sizeof(TCHAR));
1199 LoadString(hInst,IDS_ABORTSETUP2, abort_title,sizeof(abort_title)/sizeof(TCHAR));
1200
1201 LoadSetupData();
1202
1203 /* Create the Start page, until setup is working */
1204 psp.dwSize = sizeof(PROPSHEETPAGE);
1205 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
1206 psp.hInstance = hInst;
1207 psp.lParam = 0;
1208 psp.pfnDlgProc = StartDlgProc;
1209 psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
1210 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1211
1212 /* Create language selection page */
1213 psp.dwSize = sizeof(PROPSHEETPAGE);
1214 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1215 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LANGTITLE);
1216 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LANGSUBTITLE);
1217 psp.hInstance = hInst;
1218 psp.lParam = 0;
1219 psp.pfnDlgProc = LangSelDlgProc;
1220 psp.pszTemplate = MAKEINTRESOURCE(IDD_LANGSELPAGE);
1221 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1222
1223 /* Create install type selection page */
1224 psp.dwSize = sizeof(PROPSHEETPAGE);
1225 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1226 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
1227 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
1228 psp.hInstance = hInst;
1229 psp.lParam = 0;
1230 psp.pfnDlgProc = TypeDlgProc;
1231 psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE);
1232 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1233
1234 /* Create device settings page */
1235 psp.dwSize = sizeof(PROPSHEETPAGE);
1236 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1237 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE);
1238 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE);
1239 psp.hInstance = hInst;
1240 psp.lParam = 0;
1241 psp.pfnDlgProc = DeviceDlgProc;
1242 psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE);
1243 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1244
1245 /* Create install device settings page / boot method / install directory */
1246 psp.dwSize = sizeof(PROPSHEETPAGE);
1247 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1248 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE);
1249 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE);
1250 psp.hInstance = hInst;
1251 psp.lParam = 0;
1252 psp.pfnDlgProc = DriveDlgProc;
1253 psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE);
1254 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1255
1256 /* Create summary page */
1257 psp.dwSize = sizeof(PROPSHEETPAGE);
1258 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1259 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE);
1260 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE);
1261 psp.hInstance = hInst;
1262 psp.lParam = 0;
1263 psp.pfnDlgProc = SummaryDlgProc;
1264 psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE);
1265 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1266 }
1267
1268 /* Create installation progress page */
1269 psp.dwSize = sizeof(PROPSHEETPAGE);
1270 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1271 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
1272 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
1273 psp.hInstance = hInst;
1274 psp.lParam = 0;
1275 psp.pfnDlgProc = ProcessDlgProc;
1276 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
1277 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1278
1279 if (!isUnattend)
1280 {
1281 /* Create finish to reboot page */
1282 psp.dwSize = sizeof(PROPSHEETPAGE);
1283 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1284 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_RESTARTTITLE);
1285 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_RESTARTSUBTITLE);
1286 psp.hInstance = hInst;
1287 psp.lParam = 0;
1288 psp.pfnDlgProc = RestartDlgProc;
1289 psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE);
1290 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
1291 }
1292
1293 /* Create the property sheet */
1294 psh.dwSize = sizeof(PROPSHEETHEADER);
1295 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
1296 psh.hInstance = hInst;
1297 psh.hwndParent = NULL;
1298 psh.nPages = nPages;
1299 psh.nStartPage = 0;
1300 psh.phpage = ahpsp;
1301 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
1302 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
1303
1304 /* Create title font */
1305 hTitleFont = CreateTitleFont();
1306
1307 /* Display the wizard */
1308 PropertySheet(&psh);
1309
1310 DeleteObject(hTitleFont);
1311
1312 return 0;
1313 }
1314
1315 /* EOF */