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
;
65 UINT FreeDevPropSheets
: 1;
67 UINT DeviceStarted
: 1;
68 UINT DeviceUsageChanged
: 1;
69 UINT CloseDevInst
: 1;
71 UINT DoDefaultDevAction
: 1;
72 UINT PageInitialized
: 1;
73 UINT ShowRemotePages
: 1;
74 UINT HasDriverPage
: 1;
75 UINT HasResourcePage
: 1;
76 UINT HasPowerPage
: 1;
83 /* struct may be dynamically expanded here! */
84 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
87 typedef struct _ENUMDRIVERFILES_CONTEXT
89 HWND hDriversListView
;
91 } ENUMDRIVERFILES_CONTEXT
, *PENUMDRIVERFILES_CONTEXT
;
93 #define PM_INITIALIZE (WM_APP + 0x101)
97 EnumDeviceDriverFilesCallback(IN PVOID Context
,
103 PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext
= (PENUMDRIVERFILES_CONTEXT
)Context
;
105 li
.mask
= LVIF_TEXT
| LVIF_STATE
;
106 li
.iItem
= EnumDriverFilesContext
->nCount
++;
108 li
.state
= (li
.iItem
== 0 ? LVIS_SELECTED
: 0);
109 li
.stateMask
= LVIS_SELECTED
;
110 li
.pszText
= (LPWSTR
)Param1
;
111 (void)ListView_InsertItem(EnumDriverFilesContext
->hDriversListView
,
118 UpdateDriverDetailsDlg(IN HWND hwndDlg
,
119 IN HWND hDriversListView
,
120 IN PDEVADVPROP_INFO dap
)
122 HDEVINFO DeviceInfoSet
;
123 PSP_DEVINFO_DATA DeviceInfoData
;
124 SP_DRVINFO_DATA DriverInfoData
;
125 ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext
;
127 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
129 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
130 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
134 DeviceInfoSet
= dap
->DeviceInfoSet
;
135 DeviceInfoData
= &dap
->DeviceInfoData
;
138 /* set the device image */
139 SendDlgItemMessage(hwndDlg
,
142 (WPARAM
)dap
->hDevIcon
,
145 /* set the device name edit control text */
146 SetDlgItemText(hwndDlg
,
150 /* fill the driver files list view */
151 EnumDriverFilesContext
.hDriversListView
= hDriversListView
;
152 EnumDriverFilesContext
.nCount
= 0;
154 (void)ListView_DeleteAllItems(EnumDriverFilesContext
.hDriversListView
);
155 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA
);
156 if (FindCurrentDriver(DeviceInfoSet
,
159 SetupDiSetSelectedDriver(DeviceInfoSet
,
163 HSPFILEQ queueHandle
;
165 queueHandle
= SetupOpenFileQueue();
166 if (queueHandle
!= (HSPFILEQ
)INVALID_HANDLE_VALUE
)
168 SP_DEVINSTALL_PARAMS DeviceInstallParams
= {0};
169 DeviceInstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
170 if (SetupDiGetDeviceInstallParams(DeviceInfoSet
,
172 &DeviceInstallParams
))
174 DeviceInstallParams
.FileQueue
= queueHandle
;
175 DeviceInstallParams
.Flags
|= DI_NOVCP
;
177 if (SetupDiSetDeviceInstallParams(DeviceInfoSet
,
179 &DeviceInstallParams
) &&
180 SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES
,
188 /* enumerate the driver files */
189 SetupScanFileQueue(queueHandle
,
190 SPQ_SCAN_USE_CALLBACK
,
192 EnumDeviceDriverFilesCallback
,
193 &EnumDriverFilesContext
,
196 /* update the list view column width */
197 GetClientRect(hDriversListView
,
199 lvc
.mask
= LVCF_WIDTH
;
200 lvc
.cx
= rcClient
.right
;
201 (void)ListView_SetColumn(hDriversListView
,
207 SetupCloseFileQueue(queueHandle
);
215 DriverDetailsDlgProc(IN HWND hwndDlg
,
220 PDEVADVPROP_INFO dap
;
223 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
226 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
232 switch (LOWORD(wParam
))
254 HWND hDriversListView
;
256 dap
= (PDEVADVPROP_INFO
)lParam
;
259 SetWindowLongPtr(hwndDlg
,
263 hDriversListView
= GetDlgItem(hwndDlg
,
266 /* add a column to the list view control */
267 lvc
.mask
= LVCF_FMT
| LVCF_WIDTH
;
268 lvc
.fmt
= LVCFMT_LEFT
;
270 (void)ListView_InsertColumn(hDriversListView
,
274 UpdateDriverDetailsDlg(hwndDlg
,
290 UpdateDriverDlg(IN HWND hwndDlg
,
291 IN PDEVADVPROP_INFO dap
)
293 HDEVINFO DeviceInfoSet
;
294 PSP_DEVINFO_DATA DeviceInfoData
;
296 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
298 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
299 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
303 DeviceInfoSet
= dap
->DeviceInfoSet
;
304 DeviceInfoData
= &dap
->DeviceInfoData
;
307 /* set the device image */
308 SendDlgItemMessage(hwndDlg
,
311 (WPARAM
)dap
->hDevIcon
,
314 /* set the device name edit control text */
315 SetDlgItemText(hwndDlg
,
319 /* query the driver provider */
320 if (GetDriverProviderString(DeviceInfoSet
,
323 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
325 SetDlgItemText(hwndDlg
,
330 /* query the driver date */
331 if (GetDriverDateString(DeviceInfoSet
,
334 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
336 SetDlgItemText(hwndDlg
,
341 /* query the driver version */
342 if (GetDriverVersionString(DeviceInfoSet
,
345 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
347 SetDlgItemText(hwndDlg
,
356 AdvProcDriverDlgProc(IN HWND hwndDlg
,
361 PDEVADVPROP_INFO dap
;
364 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
367 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
373 switch (LOWORD(wParam
))
375 case IDC_DRIVERDETAILS
:
377 DialogBoxParam(hDllInstance
,
378 MAKEINTRESOURCE(IDD_DRIVERDETAILS
),
380 DriverDetailsDlgProc
,
390 NMHDR
*hdr
= (NMHDR
*)lParam
;
401 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
404 SetWindowLongPtr(hwndDlg
,
408 UpdateDriverDlg(hwndDlg
,
422 InitDevUsageActions(IN HWND hwndDlg
,
424 IN PDEVADVPROP_INFO dap
)
435 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
438 /* fill in the device usage combo box */
439 if (LoadString(hDllInstance
,
442 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
444 Index
= (INT
)SendMessage(hComboBox
,
447 (LPARAM
)dap
->szTemp
);
450 SendMessage(hComboBox
,
457 case IDS_ENABLEDEVICE
:
458 if (dap
->DeviceStarted
)
460 SendMessage(hComboBox
,
467 case IDS_DISABLEDEVICE
:
468 if (!dap
->DeviceStarted
)
470 SendMessage(hComboBox
,
487 GetSelectedUsageAction(IN HWND hComboBox
)
492 Index
= (INT
)SendMessage(hComboBox
,
498 INT iRet
= (INT
) SendMessage(hComboBox
,
513 ApplyGeneralSettings(IN HWND hwndDlg
,
514 IN PDEVADVPROP_INFO dap
)
518 if (dap
->DeviceUsageChanged
&& dap
->IsAdmin
&& dap
->CanDisable
)
520 UINT SelectedUsageAction
;
521 BOOL NeedReboot
= FALSE
;
523 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
525 switch (SelectedUsageAction
)
527 case IDS_ENABLEDEVICE
:
528 if (!dap
->DeviceStarted
)
530 Ret
= EnableDevice(dap
->DeviceInfoSet
,
531 &dap
->DeviceInfoData
,
538 case IDS_DISABLEDEVICE
:
539 if (dap
->DeviceStarted
)
541 Ret
= EnableDevice(dap
->DeviceInfoSet
,
542 &dap
->DeviceInfoData
,
557 /* make PropertySheet() return PSM_REBOOTSYSTEM */
558 PropSheet_RebootSystem(hwndDlg
);
563 /* FIXME - display an error message */
564 DPRINT1("Failed to enable/disable device! LastError: %d\n",
569 Ret
= !dap
->DeviceUsageChanged
;
571 /* disable the apply button */
572 PropSheet_UnChanged(GetParent(hwndDlg
),
574 dap
->DeviceUsageChanged
= FALSE
;
580 UpdateDevInfo(IN HWND hwndDlg
,
581 IN PDEVADVPROP_INFO dap
,
584 HWND hDevUsage
, hPropSheetDlg
, hDevProbBtn
;
586 ULONG Status
, ProblemNumber
;
587 SP_DEVINSTALL_PARAMS_W InstallParams
;
588 UINT TroubleShootStrId
= IDS_TROUBLESHOOTDEV
;
589 BOOL bFlag
, bDevActionAvailable
= TRUE
;
590 BOOL bDrvInstalled
= FALSE
;
592 HDEVINFO DeviceInfoSet
= NULL
;
593 PSP_DEVINFO_DATA DeviceInfoData
= NULL
;
595 DWORD nDriverPages
= 0;
596 BOOL RecalcPages
= FALSE
;
598 hPropSheetDlg
= GetParent(hwndDlg
);
600 if (dap
->PageInitialized
)
602 /* switch to the General page */
603 PropSheet_SetCurSelByID(hPropSheetDlg
,
606 /* remove and destroy the existing device property sheet pages */
607 if (dap
->DevPropSheets
!= NULL
)
610 iPage
!= dap
->nDevPropSheets
;
613 if (dap
->DevPropSheets
[iPage
] != NULL
)
615 PropSheet_RemovePage(hPropSheetDlg
,
617 dap
->DevPropSheets
[iPage
]);
626 if (dap
->FreeDevPropSheets
)
628 /* don't free the array if it's the one allocated in
629 DisplayDeviceAdvancedProperties */
630 HeapFree(GetProcessHeap(),
634 dap
->FreeDevPropSheets
= FALSE
;
637 dap
->DevPropSheets
= NULL
;
638 dap
->nDevPropSheets
= 0;
642 /* create a new device info set and re-open the device */
643 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
645 SetupDiDestroyDeviceInfoList(dap
->CurrentDeviceInfoSet
);
648 dap
->ParentDevInst
= 0;
649 dap
->CurrentDeviceInfoSet
= SetupDiCreateDeviceInfoListEx(NULL
,
653 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
655 if (SetupDiOpenDeviceInfo(dap
->CurrentDeviceInfoSet
,
659 &dap
->CurrentDeviceInfoData
))
661 if (dap
->CloseDevInst
)
663 SetupDiDestroyDeviceInfoList(dap
->DeviceInfoSet
);
666 dap
->CloseDevInst
= TRUE
;
667 dap
->DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
668 dap
->DeviceInfoData
= dap
->CurrentDeviceInfoData
;
669 dap
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
677 /* get the parent node from the initial devinst */
678 CM_Get_Parent_Ex(&dap
->ParentDevInst
,
679 dap
->DeviceInfoData
.DevInst
,
684 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
686 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
687 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
691 DeviceInfoSet
= dap
->DeviceInfoSet
;
692 DeviceInfoData
= &dap
->DeviceInfoData
;
697 DeviceInfoSet
= dap
->DeviceInfoSet
;
698 DeviceInfoData
= &dap
->DeviceInfoData
;
701 dap
->HasDriverPage
= FALSE
;
702 dap
->HasResourcePage
= FALSE
;
703 dap
->HasPowerPage
= FALSE
;
704 if (IsDriverInstalled(DeviceInfoData
->DevInst
,
709 if (SetupDiCallClassInstaller((dap
->ShowRemotePages
?
710 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
711 DIF_ADDPROPERTYPAGE_ADVANCED
),
715 /* get install params */
716 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
717 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
,
722 InstallParams
.Flags
= 0;
725 dap
->HasDriverPage
= !(InstallParams
.Flags
& DI_DRIVERPAGE_ADDED
);
726 dap
->HasResourcePage
= !(InstallParams
.Flags
& DI_RESOURCEPAGE_ADDED
);
727 dap
->HasPowerPage
= !(InstallParams
.Flags
& DI_FLAGSEX_POWERPAGE_ADDED
);
731 /* get the device icon */
732 if (dap
->hDevIcon
!= NULL
)
734 DestroyIcon(dap
->hDevIcon
);
735 dap
->hDevIcon
= NULL
;
737 if (!SetupDiLoadClassIcon(&DeviceInfoData
->ClassGuid
,
741 dap
->hDevIcon
= NULL
;
744 /* get the device name */
745 if (GetDeviceDescriptionString(DeviceInfoSet
,
748 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
750 PropSheet_SetTitle(hPropSheetDlg
,
755 /* set the device image */
756 SendDlgItemMessage(hwndDlg
,
759 (WPARAM
)dap
->hDevIcon
,
762 /* set the device name edit control text */
763 SetDlgItemText(hwndDlg
,
767 /* set the device type edit control text */
768 if (GetDeviceTypeString(DeviceInfoData
,
770 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
772 SetDlgItemText(hwndDlg
,
777 /* set the device manufacturer edit control text */
778 if (GetDeviceManufacturerString(DeviceInfoSet
,
781 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
783 SetDlgItemText(hwndDlg
,
788 /* set the device location edit control text */
789 if (GetDeviceLocationString(DeviceInfoData
->DevInst
,
792 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
794 SetDlgItemText(hwndDlg
,
799 /* set the device status edit control text */
800 if (GetDeviceStatusString(DeviceInfoData
->DevInst
,
803 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
805 SetDlgItemText(hwndDlg
,
810 /* set the device troubleshoot button text and disable it if necessary */
811 hDevProbBtn
= GetDlgItem(hwndDlg
,
813 cr
= CM_Get_DevNode_Status_Ex(&Status
,
815 DeviceInfoData
->DevInst
,
818 if (cr
== CR_SUCCESS
&& (Status
& DN_HAS_PROBLEM
))
820 switch (ProblemNumber
)
822 case CM_PROB_DEVLOADER_FAILED
:
824 /* FIXME - only if it's not a root bus devloader,
825 disable the button otherwise */
826 TroubleShootStrId
= IDS_UPDATEDRV
;
830 case CM_PROB_OUT_OF_MEMORY
:
831 case CM_PROB_ENTRY_IS_WRONG_TYPE
:
832 case CM_PROB_LACKED_ARBITRATOR
:
833 case CM_PROB_FAILED_START
:
835 case CM_PROB_UNKNOWN_RESOURCE
:
837 TroubleShootStrId
= IDS_UPDATEDRV
;
841 case CM_PROB_BOOT_CONFIG_CONFLICT
:
842 case CM_PROB_NORMAL_CONFLICT
:
843 case CM_PROB_REENUMERATION
:
845 /* FIXME - Troubleshoot conflict */
849 case CM_PROB_FAILED_FILTER
:
850 case CM_PROB_REINSTALL
:
851 case CM_PROB_FAILED_INSTALL
:
853 TroubleShootStrId
= IDS_REINSTALLDRV
;
857 case CM_PROB_DEVLOADER_NOT_FOUND
:
860 1) if it's a missing system devloader:
861 - disable the button (Reinstall Driver)
862 2) if it's not a system devloader but still missing:
864 3) if it's not a system devloader but the file can be found:
866 4) if it's a missing or empty software key
872 case CM_PROB_INVALID_DATA
:
873 case CM_PROB_PARTIAL_LOG_CONF
:
874 case CM_PROB_NO_VALID_LOG_CONF
:
875 case CM_PROB_HARDWARE_DISABLED
:
876 case CM_PROB_CANT_SHARE_IRQ
:
877 case CM_PROB_TRANSLATION_FAILED
:
878 case CM_PROB_SYSTEM_SHUTDOWN
:
879 case CM_PROB_PHANTOM
:
880 bDevActionAvailable
= FALSE
;
883 case CM_PROB_NOT_VERIFIED
:
884 case CM_PROB_DEVICE_NOT_THERE
:
885 /* FIXME - search hardware */
888 case CM_PROB_NEED_RESTART
:
889 case CM_PROB_WILL_BE_REMOVED
:
891 case CM_PROB_TOO_EARLY
:
892 case CM_PROB_DISABLED_SERVICE
:
893 TroubleShootStrId
= IDS_REBOOT
;
896 case CM_PROB_REGISTRY
:
897 /* FIXME - check registry? */
900 case CM_PROB_DISABLED
:
901 /* if device was disabled by the user: */
902 TroubleShootStrId
= IDS_ENABLEDEV
;
903 /* FIXME - otherwise disable button because the device was
904 disabled by the system*/
907 case CM_PROB_DEVLOADER_NOT_READY
:
908 /* FIXME - if it's a graphics adapter:
909 - if it's a a secondary adapter and the main adapter
919 case CM_PROB_FAILED_ADD
:
920 TroubleShootStrId
= IDS_PROPERTIES
;
925 if (LoadString(hDllInstance
,
928 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])) != 0)
930 SetWindowText(hDevProbBtn
,
933 EnableWindow(hDevProbBtn
,
934 dap
->IsAdmin
&& bDevActionAvailable
);
936 /* check if the device can be enabled/disabled */
937 hDevUsage
= GetDlgItem(hwndDlg
,
940 dap
->CanDisable
= FALSE
;
941 dap
->DeviceStarted
= FALSE
;
943 if (CanDisableDevice(DeviceInfoData
->DevInst
,
947 dap
->CanDisable
= bFlag
;
950 if (IsDeviceStarted(DeviceInfoData
->DevInst
,
954 dap
->DeviceStarted
= bFlag
;
957 /* enable/disable the device usage controls */
958 EnableWindow(GetDlgItem(hwndDlg
,
960 dap
->CanDisable
&& dap
->IsAdmin
);
961 EnableWindow(hDevUsage
,
962 dap
->CanDisable
&& dap
->IsAdmin
);
964 /* clear the combobox */
965 SendMessage(hDevUsage
,
971 InitDevUsageActions(hwndDlg
,
976 /* find out how many new device property sheets to add.
977 fake a PROPSHEETHEADER structure, we don't plan to
978 call PropertySheet again!*/
979 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
983 /* get the number of device property sheets for the device */
984 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
989 dap
->PropertySheetType
) &&
990 nDriverPages
!= 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
992 dap
->nDevPropSheets
+= nDriverPages
;
999 /* include the driver page */
1000 if (dap
->HasDriverPage
)
1001 dap
->nDevPropSheets
++;
1003 /* add the device property sheets */
1004 if (dap
->nDevPropSheets
!= 0)
1006 dap
->DevPropSheets
= HeapAlloc(GetProcessHeap(),
1008 dap
->nDevPropSheets
* sizeof(HPROPSHEETPAGE
));
1009 if (dap
->DevPropSheets
!= NULL
)
1011 if (nDriverPages
!= 0)
1013 psh
.phpage
= dap
->DevPropSheets
;
1015 /* query the device property sheet pages to add */
1016 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
1019 dap
->nDevPropSheets
,
1021 dap
->PropertySheetType
))
1023 /* add the property sheets */
1025 iPage
!= nDriverPages
;
1028 if (PropSheet_AddPage(hPropSheetDlg
,
1029 dap
->DevPropSheets
[iPage
]))
1035 dap
->FreeDevPropSheets
= TRUE
;
1039 /* cleanup, we were unable to get the device property sheets */
1040 iPage
= nDriverPages
;
1041 dap
->nDevPropSheets
-= nDriverPages
;
1048 /* add the driver page if necessary */
1049 if (dap
->HasDriverPage
)
1051 PROPSHEETPAGE pspDriver
= {0};
1052 pspDriver
.dwSize
= sizeof(PROPSHEETPAGE
);
1053 pspDriver
.dwFlags
= PSP_DEFAULT
;
1054 pspDriver
.hInstance
= hDllInstance
;
1055 pspDriver
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEDRIVER
);
1056 pspDriver
.pfnDlgProc
= AdvProcDriverDlgProc
;
1057 pspDriver
.lParam
= (LPARAM
)dap
;
1058 dap
->DevPropSheets
[iPage
] = dap
->pCreatePropertySheetPageW(&pspDriver
);
1059 if (dap
->DevPropSheets
[iPage
] != NULL
)
1061 if (PropSheet_AddPage(hPropSheetDlg
,
1062 dap
->DevPropSheets
[iPage
]))
1069 dap
->pDestroyPropertySheetPage(dap
->DevPropSheets
[iPage
]);
1070 dap
->DevPropSheets
[iPage
] = NULL
;
1076 dap
->nDevPropSheets
= 0;
1081 PropSheet_RecalcPageSizes(hPropSheetDlg
);
1084 /* finally, disable the apply button */
1085 PropSheet_UnChanged(hPropSheetDlg
,
1087 dap
->DeviceUsageChanged
= FALSE
;
1093 DlgParentSubWndProc(IN HWND hwnd
,
1098 PDEVADVPROP_INFO dap
;
1100 dap
= (PDEVADVPROP_INFO
)GetProp(hwnd
,
1101 L
"DevMgrDevChangeSub");
1104 if (uMsg
== WM_DEVICECHANGE
&& !IsWindowVisible(dap
->hWndGeneralPage
))
1106 SendMessage(dap
->hWndGeneralPage
,
1112 /* pass the message the the old window proc */
1113 return CallWindowProc(dap
->ParentOldWndProc
,
1121 /* this is not a good idea if the subclassed window was an ansi
1122 window, but we failed finding out the previous window proc
1123 so we can't use CallWindowProc. This should rarely - if ever -
1126 return DefWindowProc(hwnd
,
1136 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
1141 PDEVADVPROP_INFO dap
;
1142 INT_PTR Ret
= FALSE
;
1144 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
1147 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
1153 switch (LOWORD(wParam
))
1157 if (HIWORD(wParam
) == CBN_SELCHANGE
)
1159 PropSheet_Changed(GetParent(hwndDlg
),
1161 dap
->DeviceUsageChanged
= TRUE
;
1166 case IDC_DEVPROBLEM
:
1170 /* display the device problem wizard */
1171 ShowDeviceProblemWizard(hwndDlg
,
1173 &dap
->DeviceInfoData
,
1184 NMHDR
*hdr
= (NMHDR
*)lParam
;
1188 ApplyGeneralSettings(hwndDlg
,
1197 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1202 dap
->hWndGeneralPage
= hwndDlg
;
1204 SetWindowLongPtr(hwndDlg
,
1208 /* subclass the parent window to always receive
1209 WM_DEVICECHANGE messages */
1210 hWndParent
= GetParent(hwndDlg
);
1211 if (hWndParent
!= NULL
)
1213 /* subclass the parent window. This is not safe
1214 if the parent window belongs to another thread! */
1215 dap
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
1217 (LONG_PTR
)DlgParentSubWndProc
);
1219 if (dap
->ParentOldWndProc
!= NULL
&&
1221 L
"DevMgrDevChangeSub",
1224 dap
->hWndParent
= hWndParent
;
1228 /* do not call UpdateDevInfo directly in here because it modifies
1229 the pages of the property sheet! */
1230 PostMessage(hwndDlg
,
1239 case WM_DEVICECHANGE
:
1241 /* FIXME - don't call UpdateDevInfo for all events */
1242 UpdateDevInfo(hwndDlg
,
1251 UpdateDevInfo(hwndDlg
,
1254 dap
->PageInitialized
= TRUE
;
1260 /* restore the old window proc of the subclassed parent window */
1261 if (dap
->hWndParent
!= NULL
&& dap
->ParentOldWndProc
!= NULL
)
1263 if (SetWindowLongPtr(dap
->hWndParent
,
1265 (LONG_PTR
)dap
->ParentOldWndProc
) == (LONG_PTR
)DlgParentSubWndProc
)
1267 RemoveProp(dap
->hWndParent
,
1268 L
"DevMgrDevChangeSub");
1281 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
1282 IN LPCWSTR lpDeviceID OPTIONAL
,
1283 IN HDEVINFO DeviceInfoSet
,
1284 IN PSP_DEVINFO_DATA DeviceInfoData
,
1285 IN HINSTANCE hComCtl32
,
1286 IN LPCWSTR lpMachineName
,
1289 PROPSHEETHEADER psh
= {0};
1290 PROPSHEETPAGE pspGeneral
= {0};
1291 PPROPERTYSHEETW pPropertySheetW
;
1292 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
1293 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
1294 PDEVADVPROP_INFO DevAdvPropInfo
;
1295 HMACHINE hMachine
= NULL
;
1296 DWORD DevIdSize
= 0;
1299 /* we don't want to statically link against comctl32, so find the
1300 functions we need dynamically */
1302 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
1304 pCreatePropertySheetPageW
=
1305 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
1306 "CreatePropertySheetPageW");
1307 pDestroyPropertySheetPage
=
1308 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
1309 "DestroyPropertySheetPage");
1310 if (pPropertySheetW
== NULL
||
1311 pCreatePropertySheetPageW
== NULL
||
1312 pDestroyPropertySheetPage
== NULL
)
1317 if (lpDeviceID
== NULL
)
1319 /* find out how much size is needed for the device id */
1320 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1326 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1330 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1337 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
1340 if (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0')
1342 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
1344 if (cr
!= CR_SUCCESS
)
1350 /* create the internal structure associated with the "General",
1351 "Driver", ... pages */
1352 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
1354 FIELD_OFFSET(DEVADVPROP_INFO
,
1356 (DevIdSize
* sizeof(WCHAR
)));
1357 if (DevAdvPropInfo
== NULL
)
1359 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1363 if (lpDeviceID
== NULL
)
1365 /* read the device instance id */
1366 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1368 DevAdvPropInfo
->szDeviceID
,
1377 /* copy the device instance id supplied by the caller */
1378 wcscpy(DevAdvPropInfo
->szDeviceID
,
1382 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
1383 DevAdvPropInfo
->DeviceInfoData
= *DeviceInfoData
;
1384 DevAdvPropInfo
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
1385 DevAdvPropInfo
->CurrentDeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1387 DevAdvPropInfo
->ShowRemotePages
= (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0');
1388 DevAdvPropInfo
->hMachine
= hMachine
;
1389 DevAdvPropInfo
->lpMachineName
= lpMachineName
;
1390 DevAdvPropInfo
->szDevName
[0] = L
'\0';
1391 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
1392 DevAdvPropInfo
->pCreatePropertySheetPageW
= pCreatePropertySheetPageW
;
1393 DevAdvPropInfo
->pDestroyPropertySheetPage
= pDestroyPropertySheetPage
;
1395 DevAdvPropInfo
->IsAdmin
= IsUserAdmin();
1396 DevAdvPropInfo
->DoDefaultDevAction
= ((dwFlags
& DPF_DEVICE_STATUS_ACTION
) != 0);
1398 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1399 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
1400 psh
.hwndParent
= hWndParent
;
1401 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
1403 DevAdvPropInfo
->PropertySheetType
= DevAdvPropInfo
->ShowRemotePages
?
1404 DIGCDP_FLAG_REMOTE_ADVANCED
:
1405 DIGCDP_FLAG_ADVANCED
;
1407 psh
.phpage
= HeapAlloc(GetProcessHeap(),
1409 1 * sizeof(HPROPSHEETPAGE
));
1410 if (psh
.phpage
== NULL
)
1415 /* add the "General" property sheet */
1416 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
1417 pspGeneral
.dwFlags
= PSP_DEFAULT
;
1418 pspGeneral
.hInstance
= hDllInstance
;
1419 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
1420 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
1421 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
1422 psh
.phpage
[psh
.nPages
] = pCreatePropertySheetPageW(&pspGeneral
);
1423 if (psh
.phpage
[psh
.nPages
] != NULL
)
1428 DevAdvPropInfo
->nDevPropSheets
= psh
.nPages
;
1430 if (psh
.nPages
!= 0)
1432 Ret
= pPropertySheetW(&psh
);
1434 /* NOTE: no need to destroy the property sheets anymore! */
1441 /* in case of failure the property sheets must be destroyed */
1442 if (psh
.phpage
!= NULL
)
1448 if (psh
.phpage
[i
] != NULL
)
1450 pDestroyPropertySheetPage(psh
.phpage
[i
]);
1456 if (DevAdvPropInfo
!= NULL
)
1458 if (DevAdvPropInfo
->FreeDevPropSheets
)
1460 /* don't free the array if it's the one allocated in
1461 DisplayDeviceAdvancedProperties */
1462 HeapFree(GetProcessHeap(),
1464 DevAdvPropInfo
->DevPropSheets
);
1467 if (DevAdvPropInfo
->CloseDevInst
)
1469 /* close the device info set in case a new one was created */
1470 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->DeviceInfoSet
);
1473 if (DevAdvPropInfo
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
1475 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->CurrentDeviceInfoSet
);
1478 if (DevAdvPropInfo
->hDevIcon
!= NULL
)
1480 DestroyIcon(DevAdvPropInfo
->hDevIcon
);
1483 HeapFree(GetProcessHeap(),
1488 if (psh
.phpage
!= NULL
)
1490 HeapFree(GetProcessHeap(),
1495 if (hMachine
!= NULL
)
1497 CM_Disconnect_Machine(hMachine
);
1504 /***************************************************************************
1506 * DeviceAdvancedPropertiesW
1509 * Invokes the device properties dialog, this version may add some property pages
1513 * hWndParent: Handle to the parent window
1514 * lpMachineName: Machine Name, NULL is the local machine
1515 * lpDeviceID: Specifies the device whose properties are to be shown
1518 * Always returns -1, a call to GetLastError returns 0 if successful
1524 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL
,
1525 IN LPCWSTR lpMachineName OPTIONAL
,
1526 IN LPCWSTR lpDeviceID
)
1529 SP_DEVINFO_DATA DevInfoData
;
1530 HINSTANCE hComCtl32
;
1533 if (lpDeviceID
== NULL
)
1535 SetLastError(ERROR_INVALID_PARAMETER
);
1539 /* dynamically load comctl32 */
1540 hComCtl32
= LoadAndInitComctl32();
1541 if (hComCtl32
!= NULL
)
1543 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1547 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1549 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1550 if (SetupDiOpenDeviceInfo(hDevInfo
,
1556 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1565 SetupDiDestroyDeviceInfoList(hDevInfo
);
1568 FreeLibrary(hComCtl32
);
1575 /***************************************************************************
1577 * DeviceAdvancedPropertiesA
1580 * Invokes the device properties dialog, this version may add some property pages
1584 * hWndParent: Handle to the parent window
1585 * lpMachineName: Machine Name, NULL is the local machine
1586 * lpDeviceID: Specifies the device whose properties are to be shown
1589 * Always returns -1, a call to GetLastError returns 0 if successful
1595 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL
,
1596 IN LPCSTR lpMachineName OPTIONAL
,
1597 IN LPCSTR lpDeviceID
)
1599 LPWSTR lpMachineNameW
= NULL
;
1600 LPWSTR lpDeviceIDW
= NULL
;
1603 if (lpMachineName
!= NULL
)
1605 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1611 if (lpDeviceID
!= NULL
)
1613 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1620 Ret
= DeviceAdvancedPropertiesW(hWndParent
,
1625 if (lpMachineNameW
!= NULL
)
1627 HeapFree(GetProcessHeap(),
1631 if (lpDeviceIDW
!= NULL
)
1633 HeapFree(GetProcessHeap(),
1642 /***************************************************************************
1644 * DevicePropertiesExA
1647 * Invokes the extended device properties dialog
1650 * hWndParent: Handle to the parent window
1651 * lpMachineName: Machine Name, NULL is the local machine
1652 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1653 * bShowDevMgr is nonzero
1654 * dwFlags: This parameter can be a combination of the following flags:
1655 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1656 * the default device status action button
1657 * to be clicked (Troubleshoot, Enable
1659 * bShowDevMgr: If non-zero it displays the device manager instead of
1660 * the advanced device property dialog
1663 * 1: if bShowDevMgr is non-zero and no error occured
1664 * -1: a call to GetLastError returns 0 if successful
1670 DevicePropertiesExA(IN HWND hWndParent OPTIONAL
,
1671 IN LPCSTR lpMachineName OPTIONAL
,
1672 IN LPCSTR lpDeviceID OPTIONAL
,
1673 IN DWORD dwFlags OPTIONAL
,
1674 IN BOOL bShowDevMgr
)
1676 LPWSTR lpMachineNameW
= NULL
;
1677 LPWSTR lpDeviceIDW
= NULL
;
1680 if (lpMachineName
!= NULL
)
1682 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1688 if (lpDeviceID
!= NULL
)
1690 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1697 Ret
= DevicePropertiesExW(hWndParent
,
1704 if (lpMachineNameW
!= NULL
)
1706 HeapFree(GetProcessHeap(),
1710 if (lpDeviceIDW
!= NULL
)
1712 HeapFree(GetProcessHeap(),
1721 /***************************************************************************
1723 * DevicePropertiesExW
1726 * Invokes the extended device properties dialog
1729 * hWndParent: Handle to the parent window
1730 * lpMachineName: Machine Name, NULL is the local machine
1731 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1732 * bShowDevMgr is nonzero
1733 * dwFlags: This parameter can be a combination of the following flags:
1734 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1735 * the default device status action button
1736 * to be clicked (Troubleshoot, Enable
1738 * bShowDevMgr: If non-zero it displays the device manager instead of
1739 * the advanced device property dialog
1742 * 1: if bShowDevMgr is non-zero and no error occured
1743 * -1: a call to GetLastError returns 0 if successful
1749 DevicePropertiesExW(IN HWND hWndParent OPTIONAL
,
1750 IN LPCWSTR lpMachineName OPTIONAL
,
1751 IN LPCWSTR lpDeviceID OPTIONAL
,
1752 IN DWORD dwFlags OPTIONAL
,
1753 IN BOOL bShowDevMgr
)
1757 if (dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
))
1759 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1760 dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
));
1761 SetLastError(ERROR_INVALID_FLAGS
);
1767 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1768 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1773 SP_DEVINFO_DATA DevInfoData
;
1774 HINSTANCE hComCtl32
;
1776 if (lpDeviceID
== NULL
)
1778 SetLastError(ERROR_INVALID_PARAMETER
);
1782 /* dynamically load comctl32 */
1783 hComCtl32
= LoadAndInitComctl32();
1784 if (hComCtl32
!= NULL
)
1786 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1790 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1792 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1793 if (SetupDiOpenDeviceInfo(hDevInfo
,
1799 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1808 SetupDiDestroyDeviceInfoList(hDevInfo
);
1811 FreeLibrary(hComCtl32
);