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
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/advprop.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
25 * Ged Murphy <gedmurphy@reactos.org>
34 typedef INT_PTR (WINAPI
*PPROPERTYSHEETW
)(LPCPROPSHEETHEADERW
);
35 typedef HPROPSHEETPAGE (WINAPI
*PCREATEPROPERTYSHEETPAGEW
)(LPCPROPSHEETPAGEW
);
36 typedef BOOL (WINAPI
*PDESTROYPROPERTYSHEETPAGE
)(HPROPSHEETPAGE
);
38 typedef struct _DEVADVPROP_INFO
42 WNDPROC ParentOldWndProc
;
45 HDEVINFO DeviceInfoSet
;
46 SP_DEVINFO_DATA DeviceInfoData
;
47 HDEVINFO CurrentDeviceInfoSet
;
48 SP_DEVINFO_DATA CurrentDeviceInfoData
;
49 DEVINST ParentDevInst
;
51 LPCWSTR lpMachineName
;
54 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
55 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
57 DWORD PropertySheetType
;
59 HPROPSHEETPAGE
*DevPropSheets
;
66 UINT FreeDevPropSheets
: 1;
68 UINT DeviceStarted
: 1;
69 UINT DeviceUsageChanged
: 1;
70 UINT CloseDevInst
: 1;
72 UINT DoDefaultDevAction
: 1;
73 UINT PageInitialized
: 1;
74 UINT ShowRemotePages
: 1;
75 UINT HasDriverPage
: 1;
76 UINT HasResourcePage
: 1;
77 UINT HasPowerPage
: 1;
84 /* struct may be dynamically expanded here! */
85 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
88 typedef struct _ENUMDRIVERFILES_CONTEXT
90 HWND hDriversListView
;
92 } ENUMDRIVERFILES_CONTEXT
, *PENUMDRIVERFILES_CONTEXT
;
94 #define PM_INITIALIZE (WM_APP + 0x101)
98 EnumDeviceDriverFilesCallback(IN PVOID Context
,
104 PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext
= (PENUMDRIVERFILES_CONTEXT
)Context
;
106 li
.mask
= LVIF_TEXT
| LVIF_STATE
;
107 li
.iItem
= EnumDriverFilesContext
->nCount
++;
109 li
.state
= (li
.iItem
== 0 ? LVIS_SELECTED
: 0);
110 li
.stateMask
= LVIS_SELECTED
;
111 li
.pszText
= (LPWSTR
)Param1
;
112 (void)ListView_InsertItem(EnumDriverFilesContext
->hDriversListView
,
119 UpdateDriverDetailsDlg(IN HWND hwndDlg
,
120 IN HWND hDriversListView
,
121 IN PDEVADVPROP_INFO dap
)
123 HDEVINFO DeviceInfoSet
;
124 PSP_DEVINFO_DATA DeviceInfoData
;
125 SP_DRVINFO_DATA DriverInfoData
;
126 ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext
;
128 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
130 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
131 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
135 DeviceInfoSet
= dap
->DeviceInfoSet
;
136 DeviceInfoData
= &dap
->DeviceInfoData
;
139 /* set the device image */
140 SendDlgItemMessage(hwndDlg
,
143 (WPARAM
)dap
->hDevIcon
,
146 /* set the device name edit control text */
147 SetDlgItemText(hwndDlg
,
151 /* fill the driver files list view */
152 EnumDriverFilesContext
.hDriversListView
= hDriversListView
;
153 EnumDriverFilesContext
.nCount
= 0;
155 (void)ListView_DeleteAllItems(EnumDriverFilesContext
.hDriversListView
);
156 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
157 if (FindCurrentDriver(DeviceInfoSet
,
160 SetupDiSetSelectedDriver(DeviceInfoSet
,
164 HSPFILEQ queueHandle
;
166 queueHandle
= SetupOpenFileQueue();
167 if (queueHandle
!= (HSPFILEQ
)INVALID_HANDLE_VALUE
)
169 SP_DEVINSTALL_PARAMS DeviceInstallParams
= {0};
170 DeviceInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
171 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
173 &DeviceInstallParams
))
175 DeviceInstallParams
.FileQueue
= queueHandle
;
176 DeviceInstallParams
.Flags
|= DI_NOVCP
;
178 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
180 &DeviceInstallParams
) &&
181 SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES
,
189 /* enumerate the driver files */
190 SetupScanFileQueue(queueHandle
,
191 SPQ_SCAN_USE_CALLBACK
,
193 EnumDeviceDriverFilesCallback
,
194 &EnumDriverFilesContext
,
197 /* update the list view column width */
198 GetClientRect(hDriversListView
,
200 lvc
.mask
= LVCF_WIDTH
;
201 lvc
.cx
= rcClient
.right
;
202 (void)ListView_SetColumn(hDriversListView
,
208 SetupCloseFileQueue(queueHandle
);
216 DriverDetailsDlgProc(IN HWND hwndDlg
,
221 PDEVADVPROP_INFO dap
;
224 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
227 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
233 switch (LOWORD(wParam
))
255 HWND hDriversListView
;
257 dap
= (PDEVADVPROP_INFO
)lParam
;
260 SetWindowLongPtr(hwndDlg
,
264 hDriversListView
= GetDlgItem(hwndDlg
,
267 /* add a column to the list view control */
268 lvc
.mask
= LVCF_FMT
| LVCF_WIDTH
;
269 lvc
.fmt
= LVCFMT_LEFT
;
271 (void)ListView_InsertColumn(hDriversListView
,
275 UpdateDriverDetailsDlg(hwndDlg
,
291 UpdateDriverDlg(IN HWND hwndDlg
,
292 IN PDEVADVPROP_INFO dap
)
294 HDEVINFO DeviceInfoSet
;
295 PSP_DEVINFO_DATA DeviceInfoData
;
297 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
299 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
300 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
304 DeviceInfoSet
= dap
->DeviceInfoSet
;
305 DeviceInfoData
= &dap
->DeviceInfoData
;
308 /* set the device image */
309 SendDlgItemMessage(hwndDlg
,
312 (WPARAM
)dap
->hDevIcon
,
315 /* set the device name edit control text */
316 SetDlgItemText(hwndDlg
,
320 /* query the driver provider */
321 if (GetDriverProviderString(DeviceInfoSet
,
324 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
326 SetDlgItemText(hwndDlg
,
331 /* query the driver date */
332 if (GetDriverDateString(DeviceInfoSet
,
335 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
337 SetDlgItemText(hwndDlg
,
342 /* query the driver version */
343 if (GetDriverVersionString(DeviceInfoSet
,
346 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
348 SetDlgItemText(hwndDlg
,
357 AdvProcDriverDlgProc(IN HWND hwndDlg
,
362 PDEVADVPROP_INFO dap
;
365 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
368 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
374 switch (LOWORD(wParam
))
376 case IDC_DRIVERDETAILS
:
378 DialogBoxParam(hDllInstance
,
379 MAKEINTRESOURCE(IDD_DRIVERDETAILS
),
381 DriverDetailsDlgProc
,
391 NMHDR
*hdr
= (NMHDR
*)lParam
;
402 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
405 SetWindowLongPtr(hwndDlg
,
409 UpdateDriverDlg(hwndDlg
,
423 InitDevUsageActions(IN HWND hwndDlg
,
425 IN PDEVADVPROP_INFO dap
)
436 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
439 /* fill in the device usage combo box */
440 if (LoadString(hDllInstance
,
443 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
445 Index
= (INT
)SendMessage(hComboBox
,
448 (LPARAM
)dap
->szTemp
);
451 SendMessage(hComboBox
,
458 case IDS_ENABLEDEVICE
:
459 if (dap
->DeviceStarted
)
461 SendMessage(hComboBox
,
468 case IDS_DISABLEDEVICE
:
469 if (!dap
->DeviceStarted
)
471 SendMessage(hComboBox
,
488 GetSelectedUsageAction(IN HWND hComboBox
)
493 Index
= (INT
)SendMessage(hComboBox
,
499 INT iRet
= (INT
) SendMessage(hComboBox
,
514 ApplyGeneralSettings(IN HWND hwndDlg
,
515 IN PDEVADVPROP_INFO dap
)
519 if (dap
->DeviceUsageChanged
&& dap
->IsAdmin
&& dap
->CanDisable
)
521 UINT SelectedUsageAction
;
522 BOOL NeedReboot
= FALSE
;
524 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
526 switch (SelectedUsageAction
)
528 case IDS_ENABLEDEVICE
:
529 if (!dap
->DeviceStarted
)
531 Ret
= EnableDevice(dap
->DeviceInfoSet
,
532 &dap
->DeviceInfoData
,
539 case IDS_DISABLEDEVICE
:
540 if (dap
->DeviceStarted
)
542 Ret
= EnableDevice(dap
->DeviceInfoSet
,
543 &dap
->DeviceInfoData
,
558 /* make PropertySheet() return PSM_REBOOTSYSTEM */
559 PropSheet_RebootSystem(hwndDlg
);
564 /* FIXME - display an error message */
565 DPRINT1("Failed to enable/disable device! LastError: %d\n",
570 Ret
= !dap
->DeviceUsageChanged
;
572 /* disable the apply button */
573 PropSheet_UnChanged(GetParent(hwndDlg
),
575 dap
->DeviceUsageChanged
= FALSE
;
581 UpdateDevInfo(IN HWND hwndDlg
,
582 IN PDEVADVPROP_INFO dap
,
585 HWND hDevUsage
, hPropSheetDlg
, hDevProbBtn
;
587 ULONG Status
, ProblemNumber
;
588 SP_DEVINSTALL_PARAMS_W InstallParams
;
589 UINT TroubleShootStrId
= IDS_TROUBLESHOOTDEV
;
590 BOOL bFlag
, bDevActionAvailable
= TRUE
;
591 BOOL bDrvInstalled
= FALSE
;
593 HDEVINFO DeviceInfoSet
= NULL
;
594 PSP_DEVINFO_DATA DeviceInfoData
= NULL
;
596 DWORD nDriverPages
= 0;
597 BOOL RecalcPages
= FALSE
;
599 hPropSheetDlg
= GetParent(hwndDlg
);
601 if (dap
->PageInitialized
)
603 /* switch to the General page */
604 PropSheet_SetCurSelByID(hPropSheetDlg
,
607 /* remove and destroy the existing device property sheet pages */
608 if (dap
->DevPropSheets
!= NULL
)
611 iPage
!= dap
->nDevPropSheets
;
614 if (dap
->DevPropSheets
[iPage
] != NULL
)
616 PropSheet_RemovePage(hPropSheetDlg
,
618 dap
->DevPropSheets
[iPage
]);
627 if (dap
->FreeDevPropSheets
)
629 /* don't free the array if it's the one allocated in
630 DisplayDeviceAdvancedProperties */
631 HeapFree(GetProcessHeap(),
635 dap
->FreeDevPropSheets
= FALSE
;
638 dap
->DevPropSheets
= NULL
;
639 dap
->nDevPropSheets
= 0;
643 /* create a new device info set and re-open the device */
644 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
646 SetupDiDestroyDeviceInfoList(dap
->CurrentDeviceInfoSet
);
649 dap
->ParentDevInst
= 0;
650 dap
->CurrentDeviceInfoSet
= SetupDiCreateDeviceInfoListEx(NULL
,
654 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
656 if (SetupDiOpenDeviceInfo(dap
->CurrentDeviceInfoSet
,
660 &dap
->CurrentDeviceInfoData
))
662 if (dap
->CloseDevInst
)
664 SetupDiDestroyDeviceInfoList(dap
->DeviceInfoSet
);
667 dap
->CloseDevInst
= TRUE
;
668 dap
->DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
669 dap
->DeviceInfoData
= dap
->CurrentDeviceInfoData
;
670 dap
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
678 /* get the parent node from the initial devinst */
679 CM_Get_Parent_Ex(&dap
->ParentDevInst
,
680 dap
->DeviceInfoData
.DevInst
,
685 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
687 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
688 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
692 DeviceInfoSet
= dap
->DeviceInfoSet
;
693 DeviceInfoData
= &dap
->DeviceInfoData
;
698 DeviceInfoSet
= dap
->DeviceInfoSet
;
699 DeviceInfoData
= &dap
->DeviceInfoData
;
702 dap
->HasDriverPage
= FALSE
;
703 dap
->HasResourcePage
= FALSE
;
704 dap
->HasPowerPage
= FALSE
;
705 if (IsDriverInstalled(DeviceInfoData
->DevInst
,
710 if (SetupDiCallClassInstaller((dap
->ShowRemotePages
?
711 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
712 DIF_ADDPROPERTYPAGE_ADVANCED
),
716 /* get install params */
717 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
718 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
,
723 InstallParams
.Flags
= 0;
726 dap
->HasDriverPage
= !(InstallParams
.Flags
& DI_DRIVERPAGE_ADDED
);
727 dap
->HasResourcePage
= !(InstallParams
.Flags
& DI_RESOURCEPAGE_ADDED
);
728 dap
->HasPowerPage
= !(InstallParams
.Flags
& DI_FLAGSEX_POWERPAGE_ADDED
);
732 /* get the device icon */
733 if (dap
->hDevIcon
!= NULL
)
735 DestroyIcon(dap
->hDevIcon
);
736 dap
->hDevIcon
= NULL
;
738 if (!SetupDiLoadClassIcon(&DeviceInfoData
->ClassGuid
,
742 dap
->hDevIcon
= NULL
;
745 /* get the device name */
746 if (GetDeviceDescriptionString(DeviceInfoSet
,
749 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
751 PropSheet_SetTitle(hPropSheetDlg
,
756 /* set the device image */
757 SendDlgItemMessage(hwndDlg
,
760 (WPARAM
)dap
->hDevIcon
,
763 /* set the device name edit control text */
764 SetDlgItemText(hwndDlg
,
768 /* set the device type edit control text */
769 if (GetDeviceTypeString(DeviceInfoData
,
771 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
773 SetDlgItemText(hwndDlg
,
778 /* set the device manufacturer edit control text */
779 if (GetDeviceManufacturerString(DeviceInfoSet
,
782 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
784 SetDlgItemText(hwndDlg
,
789 /* set the device location edit control text */
790 if (GetDeviceLocationString(DeviceInfoData
->DevInst
,
793 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
795 SetDlgItemText(hwndDlg
,
800 /* set the device status edit control text */
801 if (GetDeviceStatusString(DeviceInfoData
->DevInst
,
804 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
806 SetDlgItemText(hwndDlg
,
811 /* set the device troubleshoot button text and disable it if necessary */
812 hDevProbBtn
= GetDlgItem(hwndDlg
,
814 cr
= CM_Get_DevNode_Status_Ex(&Status
,
816 DeviceInfoData
->DevInst
,
819 if (cr
== CR_SUCCESS
&& (Status
& DN_HAS_PROBLEM
))
821 switch (ProblemNumber
)
823 case CM_PROB_DEVLOADER_FAILED
:
825 /* FIXME - only if it's not a root bus devloader,
826 disable the button otherwise */
827 TroubleShootStrId
= IDS_UPDATEDRV
;
831 case CM_PROB_OUT_OF_MEMORY
:
832 case CM_PROB_ENTRY_IS_WRONG_TYPE
:
833 case CM_PROB_LACKED_ARBITRATOR
:
834 case CM_PROB_FAILED_START
:
836 case CM_PROB_UNKNOWN_RESOURCE
:
838 TroubleShootStrId
= IDS_UPDATEDRV
;
842 case CM_PROB_BOOT_CONFIG_CONFLICT
:
843 case CM_PROB_NORMAL_CONFLICT
:
844 case CM_PROB_REENUMERATION
:
846 /* FIXME - Troubleshoot conflict */
850 case CM_PROB_FAILED_FILTER
:
851 case CM_PROB_REINSTALL
:
852 case CM_PROB_FAILED_INSTALL
:
854 TroubleShootStrId
= IDS_REINSTALLDRV
;
858 case CM_PROB_DEVLOADER_NOT_FOUND
:
861 1) if it's a missing system devloader:
862 - disable the button (Reinstall Driver)
863 2) if it's not a system devloader but still missing:
865 3) if it's not a system devloader but the file can be found:
867 4) if it's a missing or empty software key
873 case CM_PROB_INVALID_DATA
:
874 case CM_PROB_PARTIAL_LOG_CONF
:
875 case CM_PROB_NO_VALID_LOG_CONF
:
876 case CM_PROB_HARDWARE_DISABLED
:
877 case CM_PROB_CANT_SHARE_IRQ
:
878 case CM_PROB_TRANSLATION_FAILED
:
879 case CM_PROB_SYSTEM_SHUTDOWN
:
880 case CM_PROB_PHANTOM
:
881 bDevActionAvailable
= FALSE
;
884 case CM_PROB_NOT_VERIFIED
:
885 case CM_PROB_DEVICE_NOT_THERE
:
886 /* FIXME - search hardware */
889 case CM_PROB_NEED_RESTART
:
890 case CM_PROB_WILL_BE_REMOVED
:
892 case CM_PROB_TOO_EARLY
:
893 case CM_PROB_DISABLED_SERVICE
:
894 TroubleShootStrId
= IDS_REBOOT
;
897 case CM_PROB_REGISTRY
:
898 /* FIXME - check registry? */
901 case CM_PROB_DISABLED
:
902 /* if device was disabled by the user: */
903 TroubleShootStrId
= IDS_ENABLEDEV
;
904 /* FIXME - otherwise disable button because the device was
905 disabled by the system*/
908 case CM_PROB_DEVLOADER_NOT_READY
:
909 /* FIXME - if it's a graphics adapter:
910 - if it's a a secondary adapter and the main adapter
920 case CM_PROB_FAILED_ADD
:
921 TroubleShootStrId
= IDS_PROPERTIES
;
926 if (LoadString(hDllInstance
,
929 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])) != 0)
931 SetWindowText(hDevProbBtn
,
934 EnableWindow(hDevProbBtn
,
935 dap
->IsAdmin
&& bDevActionAvailable
);
937 /* check if the device can be enabled/disabled */
938 hDevUsage
= GetDlgItem(hwndDlg
,
941 dap
->CanDisable
= FALSE
;
942 dap
->DeviceStarted
= FALSE
;
944 if (CanDisableDevice(DeviceInfoData
->DevInst
,
948 dap
->CanDisable
= bFlag
;
951 if (IsDeviceStarted(DeviceInfoData
->DevInst
,
955 dap
->DeviceStarted
= bFlag
;
958 /* enable/disable the device usage controls */
959 EnableWindow(GetDlgItem(hwndDlg
,
961 dap
->CanDisable
&& dap
->IsAdmin
);
962 EnableWindow(hDevUsage
,
963 dap
->CanDisable
&& dap
->IsAdmin
);
965 /* clear the combobox */
966 SendMessage(hDevUsage
,
972 InitDevUsageActions(hwndDlg
,
977 /* find out how many new device property sheets to add.
978 fake a PROPSHEETHEADER structure, we don't plan to
979 call PropertySheet again!*/
980 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
984 /* get the number of device property sheets for the device */
985 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
990 dap
->PropertySheetType
) &&
991 nDriverPages
!= 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
993 dap
->nDevPropSheets
+= nDriverPages
;
1000 /* include the driver page */
1001 if (dap
->HasDriverPage
)
1002 dap
->nDevPropSheets
++;
1004 /* add the device property sheets */
1005 if (dap
->nDevPropSheets
!= 0)
1007 dap
->DevPropSheets
= HeapAlloc(GetProcessHeap(),
1009 dap
->nDevPropSheets
* sizeof(HPROPSHEETPAGE
));
1010 if (dap
->DevPropSheets
!= NULL
)
1012 if (nDriverPages
!= 0)
1014 psh
.phpage
= dap
->DevPropSheets
;
1016 /* query the device property sheet pages to add */
1017 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
1020 dap
->nDevPropSheets
,
1022 dap
->PropertySheetType
))
1024 /* add the property sheets */
1026 iPage
!= nDriverPages
;
1029 if (PropSheet_AddPage(hPropSheetDlg
,
1030 dap
->DevPropSheets
[iPage
]))
1036 dap
->FreeDevPropSheets
= TRUE
;
1040 /* cleanup, we were unable to get the device property sheets */
1041 iPage
= nDriverPages
;
1042 dap
->nDevPropSheets
-= nDriverPages
;
1049 /* add the driver page if necessary */
1050 if (dap
->HasDriverPage
)
1052 PROPSHEETPAGE pspDriver
= {0};
1053 pspDriver
.dwSize
= sizeof(PROPSHEETPAGE
);
1054 pspDriver
.dwFlags
= PSP_DEFAULT
;
1055 pspDriver
.hInstance
= hDllInstance
;
1056 pspDriver
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEDRIVER
);
1057 pspDriver
.pfnDlgProc
= AdvProcDriverDlgProc
;
1058 pspDriver
.lParam
= (LPARAM
)dap
;
1059 dap
->DevPropSheets
[iPage
] = dap
->pCreatePropertySheetPageW(&pspDriver
);
1060 if (dap
->DevPropSheets
[iPage
] != NULL
)
1062 if (PropSheet_AddPage(hPropSheetDlg
,
1063 dap
->DevPropSheets
[iPage
]))
1070 dap
->pDestroyPropertySheetPage(dap
->DevPropSheets
[iPage
]);
1071 dap
->DevPropSheets
[iPage
] = NULL
;
1077 dap
->nDevPropSheets
= 0;
1082 PropSheet_RecalcPageSizes(hPropSheetDlg
);
1085 /* finally, disable the apply button */
1086 PropSheet_UnChanged(hPropSheetDlg
,
1088 dap
->DeviceUsageChanged
= FALSE
;
1094 DlgParentSubWndProc(IN HWND hwnd
,
1099 PDEVADVPROP_INFO dap
;
1101 dap
= (PDEVADVPROP_INFO
)GetProp(hwnd
,
1102 L
"DevMgrDevChangeSub");
1105 if (uMsg
== WM_DEVICECHANGE
&& !IsWindowVisible(dap
->hWndGeneralPage
))
1107 SendMessage(dap
->hWndGeneralPage
,
1113 /* pass the message the the old window proc */
1114 return CallWindowProc(dap
->ParentOldWndProc
,
1122 /* this is not a good idea if the subclassed window was an ansi
1123 window, but we failed finding out the previous window proc
1124 so we can't use CallWindowProc. This should rarely - if ever -
1127 return DefWindowProc(hwnd
,
1137 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
1142 PDEVADVPROP_INFO dap
;
1143 INT_PTR Ret
= FALSE
;
1145 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
1148 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
1154 switch (LOWORD(wParam
))
1158 if (HIWORD(wParam
) == CBN_SELCHANGE
)
1160 PropSheet_Changed(GetParent(hwndDlg
),
1162 dap
->DeviceUsageChanged
= TRUE
;
1167 case IDC_DEVPROBLEM
:
1171 /* display the device problem wizard */
1172 ShowDeviceProblemWizard(hwndDlg
,
1174 &dap
->DeviceInfoData
,
1185 NMHDR
*hdr
= (NMHDR
*)lParam
;
1189 ApplyGeneralSettings(hwndDlg
,
1198 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1203 dap
->hWndGeneralPage
= hwndDlg
;
1205 SetWindowLongPtr(hwndDlg
,
1209 /* subclass the parent window to always receive
1210 WM_DEVICECHANGE messages */
1211 hWndParent
= GetParent(hwndDlg
);
1212 if (hWndParent
!= NULL
)
1214 /* subclass the parent window. This is not safe
1215 if the parent window belongs to another thread! */
1216 dap
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
1218 (LONG_PTR
)DlgParentSubWndProc
);
1220 if (dap
->ParentOldWndProc
!= NULL
&&
1222 L
"DevMgrDevChangeSub",
1225 dap
->hWndParent
= hWndParent
;
1229 /* do not call UpdateDevInfo directly in here because it modifies
1230 the pages of the property sheet! */
1231 PostMessage(hwndDlg
,
1240 case WM_DEVICECHANGE
:
1242 /* FIXME - don't call UpdateDevInfo for all events */
1243 UpdateDevInfo(hwndDlg
,
1252 UpdateDevInfo(hwndDlg
,
1255 dap
->PageInitialized
= TRUE
;
1261 /* restore the old window proc of the subclassed parent window */
1262 if (dap
->hWndParent
!= NULL
&& dap
->ParentOldWndProc
!= NULL
)
1264 if (SetWindowLongPtr(dap
->hWndParent
,
1266 (LONG_PTR
)dap
->ParentOldWndProc
) == (LONG_PTR
)DlgParentSubWndProc
)
1268 RemoveProp(dap
->hWndParent
,
1269 L
"DevMgrDevChangeSub");
1282 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
1283 IN LPCWSTR lpDeviceID OPTIONAL
,
1284 IN HDEVINFO DeviceInfoSet
,
1285 IN PSP_DEVINFO_DATA DeviceInfoData
,
1286 IN HINSTANCE hComCtl32
,
1287 IN LPCWSTR lpMachineName
,
1290 PROPSHEETHEADER psh
= {0};
1291 PROPSHEETPAGE pspGeneral
= {0};
1292 PPROPERTYSHEETW pPropertySheetW
;
1293 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
1294 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
1295 PDEVADVPROP_INFO DevAdvPropInfo
;
1296 HMACHINE hMachine
= NULL
;
1297 DWORD DevIdSize
= 0;
1300 /* we don't want to statically link against comctl32, so find the
1301 functions we need dynamically */
1303 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
1305 pCreatePropertySheetPageW
=
1306 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
1307 "CreatePropertySheetPageW");
1308 pDestroyPropertySheetPage
=
1309 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
1310 "DestroyPropertySheetPage");
1311 if (pPropertySheetW
== NULL
||
1312 pCreatePropertySheetPageW
== NULL
||
1313 pDestroyPropertySheetPage
== NULL
)
1318 if (lpDeviceID
== NULL
)
1320 /* find out how much size is needed for the device id */
1321 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1327 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1331 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1338 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
1341 if (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0')
1343 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
1345 if (cr
!= CR_SUCCESS
)
1351 /* create the internal structure associated with the "General",
1352 "Driver", ... pages */
1353 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
1355 FIELD_OFFSET(DEVADVPROP_INFO
,
1357 (DevIdSize
* sizeof(WCHAR
)));
1358 if (DevAdvPropInfo
== NULL
)
1360 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1364 if (lpDeviceID
== NULL
)
1366 /* read the device instance id */
1367 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1369 DevAdvPropInfo
->szDeviceID
,
1378 /* copy the device instance id supplied by the caller */
1379 wcscpy(DevAdvPropInfo
->szDeviceID
,
1383 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
1384 DevAdvPropInfo
->DeviceInfoData
= *DeviceInfoData
;
1385 DevAdvPropInfo
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
1386 DevAdvPropInfo
->CurrentDeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1388 DevAdvPropInfo
->ShowRemotePages
= (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0');
1389 DevAdvPropInfo
->hMachine
= hMachine
;
1390 DevAdvPropInfo
->lpMachineName
= lpMachineName
;
1391 DevAdvPropInfo
->szDevName
[0] = L
'\0';
1392 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
1393 DevAdvPropInfo
->pCreatePropertySheetPageW
= pCreatePropertySheetPageW
;
1394 DevAdvPropInfo
->pDestroyPropertySheetPage
= pDestroyPropertySheetPage
;
1396 DevAdvPropInfo
->IsAdmin
= IsUserAdmin();
1397 DevAdvPropInfo
->DoDefaultDevAction
= ((dwFlags
& DPF_DEVICE_STATUS_ACTION
) != 0);
1399 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1400 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
1401 psh
.hwndParent
= hWndParent
;
1402 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
1404 DevAdvPropInfo
->PropertySheetType
= DevAdvPropInfo
->ShowRemotePages
?
1405 DIGCDP_FLAG_REMOTE_ADVANCED
:
1406 DIGCDP_FLAG_ADVANCED
;
1408 psh
.phpage
= HeapAlloc(GetProcessHeap(),
1410 1 * sizeof(HPROPSHEETPAGE
));
1411 if (psh
.phpage
== NULL
)
1416 /* add the "General" property sheet */
1417 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
1418 pspGeneral
.dwFlags
= PSP_DEFAULT
;
1419 pspGeneral
.hInstance
= hDllInstance
;
1420 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
1421 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
1422 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
1423 psh
.phpage
[psh
.nPages
] = pCreatePropertySheetPageW(&pspGeneral
);
1424 if (psh
.phpage
[psh
.nPages
] != NULL
)
1429 DevAdvPropInfo
->nDevPropSheets
= psh
.nPages
;
1431 if (psh
.nPages
!= 0)
1433 Ret
= pPropertySheetW(&psh
);
1435 /* NOTE: no need to destroy the property sheets anymore! */
1442 /* in case of failure the property sheets must be destroyed */
1443 if (psh
.phpage
!= NULL
)
1449 if (psh
.phpage
[i
] != NULL
)
1451 pDestroyPropertySheetPage(psh
.phpage
[i
]);
1457 if (DevAdvPropInfo
!= NULL
)
1459 if (DevAdvPropInfo
->FreeDevPropSheets
)
1461 /* don't free the array if it's the one allocated in
1462 DisplayDeviceAdvancedProperties */
1463 HeapFree(GetProcessHeap(),
1465 DevAdvPropInfo
->DevPropSheets
);
1468 if (DevAdvPropInfo
->CloseDevInst
)
1470 /* close the device info set in case a new one was created */
1471 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->DeviceInfoSet
);
1474 if (DevAdvPropInfo
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
1476 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->CurrentDeviceInfoSet
);
1479 if (DevAdvPropInfo
->hDevIcon
!= NULL
)
1481 DestroyIcon(DevAdvPropInfo
->hDevIcon
);
1484 HeapFree(GetProcessHeap(),
1489 if (psh
.phpage
!= NULL
)
1491 HeapFree(GetProcessHeap(),
1496 if (hMachine
!= NULL
)
1498 CM_Disconnect_Machine(hMachine
);
1506 GetDeviceAndComputerName(LPWSTR lpString
,
1508 WCHAR szMachineName
[])
1512 szDeviceID
[0] = L
'\0';
1513 szMachineName
[0] = L
'\0';
1515 while (*lpString
!= L
'\0')
1517 if (*lpString
== L
'/')
1520 if(!wcsnicmp(lpString
, L
"DeviceID", 8))
1523 if (*lpString
!= L
'\0')
1526 while ((*lpString
!= L
' ') &&
1527 (*lpString
!= L
'\0') &&
1528 (i
<= MAX_DEVICE_ID_LEN
))
1530 szDeviceID
[i
++] = *lpString
++;
1532 szDeviceID
[i
] = L
'\0';
1536 else if (!wcsnicmp(lpString
, L
"MachineName", 11))
1539 if (*lpString
!= L
'\0')
1542 while ((*lpString
!= L
' ') &&
1543 (*lpString
!= L
'\0') &&
1544 (i
<= MAX_COMPUTERNAME_LENGTH
))
1546 szMachineName
[i
++] = *lpString
++;
1548 szMachineName
[i
] = L
'\0';
1551 /* knock the pointer back one and let the next
1552 * pointer deal with incrementing, otherwise we
1553 * go past the end of the string */
1563 /***************************************************************************
1565 * DeviceAdvancedPropertiesW
1568 * Invokes the device properties dialog, this version may add some property pages
1572 * hWndParent: Handle to the parent window
1573 * lpMachineName: Machine Name, NULL is the local machine
1574 * lpDeviceID: Specifies the device whose properties are to be shown
1577 * Always returns -1, a call to GetLastError returns 0 if successful
1583 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL
,
1584 IN LPCWSTR lpMachineName OPTIONAL
,
1585 IN LPCWSTR lpDeviceID
)
1588 SP_DEVINFO_DATA DevInfoData
;
1589 HINSTANCE hComCtl32
;
1592 if (lpDeviceID
== NULL
)
1594 SetLastError(ERROR_INVALID_PARAMETER
);
1598 /* dynamically load comctl32 */
1599 hComCtl32
= LoadAndInitComctl32();
1600 if (hComCtl32
!= NULL
)
1602 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1606 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1608 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1609 if (SetupDiOpenDeviceInfo(hDevInfo
,
1615 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1624 SetupDiDestroyDeviceInfoList(hDevInfo
);
1627 FreeLibrary(hComCtl32
);
1634 /***************************************************************************
1636 * DeviceAdvancedPropertiesA
1639 * Invokes the device properties dialog, this version may add some property pages
1643 * hWndParent: Handle to the parent window
1644 * lpMachineName: Machine Name, NULL is the local machine
1645 * lpDeviceID: Specifies the device whose properties are to be shown
1648 * Always returns -1, a call to GetLastError returns 0 if successful
1654 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL
,
1655 IN LPCSTR lpMachineName OPTIONAL
,
1656 IN LPCSTR lpDeviceID
)
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
= DeviceAdvancedPropertiesW(hWndParent
,
1684 if (lpMachineNameW
!= NULL
)
1686 HeapFree(GetProcessHeap(),
1690 if (lpDeviceIDW
!= NULL
)
1692 HeapFree(GetProcessHeap(),
1701 /***************************************************************************
1703 * DevicePropertiesExA
1706 * Invokes the extended device properties dialog
1709 * hWndParent: Handle to the parent window
1710 * lpMachineName: Machine Name, NULL is the local machine
1711 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1712 * bShowDevMgr is nonzero
1713 * dwFlags: This parameter can be a combination of the following flags:
1714 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1715 * the default device status action button
1716 * to be clicked (Troubleshoot, Enable
1718 * bShowDevMgr: If non-zero it displays the device manager instead of
1719 * the advanced device property dialog
1722 * 1: if bShowDevMgr is non-zero and no error occured
1723 * -1: a call to GetLastError returns 0 if successful
1729 DevicePropertiesExA(IN HWND hWndParent OPTIONAL
,
1730 IN LPCSTR lpMachineName OPTIONAL
,
1731 IN LPCSTR lpDeviceID OPTIONAL
,
1732 IN DWORD dwFlags OPTIONAL
,
1733 IN BOOL bShowDevMgr
)
1735 LPWSTR lpMachineNameW
= NULL
;
1736 LPWSTR lpDeviceIDW
= NULL
;
1739 if (lpMachineName
!= NULL
)
1741 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1747 if (lpDeviceID
!= NULL
)
1749 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1756 Ret
= DevicePropertiesExW(hWndParent
,
1763 if (lpMachineNameW
!= NULL
)
1765 HeapFree(GetProcessHeap(),
1769 if (lpDeviceIDW
!= NULL
)
1771 HeapFree(GetProcessHeap(),
1780 /***************************************************************************
1782 * DevicePropertiesExW
1785 * Invokes the extended device properties dialog
1788 * hWndParent: Handle to the parent window
1789 * lpMachineName: Machine Name, NULL is the local machine
1790 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1791 * bShowDevMgr is nonzero
1792 * dwFlags: This parameter can be a combination of the following flags:
1793 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1794 * the default device status action button
1795 * to be clicked (Troubleshoot, Enable
1797 * bShowDevMgr: If non-zero it displays the device manager instead of
1798 * the advanced device property dialog
1801 * 1: if bShowDevMgr is non-zero and no error occured
1802 * -1: a call to GetLastError returns 0 if successful
1808 DevicePropertiesExW(IN HWND hWndParent OPTIONAL
,
1809 IN LPCWSTR lpMachineName OPTIONAL
,
1810 IN LPCWSTR lpDeviceID OPTIONAL
,
1811 IN DWORD dwFlags OPTIONAL
,
1812 IN BOOL bShowDevMgr
)
1816 if (dwFlags
& ~(DPF_EXTENDED
| DPF_DEVICE_STATUS_ACTION
))
1818 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1819 dwFlags
& ~(DPF_EXTENDED
| DPF_DEVICE_STATUS_ACTION
));
1820 SetLastError(ERROR_INVALID_FLAGS
);
1826 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1827 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1832 SP_DEVINFO_DATA DevInfoData
;
1833 HINSTANCE hComCtl32
;
1835 if (lpDeviceID
== NULL
)
1837 SetLastError(ERROR_INVALID_PARAMETER
);
1841 /* dynamically load comctl32 */
1842 hComCtl32
= LoadAndInitComctl32();
1843 if (hComCtl32
!= NULL
)
1845 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1849 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1851 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1852 if (SetupDiOpenDeviceInfo(hDevInfo
,
1858 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1867 SetupDiDestroyDeviceInfoList(hDevInfo
);
1870 FreeLibrary(hComCtl32
);
1878 /***************************************************************************
1883 * Invokes the device properties dialog directly
1886 * hWndParent: Handle to the parent window
1887 * lpMachineName: Machine Name, NULL is the local machine
1888 * lpDeviceID: Specifies the device whose properties are to be shown
1889 * bShowDevMgr: If non-zero it displays the device manager instead of
1890 * the device property dialog
1893 * >=0: if no errors occured
1894 * -1: if errors occured
1902 DevicePropertiesA(HWND hWndParent
,
1903 LPCSTR lpMachineName
,
1907 return DevicePropertiesExA(hWndParent
,
1915 /***************************************************************************
1920 * Invokes the device properties dialog directly
1923 * hWndParent: Handle to the parent window
1924 * lpMachineName: Machine Name, NULL is the local machine
1925 * lpDeviceID: Specifies the device whose properties are to be shown
1926 * bShowDevMgr: If non-zero it displays the device manager instead of
1927 * the device property dialog
1930 * >=0: if no errors occured
1931 * -1: if errors occured
1939 DevicePropertiesW(HWND hWndParent
,
1940 LPCWSTR lpMachineName
,
1944 return DevicePropertiesExW(hWndParent
,
1952 /***************************************************************************
1954 * DeviceProperties_RunDLLA
1957 * Invokes the device properties dialog
1960 * hWndParent: Handle to the parent window
1961 * hInst: Handle to the application instance
1962 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
1964 * nCmdShow: Specifies how the window should be shown
1971 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
1972 * (/MachineName is optional). This function only parses this string and eventually
1973 * calls DeviceProperties().
1979 DeviceProperties_RunDLLA(HWND hWndParent
,
1984 LPWSTR lpDeviceCmdW
= NULL
;
1986 if (lpDeviceCmd
!= NULL
)
1988 if ((lpDeviceCmdW
= ConvertMultiByteToUnicode(lpDeviceCmd
,
1991 DeviceProperties_RunDLLW(hWndParent
,
1998 if (lpDeviceCmdW
!= NULL
)
2000 HeapFree(GetProcessHeap(),
2007 /***************************************************************************
2009 * DeviceProperties_RunDLLW
2012 * Invokes the device properties dialog
2015 * hWndParent: Handle to the parent window
2016 * hInst: Handle to the application instance
2017 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
2019 * nCmdShow: Specifies how the window should be shown
2026 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
2027 * (/MachineName is optional). This function only parses this string and eventually
2028 * calls DeviceProperties().
2034 DeviceProperties_RunDLLW(HWND hWndParent
,
2036 LPCWSTR lpDeviceCmd
,
2039 WCHAR szDeviceID
[MAX_DEVICE_ID_LEN
+1];
2040 WCHAR szMachineName
[MAX_COMPUTERNAME_LENGTH
+1];
2041 LPWSTR lpString
= (LPWSTR
)lpDeviceCmd
;
2043 if (!GetDeviceAndComputerName(lpString
,
2047 DPRINT1("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID
, szMachineName
);
2051 DevicePropertiesW(hWndParent
,