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
), Enabled
);
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
));
701 BROWSEINFO bi
= { 0, };
704 bi
.hwndOwner
= hwndDlg
;
705 bi
.ulFlags
= BIF_RETURNONLYFSDIRS
;
706 pidl
= SHBrowseForFolder(&bi
);
709 TCHAR Directory
[MAX_PATH
];
712 if (SHGetPathFromIDList(pidl
, Directory
))
714 /* Set the IDC_COMBO_PATH text */
715 ComboBox_SetText(GetDlgItem(hwndDlg
, IDC_COMBO_PATH
), Directory
);
718 /* Free memory, if possible */
719 if (SUCCEEDED(SHGetMalloc(&malloc
)))
721 FIXME("Memory leak!\n");
722 //malloc->Free(pidl);
735 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
740 /* Enable the Next and Back buttons */
741 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
| PSWIZB_BACK
);
745 /* Handle a Next button click, if necessary */
746 if (IsDlgButtonChecked(hwndDlg
, IDC_RADIO_SEARCHHERE
))
748 SaveCustomPath(GetDlgItem(hwndDlg
, IDC_COMBO_PATH
));
749 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
750 DevInstData
->CustomSearchPath
= NULL
;
751 if (PrepareFoldersToScan(DevInstData
, hwndDlg
))
752 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_SEARCHDRV
);
754 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLFAILED
);
773 static INT_PTR CALLBACK
780 PDEVINSTDATA DevInstData
;
783 /* Retrieve pointer to the global setup data */
784 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
793 /* Get pointer to the global setup data */
794 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
795 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
797 DevInstData
->hDialog
= hwndDlg
;
798 hwndControl
= GetParent(hwndDlg
);
800 /* Center the wizard window */
801 CenterWindow(hwndControl
);
808 (LPARAM
)DevInstData
->buffer
);
810 /* Hide the system menu */
811 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
812 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
816 case WM_SEARCH_FINISHED
:
818 CloseHandle(hThread
);
821 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_NODRIVER
);
823 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLDRV
);
829 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
834 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
835 hThread
= CreateThread(NULL
, 0, FindDriverProc
, DevInstData
, 0, &dwThreadId
);
841 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
847 /* Handle a Next button click, if necessary */
863 static INT_PTR CALLBACK
870 PDEVINSTDATA DevInstData
;
873 /* Retrieve pointer to the global setup data */
874 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
883 /* Get pointer to the global setup data */
884 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
885 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
887 DevInstData
->hDialog
= hwndDlg
;
888 hwndControl
= GetParent(hwndDlg
);
890 /* Center the wizard window */
891 CenterWindow(hwndControl
);
898 (LPARAM
)DevInstData
->drvInfoData
.Description
);
900 /* Hide the system menu */
901 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
902 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
906 case WM_INSTALL_FINISHED
:
908 CloseHandle(hThread
);
911 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_FINISHPAGE
);
913 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_INSTALLFAILED
);
919 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
924 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
925 hThread
= CreateThread(NULL
, 0, InstallDriverProc
, DevInstData
, 0, &dwThreadId
);
931 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
937 /* Handle a Next button click, if necessary */
953 static INT_PTR CALLBACK
960 PDEVINSTDATA DevInstData
;
963 /* Get pointer to the global setup data */
964 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
970 BOOL DisableableDevice
= FALSE
;
972 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
973 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
975 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
976 ShowWindow(hwndControl
, SW_HIDE
);
977 EnableWindow(hwndControl
, FALSE
);
984 (WPARAM
)DevInstData
->hTitleFont
,
987 /* disable the "do not show this dialog anymore" checkbox
988 if the device cannot be disabled */
990 DevInstData
->devInfoData
.DevInst
,
994 GetDlgItem(hwndDlg
, IDC_DONOTSHOWDLG
),
1001 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1006 /* Enable the correct buttons on for the active page */
1007 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
1011 /* Handle a Back button click, if necessary */
1012 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
1013 ShowWindow(hwndControl
, SW_SHOW
);
1014 EnableWindow(hwndControl
, TRUE
);
1015 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_CHSOURCE
);
1020 BOOL DisableableDevice
= FALSE
;
1021 BOOL IsStarted
= FALSE
;
1023 if (CanDisableDevice(DevInstData
->devInfoData
.DevInst
,
1025 &DisableableDevice
) &&
1026 DisableableDevice
&&
1028 DevInstData
->devInfoData
.DevInst
,
1036 (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
1038 /* disable the device */
1040 DevInstData
->hDevInfo
,
1041 &DevInstData
->devInfoData
,
1062 static INT_PTR CALLBACK
1063 InstallFailedDlgProc(
1069 PDEVINSTDATA DevInstData
;
1071 /* Retrieve pointer to the global setup data */
1072 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
1080 /* Get pointer to the global setup data */
1081 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1082 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
1084 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
1085 ShowWindow(hwndControl
, SW_HIDE
);
1086 EnableWindow(hwndControl
, FALSE
);
1093 (LPARAM
)DevInstData
->drvInfoData
.Description
);
1095 /* Set title font */
1100 (WPARAM
)DevInstData
->hTitleFont
,
1107 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1112 /* Enable the correct buttons on for the active page */
1113 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
1117 /* Handle a Back button click, if necessary */
1121 /* Handle a Finish button click, if necessary */
1137 static INT_PTR CALLBACK
1144 PDEVINSTDATA DevInstData
;
1146 /* Retrieve pointer to the global setup data */
1147 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
1155 /* Get pointer to the global setup data */
1156 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1157 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
1159 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
1160 ShowWindow(hwndControl
, SW_HIDE
);
1161 EnableWindow(hwndControl
, FALSE
);
1168 (LPARAM
)DevInstData
->drvInfoData
.Description
);
1170 /* Set title font */
1175 (WPARAM
)DevInstData
->hTitleFont
,
1182 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1187 /* Enable the correct buttons on for the active page */
1188 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
1192 /* Handle a Back button click, if necessary */
1196 /* Handle a Finish button click, if necessary */
1213 CreateTitleFont(VOID
)
1215 NONCLIENTMETRICS ncm
;
1221 ncm
.cbSize
= sizeof(NONCLIENTMETRICS
);
1222 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, &ncm
, 0);
1224 LogFont
= ncm
.lfMessageFont
;
1225 LogFont
.lfWeight
= FW_BOLD
;
1226 _tcscpy(LogFont
.lfFaceName
, _T("MS Shell Dlg"));
1230 LogFont
.lfHeight
= 0 - GetDeviceCaps (hdc
, LOGPIXELSY
) * FontSize
/ 72;
1231 hFont
= CreateFontIndirect(&LogFont
);
1232 ReleaseDC(NULL
, hdc
);
1239 IN PDEVINSTDATA DevInstData
,
1243 PROPSHEETHEADER psh
;
1244 HPROPSHEETPAGE ahpsp
[IDD_FINISHPAGE
+ 1];
1247 /* Create the Welcome page */
1248 ZeroMemory(&psp
, sizeof(PROPSHEETPAGE
));
1249 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
1250 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1251 psp
.hInstance
= hDllInstance
;
1252 psp
.lParam
= (LPARAM
)DevInstData
;
1253 psp
.pfnDlgProc
= WelcomeDlgProc
;
1254 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_WELCOMEPAGE
);
1255 ahpsp
[IDD_WELCOMEPAGE
] = CreatePropertySheetPage(&psp
);
1257 /* Create the Select Source page */
1258 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1259 psp
.pfnDlgProc
= CHSourceDlgProc
;
1260 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_CHSOURCE
);
1261 ahpsp
[IDD_CHSOURCE
] = CreatePropertySheetPage(&psp
);
1263 /* Create the Search driver page */
1264 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1265 psp
.pfnDlgProc
= SearchDrvDlgProc
;
1266 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_SEARCHDRV
);
1267 ahpsp
[IDD_SEARCHDRV
] = CreatePropertySheetPage(&psp
);
1269 /* Create the Install driver page */
1270 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
1271 psp
.pfnDlgProc
= InstallDrvDlgProc
;
1272 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_INSTALLDRV
);
1273 ahpsp
[IDD_INSTALLDRV
] = CreatePropertySheetPage(&psp
);
1275 /* Create the No driver page */
1276 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1277 psp
.pfnDlgProc
= NoDriverDlgProc
;
1278 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_NODRIVER
);
1279 ahpsp
[IDD_NODRIVER
] = CreatePropertySheetPage(&psp
);
1281 /* Create the Install failed page */
1282 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1283 psp
.pfnDlgProc
= InstallFailedDlgProc
;
1284 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_INSTALLFAILED
);
1285 ahpsp
[IDD_INSTALLFAILED
] = CreatePropertySheetPage(&psp
);
1287 /* Create the Finish page */
1288 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
1289 psp
.pfnDlgProc
= FinishDlgProc
;
1290 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_FINISHPAGE
);
1291 ahpsp
[IDD_FINISHPAGE
] = CreatePropertySheetPage(&psp
);
1293 /* Create the property sheet */
1294 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1295 psh
.dwFlags
= PSH_WIZARD97
| PSH_WATERMARK
| PSH_HEADER
;
1296 psh
.hInstance
= hDllInstance
;
1297 psh
.hwndParent
= hwndParent
;
1298 psh
.nPages
= IDD_FINISHPAGE
+ 1;
1299 psh
.nStartPage
= startPage
;
1301 psh
.pszbmWatermark
= MAKEINTRESOURCE(IDB_WATERMARK
);
1302 psh
.pszbmHeader
= MAKEINTRESOURCE(IDB_HEADER
);
1304 /* Create title font */
1305 DevInstData
->hTitleFont
= CreateTitleFont();
1307 /* Display the wizard */
1308 PropertySheet(&psh
);
1310 DeleteObject(DevInstData
->hTitleFont
);