2 * ReactOS Device Manager Applet
3 * Copyright (C) 2004 - 2005 ReactOS Team
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* $Id: hwpage.c 19599 2005-11-26 02:12:58Z weiden $
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/advprop.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 typedef INT_PTR (WINAPI
*PPROPERTYSHEETW
)(LPCPROPSHEETHEADERW
);
34 typedef HPROPSHEETPAGE (WINAPI
*PCREATEPROPERTYSHEETPAGEW
)(LPCPROPSHEETPAGEW
);
35 typedef BOOL (WINAPI
*PDESTROYPROPERTYSHEETPAGE
)(HPROPSHEETPAGE
);
37 typedef struct _DEVADVPROP_INFO
41 WNDPROC ParentOldWndProc
;
44 HDEVINFO DeviceInfoSet
;
45 SP_DEVINFO_DATA DeviceInfoData
;
46 HDEVINFO CurrentDeviceInfoSet
;
47 SP_DEVINFO_DATA CurrentDeviceInfoData
;
48 DEVINST ParentDevInst
;
50 LPCWSTR lpMachineName
;
53 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
54 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
56 DWORD PropertySheetType
;
58 HPROPSHEETPAGE
*DevPropSheets
;
60 BOOL FreeDevPropSheets
: 1;
62 BOOL DeviceStarted
: 1;
63 BOOL DeviceUsageChanged
: 1;
64 BOOL CloseDevInst
: 1;
66 BOOL DoDefaultDevAction
: 1;
67 BOOL PageInitialized
: 1;
68 BOOL ShowRemotePages
: 1;
69 BOOL HasDriverPage
: 1;
70 BOOL HasResourcePage
: 1;
71 BOOL HasPowerPage
: 1;
76 /* struct may be dynamically expanded here! */
77 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
80 typedef struct _ENUMDRIVERFILES_CONTEXT
82 HWND hDriversListView
;
84 } ENUMDRIVERFILES_CONTEXT
, *PENUMDRIVERFILES_CONTEXT
;
86 #define PM_INITIALIZE (WM_APP + 0x101)
90 EnumDeviceDriverFilesCallback(IN PVOID Context
,
96 PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext
= (PENUMDRIVERFILES_CONTEXT
)Context
;
98 li
.mask
= LVIF_TEXT
| LVIF_STATE
;
99 li
.iItem
= EnumDriverFilesContext
->nCount
++;
101 li
.state
= (li
.iItem
== 0 ? LVIS_SELECTED
: 0);
102 li
.stateMask
= LVIS_SELECTED
;
103 li
.pszText
= (LPWSTR
)Param1
;
104 ListView_InsertItem(EnumDriverFilesContext
->hDriversListView
,
111 UpdateDriverDetailsDlg(IN HWND hwndDlg
,
112 IN HWND hDriversListView
,
113 IN PDEVADVPROP_INFO dap
)
115 HDEVINFO DeviceInfoSet
;
116 PSP_DEVINFO_DATA DeviceInfoData
;
117 SP_DRVINFO_DATA DriverInfoData
;
118 ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext
;
120 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
122 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
123 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
127 DeviceInfoSet
= dap
->DeviceInfoSet
;
128 DeviceInfoData
= &dap
->DeviceInfoData
;
131 /* set the device image */
132 SendDlgItemMessage(hwndDlg
,
135 (WPARAM
)dap
->hDevIcon
,
138 /* set the device name edit control text */
139 SetDlgItemText(hwndDlg
,
143 /* fill the driver files list view */
144 EnumDriverFilesContext
.hDriversListView
= hDriversListView
;
145 EnumDriverFilesContext
.nCount
= 0;
147 ListView_DeleteAllItems(EnumDriverFilesContext
.hDriversListView
);
148 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
149 if (FindCurrentDriver(DeviceInfoSet
,
152 SetupDiSetSelectedDriver(DeviceInfoSet
,
156 HSPFILEQ queueHandle
;
158 queueHandle
= SetupOpenFileQueue();
159 if (queueHandle
!= (HSPFILEQ
)INVALID_HANDLE_VALUE
)
161 SP_DEVINSTALL_PARAMS DeviceInstallParams
= {0};
162 DeviceInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
163 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
165 &DeviceInstallParams
))
167 DeviceInstallParams
.FileQueue
= queueHandle
;
168 DeviceInstallParams
.Flags
|= DI_NOVCP
;
170 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
172 &DeviceInstallParams
) &&
173 SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES
,
181 /* enumerate the driver files */
182 SetupScanFileQueue(queueHandle
,
183 SPQ_SCAN_USE_CALLBACK
,
185 EnumDeviceDriverFilesCallback
,
186 &EnumDriverFilesContext
,
189 /* update the list view column width */
190 GetClientRect(hDriversListView
,
192 lvc
.mask
= LVCF_WIDTH
;
193 lvc
.cx
= rcClient
.right
;
194 ListView_SetColumn(hDriversListView
,
200 SetupCloseFileQueue(queueHandle
);
208 DriverDetailsDlgProc(IN HWND hwndDlg
,
213 PDEVADVPROP_INFO dap
;
216 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
219 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
225 switch (LOWORD(wParam
))
247 HWND hDriversListView
;
249 dap
= (PDEVADVPROP_INFO
)lParam
;
252 SetWindowLongPtr(hwndDlg
,
256 hDriversListView
= GetDlgItem(hwndDlg
,
259 /* add a column to the list view control */
260 lvc
.mask
= LVCF_FMT
| LVCF_WIDTH
;
261 lvc
.fmt
= LVCFMT_LEFT
;
263 ListView_InsertColumn(hDriversListView
,
267 UpdateDriverDetailsDlg(hwndDlg
,
283 UpdateDriverDlg(IN HWND hwndDlg
,
284 IN PDEVADVPROP_INFO dap
)
286 HDEVINFO DeviceInfoSet
;
287 PSP_DEVINFO_DATA DeviceInfoData
;
289 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
291 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
292 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
296 DeviceInfoSet
= dap
->DeviceInfoSet
;
297 DeviceInfoData
= &dap
->DeviceInfoData
;
300 /* set the device image */
301 SendDlgItemMessage(hwndDlg
,
304 (WPARAM
)dap
->hDevIcon
,
307 /* set the device name edit control text */
308 SetDlgItemText(hwndDlg
,
312 /* query the driver provider */
313 if (GetDriverProviderString(DeviceInfoSet
,
316 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
318 SetDlgItemText(hwndDlg
,
323 /* query the driver date */
324 if (GetDriverDateString(DeviceInfoSet
,
327 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
329 SetDlgItemText(hwndDlg
,
334 /* query the driver version */
335 if (GetDriverVersionString(DeviceInfoSet
,
338 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
340 SetDlgItemText(hwndDlg
,
349 AdvProcDriverDlgProc(IN HWND hwndDlg
,
354 PDEVADVPROP_INFO dap
;
357 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
360 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
366 switch (LOWORD(wParam
))
368 case IDC_DRIVERDETAILS
:
370 DialogBoxParam(hDllInstance
,
371 MAKEINTRESOURCE(IDD_DRIVERDETAILS
),
373 DriverDetailsDlgProc
,
383 NMHDR
*hdr
= (NMHDR
*)lParam
;
394 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
397 SetWindowLongPtr(hwndDlg
,
401 UpdateDriverDlg(hwndDlg
,
415 InitDevUsageActions(IN HWND hwndDlg
,
417 IN PDEVADVPROP_INFO dap
)
428 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
431 /* fill in the device usage combo box */
432 if (LoadString(hDllInstance
,
435 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
437 Index
= (INT
)SendMessage(hComboBox
,
440 (LPARAM
)dap
->szTemp
);
443 SendMessage(hComboBox
,
450 case IDS_ENABLEDEVICE
:
451 if (dap
->DeviceStarted
)
453 SendMessage(hComboBox
,
460 case IDS_DISABLEDEVICE
:
461 if (!dap
->DeviceStarted
)
463 SendMessage(hComboBox
,
480 GetSelectedUsageAction(IN HWND hComboBox
)
485 Index
= (INT
)SendMessage(hComboBox
,
491 INT iRet
= SendMessage(hComboBox
,
506 ApplyGeneralSettings(IN HWND hwndDlg
,
507 IN PDEVADVPROP_INFO dap
)
511 if (dap
->DeviceUsageChanged
&& dap
->IsAdmin
&& dap
->CanDisable
)
513 UINT SelectedUsageAction
;
514 BOOL NeedReboot
= FALSE
;
516 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
518 switch (SelectedUsageAction
)
520 case IDS_ENABLEDEVICE
:
521 if (!dap
->DeviceStarted
)
523 Ret
= EnableDevice(dap
->DeviceInfoSet
,
524 &dap
->DeviceInfoData
,
531 case IDS_DISABLEDEVICE
:
532 if (dap
->DeviceStarted
)
534 Ret
= EnableDevice(dap
->DeviceInfoSet
,
535 &dap
->DeviceInfoData
,
550 /* make PropertySheet() return PSM_REBOOTSYSTEM */
551 PropSheet_RebootSystem(hwndDlg
);
556 /* FIXME - display an error message */
557 DPRINT1("Failed to enable/disable device! LastError: %d\n",
562 Ret
= !dap
->DeviceUsageChanged
;
564 /* disable the apply button */
565 PropSheet_UnChanged(GetParent(hwndDlg
),
567 dap
->DeviceUsageChanged
= FALSE
;
573 UpdateDevInfo(IN HWND hwndDlg
,
574 IN PDEVADVPROP_INFO dap
,
577 HWND hDevUsage
, hPropSheetDlg
, hDevProbBtn
;
579 ULONG Status
, ProblemNumber
;
580 SP_DEVINSTALL_PARAMS_W InstallParams
;
581 UINT TroubleShootStrId
= IDS_TROUBLESHOOTDEV
;
582 BOOL bFlag
, bDevActionAvailable
= TRUE
;
583 BOOL bDrvInstalled
= FALSE
;
585 HDEVINFO DeviceInfoSet
= NULL
;
586 PSP_DEVINFO_DATA DeviceInfoData
= NULL
;
588 DWORD nDriverPages
= 0;
590 hPropSheetDlg
= GetParent(hwndDlg
);
592 if (dap
->PageInitialized
)
594 /* switch to the General page */
595 PropSheet_SetCurSelByID(hPropSheetDlg
,
598 /* remove and destroy the existing device property sheet pages */
599 if (dap
->DevPropSheets
!= NULL
)
602 iPage
!= dap
->nDevPropSheets
;
605 if (dap
->DevPropSheets
[iPage
] != NULL
)
607 PropSheet_RemovePage(hPropSheetDlg
,
609 dap
->DevPropSheets
[iPage
]);
617 if (dap
->FreeDevPropSheets
)
619 /* don't free the array if it's the one allocated in
620 DisplayDeviceAdvancedProperties */
621 HeapFree(GetProcessHeap(),
625 dap
->FreeDevPropSheets
= FALSE
;
628 dap
->DevPropSheets
= NULL
;
629 dap
->nDevPropSheets
= 0;
633 /* create a new device info set and re-open the device */
634 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
636 SetupDiDestroyDeviceInfoList(dap
->CurrentDeviceInfoSet
);
639 dap
->ParentDevInst
= 0;
640 dap
->CurrentDeviceInfoSet
= SetupDiCreateDeviceInfoListEx(NULL
,
644 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
646 if (SetupDiOpenDeviceInfo(dap
->CurrentDeviceInfoSet
,
650 &dap
->CurrentDeviceInfoData
))
652 if (dap
->CloseDevInst
)
654 SetupDiDestroyDeviceInfoList(dap
->DeviceInfoSet
);
657 dap
->CloseDevInst
= TRUE
;
658 dap
->DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
659 dap
->DeviceInfoData
= dap
->CurrentDeviceInfoData
;
660 dap
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
668 /* get the parent node from the initial devinst */
669 CM_Get_Parent_Ex(&dap
->ParentDevInst
,
670 dap
->DeviceInfoData
.DevInst
,
675 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
677 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
678 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
682 DeviceInfoSet
= dap
->DeviceInfoSet
;
683 DeviceInfoData
= &dap
->DeviceInfoData
;
688 DeviceInfoSet
= dap
->DeviceInfoSet
;
689 DeviceInfoData
= &dap
->DeviceInfoData
;
692 dap
->HasDriverPage
= FALSE
;
693 dap
->HasResourcePage
= FALSE
;
694 dap
->HasPowerPage
= FALSE
;
695 if (IsDriverInstalled(DeviceInfoData
->DevInst
,
700 if (SetupDiCallClassInstaller((dap
->ShowRemotePages
?
701 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
702 DIF_ADDPROPERTYPAGE_ADVANCED
),
706 /* get install params */
707 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
708 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
,
713 InstallParams
.Flags
= 0;
716 dap
->HasDriverPage
= !(InstallParams
.Flags
& DI_DRIVERPAGE_ADDED
);
717 dap
->HasResourcePage
= !(InstallParams
.Flags
& DI_RESOURCEPAGE_ADDED
);
718 dap
->HasPowerPage
= !(InstallParams
.Flags
& DI_FLAGSEX_POWERPAGE_ADDED
);
722 /* get the device icon */
723 if (dap
->hDevIcon
!= NULL
)
725 DestroyIcon(dap
->hDevIcon
);
726 dap
->hDevIcon
= NULL
;
728 if (!SetupDiLoadClassIcon(&DeviceInfoData
->ClassGuid
,
732 dap
->hDevIcon
= NULL
;
735 /* get the device name */
736 if (GetDeviceDescriptionString(DeviceInfoSet
,
739 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
741 PropSheet_SetTitle(hPropSheetDlg
,
746 /* set the device image */
747 SendDlgItemMessage(hwndDlg
,
750 (WPARAM
)dap
->hDevIcon
,
753 /* set the device name edit control text */
754 SetDlgItemText(hwndDlg
,
758 /* set the device type edit control text */
759 if (GetDeviceTypeString(DeviceInfoData
,
761 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
763 SetDlgItemText(hwndDlg
,
768 /* set the device manufacturer edit control text */
769 if (GetDeviceManufacturerString(DeviceInfoSet
,
772 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
774 SetDlgItemText(hwndDlg
,
779 /* set the device location edit control text */
780 if (GetDeviceLocationString(DeviceInfoData
->DevInst
,
783 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
785 SetDlgItemText(hwndDlg
,
790 /* set the device status edit control text */
791 if (GetDeviceStatusString(DeviceInfoData
->DevInst
,
794 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
796 SetDlgItemText(hwndDlg
,
801 /* set the device troubleshoot button text and disable it if necessary */
802 hDevProbBtn
= GetDlgItem(hwndDlg
,
804 cr
= CM_Get_DevNode_Status_Ex(&Status
,
806 DeviceInfoData
->DevInst
,
809 if (cr
== CR_SUCCESS
&& (Status
& DN_HAS_PROBLEM
))
811 switch (ProblemNumber
)
813 case CM_PROB_DEVLOADER_FAILED
:
815 /* FIXME - only if it's not a root bus devloader,
816 disable the button otherwise */
817 TroubleShootStrId
= IDS_UPDATEDRV
;
821 case CM_PROB_OUT_OF_MEMORY
:
822 case CM_PROB_ENTRY_IS_WRONG_TYPE
:
823 case CM_PROB_LACKED_ARBITRATOR
:
824 case CM_PROB_FAILED_START
:
826 case CM_PROB_UNKNOWN_RESOURCE
:
828 TroubleShootStrId
= IDS_UPDATEDRV
;
832 case CM_PROB_BOOT_CONFIG_CONFLICT
:
833 case CM_PROB_NORMAL_CONFLICT
:
834 case CM_PROB_REENUMERATION
:
836 /* FIXME - Troubleshoot conflict */
840 case CM_PROB_FAILED_FILTER
:
841 case CM_PROB_REINSTALL
:
842 case CM_PROB_FAILED_INSTALL
:
844 TroubleShootStrId
= IDS_REINSTALLDRV
;
848 case CM_PROB_DEVLOADER_NOT_FOUND
:
851 1) if it's a missing system devloader:
852 - disable the button (Reinstall Driver)
853 2) if it's not a system devloader but still missing:
855 3) if it's not a system devloader but the file can be found:
857 4) if it's a missing or empty software key
863 case CM_PROB_INVALID_DATA
:
864 case CM_PROB_PARTIAL_LOG_CONF
:
865 case CM_PROB_NO_VALID_LOG_CONF
:
866 case CM_PROB_HARDWARE_DISABLED
:
867 case CM_PROB_CANT_SHARE_IRQ
:
868 case CM_PROB_TRANSLATION_FAILED
:
869 case CM_PROB_SYSTEM_SHUTDOWN
:
870 case CM_PROB_PHANTOM
:
871 bDevActionAvailable
= FALSE
;
874 case CM_PROB_NOT_VERIFIED
:
875 case CM_PROB_DEVICE_NOT_THERE
:
876 /* FIXME - search hardware */
879 case CM_PROB_NEED_RESTART
:
880 case CM_PROB_WILL_BE_REMOVED
:
882 case CM_PROB_TOO_EARLY
:
883 case CM_PROB_DISABLED_SERVICE
:
884 TroubleShootStrId
= IDS_REBOOT
;
887 case CM_PROB_REGISTRY
:
888 /* FIXME - check registry? */
891 case CM_PROB_DISABLED
:
892 /* if device was disabled by the user: */
893 TroubleShootStrId
= IDS_ENABLEDEV
;
894 /* FIXME - otherwise disable button because the device was
895 disabled by the system*/
898 case CM_PROB_DEVLOADER_NOT_READY
:
899 /* FIXME - if it's a graphics adapter:
900 - if it's a a secondary adapter and the main adapter
910 case CM_PROB_FAILED_ADD
:
911 TroubleShootStrId
= IDS_PROPERTIES
;
916 if (LoadString(hDllInstance
,
919 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])) != 0)
921 SetWindowText(hDevProbBtn
,
924 EnableWindow(hDevProbBtn
,
925 dap
->IsAdmin
&& bDevActionAvailable
);
927 /* check if the device can be enabled/disabled */
928 hDevUsage
= GetDlgItem(hwndDlg
,
931 dap
->CanDisable
= FALSE
;
932 dap
->DeviceStarted
= FALSE
;
934 if (CanDisableDevice(DeviceInfoData
->DevInst
,
938 dap
->CanDisable
= bFlag
;
941 if (IsDeviceStarted(DeviceInfoData
->DevInst
,
945 dap
->DeviceStarted
= bFlag
;
948 /* enable/disable the device usage controls */
949 EnableWindow(GetDlgItem(hwndDlg
,
951 dap
->CanDisable
&& dap
->IsAdmin
);
952 EnableWindow(hDevUsage
,
953 dap
->CanDisable
&& dap
->IsAdmin
);
955 /* clear the combobox */
956 SendMessage(hDevUsage
,
962 InitDevUsageActions(hwndDlg
,
967 /* find out how many new device property sheets to add.
968 fake a PROPSHEETHEADER structure, we don't plan to
969 call PropertySheet again!*/
970 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
974 /* get the number of device property sheets for the device */
975 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
980 dap
->PropertySheetType
) &&
981 nDriverPages
!= 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
983 dap
->nDevPropSheets
+= nDriverPages
;
990 /* include the driver page */
991 if (dap
->HasDriverPage
)
992 dap
->nDevPropSheets
++;
994 /* add the device property sheets */
995 if (dap
->nDevPropSheets
!= 0)
997 dap
->DevPropSheets
= HeapAlloc(GetProcessHeap(),
999 dap
->nDevPropSheets
* sizeof(HPROPSHEETPAGE
));
1000 if (dap
->DevPropSheets
!= NULL
)
1002 if (nDriverPages
!= 0)
1004 psh
.phpage
= dap
->DevPropSheets
;
1006 /* query the device property sheet pages to add */
1007 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
1010 dap
->nDevPropSheets
,
1012 dap
->PropertySheetType
))
1014 /* add the property sheets */
1016 iPage
!= nDriverPages
;
1019 PropSheet_AddPage(hPropSheetDlg
,
1020 dap
->DevPropSheets
[iPage
]);
1023 dap
->FreeDevPropSheets
= TRUE
;
1027 /* cleanup, we were unable to get the device property sheets */
1028 iPage
= nDriverPages
;
1029 dap
->nDevPropSheets
-= nDriverPages
;
1036 /* add the driver page if necessary */
1037 if (dap
->HasDriverPage
)
1039 PROPSHEETPAGE pspDriver
= {0};
1040 pspDriver
.dwSize
= sizeof(PROPSHEETPAGE
);
1041 pspDriver
.dwFlags
= PSP_DEFAULT
;
1042 pspDriver
.hInstance
= hDllInstance
;
1043 pspDriver
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEDRIVER
);
1044 pspDriver
.pfnDlgProc
= AdvProcDriverDlgProc
;
1045 pspDriver
.lParam
= (LPARAM
)dap
;
1046 dap
->DevPropSheets
[iPage
] = dap
->pCreatePropertySheetPageW(&pspDriver
);
1047 if (dap
->DevPropSheets
[iPage
] != NULL
)
1049 if (PropSheet_AddPage(hPropSheetDlg
,
1050 dap
->DevPropSheets
[iPage
]))
1056 dap
->pDestroyPropertySheetPage(dap
->DevPropSheets
[iPage
]);
1057 dap
->DevPropSheets
[iPage
] = NULL
;
1063 dap
->nDevPropSheets
= 0;
1066 /* finally, disable the apply button */
1067 PropSheet_UnChanged(hPropSheetDlg
,
1069 dap
->DeviceUsageChanged
= FALSE
;
1075 DlgParentSubWndProc(IN HWND hwnd
,
1080 PDEVADVPROP_INFO dap
;
1082 dap
= (PDEVADVPROP_INFO
)GetProp(hwnd
,
1083 L
"DevMgrDevChangeSub");
1086 if (uMsg
== WM_DEVICECHANGE
&& !IsWindowVisible(dap
->hWndGeneralPage
))
1088 SendMessage(dap
->hWndGeneralPage
,
1094 /* pass the message the the old window proc */
1095 return CallWindowProc(dap
->ParentOldWndProc
,
1103 /* this is not a good idea if the subclassed window was an ansi
1104 window, but we failed finding out the previous window proc
1105 so we can't use CallWindowProc. This should rarely - if ever -
1108 return DefWindowProc(hwnd
,
1118 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
1123 PDEVADVPROP_INFO dap
;
1124 INT_PTR Ret
= FALSE
;
1126 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
1129 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
1135 switch (LOWORD(wParam
))
1139 if (HIWORD(wParam
) == CBN_SELCHANGE
)
1141 PropSheet_Changed(GetParent(hwndDlg
),
1143 dap
->DeviceUsageChanged
= TRUE
;
1148 case IDC_DEVPROBLEM
:
1152 /* display the device problem wizard */
1153 ShowDeviceProblemWizard(hwndDlg
,
1155 &dap
->DeviceInfoData
,
1166 NMHDR
*hdr
= (NMHDR
*)lParam
;
1170 ApplyGeneralSettings(hwndDlg
,
1179 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1184 dap
->hWndGeneralPage
= hwndDlg
;
1186 SetWindowLongPtr(hwndDlg
,
1190 /* subclass the parent window to always receive
1191 WM_DEVICECHANGE messages */
1192 hWndParent
= GetParent(hwndDlg
);
1193 if (hWndParent
!= NULL
)
1195 /* subclass the parent window. This is not safe
1196 if the parent window belongs to another thread! */
1197 dap
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
1199 (LONG_PTR
)DlgParentSubWndProc
);
1201 if (dap
->ParentOldWndProc
!= NULL
&&
1203 L
"DevMgrDevChangeSub",
1206 dap
->hWndParent
= hWndParent
;
1210 /* do not call UpdateDevInfo directly in here because it modifies
1211 the pages of the property sheet! */
1212 PostMessage(hwndDlg
,
1221 case WM_DEVICECHANGE
:
1223 /* FIXME - don't call UpdateDevInfo for all events */
1224 UpdateDevInfo(hwndDlg
,
1233 UpdateDevInfo(hwndDlg
,
1236 dap
->PageInitialized
= TRUE
;
1242 /* restore the old window proc of the subclassed parent window */
1243 if (dap
->hWndParent
!= NULL
&& dap
->ParentOldWndProc
!= NULL
)
1245 if (SetWindowLongPtr(dap
->hWndParent
,
1247 (LONG_PTR
)dap
->ParentOldWndProc
) == (LONG_PTR
)DlgParentSubWndProc
)
1249 RemoveProp(dap
->hWndParent
,
1250 L
"DevMgrDevChangeSub");
1263 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
1264 IN LPCWSTR lpDeviceID OPTIONAL
,
1265 IN HDEVINFO DeviceInfoSet
,
1266 IN PSP_DEVINFO_DATA DeviceInfoData
,
1267 IN HINSTANCE hComCtl32
,
1268 IN LPCWSTR lpMachineName
,
1271 PROPSHEETHEADER psh
= {0};
1272 PROPSHEETPAGE pspGeneral
= {0};
1273 PPROPERTYSHEETW pPropertySheetW
;
1274 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
1275 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
1276 PDEVADVPROP_INFO DevAdvPropInfo
;
1277 HMACHINE hMachine
= NULL
;
1278 DWORD DevIdSize
= 0;
1281 /* we don't want to statically link against comctl32, so find the
1282 functions we need dynamically */
1284 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
1286 pCreatePropertySheetPageW
=
1287 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
1288 "CreatePropertySheetPageW");
1289 pDestroyPropertySheetPage
=
1290 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
1291 "DestroyPropertySheetPage");
1292 if (pPropertySheetW
== NULL
||
1293 pCreatePropertySheetPageW
== NULL
||
1294 pDestroyPropertySheetPage
== NULL
)
1299 if (lpDeviceID
== NULL
)
1301 /* find out how much size is needed for the device id */
1302 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1308 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1312 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1319 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
1322 if (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0')
1324 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
1326 if (cr
!= CR_SUCCESS
)
1332 /* create the internal structure associated with the "General",
1333 "Driver", ... pages */
1334 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
1336 FIELD_OFFSET(DEVADVPROP_INFO
,
1338 (DevIdSize
* sizeof(WCHAR
)));
1339 if (DevAdvPropInfo
== NULL
)
1341 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1345 if (lpDeviceID
== NULL
)
1347 /* read the device instance id */
1348 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1350 DevAdvPropInfo
->szDeviceID
,
1359 /* copy the device instance id supplied by the caller */
1360 wcscpy(DevAdvPropInfo
->szDeviceID
,
1364 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
1365 DevAdvPropInfo
->DeviceInfoData
= *DeviceInfoData
;
1366 DevAdvPropInfo
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
1367 DevAdvPropInfo
->CurrentDeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1369 DevAdvPropInfo
->ShowRemotePages
= (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0');
1370 DevAdvPropInfo
->hMachine
= hMachine
;
1371 DevAdvPropInfo
->lpMachineName
= lpMachineName
;
1372 DevAdvPropInfo
->szDevName
[0] = L
'\0';
1373 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
1374 DevAdvPropInfo
->pCreatePropertySheetPageW
= pCreatePropertySheetPageW
;
1375 DevAdvPropInfo
->pDestroyPropertySheetPage
= pDestroyPropertySheetPage
;
1377 DevAdvPropInfo
->IsAdmin
= IsUserAdmin();
1378 DevAdvPropInfo
->DoDefaultDevAction
= ((dwFlags
& DPF_DEVICE_STATUS_ACTION
) != 0);
1380 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1381 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
1382 psh
.hwndParent
= hWndParent
;
1383 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
1385 DevAdvPropInfo
->PropertySheetType
= DevAdvPropInfo
->ShowRemotePages
?
1386 DIGCDP_FLAG_REMOTE_ADVANCED
:
1387 DIGCDP_FLAG_ADVANCED
;
1389 psh
.phpage
= HeapAlloc(GetProcessHeap(),
1391 1 * sizeof(HPROPSHEETPAGE
));
1392 if (psh
.phpage
== NULL
)
1397 /* add the "General" property sheet */
1398 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
1399 pspGeneral
.dwFlags
= PSP_DEFAULT
;
1400 pspGeneral
.hInstance
= hDllInstance
;
1401 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
1402 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
1403 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
1404 psh
.phpage
[psh
.nPages
] = pCreatePropertySheetPageW(&pspGeneral
);
1405 if (psh
.phpage
[psh
.nPages
] != NULL
)
1410 DevAdvPropInfo
->nDevPropSheets
= psh
.nPages
;
1412 if (psh
.nPages
!= 0)
1414 Ret
= pPropertySheetW(&psh
);
1416 /* NOTE: no need to destroy the property sheets anymore! */
1423 /* in case of failure the property sheets must be destroyed */
1424 if (psh
.phpage
!= NULL
)
1430 if (psh
.phpage
[i
] != NULL
)
1432 pDestroyPropertySheetPage(psh
.phpage
[i
]);
1438 if (DevAdvPropInfo
!= NULL
)
1440 if (DevAdvPropInfo
->FreeDevPropSheets
)
1442 /* don't free the array if it's the one allocated in
1443 DisplayDeviceAdvancedProperties */
1444 HeapFree(GetProcessHeap(),
1446 DevAdvPropInfo
->DevPropSheets
);
1449 if (DevAdvPropInfo
->CloseDevInst
)
1451 /* close the device info set in case a new one was created */
1452 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->DeviceInfoSet
);
1455 if (DevAdvPropInfo
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
1457 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->CurrentDeviceInfoSet
);
1460 if (DevAdvPropInfo
->hDevIcon
!= NULL
)
1462 DestroyIcon(DevAdvPropInfo
->hDevIcon
);
1465 HeapFree(GetProcessHeap(),
1470 if (psh
.phpage
!= NULL
)
1472 HeapFree(GetProcessHeap(),
1477 if (hMachine
!= NULL
)
1479 CM_Disconnect_Machine(hMachine
);
1486 /***************************************************************************
1488 * DeviceAdvancedPropertiesW
1491 * Invokes the device properties dialog, this version may add some property pages
1495 * hWndParent: Handle to the parent window
1496 * lpMachineName: Machine Name, NULL is the local machine
1497 * lpDeviceID: Specifies the device whose properties are to be shown
1500 * Always returns -1, a call to GetLastError returns 0 if successful
1506 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL
,
1507 IN LPCWSTR lpMachineName OPTIONAL
,
1508 IN LPCWSTR lpDeviceID
)
1511 SP_DEVINFO_DATA DevInfoData
;
1512 HINSTANCE hComCtl32
;
1515 if (lpDeviceID
== NULL
)
1517 SetLastError(ERROR_INVALID_PARAMETER
);
1521 /* dynamically load comctl32 */
1522 hComCtl32
= LoadAndInitComctl32();
1523 if (hComCtl32
!= NULL
)
1525 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1529 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1531 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1532 if (SetupDiOpenDeviceInfo(hDevInfo
,
1538 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1547 SetupDiDestroyDeviceInfoList(hDevInfo
);
1550 FreeLibrary(hComCtl32
);
1557 /***************************************************************************
1559 * DeviceAdvancedPropertiesA
1562 * Invokes the device properties dialog, this version may add some property pages
1566 * hWndParent: Handle to the parent window
1567 * lpMachineName: Machine Name, NULL is the local machine
1568 * lpDeviceID: Specifies the device whose properties are to be shown
1571 * Always returns -1, a call to GetLastError returns 0 if successful
1577 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL
,
1578 IN LPCSTR lpMachineName OPTIONAL
,
1579 IN LPCSTR lpDeviceID
)
1581 LPWSTR lpMachineNameW
= NULL
;
1582 LPWSTR lpDeviceIDW
= NULL
;
1585 if (lpMachineName
!= NULL
)
1587 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1593 if (lpDeviceID
!= NULL
)
1595 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1602 Ret
= DeviceAdvancedPropertiesW(hWndParent
,
1607 if (lpMachineNameW
!= NULL
)
1609 HeapFree(GetProcessHeap(),
1613 if (lpDeviceIDW
!= NULL
)
1615 HeapFree(GetProcessHeap(),
1624 /***************************************************************************
1626 * DevicePropertiesExA
1629 * Invokes the extended device properties dialog
1632 * hWndParent: Handle to the parent window
1633 * lpMachineName: Machine Name, NULL is the local machine
1634 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1635 * bShowDevMgr is nonzero
1636 * dwFlags: This parameter can be a combination of the following flags:
1637 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1638 * the default device status action button
1639 * to be clicked (Troubleshoot, Enable
1641 * bShowDevMgr: If non-zero it displays the device manager instead of
1642 * the advanced device property dialog
1645 * 1: if bShowDevMgr is non-zero and no error occured
1646 * -1: a call to GetLastError returns 0 if successful
1652 DevicePropertiesExA(IN HWND hWndParent OPTIONAL
,
1653 IN LPCSTR lpMachineName OPTIONAL
,
1654 IN LPCSTR lpDeviceID OPTIONAL
,
1655 IN DWORD dwFlags OPTIONAL
,
1656 IN BOOL bShowDevMgr
)
1658 LPWSTR lpMachineNameW
= NULL
;
1659 LPWSTR lpDeviceIDW
= NULL
;
1662 if (lpMachineName
!= NULL
)
1664 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1670 if (lpDeviceID
!= NULL
)
1672 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1679 Ret
= DevicePropertiesExW(hWndParent
,
1686 if (lpMachineNameW
!= NULL
)
1688 HeapFree(GetProcessHeap(),
1692 if (lpDeviceIDW
!= NULL
)
1694 HeapFree(GetProcessHeap(),
1703 /***************************************************************************
1705 * DevicePropertiesExW
1708 * Invokes the extended device properties dialog
1711 * hWndParent: Handle to the parent window
1712 * lpMachineName: Machine Name, NULL is the local machine
1713 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1714 * bShowDevMgr is nonzero
1715 * dwFlags: This parameter can be a combination of the following flags:
1716 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1717 * the default device status action button
1718 * to be clicked (Troubleshoot, Enable
1720 * bShowDevMgr: If non-zero it displays the device manager instead of
1721 * the advanced device property dialog
1724 * 1: if bShowDevMgr is non-zero and no error occured
1725 * -1: a call to GetLastError returns 0 if successful
1731 DevicePropertiesExW(IN HWND hWndParent OPTIONAL
,
1732 IN LPCWSTR lpMachineName OPTIONAL
,
1733 IN LPCWSTR lpDeviceID OPTIONAL
,
1734 IN DWORD dwFlags OPTIONAL
,
1735 IN BOOL bShowDevMgr
)
1739 if (dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
))
1741 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1742 dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
));
1743 SetLastError(ERROR_INVALID_FLAGS
);
1749 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1750 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1755 SP_DEVINFO_DATA DevInfoData
;
1756 HINSTANCE hComCtl32
;
1758 if (lpDeviceID
== NULL
)
1760 SetLastError(ERROR_INVALID_PARAMETER
);
1764 /* dynamically load comctl32 */
1765 hComCtl32
= LoadAndInitComctl32();
1766 if (hComCtl32
!= NULL
)
1768 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1772 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1774 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1775 if (SetupDiOpenDeviceInfo(hDevInfo
,
1781 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1790 SetupDiDestroyDeviceInfoList(hDevInfo
);
1793 FreeLibrary(hComCtl32
);