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 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");
194 TCHAR drive
[] = {'?',':',0};
197 PDEVINSTDATA DevInstData
;
201 DevInstData
= (PDEVINSTDATA
)lpParam
;
202 DPRINT1("FindDriverProc(%p)\n", DevInstData
->CustomSearchPath
);
203 if (DevInstData
->CustomSearchPath
)
206 for (Path
= DevInstData
->CustomSearchPath
; *Path
!= '\0'; Path
+= _tcslen(Path
) + 1)
207 DPRINT1("Path %S\n", Path
);
210 dwDrives
= GetLogicalDrives();
211 for (drive
[0] = 'A'; drive
[0] <= 'Z'; drive
[0]++)
215 nType
= GetDriveType(drive
);
216 if (nType
== DRIVE_REMOVABLE
|| nType
== DRIVE_CDROM
)
218 /* search for valid inf file */
219 if (SearchDriverRecursive(DevInstData
, drive
))
221 InstallCurrentDriver(DevInstData
);
222 PostMessage(DevInstData
->hDialog
, WM_SEARCH_FINISHED
, 1, 0);
230 /* update device configuration */
231 if (SetupDiGetDeviceRegistryProperty(
232 DevInstData
->hDevInfo
,
233 &DevInstData
->devInfoData
,
236 (BYTE
*)&config_flags
,
237 sizeof(config_flags
),
240 config_flags
|= CONFIGFLAG_FAILEDINSTALL
;
241 SetupDiSetDeviceRegistryProperty(
242 DevInstData
->hDevInfo
,
243 &DevInstData
->devInfoData
,
245 (BYTE
*)&config_flags
, sizeof(config_flags
));
248 PostMessage(DevInstData
->hDialog
, WM_SEARCH_FINISHED
, 0, 0);
252 static INT_PTR CALLBACK
259 PDEVINSTDATA DevInstData
;
261 /* Retrieve pointer to the global setup data */
262 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
271 /* Get pointer to the global setup data */
272 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
273 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
275 hwndControl
= GetParent(hwndDlg
);
277 /* Center the wizard window */
278 CenterWindow(hwndControl
);
280 /* Hide the system menu */
281 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
282 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
289 (WPARAM
)DevInstData
->hTitleFont
,
297 (LPARAM
)DevInstData
->buffer
);
310 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
315 /* Enable the Next button */
316 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
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
);
339 IncludePath(HWND Dlg
, BOOL Enabled
)
341 EnableWindow(GetDlgItem(Dlg
, IDC_COMBO_PATH
), Enabled
);
342 EnableWindow(GetDlgItem(Dlg
, IDC_BROWSE
), /*FIXME: Enabled*/ FALSE
);
346 AutoDriver(HWND Dlg
, BOOL Enabled
)
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
));
353 static INT_PTR CALLBACK
360 PDEVINSTDATA DevInstData
;
362 /* Retrieve pointer to the global setup data */
363 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
372 /* Get pointer to the global setup data */
373 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
374 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
376 hwndControl
= GetParent(hwndDlg
);
378 /* Center the wizard window */
379 CenterWindow(hwndControl
);
381 /* Hide the system menu */
382 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
383 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
387 IDC_RADIO_SEARCHHERE
,
391 AutoDriver(hwndDlg
, TRUE
);
392 IncludePath(hwndDlg
, FALSE
);
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
);
403 switch (LOWORD(wParam
))
405 case IDC_RADIO_SEARCHHERE
:
406 AutoDriver(hwndDlg
, TRUE
);
409 case IDC_RADIO_CHOOSE
:
410 AutoDriver(hwndDlg
, FALSE
);
414 IncludePath(hwndDlg
, IsDlgButtonChecked(hwndDlg
, IDC_CHECK_PATH
));
418 /* FIXME: set the IDC_COMBO_PATH text */
419 FIXME("Should display browse folder dialog\n");
427 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
432 /* Enable the Next and Back buttons */
433 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
| PSWIZB_BACK
);
437 /* Handle a Next button click, if necessary */
438 if (IsDlgButtonChecked(hwndDlg
, IDC_RADIO_SEARCHHERE
))
440 HeapFree(GetProcessHeap(), 0, DevInstData
->CustomSearchPath
);
441 DevInstData
->CustomSearchPath
= NULL
;
442 if (PrepareFoldersToScan(DevInstData
, hwndDlg
))
443 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_SEARCHDRV
);
462 static INT_PTR CALLBACK
469 PDEVINSTDATA DevInstData
;
472 /* Retrieve pointer to the global setup data */
473 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr(hwndDlg
, GWL_USERDATA
);
482 /* Get pointer to the global setup data */
483 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
484 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
486 DevInstData
->hDialog
= hwndDlg
;
487 hwndControl
= GetParent(hwndDlg
);
489 /* Center the wizard window */
490 CenterWindow(hwndControl
);
497 (LPARAM
)DevInstData
->buffer
);
499 /* Hide the system menu */
500 dwStyle
= GetWindowLong(hwndControl
, GWL_STYLE
);
501 SetWindowLong(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
505 case WM_SEARCH_FINISHED
:
507 CloseHandle(hThread
);
510 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_NODRIVER
);
512 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_FINISHPAGE
);
518 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
523 PropSheet_SetWizButtons(GetParent(hwndDlg
), !PSWIZB_NEXT
| !PSWIZB_BACK
);
524 hThread
= CreateThread(NULL
, 0, FindDriverProc
, DevInstData
, 0, &dwThreadId
);
530 SetWindowLong(hwndDlg
, DWL_MSGRESULT
, TRUE
);
536 /* Handle a Next button click, if necessary */
552 static INT_PTR CALLBACK
562 static INT_PTR CALLBACK
569 PDEVINSTDATA DevInstData
;
571 /* Get pointer to the global setup data */
572 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr (hwndDlg
, GWL_USERDATA
);
579 BOOL DisableableDevice
= FALSE
;
581 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
582 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
584 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
585 ShowWindow (hwndControl
, SW_HIDE
);
586 EnableWindow (hwndControl
, FALSE
);
593 (WPARAM
)DevInstData
->hTitleFont
,
596 /* disable the "do not show this dialog anymore" checkbox
597 if the device cannot be disabled */
599 DevInstData
->devInfoData
.DevInst
,
603 GetDlgItem(hwndDlg
, IDC_DONOTSHOWDLG
),
610 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
615 /* Enable the correct buttons on for the active page */
616 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
620 /* Handle a Back button click, if necessary */
621 PropSheet_SetCurSelByID(GetParent(hwndDlg
), IDD_WELCOMEPAGE
);
626 BOOL DisableableDevice
= FALSE
;
627 BOOL IsStarted
= FALSE
;
629 if (CanDisableDevice(DevInstData
->devInfoData
.DevInst
,
631 &DisableableDevice
) &&
634 DevInstData
->devInfoData
.DevInst
,
642 (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
644 /* disable the device */
646 DevInstData
->hDevInfo
,
647 &DevInstData
->devInfoData
,
668 static INT_PTR CALLBACK
675 PDEVINSTDATA DevInstData
;
677 /* Retrieve pointer to the global setup data */
678 DevInstData
= (PDEVINSTDATA
)GetWindowLongPtr (hwndDlg
, GWL_USERDATA
);
686 /* Get pointer to the global setup data */
687 DevInstData
= (PDEVINSTDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
688 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)DevInstData
);
690 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
691 ShowWindow (hwndControl
, SW_HIDE
);
692 EnableWindow (hwndControl
, FALSE
);
699 (LPARAM
)DevInstData
->drvInfoData
.Description
);
706 (WPARAM
)DevInstData
->hTitleFont
,
713 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
718 /* Enable the correct buttons on for the active page */
719 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
723 /* Handle a Back button click, if necessary */
727 /* Handle a Finish button click, if necessary */
744 CreateTitleFont(VOID
)
746 NONCLIENTMETRICS ncm
;
752 ncm
.cbSize
= sizeof(NONCLIENTMETRICS
);
753 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, &ncm
, 0);
755 LogFont
= ncm
.lfMessageFont
;
756 LogFont
.lfWeight
= FW_BOLD
;
757 _tcscpy(LogFont
.lfFaceName
, _T("MS Shell Dlg"));
761 LogFont
.lfHeight
= 0 - GetDeviceCaps (hdc
, LOGPIXELSY
) * FontSize
/ 72;
762 hFont
= CreateFontIndirect(&LogFont
);
763 ReleaseDC(NULL
, hdc
);
770 IN PDEVINSTDATA DevInstData
,
775 HPROPSHEETPAGE ahpsp
[IDD_FINISHPAGE
+ 1];
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
);
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
);
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
);
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
);
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
);
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
);
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
;
824 psh
.nStartPage
= startPage
;
826 psh
.pszbmWatermark
= MAKEINTRESOURCE(IDB_WATERMARK
);
827 psh
.pszbmHeader
= MAKEINTRESOURCE(IDB_HEADER
);
829 /* Create title font */
830 DevInstData
->hTitleFont
= CreateTitleFont();
832 /* Display the wizard */
835 DeleteObject(DevInstData
->hTitleFont
);