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
21 #include "newdev_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(newdev
);
35 hWndParent
= GetParent(hWnd
);
36 if (hWndParent
== NULL
)
37 hWndParent
= GetDesktopWindow();
39 GetWindowRect(hWndParent
, &rcParent
);
40 GetWindowRect(hWnd
, &rcWindow
);
45 ((rcParent
.right
- rcParent
.left
) - (rcWindow
.right
- rcWindow
.left
)) / 2,
46 ((rcParent
.bottom
- rcParent
.top
) - (rcWindow
.bottom
- rcWindow
.top
)) / 2,
59 /* hpoussin, Dec 2005. I've disabled this code because
60 * ntoskrnl never sets the DN_DISABLEABLE flag.
63 ULONG Status
, ProblemNumber
;
66 cr
= CM_Get_DevNode_Status_Ex(
74 *CanDisable
= ((Status
& DN_DISABLEABLE
) != 0);
92 ULONG Status
, ProblemNumber
;
95 cr
= CM_Get_DevNode_Status_Ex(
101 if (cr
== CR_SUCCESS
)
103 *IsEnabled
= ((Status
& DN_STARTED
) != 0);
112 IN HDEVINFO DeviceInfoSet
,
113 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
,
115 IN DWORD HardwareProfile OPTIONAL
,
116 OUT BOOL
*bNeedReboot OPTIONAL
)
118 SP_PROPCHANGE_PARAMS pcp
;
119 SP_DEVINSTALL_PARAMS dp
;
123 pcp
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
124 pcp
.ClassInstallHeader
.InstallFunction
= DIF_PROPERTYCHANGE
;
125 pcp
.HwProfile
= HardwareProfile
;
129 /* try to enable the device on the global profile */
130 pcp
.StateChange
= DICS_ENABLE
;
131 pcp
.Scope
= DICS_FLAG_GLOBAL
;
134 LastErr
= GetLastError();
135 if (SetupDiSetClassInstallParams(
138 &pcp
.ClassInstallHeader
,
139 sizeof(SP_PROPCHANGE_PARAMS
)))
141 SetupDiCallClassInstaller(
146 SetLastError(LastErr
);
149 /* try config-specific */
150 pcp
.StateChange
= (bEnable
? DICS_ENABLE
: DICS_DISABLE
);
151 pcp
.Scope
= DICS_FLAG_CONFIGSPECIFIC
;
153 if (SetupDiSetClassInstallParams(
156 &pcp
.ClassInstallHeader
,
157 sizeof(SP_PROPCHANGE_PARAMS
)) &&
158 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE
,
162 dp
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
163 if (SetupDiGetDeviceInstallParams(
168 if (bNeedReboot
!= NULL
)
170 *bNeedReboot
= ((dp
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
)) != 0);
180 PrepareFoldersToScan(
181 IN PDEVINSTDATA DevInstData
,
184 TCHAR drive
[] = {'?',':',0};
188 DWORD CustomTextLength
= 0;
189 DWORD LengthNeeded
= 0;
192 TRACE("Include removable devices: %s\n", IsDlgButtonChecked(hwndDlg
, IDC_CHECK_MEDIA
) ? "yes" : "no");
193 TRACE("Include custom path : %s\n", IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
) ? "yes" : "no");
195 /* Calculate length needed to store the search paths */
196 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_MEDIA
))
198 dwDrives
= GetLogicalDrives();
199 for (drive
[0] = 'A', i
= 1; drive
[0] <= 'Z'; drive
[0]++, i
<<= 1)
203 nType
= GetDriveType(drive
);
204 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
211 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
))
213 CustomTextLength
= 1 + SendDlgItemMessage(
219 LengthNeeded
+= CustomTextLength
;
222 /* Allocate space for search paths */
223 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
224 DevInstData
->CustomSearchPath
= Buffer
= HeapAlloc(
227 (LengthNeeded
+ 1) * sizeof(TCHAR
));
230 TRACE("HeapAlloc() failed\n");
231 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
235 /* Fill search paths */
236 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_MEDIA
))
238 for (drive
[0] = 'A', i
= 1; drive
[0] <= 'Z'; drive
[0]++, i
<<= 1)
242 nType
= GetDriveType(drive
);
243 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
245 Buffer
+= 1 + _stprintf(Buffer
, drive
);
250 if (IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
))
252 Buffer
+= 1 + SendDlgItemMessage(
256 (WPARAM
)CustomTextLength
,
268 PDEVINSTDATA DevInstData
;
272 DevInstData
= (PDEVINSTDATA
)lpParam
;
274 /* Yes, we can safely ignore the problem (if any) */
275 SetupDiDestroyDriverInfoList(
276 DevInstData
->hDevInfo
,
277 &DevInstData
->devInfoData
,
280 if (!DevInstData
->CustomSearchPath
)
282 /* Search in default location */
283 result
= SearchDriver(DevInstData
, NULL
, NULL
);
287 /* Search only in specified paths */
288 /* We need to check all specified directories to be
289 * sure to find the best driver for the device.
292 for (Path
= DevInstData
->CustomSearchPath
; *Path
!= '\0'; Path
+= _tcslen(Path
) + 1)
294 TRACE("Search driver in %S\n", Path
);
295 if (_tcslen(Path
) == 2 && Path
[1] == ':')
297 if (SearchDriverRecursive(DevInstData
, Path
))
302 if (SearchDriver(DevInstData
, Path
, NULL
))
310 PostMessage(DevInstData
->hDialog
, WM_SEARCH_FINISHED
, 1, 0);
314 /* Update device configuration */
315 if (SetupDiGetDeviceRegistryProperty(
316 DevInstData
->hDevInfo
,
317 &DevInstData
->devInfoData
,
320 (BYTE
*)&config_flags
,
321 sizeof(config_flags
),
324 config_flags
|= CONFIGFLAG_FAILEDINSTALL
;
325 SetupDiSetDeviceRegistryProperty(
326 DevInstData
->hDevInfo
,
327 &DevInstData
->devInfoData
,
329 (BYTE
*)&config_flags
, sizeof(config_flags
));
332 PostMessage(DevInstData
->hDialog
, WM_SEARCH_FINISHED
, 0, 0);
341 PDEVINSTDATA DevInstData
;
344 DevInstData
= (PDEVINSTDATA
)lpParam
;
345 res
= InstallCurrentDriver(DevInstData
);
346 PostMessage(DevInstData
->hDialog
, WM_INSTALL_FINISHED
, res
? 0 : 1, 0);
351 PopulateCustomPathCombo(
357 LPTSTR Buffer
= NULL
;
361 (void)ComboBox_ResetContent(hwndCombo
);
363 /* RegGetValue would have been better... */
366 REGSTR_PATH_SETUP REGSTR_KEY_SETUP
,
370 if (rc
!= ERROR_SUCCESS
)
372 TRACE("RegOpenKeyEx() failed with error 0x%lx\n", rc
);
375 rc
= RegQueryValueEx(
377 _T("Installation Sources"),
382 if (rc
!= ERROR_SUCCESS
|| dwRegType
!= REG_MULTI_SZ
)
384 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
) + 1)
412 (void)ComboBox_AddString(hwndCombo
, Path
);
414 (void)ComboBox_SetCurSel(hwndCombo
, 0);
420 HeapFree(GetProcessHeap(), 0, Buffer
);
427 LPTSTR CustomPath
= NULL
;
428 DWORD CustomPathLength
;
429 LPTSTR Buffer
= NULL
;
430 LPTSTR pBuffer
; /* Pointer into Buffer */
431 int ItemsCount
, Length
;
433 DWORD TotalLength
= 0;
434 BOOL UseCustomPath
= TRUE
;
438 /* Get custom path */
439 Length
= ComboBox_GetTextLength(hwndCombo
) + 1;
440 CustomPath
= HeapAlloc(GetProcessHeap(), 0, Length
* sizeof(TCHAR
));
443 TRACE("HeapAlloc() failed\n");
446 CustomPathLength
= ComboBox_GetText(hwndCombo
, CustomPath
, Length
) + 1;
448 /* Calculate length of the buffer */
449 ItemsCount
= ComboBox_GetCount(hwndCombo
);
450 if (ItemsCount
== CB_ERR
)
452 TRACE("ComboBox_GetCount() failed\n");
455 for (i
= 0; i
< ItemsCount
; i
++)
457 Length
= ComboBox_GetLBTextLen(hwndCombo
, i
);
458 if (Length
== CB_ERR
)
460 TRACE("ComboBox_GetLBTextLen() failed\n");
463 TotalLength
+= Length
+ 1;
465 TotalLength
++; /* Final NULL char */
467 /* Allocate buffer */
468 Buffer
= HeapAlloc(GetProcessHeap(), 0, (CustomPathLength
+ TotalLength
+ 1) * sizeof(TCHAR
));
471 TRACE("HeapAlloc() failed\n");
475 /* Fill the buffer */
476 pBuffer
= &Buffer
[CustomPathLength
];
477 for (i
= 0; i
< ItemsCount
; i
++)
479 Length
= ComboBox_GetLBText(hwndCombo
, i
, pBuffer
);
480 if (Length
== CB_ERR
)
482 TRACE("ComboBox_GetLBText() failed\n");
485 else if (UseCustomPath
&& _tcsicmp(CustomPath
, pBuffer
) == 0)
486 UseCustomPath
= FALSE
;
487 pBuffer
+= 1 + Length
;
489 *pBuffer
= '\0'; /* Add final NULL char */
493 /* Nothing to save to registry */
497 TotalLength
+= CustomPathLength
;
498 _tcscpy(Buffer
, CustomPath
);
500 /* Save the buffer */
501 /* RegSetKeyValue would have been better... */
504 REGSTR_PATH_SETUP REGSTR_KEY_SETUP
,
508 if (rc
!= ERROR_SUCCESS
)
510 TRACE("RegOpenKeyEx() failed with error 0x%lx\n", rc
);
515 _T("Installation Sources"),
519 TotalLength
* sizeof(TCHAR
));
520 if (rc
!= ERROR_SUCCESS
)
522 TRACE("RegSetValueEx() failed with error 0x%lx\n", rc
);
529 HeapFree(GetProcessHeap(), 0, CustomPath
);
530 HeapFree(GetProcessHeap(), 0, Buffer
);
533 static INT_PTR CALLBACK
540 PDEVINSTDATA DevInstData
;
542 /* Retrieve pointer to the global setup data */
543 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
552 /* Get pointer to the global setup data */
553 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
554 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
556 hwndControl
= GetParent(hwndDlg
);
558 /* Center the wizard window */
559 CenterWindow(hwndControl
);
561 /* Hide the system menu */
562 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
563 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
570 (WPARAM
)DevInstData
->hTitleFont
,
578 (LPARAM
)DevInstData
->buffer
);
591 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
596 /* Enable the Next button */
597 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
601 /* Handle a Next button click, if necessary */
602 if (SendDlgItemMessage(hwndDlg
, IDC_RADIO_AUTO
, BM_GETCHECK
, (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
603 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_SEARCHDRV
);
620 IncludePath(HWND Dlg
, BOOL Enabled
)
622 EnableWindow(GetDlgItem(Dlg
, IDC_COMBO_PATH
), Enabled
);
623 EnableWindow(GetDlgItem(Dlg
, IDC_BROWSE
), /*FIXME: Enabled*/ FALSE
);
627 AutoDriver(HWND Dlg
, BOOL Enabled
)
629 EnableWindow(GetDlgItem(Dlg
, IDC_CHECK_MEDIA
), Enabled
);
630 EnableWindow(GetDlgItem(Dlg
, IDC_CHECK_PATH
), Enabled
);
631 IncludePath(Dlg
, Enabled
& IsDlgButtonChecked(Dlg
, IDC_CHECK_PATH
));
634 static INT_PTR CALLBACK
641 PDEVINSTDATA DevInstData
;
643 /* Retrieve pointer to the global setup data */
644 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
653 /* Get pointer to the global setup data */
654 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
655 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
657 hwndControl
= GetParent(hwndDlg
);
659 /* Center the wizard window */
660 CenterWindow(hwndControl
);
662 /* Hide the system menu */
663 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
664 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
666 PopulateCustomPathCombo(GetDlgItem(hwndDlg
, IDC_COMBO_PATH
));
670 IDC_RADIO_SEARCHHERE
,
674 AutoDriver(hwndDlg
, TRUE
);
675 IncludePath(hwndDlg
, FALSE
);
677 /* Disable manual driver choice for now */
678 EnableWindow(GetDlgItem(hwndDlg
, IDC_RADIO_CHOOSE
), FALSE
);
685 switch (LOWORD(wParam
))
687 case IDC_RADIO_SEARCHHERE
:
688 AutoDriver(hwndDlg
, TRUE
);
691 case IDC_RADIO_CHOOSE
:
692 AutoDriver(hwndDlg
, FALSE
);
696 IncludePath(hwndDlg
, IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
));
700 /* FIXME: set the IDC_COMBO_PATH text */
701 FIXME("Should display browse folder dialog\n");
709 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
714 /* Enable the Next and Back buttons */
715 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
| PSWIZB_BACK
);
719 /* Handle a Next button click, if necessary */
720 if (IsDlgButtonChecked(hwndDlg
, IDC_RADIO_SEARCHHERE
))
722 SaveCustomPath(GetDlgItem(hwndDlg
, IDC_COMBO_PATH
));
723 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
724 DevInstData
->CustomSearchPath
= NULL
;
725 if (PrepareFoldersToScan(DevInstData
, hwndDlg
))
726 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_SEARCHDRV
);
728 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLFAILED
);
747 static INT_PTR CALLBACK
754 PDEVINSTDATA DevInstData
;
757 /* Retrieve pointer to the global setup data */
758 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
767 /* Get pointer to the global setup data */
768 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
769 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
771 DevInstData
->hDialog
= hwndDlg
;
772 hwndControl
= GetParent(hwndDlg
);
774 /* Center the wizard window */
775 CenterWindow(hwndControl
);
782 (LPARAM
)DevInstData
->buffer
);
784 /* Hide the system menu */
785 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
786 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
790 case WM_SEARCH_FINISHED
:
792 CloseHandle(hThread
);
795 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_NODRIVER
);
797 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLDRV
);
803 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
808 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
809 hThread
= CreateThread(NULL
, 0, FindDriverProc
, DevInstData
, 0, &dwThreadId
);
815 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
821 /* Handle a Next button click, if necessary */
837 static INT_PTR CALLBACK
844 PDEVINSTDATA DevInstData
;
847 /* Retrieve pointer to the global setup data */
848 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
857 /* Get pointer to the global setup data */
858 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
859 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
861 DevInstData
->hDialog
= hwndDlg
;
862 hwndControl
= GetParent(hwndDlg
);
864 /* Center the wizard window */
865 CenterWindow(hwndControl
);
872 (LPARAM
)DevInstData
->drvInfoData
.Description
);
874 /* Hide the system menu */
875 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
876 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
880 case WM_INSTALL_FINISHED
:
882 CloseHandle(hThread
);
885 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_FINISHPAGE
);
887 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLFAILED
);
893 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
898 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
899 hThread
= CreateThread(NULL
, 0, InstallDriverProc
, DevInstData
, 0, &dwThreadId
);
905 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
911 /* Handle a Next button click, if necessary */
927 static INT_PTR CALLBACK
934 PDEVINSTDATA DevInstData
;
936 /* Get pointer to the global setup data */
937 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
944 BOOL DisableableDevice
= FALSE
;
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 (WPARAM
)DevInstData
->hTitleFont
,
961 /* disable the "do not show this dialog anymore" checkbox
962 if the device cannot be disabled */
964 DevInstData
->devInfoData
.DevInst
,
968 GetDlgItem(hwndDlg
, IDC_DONOTSHOWDLG
),
975 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
980 /* Enable the correct buttons on for the active page */
981 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
985 /* Handle a Back button click, if necessary */
986 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_CHSOURCE
);
991 BOOL DisableableDevice
= FALSE
;
992 BOOL IsStarted
= FALSE
;
994 if (CanDisableDevice(DevInstData
->devInfoData
.DevInst
,
996 &DisableableDevice
) &&
999 DevInstData
->devInfoData
.DevInst
,
1007 (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
1009 /* disable the device */
1011 DevInstData
->hDevInfo
,
1012 &DevInstData
->devInfoData
,
1033 static INT_PTR CALLBACK
1034 InstallFailedDlgProc(
1040 PDEVINSTDATA DevInstData
;
1042 /* Retrieve pointer to the global setup data */
1043 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
1051 /* Get pointer to the global setup data */
1052 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1053 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
1055 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
1056 ShowWindow(hwndControl
, SW_HIDE
);
1057 EnableWindow(hwndControl
, FALSE
);
1064 (LPARAM
)DevInstData
->drvInfoData
.Description
);
1066 /* Set title font */
1071 (WPARAM
)DevInstData
->hTitleFont
,
1078 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1083 /* Enable the correct buttons on for the active page */
1084 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
1088 /* Handle a Back button click, if necessary */
1092 /* Handle a Finish button click, if necessary */
1108 static INT_PTR CALLBACK
1115 PDEVINSTDATA DevInstData
;
1117 /* Retrieve pointer to the global setup data */
1118 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
1126 /* Get pointer to the global setup data */
1127 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1128 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
1130 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
1131 ShowWindow(hwndControl
, SW_HIDE
);
1132 EnableWindow(hwndControl
, FALSE
);
1139 (LPARAM
)DevInstData
->drvInfoData
.Description
);
1141 /* Set title font */
1146 (WPARAM
)DevInstData
->hTitleFont
,
1153 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1158 /* Enable the correct buttons on for the active page */
1159 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
1163 /* Handle a Back button click, if necessary */
1167 /* Handle a Finish button click, if necessary */
1184 CreateTitleFont(VOID
)
1186 NONCLIENTMETRICS ncm
;
1192 ncm
.cbSize
= sizeof(NONCLIENTMETRICS
);
1193 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, &ncm
, 0);
1195 LogFont
= ncm
.lfMessageFont
;
1196 LogFont
.lfWeight
= FW_BOLD
;
1197 _tcscpy(LogFont
.lfFaceName
, _T("MS Shell Dlg"));
1201 LogFont
.lfHeight
= 0 - GetDeviceCaps (hdc
, LOGPIXELSY
) * FontSize
/ 72;
1202 hFont
= CreateFontIndirect(&LogFont
);
1203 ReleaseDC(NULL
, hdc
);
1210 IN PDEVINSTDATA DevInstData
,
1214 PROPSHEETHEADER psh
;
1215 HPROPSHEETPAGE ahpsp
[IDD_FINISHPAGE
+ 1];
1218 /* Create the Welcome page */
1219 ZeroMemory(&psp
, sizeof(PROPSHEETPAGE
));
1220 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
1221 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1222 psp
.hInstance
= hDllInstance
;
1223 psp
.lParam
= (LPARAM
)DevInstData
;
1224 psp
.pfnDlgProc
= WelcomeDlgProc
;
1225 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_WELCOMEPAGE
);
1226 ahpsp
[IDD_WELCOMEPAGE
] = CreatePropertySheetPage(&psp
);
1228 /* Create the Select Source page */
1229 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1230 psp
.pfnDlgProc
= CHSourceDlgProc
;
1231 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_CHSOURCE
);
1232 ahpsp
[IDD_CHSOURCE
] = CreatePropertySheetPage(&psp
);
1234 /* Create the Search driver page */
1235 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1236 psp
.pfnDlgProc
= SearchDrvDlgProc
;
1237 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_SEARCHDRV
);
1238 ahpsp
[IDD_SEARCHDRV
] = CreatePropertySheetPage(&psp
);
1240 /* Create the Install driver page */
1241 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1242 psp
.pfnDlgProc
= InstallDrvDlgProc
;
1243 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_INSTALLDRV
);
1244 ahpsp
[IDD_INSTALLDRV
] = CreatePropertySheetPage(&psp
);
1246 /* Create the No driver page */
1247 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1248 psp
.pfnDlgProc
= NoDriverDlgProc
;
1249 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_NODRIVER
);
1250 ahpsp
[IDD_NODRIVER
] = CreatePropertySheetPage(&psp
);
1252 /* Create the Install failed page */
1253 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1254 psp
.pfnDlgProc
= InstallFailedDlgProc
;
1255 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_INSTALLFAILED
);
1256 ahpsp
[IDD_INSTALLFAILED
] = CreatePropertySheetPage(&psp
);
1258 /* Create the Finish page */
1259 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1260 psp
.pfnDlgProc
= FinishDlgProc
;
1261 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_FINISHPAGE
);
1262 ahpsp
[IDD_FINISHPAGE
] = CreatePropertySheetPage(&psp
);
1264 /* Create the property sheet */
1265 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1266 psh
.dwFlags
= PSH_WIZARD97
| PSH_WATERMARK
| PSH_HEADER
;
1267 psh
.hInstance
= hDllInstance
;
1268 psh
.hwndParent
= hwndParent
;
1269 psh
.nPages
= IDD_FINISHPAGE
+ 1;
1270 psh
.nStartPage
= startPage
;
1272 psh
.pszbmWatermark
= MAKEINTRESOURCE(IDB_WATERMARK
);
1273 psh
.pszbmHeader
= MAKEINTRESOURCE(IDB_HEADER
);
1275 /* Create title font */
1276 DevInstData
->hTitleFont
= CreateTitleFont();
1278 /* Display the wizard */
1279 PropertySheet(&psh
);
1281 DeleteObject(DevInstData
->hTitleFont
);