Of course, I forgot to commit the new file in revision 22049...
[reactos.git] / reactos / dll / win32 / newdev / wizard.c
1 /*
2 * New device installer (newdev.dll)
3 *
4 * Copyright 2006 Hervé Poussineau (hpoussin@reactos.org)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define YDEBUG
22 #include "newdev.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(newdev);
25
26 HANDLE hThread;
27
28 static VOID
29 CenterWindow(
30 IN HWND hWnd)
31 {
32 HWND hWndParent;
33 RECT rcParent;
34 RECT rcWindow;
35
36 hWndParent = GetParent(hWnd);
37 if (hWndParent == NULL)
38 hWndParent = GetDesktopWindow();
39
40 GetWindowRect(hWndParent, &rcParent);
41 GetWindowRect(hWnd, &rcWindow);
42
43 SetWindowPos(
44 hWnd,
45 HWND_TOP,
46 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
47 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
48 0,
49 0,
50 SWP_NOSIZE);
51 }
52
53 static BOOL
54 CanDisableDevice(
55 IN DEVINST DevInst,
56 IN HMACHINE hMachine,
57 OUT BOOL *CanDisable)
58 {
59 #if 0
60 /* hpoussin, Dec 2005. I've disabled this code because
61 * ntoskrnl never sets the DN_DISABLEABLE flag.
62 */
63 CONFIGRET cr;
64 ULONG Status, ProblemNumber;
65 BOOL Ret = FALSE;
66
67 cr = CM_Get_DevNode_Status_Ex(
68 &Status,
69 &ProblemNumber,
70 DevInst,
71 0,
72 hMachine);
73 if (cr == CR_SUCCESS)
74 {
75 *CanDisable = ((Status & DN_DISABLEABLE) != 0);
76 Ret = TRUE;
77 }
78
79 return Ret;
80 #else
81 *CanDisable = TRUE;
82 return TRUE;
83 #endif
84 }
85
86 static BOOL
87 IsDeviceStarted(
88 IN DEVINST DevInst,
89 IN HMACHINE hMachine,
90 OUT BOOL *IsEnabled)
91 {
92 CONFIGRET cr;
93 ULONG Status, ProblemNumber;
94 BOOL Ret = FALSE;
95
96 cr = CM_Get_DevNode_Status_Ex(
97 &Status,
98 &ProblemNumber,
99 DevInst,
100 0,
101 hMachine);
102 if (cr == CR_SUCCESS)
103 {
104 *IsEnabled = ((Status & DN_STARTED) != 0);
105 Ret = TRUE;
106 }
107
108 return Ret;
109 }
110
111 static BOOL
112 StartDevice(
113 IN HDEVINFO DeviceInfoSet,
114 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL,
115 IN BOOL bEnable,
116 IN DWORD HardwareProfile OPTIONAL,
117 OUT BOOL *bNeedReboot OPTIONAL)
118 {
119 SP_PROPCHANGE_PARAMS pcp;
120 SP_DEVINSTALL_PARAMS dp;
121 DWORD LastErr;
122 BOOL Ret = FALSE;
123
124 pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
125 pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
126 pcp.HwProfile = HardwareProfile;
127
128 if (bEnable)
129 {
130 /* try to enable the device on the global profile */
131 pcp.StateChange = DICS_ENABLE;
132 pcp.Scope = DICS_FLAG_GLOBAL;
133
134 /* ignore errors */
135 LastErr = GetLastError();
136 if (SetupDiSetClassInstallParams(
137 DeviceInfoSet,
138 DevInfoData,
139 &pcp.ClassInstallHeader,
140 sizeof(SP_PROPCHANGE_PARAMS)))
141 {
142 SetupDiCallClassInstaller(
143 DIF_PROPERTYCHANGE,
144 DeviceInfoSet,
145 DevInfoData);
146 }
147 SetLastError(LastErr);
148 }
149
150 /* try config-specific */
151 pcp.StateChange = (bEnable ? DICS_ENABLE : DICS_DISABLE);
152 pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
153
154 if (SetupDiSetClassInstallParams(
155 DeviceInfoSet,
156 DevInfoData,
157 &pcp.ClassInstallHeader,
158 sizeof(SP_PROPCHANGE_PARAMS)) &&
159 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
160 DeviceInfoSet,
161 DevInfoData))
162 {
163 dp.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
164 if (SetupDiGetDeviceInstallParams(
165 DeviceInfoSet,
166 DevInfoData,
167 &dp))
168 {
169 if (bNeedReboot != NULL)
170 {
171 *bNeedReboot = ((dp.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0);
172 }
173
174 Ret = TRUE;
175 }
176 }
177 return Ret;
178 }
179
180 static BOOL
181 PrepareFoldersToScan(
182 IN PDEVINSTDATA DevInstData,
183 IN HWND hwndDlg)
184 {
185 FIXME("Include removable devices: %s\n", IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEDIA) ? "yes" : "no");
186 FIXME("Include custom path : %s\n", IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH) ? "yes" : "no");
187 return TRUE;
188 }
189
190 static DWORD WINAPI
191 FindDriverProc(
192 IN LPVOID lpParam)
193 {
194 TCHAR drive[] = {'?',':',0};
195 size_t nType;
196 DWORD dwDrives;
197 PDEVINSTDATA DevInstData;
198 DWORD config_flags;
199 UINT i = 1;
200
201 DevInstData = (PDEVINSTDATA)lpParam;
202 DPRINT1("FindDriverProc(%p)\n", DevInstData->CustomSearchPath);
203 if (DevInstData->CustomSearchPath)
204 {
205 LPCTSTR Path;
206 for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += _tcslen(Path) + 1)
207 DPRINT1("Path %S\n", Path);
208 }
209
210 dwDrives = GetLogicalDrives();
211 for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
212 {
213 if (dwDrives & i)
214 {
215 nType = GetDriveType(drive);
216 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
217 {
218 /* search for valid inf file */
219 if (SearchDriverRecursive(DevInstData, drive))
220 {
221 InstallCurrentDriver(DevInstData);
222 PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
223 return 0;
224 }
225 }
226 }
227 i <<= 1;
228 }
229
230 /* update device configuration */
231 if (SetupDiGetDeviceRegistryProperty(
232 DevInstData->hDevInfo,
233 &DevInstData->devInfoData,
234 SPDRP_CONFIGFLAGS,
235 NULL,
236 (BYTE *)&config_flags,
237 sizeof(config_flags),
238 NULL))
239 {
240 config_flags |= CONFIGFLAG_FAILEDINSTALL;
241 SetupDiSetDeviceRegistryProperty(
242 DevInstData->hDevInfo,
243 &DevInstData->devInfoData,
244 SPDRP_CONFIGFLAGS,
245 (BYTE *)&config_flags, sizeof(config_flags));
246 }
247
248 PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0);
249 return 0;
250 }
251
252 static INT_PTR CALLBACK
253 WelcomeDlgProc(
254 IN HWND hwndDlg,
255 IN UINT uMsg,
256 IN WPARAM wParam,
257 IN LPARAM lParam)
258 {
259 PDEVINSTDATA DevInstData;
260
261 /* Retrieve pointer to the global setup data */
262 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
263
264 switch (uMsg)
265 {
266 case WM_INITDIALOG:
267 {
268 HWND hwndControl;
269 DWORD dwStyle;
270
271 /* Get pointer to the global setup data */
272 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
273 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
274
275 hwndControl = GetParent(hwndDlg);
276
277 /* Center the wizard window */
278 CenterWindow(hwndControl);
279
280 /* Hide the system menu */
281 dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
282 SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
283
284 /* Set title font */
285 SendDlgItemMessage(
286 hwndDlg,
287 IDC_WELCOMETITLE,
288 WM_SETFONT,
289 (WPARAM)DevInstData->hTitleFont,
290 (LPARAM)TRUE);
291
292 SendDlgItemMessage(
293 hwndDlg,
294 IDC_DEVICE,
295 WM_SETTEXT,
296 0,
297 (LPARAM)DevInstData->buffer);
298
299 SendDlgItemMessage(
300 hwndDlg,
301 IDC_RADIO_AUTO,
302 BM_SETCHECK,
303 (WPARAM)TRUE,
304 (LPARAM)0);
305 break;
306 }
307
308 case WM_NOTIFY:
309 {
310 LPNMHDR lpnm = (LPNMHDR)lParam;
311
312 switch (lpnm->code)
313 {
314 case PSN_SETACTIVE:
315 /* Enable the Next button */
316 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
317 break;
318
319 case PSN_WIZNEXT:
320 /* Handle a Next button click, if necessary */
321 if (SendDlgItemMessage(hwndDlg, IDC_RADIO_AUTO, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_CHECKED)
322 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_SEARCHDRV);
323 return TRUE;
324
325 default:
326 break;
327 }
328 break;
329 }
330
331 default:
332 break;
333 }
334
335 return FALSE;
336 }
337
338 static void
339 IncludePath(HWND Dlg, BOOL Enabled)
340 {
341 EnableWindow(GetDlgItem(Dlg, IDC_COMBO_PATH), Enabled);
342 EnableWindow(GetDlgItem(Dlg, IDC_BROWSE), /*FIXME: Enabled*/ FALSE);
343 }
344
345 static void
346 AutoDriver(HWND Dlg, BOOL Enabled)
347 {
348 EnableWindow(GetDlgItem(Dlg, IDC_CHECK_MEDIA), Enabled);
349 EnableWindow(GetDlgItem(Dlg, IDC_CHECK_PATH), Enabled);
350 IncludePath(Dlg, Enabled & IsDlgButtonChecked(Dlg, IDC_CHECK_PATH));
351 }
352
353 static INT_PTR CALLBACK
354 CHSourceDlgProc(
355 IN HWND hwndDlg,
356 IN UINT uMsg,
357 IN WPARAM wParam,
358 IN LPARAM lParam)
359 {
360 PDEVINSTDATA DevInstData;
361
362 /* Retrieve pointer to the global setup data */
363 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
364
365 switch (uMsg)
366 {
367 case WM_INITDIALOG:
368 {
369 HWND hwndControl;
370 DWORD dwStyle;
371
372 /* Get pointer to the global setup data */
373 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
374 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
375
376 hwndControl = GetParent(hwndDlg);
377
378 /* Center the wizard window */
379 CenterWindow(hwndControl);
380
381 /* Hide the system menu */
382 dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
383 SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
384
385 SendDlgItemMessage(
386 hwndDlg,
387 IDC_RADIO_SEARCHHERE,
388 BM_SETCHECK,
389 (WPARAM)TRUE,
390 (LPARAM)0);
391 AutoDriver(hwndDlg, TRUE);
392 IncludePath(hwndDlg, FALSE);
393
394 /* Disable manual driver choice for now */
395 EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_CHOOSE), FALSE);
396 /* Disable custom path for now */
397 EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_PATH), FALSE);
398 break;
399 }
400
401 case WM_COMMAND:
402 {
403 switch (LOWORD(wParam))
404 {
405 case IDC_RADIO_SEARCHHERE:
406 AutoDriver(hwndDlg, TRUE);
407 return TRUE;
408
409 case IDC_RADIO_CHOOSE:
410 AutoDriver(hwndDlg, FALSE);
411 return TRUE;
412
413 case IDC_CHECK_PATH:
414 IncludePath(hwndDlg, IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH));
415 return TRUE;
416
417 case IDC_BROWSE:
418 /* FIXME: set the IDC_COMBO_PATH text */
419 FIXME("Should display browse folder dialog\n");
420 return FALSE;
421 }
422 break;
423 }
424
425 case WM_NOTIFY:
426 {
427 LPNMHDR lpnm = (LPNMHDR)lParam;
428
429 switch (lpnm->code)
430 {
431 case PSN_SETACTIVE:
432 /* Enable the Next and Back buttons */
433 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
434 break;
435
436 case PSN_WIZNEXT:
437 /* Handle a Next button click, if necessary */
438 if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_SEARCHHERE))
439 {
440 HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath);
441 DevInstData->CustomSearchPath = NULL;
442 if (PrepareFoldersToScan(DevInstData, hwndDlg))
443 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_SEARCHDRV);
444 }
445 else
446 /* FIXME */;
447 return TRUE;
448
449 default:
450 break;
451 }
452 break;
453 }
454
455 default:
456 break;
457 }
458
459 return FALSE;
460 }
461
462 static INT_PTR CALLBACK
463 SearchDrvDlgProc(
464 IN HWND hwndDlg,
465 IN UINT uMsg,
466 IN WPARAM wParam,
467 IN LPARAM lParam)
468 {
469 PDEVINSTDATA DevInstData;
470 DWORD dwThreadId;
471
472 /* Retrieve pointer to the global setup data */
473 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
474
475 switch (uMsg)
476 {
477 case WM_INITDIALOG:
478 {
479 HWND hwndControl;
480 DWORD dwStyle;
481
482 /* Get pointer to the global setup data */
483 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
484 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
485
486 DevInstData->hDialog = hwndDlg;
487 hwndControl = GetParent(hwndDlg);
488
489 /* Center the wizard window */
490 CenterWindow(hwndControl);
491
492 SendDlgItemMessage(
493 hwndDlg,
494 IDC_DEVICE,
495 WM_SETTEXT,
496 0,
497 (LPARAM)DevInstData->buffer);
498
499 /* Hide the system menu */
500 dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
501 SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
502 break;
503 }
504
505 case WM_SEARCH_FINISHED:
506 {
507 CloseHandle(hThread);
508 hThread = 0;
509 if (wParam == 0)
510 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_NODRIVER);
511 else
512 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_FINISHPAGE);
513 break;
514 }
515
516 case WM_NOTIFY:
517 {
518 LPNMHDR lpnm = (LPNMHDR)lParam;
519
520 switch (lpnm->code)
521 {
522 case PSN_SETACTIVE:
523 PropSheet_SetWizButtons(GetParent(hwndDlg), !PSWIZB_NEXT | !PSWIZB_BACK);
524 hThread = CreateThread(NULL, 0, FindDriverProc, DevInstData, 0, &dwThreadId);
525 break;
526
527 case PSN_KILLACTIVE:
528 if (hThread != 0)
529 {
530 SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE);
531 return TRUE;
532 }
533 break;
534
535 case PSN_WIZNEXT:
536 /* Handle a Next button click, if necessary */
537 break;
538
539 default:
540 break;
541 }
542 break;
543 }
544
545 default:
546 break;
547 }
548
549 return FALSE;
550 }
551
552 static INT_PTR CALLBACK
553 InstallDrvDlgProc(
554 IN HWND hwndDlg,
555 IN UINT uMsg,
556 IN WPARAM wParam,
557 IN LPARAM lParam)
558 {
559 return FALSE;
560 }
561
562 static INT_PTR CALLBACK
563 NoDriverDlgProc(
564 IN HWND hwndDlg,
565 IN UINT uMsg,
566 IN WPARAM wParam,
567 IN LPARAM lParam)
568 {
569 PDEVINSTDATA DevInstData;
570
571 /* Get pointer to the global setup data */
572 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
573
574 switch (uMsg)
575 {
576 case WM_INITDIALOG:
577 {
578 HWND hwndControl;
579 BOOL DisableableDevice = FALSE;
580
581 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
582 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
583
584 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
585 ShowWindow (hwndControl, SW_HIDE);
586 EnableWindow (hwndControl, FALSE);
587
588 /* Set title font */
589 SendDlgItemMessage(
590 hwndDlg,
591 IDC_FINISHTITLE,
592 WM_SETFONT,
593 (WPARAM)DevInstData->hTitleFont,
594 (LPARAM)TRUE);
595
596 /* disable the "do not show this dialog anymore" checkbox
597 if the device cannot be disabled */
598 CanDisableDevice(
599 DevInstData->devInfoData.DevInst,
600 NULL,
601 &DisableableDevice);
602 EnableWindow(
603 GetDlgItem(hwndDlg, IDC_DONOTSHOWDLG),
604 DisableableDevice);
605 break;
606 }
607
608 case WM_NOTIFY:
609 {
610 LPNMHDR lpnm = (LPNMHDR)lParam;
611
612 switch (lpnm->code)
613 {
614 case PSN_SETACTIVE:
615 /* Enable the correct buttons on for the active page */
616 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
617 break;
618
619 case PSN_WIZBACK:
620 /* Handle a Back button click, if necessary */
621 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_WELCOMEPAGE);
622 return TRUE;
623
624 case PSN_WIZFINISH:
625 {
626 BOOL DisableableDevice = FALSE;
627 BOOL IsStarted = FALSE;
628
629 if (CanDisableDevice(DevInstData->devInfoData.DevInst,
630 NULL,
631 &DisableableDevice) &&
632 DisableableDevice &&
633 IsDeviceStarted(
634 DevInstData->devInfoData.DevInst,
635 NULL,
636 &IsStarted) &&
637 !IsStarted &&
638 SendDlgItemMessage(
639 hwndDlg,
640 IDC_DONOTSHOWDLG,
641 BM_GETCHECK,
642 (WPARAM)0, (LPARAM)0) == BST_CHECKED)
643 {
644 /* disable the device */
645 StartDevice(
646 DevInstData->hDevInfo,
647 &DevInstData->devInfoData,
648 FALSE,
649 0,
650 NULL);
651 }
652 break;
653 }
654
655 default:
656 break;
657 }
658 break;
659 }
660
661 default:
662 break;
663 }
664
665 return FALSE;
666 }
667
668 static INT_PTR CALLBACK
669 FinishDlgProc(
670 IN HWND hwndDlg,
671 IN UINT uMsg,
672 IN WPARAM wParam,
673 IN LPARAM lParam)
674 {
675 PDEVINSTDATA DevInstData;
676
677 /* Retrieve pointer to the global setup data */
678 DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
679
680 switch (uMsg)
681 {
682 case WM_INITDIALOG:
683 {
684 HWND hwndControl;
685
686 /* Get pointer to the global setup data */
687 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
688 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
689
690 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
691 ShowWindow (hwndControl, SW_HIDE);
692 EnableWindow (hwndControl, FALSE);
693
694 SendDlgItemMessage(
695 hwndDlg,
696 IDC_DEVICE,
697 WM_SETTEXT,
698 0,
699 (LPARAM)DevInstData->drvInfoData.Description);
700
701 /* Set title font */
702 SendDlgItemMessage(
703 hwndDlg,
704 IDC_FINISHTITLE,
705 WM_SETFONT,
706 (WPARAM)DevInstData->hTitleFont,
707 (LPARAM)TRUE);
708 break;
709 }
710
711 case WM_NOTIFY:
712 {
713 LPNMHDR lpnm = (LPNMHDR)lParam;
714
715 switch (lpnm->code)
716 {
717 case PSN_SETACTIVE:
718 /* Enable the correct buttons on for the active page */
719 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
720 break;
721
722 case PSN_WIZBACK:
723 /* Handle a Back button click, if necessary */
724 break;
725
726 case PSN_WIZFINISH:
727 /* Handle a Finish button click, if necessary */
728 break;
729
730 default:
731 break;
732 }
733 break;
734 }
735
736 default:
737 break;
738 }
739
740 return FALSE;
741 }
742
743 static HFONT
744 CreateTitleFont(VOID)
745 {
746 NONCLIENTMETRICS ncm;
747 LOGFONT LogFont;
748 HDC hdc;
749 INT FontSize;
750 HFONT hFont;
751
752 ncm.cbSize = sizeof(NONCLIENTMETRICS);
753 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
754
755 LogFont = ncm.lfMessageFont;
756 LogFont.lfWeight = FW_BOLD;
757 _tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
758
759 hdc = GetDC(NULL);
760 FontSize = 12;
761 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
762 hFont = CreateFontIndirect(&LogFont);
763 ReleaseDC(NULL, hdc);
764
765 return hFont;
766 }
767
768 BOOL
769 DisplayWizard(
770 IN PDEVINSTDATA DevInstData,
771 IN HWND hwndParent,
772 IN UINT startPage)
773 {
774 PROPSHEETHEADER psh;
775 HPROPSHEETPAGE ahpsp[IDD_FINISHPAGE + 1];
776 PROPSHEETPAGE psp;
777
778 /* Create the Welcome page */
779 ZeroMemory(&psp, sizeof(PROPSHEETPAGE));
780 psp.dwSize = sizeof(PROPSHEETPAGE);
781 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
782 psp.hInstance = hDllInstance;
783 psp.lParam = (LPARAM)DevInstData;
784 psp.pfnDlgProc = WelcomeDlgProc;
785 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE);
786 ahpsp[IDD_WELCOMEPAGE] = CreatePropertySheetPage(&psp);
787
788 /* Create the Select Source page */
789 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
790 psp.pfnDlgProc = CHSourceDlgProc;
791 psp.pszTemplate = MAKEINTRESOURCE(IDD_CHSOURCE);
792 ahpsp[IDD_CHSOURCE] = CreatePropertySheetPage(&psp);
793
794 /* Create the Search driver page */
795 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
796 psp.pfnDlgProc = SearchDrvDlgProc;
797 psp.pszTemplate = MAKEINTRESOURCE(IDD_SEARCHDRV);
798 ahpsp[IDD_SEARCHDRV] = CreatePropertySheetPage(&psp);
799
800 /* Create the Install driver page */
801 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
802 psp.pfnDlgProc = InstallDrvDlgProc;
803 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLDRV);
804 ahpsp[IDD_INSTALLDRV] = CreatePropertySheetPage(&psp);
805
806 /* Create the Install failed page */
807 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
808 psp.pfnDlgProc = NoDriverDlgProc;
809 psp.pszTemplate = MAKEINTRESOURCE(IDD_NODRIVER);
810 ahpsp[IDD_NODRIVER] = CreatePropertySheetPage(&psp);
811
812 /* Create the Finish page */
813 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
814 psp.pfnDlgProc = FinishDlgProc;
815 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
816 ahpsp[IDD_FINISHPAGE] = CreatePropertySheetPage(&psp);
817
818 /* Create the property sheet */
819 psh.dwSize = sizeof(PROPSHEETHEADER);
820 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
821 psh.hInstance = hDllInstance;
822 psh.hwndParent = hwndParent;
823 psh.nPages = 7;
824 psh.nStartPage = startPage;
825 psh.phpage = ahpsp;
826 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
827 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
828
829 /* Create title font */
830 DevInstData->hTitleFont = CreateTitleFont();
831
832 /* Display the wizard */
833 PropertySheet(&psh);
834
835 DeleteObject(DevInstData->hTitleFont);
836
837 return TRUE;
838 }