2 * New device installer (newdev.dll)
4 * Copyright 2006 Hervé Poussineau (hpoussin@reactos.org)
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.
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.
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
24 WINE_DEFAULT_DEBUG_CHANNEL(newdev
);
36 hWndParent
= GetParent(hWnd
);
37 if (hWndParent
== NULL
)
38 hWndParent
= GetDesktopWindow();
40 GetWindowRect(hWndParent
, &rcParent
);
41 GetWindowRect(hWnd
, &rcWindow
);
46 ((rcParent
.right
- rcParent
.left
) - (rcWindow
.right
- rcWindow
.left
)) / 2,
47 ((rcParent
.bottom
- rcParent
.top
) - (rcWindow
.bottom
- rcWindow
.top
)) / 2,
60 /* hpoussin, Dec 2005. I've disabled this code because
61 * ntoskrnl never sets the DN_DISABLEABLE flag.
64 ULONG Status
, ProblemNumber
;
67 cr
= CM_Get_DevNode_Status_Ex(
75 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
93 ULONG Status
, ProblemNumber
;
96 cr
= CM_Get_DevNode_Status_Ex(
102 if (cr
== CR_SUCCESS
)
104 *IsEnabled
= ((Status
& DN_STARTED
) != 0);
113 IN HDEVINFO DeviceInfoSet
,
114 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
116 IN DWORD HardwareProfile OPTIONAL
,
117 OUT BOOL
*bNeedReboot OPTIONAL
)
119 SP_PROPCHANGE_PARAMS pcp
;
120 SP_DEVINSTALL_PARAMS dp
;
124 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
125 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
126 pcp
.HwProfile
= HardwareProfile
;
130 /* try to enable the device on the global profile */
131 pcp
.StateChange
= DICS_ENABLE
;
132 pcp
.Scope
= DICS_FLAG_GLOBAL
;
135 LastErr
= GetLastError();
136 if (SetupDiSetClassInstallParams(
139 &pcp
.ClassInstallHeader
,
140 sizeof(SP_PROPCHANGE_PARAMS
)))
142 SetupDiCallClassInstaller(
147 SetLastError(LastErr
);
150 /* try config-specific */
151 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
152 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
154 if (SetupDiSetClassInstallParams(
157 &pcp
.ClassInstallHeader
,
158 sizeof(SP_PROPCHANGE_PARAMS
)) &&
159 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
163 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
164 if (SetupDiGetDeviceInstallParams(
169 if (bNeedReboot
!= NULL
)
171 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
181 PrepareFoldersToScan(
182 IN PDEVINSTDATA DevInstData
,
185 TCHAR drive
[] = {'?',':',0};
189 DWORD CustomTextLength
= 0;
190 DWORD LengthNeeded
= 0;
193 TRACE("Include removable devices: %s\n", IsDlgButtonChecked(hwndDlg
, IDC_CHECK_MEDIA
) ? "yes" : "no");
194 TRACE("Include custom path : %s\n", IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
) ? "yes" : "no");
196 /* Calculate length needed to store the search paths */
197 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_MEDIA
))
199 dwDrives
= GetLogicalDrives();
200 for (drive
[0] = 'A', i
= 1; drive
[0] <= 'Z'; drive
[0]++, i
<<= 1)
204 nType
= GetDriveType(drive
);
205 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
212 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
))
214 CustomTextLength
= 1 + SendDlgItemMessage(
220 LengthNeeded
+= CustomTextLength
;
223 /* Allocate space for search paths */
224 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
225 DevInstData
->CustomSearchPath
= Buffer
= HeapAlloc(
228 (LengthNeeded
+ 1) * sizeof(TCHAR
));
231 TRACE("HeapAlloc() failed\n");
232 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
236 /* Fill search paths */
237 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_MEDIA
))
239 for (drive
[0] = 'A', i
= 1; drive
[0] <= 'Z'; drive
[0]++, i
<<= 1)
243 nType
= GetDriveType(drive
);
244 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
246 Buffer
+= 1 + _stprintf(Buffer
, drive
);
251 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
))
253 Buffer
+= 1 + SendDlgItemMessage(
257 (WPARAM
)CustomTextLength
,
269 PDEVINSTDATA DevInstData
;
273 DevInstData
= (PDEVINSTDATA
)lpParam
;
275 /* Yes, we can safely ignore the problem (if any) */
276 SetupDiDestroyDriverInfoList(
277 DevInstData
->hDevInfo
,
278 &DevInstData
->devInfoData
,
281 if (!DevInstData
->CustomSearchPath
)
283 /* Search in default location */
284 result
= SearchDriver(DevInstData
, NULL
, NULL
);
288 /* Search only in specified paths */
289 /* We need to check all specified directories to be
290 * sure to find the best driver for the device.
293 for (Path
= DevInstData
->CustomSearchPath
; *Path
!= '\0'; Path
+= _tcslen(Path
) + 1)
295 TRACE("Search driver in %S\n", Path
);
296 if (_tcslen(Path
) == 2 && Path
[1] == ':')
298 if (SearchDriverRecursive(DevInstData
, Path
))
303 if (SearchDriver(DevInstData
, Path
, NULL
))
311 PostMessage(DevInstData
->hDialog
, WM_SEARCH_FINISHED
, 1, 0);
315 /* Update device configuration */
316 if (SetupDiGetDeviceRegistryProperty(
317 DevInstData
->hDevInfo
,
318 &DevInstData
->devInfoData
,
321 (BYTE
*)&config_flags
,
322 sizeof(config_flags
),
325 config_flags
|= CONFIGFLAG_FAILEDINSTALL
;
326 SetupDiSetDeviceRegistryProperty(
327 DevInstData
->hDevInfo
,
328 &DevInstData
->devInfoData
,
330 (BYTE
*)&config_flags
, sizeof(config_flags
));
333 PostMessage(DevInstData
->hDialog
, WM_SEARCH_FINISHED
, 0, 0);
342 PDEVINSTDATA DevInstData
;
345 DevInstData
= (PDEVINSTDATA
)lpParam
;
346 res
= InstallCurrentDriver(DevInstData
);
347 PostMessage(DevInstData
->hDialog
, WM_INSTALL_FINISHED
, res
? 0 : 1, 0);
352 PopulateCustomPathCombo(
358 LPTSTR Buffer
= NULL
;
362 (void)ComboBox_ResetContent(hwndCombo
);
364 /* RegGetValue would have been better... */
367 REGSTR_PATH_SETUP REGSTR_KEY_SETUP
,
371 if (rc
!= ERROR_SUCCESS
)
373 TRACE("RegOpenKeyEx() failed with error 0x%lx\n", rc
);
376 rc
= RegQueryValueEx(
378 _T("Installation Sources"),
383 if (rc
!= ERROR_SUCCESS
|| dwRegType
!= REG_MULTI_SZ
)
385 TRACE("RegQueryValueEx() failed with error 0x%lx\n", rc
);
388 /* Allocate enough space to add 2 NULL chars at the end of the string */
389 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwPathLength
+ 2 * sizeof(TCHAR
));
392 TRACE("HeapAlloc() failed\n");
395 rc
= RegQueryValueEx(
397 _T("Installation Sources"),
402 if (rc
!= ERROR_SUCCESS
)
404 TRACE("RegQueryValueEx() failed with error 0x%lx\n", rc
);
407 Buffer
[dwPathLength
] = Buffer
[dwPathLength
+ 1] = '\0';
409 /* Populate combo box */
410 for (Path
= Buffer
; *Path
; Path
+= _tcslen(Path
))
411 (void)ComboBox_AddString(hwndCombo
, Path
);
412 (void)ComboBox_SetCurSel(hwndCombo
, 0);
417 HeapFree(GetProcessHeap(), 0, Buffer
);
427 static INT_PTR CALLBACK
434 PDEVINSTDATA DevInstData
;
436 /* Retrieve pointer to the global setup data */
437 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
446 /* Get pointer to the global setup data */
447 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
448 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
450 hwndControl
= GetParent(hwndDlg
);
452 /* Center the wizard window */
453 CenterWindow(hwndControl
);
455 /* Hide the system menu */
456 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
457 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
464 (WPARAM
)DevInstData
->hTitleFont
,
472 (LPARAM
)DevInstData
->buffer
);
485 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
490 /* Enable the Next button */
491 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
495 /* Handle a Next button click, if necessary */
496 if (SendDlgItemMessage(hwndDlg
, IDC_RADIO_AUTO
, BM_GETCHECK
, (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
497 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_SEARCHDRV
);
514 IncludePath(HWND Dlg
, BOOL Enabled
)
516 EnableWindow(GetDlgItem(Dlg
, IDC_COMBO_PATH
), Enabled
);
517 EnableWindow(GetDlgItem(Dlg
, IDC_BROWSE
), /*FIXME: Enabled*/ FALSE
);
521 AutoDriver(HWND Dlg
, BOOL Enabled
)
523 EnableWindow(GetDlgItem(Dlg
, IDC_CHECK_MEDIA
), Enabled
);
524 EnableWindow(GetDlgItem(Dlg
, IDC_CHECK_PATH
), Enabled
);
525 IncludePath(Dlg
, Enabled
& IsDlgButtonChecked(Dlg
, IDC_CHECK_PATH
));
528 static INT_PTR CALLBACK
535 PDEVINSTDATA DevInstData
;
537 /* Retrieve pointer to the global setup data */
538 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
547 /* Get pointer to the global setup data */
548 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
549 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
551 hwndControl
= GetParent(hwndDlg
);
553 /* Center the wizard window */
554 CenterWindow(hwndControl
);
556 /* Hide the system menu */
557 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
558 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
560 PopulateCustomPathCombo(GetDlgItem(hwndDlg
, IDC_COMBO_PATH
));
564 IDC_RADIO_SEARCHHERE
,
568 AutoDriver(hwndDlg
, TRUE
);
569 IncludePath(hwndDlg
, FALSE
);
571 /* Disable manual driver choice for now */
572 EnableWindow(GetDlgItem(hwndDlg
, IDC_RADIO_CHOOSE
), FALSE
);
579 switch (LOWORD(wParam
))
581 case IDC_RADIO_SEARCHHERE
:
582 AutoDriver(hwndDlg
, TRUE
);
585 case IDC_RADIO_CHOOSE
:
586 AutoDriver(hwndDlg
, FALSE
);
590 IncludePath(hwndDlg
, IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
));
594 /* FIXME: set the IDC_COMBO_PATH text */
595 FIXME("Should display browse folder dialog\n");
603 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
608 /* Enable the Next and Back buttons */
609 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
| PSWIZB_BACK
);
613 /* Handle a Next button click, if necessary */
614 if (IsDlgButtonChecked(hwndDlg
, IDC_RADIO_SEARCHHERE
))
616 SaveCustomPath(GetDlgItem(hwndDlg
, IDC_COMBO_PATH
));
617 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
618 DevInstData
->CustomSearchPath
= NULL
;
619 if (PrepareFoldersToScan(DevInstData
, hwndDlg
))
620 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_SEARCHDRV
);
622 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLFAILED
);
641 static INT_PTR CALLBACK
648 PDEVINSTDATA DevInstData
;
651 /* Retrieve pointer to the global setup data */
652 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
661 /* Get pointer to the global setup data */
662 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
663 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
665 DevInstData
->hDialog
= hwndDlg
;
666 hwndControl
= GetParent(hwndDlg
);
668 /* Center the wizard window */
669 CenterWindow(hwndControl
);
676 (LPARAM
)DevInstData
->buffer
);
678 /* Hide the system menu */
679 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
680 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
684 case WM_SEARCH_FINISHED
:
686 CloseHandle(hThread
);
689 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_NODRIVER
);
691 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLDRV
);
697 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
702 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
703 hThread
= CreateThread(NULL
, 0, FindDriverProc
, DevInstData
, 0, &dwThreadId
);
709 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
715 /* Handle a Next button click, if necessary */
731 static INT_PTR CALLBACK
738 PDEVINSTDATA DevInstData
;
741 /* Retrieve pointer to the global setup data */
742 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
751 /* Get pointer to the global setup data */
752 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
753 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
755 DevInstData
->hDialog
= hwndDlg
;
756 hwndControl
= GetParent(hwndDlg
);
758 /* Center the wizard window */
759 CenterWindow(hwndControl
);
766 (LPARAM
)DevInstData
->drvInfoData
.Description
);
768 /* Hide the system menu */
769 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
770 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
774 case WM_INSTALL_FINISHED
:
776 CloseHandle(hThread
);
779 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_FINISHPAGE
);
781 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLFAILED
);
787 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
792 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
793 hThread
= CreateThread(NULL
, 0, InstallDriverProc
, DevInstData
, 0, &dwThreadId
);
799 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
805 /* Handle a Next button click, if necessary */
821 static INT_PTR CALLBACK
828 PDEVINSTDATA DevInstData
;
830 /* Get pointer to the global setup data */
831 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
838 BOOL DisableableDevice
= FALSE
;
840 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
841 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
843 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
844 ShowWindow(hwndControl
, SW_HIDE
);
845 EnableWindow(hwndControl
, FALSE
);
852 (WPARAM
)DevInstData
->hTitleFont
,
855 /* disable the "do not show this dialog anymore" checkbox
856 if the device cannot be disabled */
858 DevInstData
->devInfoData
.DevInst
,
862 GetDlgItem(hwndDlg
, IDC_DONOTSHOWDLG
),
869 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
874 /* Enable the correct buttons on for the active page */
875 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
879 /* Handle a Back button click, if necessary */
880 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_CHSOURCE
);
885 BOOL DisableableDevice
= FALSE
;
886 BOOL IsStarted
= FALSE
;
888 if (CanDisableDevice(DevInstData
->devInfoData
.DevInst
,
890 &DisableableDevice
) &&
893 DevInstData
->devInfoData
.DevInst
,
901 (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
903 /* disable the device */
905 DevInstData
->hDevInfo
,
906 &DevInstData
->devInfoData
,
927 static INT_PTR CALLBACK
928 InstallFailedDlgProc(
934 PDEVINSTDATA DevInstData
;
936 /* Retrieve pointer to the global setup data */
937 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
945 /* Get pointer to the global setup data */
946 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
947 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
949 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
950 ShowWindow(hwndControl
, SW_HIDE
);
951 EnableWindow(hwndControl
, FALSE
);
958 (LPARAM
)DevInstData
->drvInfoData
.Description
);
965 (WPARAM
)DevInstData
->hTitleFont
,
972 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
977 /* Enable the correct buttons on for the active page */
978 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
982 /* Handle a Back button click, if necessary */
986 /* Handle a Finish button click, if necessary */
1002 static INT_PTR CALLBACK
1009 PDEVINSTDATA DevInstData
;
1011 /* Retrieve pointer to the global setup data */
1012 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
1020 /* Get pointer to the global setup data */
1021 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1022 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
1024 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
1025 ShowWindow(hwndControl
, SW_HIDE
);
1026 EnableWindow(hwndControl
, FALSE
);
1033 (LPARAM
)DevInstData
->drvInfoData
.Description
);
1035 /* Set title font */
1040 (WPARAM
)DevInstData
->hTitleFont
,
1047 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1052 /* Enable the correct buttons on for the active page */
1053 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
1057 /* Handle a Back button click, if necessary */
1061 /* Handle a Finish button click, if necessary */
1078 CreateTitleFont(VOID
)
1080 NONCLIENTMETRICS ncm
;
1086 ncm
.cbSize
= sizeof(NONCLIENTMETRICS
);
1087 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, &ncm
, 0);
1089 LogFont
= ncm
.lfMessageFont
;
1090 LogFont
.lfWeight
= FW_BOLD
;
1091 _tcscpy(LogFont
.lfFaceName
, _T("MS Shell Dlg"));
1095 LogFont
.lfHeight
= 0 - GetDeviceCaps (hdc
, LOGPIXELSY
) * FontSize
/ 72;
1096 hFont
= CreateFontIndirect(&LogFont
);
1097 ReleaseDC(NULL
, hdc
);
1104 IN PDEVINSTDATA DevInstData
,
1108 PROPSHEETHEADER psh
;
1109 HPROPSHEETPAGE ahpsp
[IDD_FINISHPAGE
+ 1];
1112 /* Create the Welcome page */
1113 ZeroMemory(&psp
, sizeof(PROPSHEETPAGE
));
1114 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
1115 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1116 psp
.hInstance
= hDllInstance
;
1117 psp
.lParam
= (LPARAM
)DevInstData
;
1118 psp
.pfnDlgProc
= WelcomeDlgProc
;
1119 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_WELCOMEPAGE
);
1120 ahpsp
[IDD_WELCOMEPAGE
] = CreatePropertySheetPage(&psp
);
1122 /* Create the Select Source page */
1123 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1124 psp
.pfnDlgProc
= CHSourceDlgProc
;
1125 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_CHSOURCE
);
1126 ahpsp
[IDD_CHSOURCE
] = CreatePropertySheetPage(&psp
);
1128 /* Create the Search driver page */
1129 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1130 psp
.pfnDlgProc
= SearchDrvDlgProc
;
1131 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_SEARCHDRV
);
1132 ahpsp
[IDD_SEARCHDRV
] = CreatePropertySheetPage(&psp
);
1134 /* Create the Install driver page */
1135 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1136 psp
.pfnDlgProc
= InstallDrvDlgProc
;
1137 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_INSTALLDRV
);
1138 ahpsp
[IDD_INSTALLDRV
] = CreatePropertySheetPage(&psp
);
1140 /* Create the No driver page */
1141 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1142 psp
.pfnDlgProc
= NoDriverDlgProc
;
1143 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_NODRIVER
);
1144 ahpsp
[IDD_NODRIVER
] = CreatePropertySheetPage(&psp
);
1146 /* Create the Install failed page */
1147 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1148 psp
.pfnDlgProc
= InstallFailedDlgProc
;
1149 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_INSTALLFAILED
);
1150 ahpsp
[IDD_INSTALLFAILED
] = CreatePropertySheetPage(&psp
);
1152 /* Create the Finish page */
1153 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1154 psp
.pfnDlgProc
= FinishDlgProc
;
1155 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_FINISHPAGE
);
1156 ahpsp
[IDD_FINISHPAGE
] = CreatePropertySheetPage(&psp
);
1158 /* Create the property sheet */
1159 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1160 psh
.dwFlags
= PSH_WIZARD97
| PSH_WATERMARK
| PSH_HEADER
;
1161 psh
.hInstance
= hDllInstance
;
1162 psh
.hwndParent
= hwndParent
;
1163 psh
.nPages
= IDD_FINISHPAGE
+ 1;
1164 psh
.nStartPage
= startPage
;
1166 psh
.pszbmWatermark
= MAKEINTRESOURCE(IDB_WATERMARK
);
1167 psh
.pszbmHeader
= MAKEINTRESOURCE(IDB_HEADER
);
1169 /* Create title font */
1170 DevInstData
->hTitleFont
= CreateTitleFont();
1172 /* Display the wizard */
1173 PropertySheet(&psh
);
1175 DeleteObject(DevInstData
->hTitleFont
);