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
);
44 typedef struct _DEVADVPROP_INFO
48 WNDPROC ParentOldWndProc
;
50 HDEVINFO DeviceInfoSet
;
51 SP_DEVINFO_DATA DeviceInfoData
;
52 HDEVINFO CurrentDeviceInfoSet
;
53 SP_DEVINFO_DATA CurrentDeviceInfoData
;
54 DEVINST ParentDevInst
;
56 LPCWSTR lpMachineName
;
60 DWORD PropertySheetType
;
62 HPROPSHEETPAGE
*DevPropSheets
;
64 BOOL FreeDevPropSheets
: 1;
66 BOOL DeviceEnabled
: 1;
67 BOOL DeviceUsageChanged
: 1;
68 BOOL CloseDevInst
: 1;
70 BOOL DoDefaultDevAction
: 1;
75 /* struct may be dynamically expanded here! */
76 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
80 InitDevUsageActions(IN HWND hwndDlg
,
82 IN PDEVADVPROP_INFO dap
)
89 DEVENABLEACTION Action
;
92 {IDS_ENABLEDEVICE
, DEA_ENABLE
},
93 {IDS_DISABLEDEVICE
, DEA_DISABLE
},
97 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
100 /* fill in the device usage combo box */
101 if (LoadString(hDllInstance
,
104 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
106 Index
= (INT
)SendMessage(hComboBox
,
109 (LPARAM
)dap
->szTemp
);
112 SendMessage(hComboBox
,
115 (LPARAM
)Actions
[i
].Action
);
117 switch (Actions
[i
].Action
)
120 if (dap
->DeviceEnabled
)
122 SendMessage(hComboBox
,
130 if (!dap
->DeviceEnabled
)
132 SendMessage(hComboBox
,
148 static DEVENABLEACTION
149 GetSelectedUsageAction(IN HWND hComboBox
)
152 DEVENABLEACTION Ret
= DEA_UNKNOWN
;
154 Index
= (INT
)SendMessage(hComboBox
,
160 INT iRet
= SendMessage(hComboBox
,
164 if (iRet
!= CB_ERR
&& iRet
< (INT
)DEA_UNKNOWN
)
166 Ret
= (DEVENABLEACTION
)iRet
;
175 ApplyGeneralSettings(IN HWND hwndDlg
,
176 IN PDEVADVPROP_INFO dap
)
178 if (dap
->DeviceUsageChanged
&& dap
->IsAdmin
)
180 DEVENABLEACTION SelectedUsageAction
;
182 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
184 if (SelectedUsageAction
!= DEA_UNKNOWN
)
186 switch (SelectedUsageAction
)
189 if (!dap
->DeviceEnabled
)
191 /* FIXME - enable device */
196 if (dap
->DeviceEnabled
)
198 /* FIXME - disable device */
208 /* disable the apply button */
209 PropSheet_UnChanged(GetParent(hwndDlg
),
211 dap
->DeviceUsageChanged
= FALSE
;
216 UpdateDevInfo(IN HWND hwndDlg
,
217 IN PDEVADVPROP_INFO dap
,
221 HWND hDevUsage
, hPropSheetDlg
, hDevProbBtn
;
223 ULONG Status
, ProblemNumber
;
224 UINT TroubleShootStrId
= IDS_TROUBLESHOOTDEV
;
227 HDEVINFO DeviceInfoSet
= NULL
;
228 PSP_DEVINFO_DATA DeviceInfoData
= NULL
;
230 hPropSheetDlg
= GetParent(hwndDlg
);
236 /* switch to the General page */
237 PropSheet_SetCurSelByID(hPropSheetDlg
,
240 /* remove and destroy the existing device property sheet pages */
242 i
!= dap
->nDevPropSheets
;
245 PropSheet_RemovePage(hPropSheetDlg
,
247 dap
->DevPropSheets
[i
]);
250 if (dap
->FreeDevPropSheets
)
252 /* don't free the array if it's the one allocated in
253 DisplayDeviceAdvancedProperties */
254 HeapFree(GetProcessHeap(),
258 dap
->FreeDevPropSheets
= FALSE
;
261 dap
->DevPropSheets
= NULL
;
262 dap
->nDevPropSheets
= 0;
264 /* create a new device info set and re-open the device */
265 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
267 SetupDiDestroyDeviceInfoList(dap
->CurrentDeviceInfoSet
);
270 dap
->ParentDevInst
= 0;
271 dap
->CurrentDeviceInfoSet
= SetupDiCreateDeviceInfoListEx(NULL
,
275 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
277 if (SetupDiOpenDeviceInfo(dap
->CurrentDeviceInfoSet
,
281 &dap
->CurrentDeviceInfoData
))
283 if (dap
->CloseDevInst
)
285 SetupDiDestroyDeviceInfoList(dap
->DeviceInfoSet
);
288 dap
->CloseDevInst
= TRUE
;
289 dap
->DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
290 dap
->DeviceInfoData
= dap
->CurrentDeviceInfoData
;
291 dap
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
299 /* get the parent node from the initial devinst */
300 CM_Get_Parent_Ex(&dap
->ParentDevInst
,
301 dap
->DeviceInfoData
.DevInst
,
306 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
308 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
309 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
313 DeviceInfoSet
= dap
->DeviceInfoSet
;
314 DeviceInfoData
= &dap
->DeviceInfoData
;
317 /* find out how many new device property sheets to add.
318 fake a PROPSHEETHEADER structure, we don't plan to
319 call PropertySheet again!*/
320 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
324 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
328 &dap
->nDevPropSheets
,
329 dap
->PropertySheetType
) &&
330 dap
->nDevPropSheets
!= 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
332 dap
->DevPropSheets
= HeapAlloc(GetProcessHeap(),
334 dap
->nDevPropSheets
* sizeof(HPROPSHEETPAGE
));
335 if (dap
->DevPropSheets
!= NULL
)
337 psh
.phpage
= dap
->DevPropSheets
;
339 /* query the new property sheet pages to add */
340 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
345 dap
->PropertySheetType
))
347 /* add the property sheets */
350 i
!= dap
->nDevPropSheets
;
353 PropSheet_AddPage(hPropSheetDlg
,
354 dap
->DevPropSheets
[i
]);
357 dap
->FreeDevPropSheets
= TRUE
;
361 /* cleanup, we were unable to get the device property sheets */
362 HeapFree(GetProcessHeap(),
366 dap
->nDevPropSheets
= 0;
367 dap
->DevPropSheets
= NULL
;
371 dap
->nDevPropSheets
= 0;
376 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
378 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
379 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
383 DeviceInfoSet
= dap
->DeviceInfoSet
;
384 DeviceInfoData
= &dap
->DeviceInfoData
;
388 /* get the device name */
389 if (GetDeviceDescriptionString(DeviceInfoSet
,
392 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
394 PropSheet_SetTitle(GetParent(hwndDlg
),
399 /* set the device image */
400 if (SetupDiLoadClassIcon(&DeviceInfoData
->ClassGuid
,
404 HICON hOldIcon
= (HICON
)SendDlgItemMessage(hwndDlg
,
409 if (hOldIcon
!= NULL
)
411 DestroyIcon(hOldIcon
);
415 /* set the device name edit control text */
416 SetDlgItemText(hwndDlg
,
420 /* set the device type edit control text */
421 if (GetDeviceTypeString(DeviceInfoData
,
423 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
425 SetDlgItemText(hwndDlg
,
430 /* set the device manufacturer edit control text */
431 if (GetDeviceManufacturerString(DeviceInfoSet
,
434 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
436 SetDlgItemText(hwndDlg
,
441 /* set the device location edit control text */
442 if (GetDeviceLocationString(DeviceInfoData
->DevInst
,
445 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
447 SetDlgItemText(hwndDlg
,
452 /* set the device status edit control text */
453 if (GetDeviceStatusString(DeviceInfoData
->DevInst
,
456 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
458 SetDlgItemText(hwndDlg
,
463 /* set the device troubleshoot button text and disable it if necessary */
464 hDevProbBtn
= GetDlgItem(hwndDlg
,
466 EnableWindow(hDevProbBtn
,
468 cr
= CM_Get_DevNode_Status_Ex(&Status
,
470 DeviceInfoData
->DevInst
,
473 if (cr
== CR_SUCCESS
&&
474 (Status
& DN_HAS_PROBLEM
) && ProblemNumber
== CM_PROB_DISABLED
)
476 TroubleShootStrId
= IDS_ENABLEDEV
;
479 if (LoadString(hDllInstance
,
482 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])) != 0)
484 SetWindowText(hDevProbBtn
,
488 /* check if the device can be enabled/disabled */
489 hDevUsage
= GetDlgItem(hwndDlg
,
492 dap
->CanDisable
= FALSE
;
493 dap
->DeviceEnabled
= FALSE
;
495 if (CanDisableDevice(DeviceInfoData
->DevInst
,
499 dap
->CanDisable
= bFlag
;
502 if (IsDeviceEnabled(DeviceInfoData
->DevInst
,
506 dap
->DeviceEnabled
= bFlag
;
509 /* enable/disable the device usage controls */
510 EnableWindow(GetDlgItem(hwndDlg
,
512 dap
->CanDisable
&& dap
->IsAdmin
);
513 EnableWindow(hDevUsage
,
514 dap
->CanDisable
&& dap
->IsAdmin
);
516 /* clear the combobox */
517 SendMessage(hDevUsage
,
523 InitDevUsageActions(hwndDlg
,
528 /* finally, disable the apply button */
529 PropSheet_UnChanged(hPropSheetDlg
,
531 dap
->DeviceUsageChanged
= FALSE
;
537 DlgParentSubWndProc(IN HWND hwnd
,
542 PDEVADVPROP_INFO dap
;
544 dap
= (PDEVADVPROP_INFO
)GetProp(hwnd
,
545 L
"DevMgrDevChangeSub");
548 if (uMsg
== WM_DEVICECHANGE
&& !IsWindowVisible(dap
->hWndGeneralPage
))
550 SendMessage(dap
->hWndGeneralPage
,
556 /* pass the message the the old window proc */
557 return CallWindowProc(dap
->ParentOldWndProc
,
565 /* this is not a good idea if the subclassed window was an ansi
566 window, but we failed finding out the previous window proc
567 so we can't use CallWindowProc. This should rarely - if ever -
570 return DefWindowProc(hwnd
,
580 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
585 PDEVADVPROP_INFO dap
;
588 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
591 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
597 switch (LOWORD(wParam
))
601 if (HIWORD(wParam
) == CBN_SELCHANGE
)
603 PropSheet_Changed(GetParent(hwndDlg
),
605 dap
->DeviceUsageChanged
= TRUE
;
614 /* display the device problem wizard */
615 ShowDeviceProblemWizard(hwndDlg
,
617 &dap
->DeviceInfoData
,
628 NMHDR
*hdr
= (NMHDR
*)lParam
;
632 ApplyGeneralSettings(hwndDlg
,
641 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
646 dap
->hWndGeneralPage
= hwndDlg
;
648 SetWindowLongPtr(hwndDlg
,
652 /* subclass the parent window to always receive
653 WM_DEVICECHANGE messages */
654 hWndParent
= GetParent(hwndDlg
);
655 if (hWndParent
!= NULL
)
657 /* subclass the parent window. This is not safe
658 if the parent window belongs to another thread! */
659 dap
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
661 (LONG_PTR
)DlgParentSubWndProc
);
663 if (dap
->ParentOldWndProc
!= NULL
&&
665 L
"DevMgrDevChangeSub",
668 dap
->hWndParent
= hWndParent
;
672 UpdateDevInfo(hwndDlg
,
680 case WM_DEVICECHANGE
:
682 /* FIXME - don't call UpdateDevInfo for all events */
683 UpdateDevInfo(hwndDlg
,
694 /* restore the old window proc of the subclassed parent window */
695 if (dap
->hWndParent
!= NULL
&& dap
->ParentOldWndProc
!= NULL
)
697 SetWindowLongPtr(dap
->hWndParent
,
699 (LONG_PTR
)dap
->ParentOldWndProc
);
702 /* destroy the device icon */
703 hDevIcon
= (HICON
)SendDlgItemMessage(hwndDlg
,
708 if (hDevIcon
!= NULL
)
710 DestroyIcon(hDevIcon
);
722 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
723 IN LPCWSTR lpDeviceID OPTIONAL
,
724 IN HDEVINFO DeviceInfoSet
,
725 IN PSP_DEVINFO_DATA DeviceInfoData
,
726 IN HINSTANCE hComCtl32
,
727 IN LPCWSTR lpMachineName
,
730 PROPSHEETHEADER psh
= {0};
731 PROPSHEETPAGE pspGeneral
= {0};
732 DWORD nPropSheets
= 0;
733 PPROPERTYSHEETW pPropertySheetW
;
734 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
735 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
736 PDEVADVPROP_INFO DevAdvPropInfo
;
737 HMACHINE hMachine
= NULL
;
741 /* we don't want to statically link against comctl32, so find the
742 functions we need dynamically */
744 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
746 pCreatePropertySheetPageW
=
747 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
748 "CreatePropertySheetPageW");
749 pDestroyPropertySheetPage
=
750 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
751 "DestroyPropertySheetPage");
752 if (pPropertySheetW
== NULL
||
753 pCreatePropertySheetPageW
== NULL
||
754 pDestroyPropertySheetPage
== NULL
)
759 if (lpDeviceID
== NULL
)
761 /* find out how much size is needed for the device id */
762 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
768 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
772 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
779 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
782 if (lpMachineName
!= NULL
)
784 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
786 if (cr
!= CR_SUCCESS
)
792 /* create the internal structure associated with the "General",
793 "Driver", ... pages */
794 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
796 FIELD_OFFSET(DEVADVPROP_INFO
,
798 (DevIdSize
* sizeof(WCHAR
)));
799 if (DevAdvPropInfo
== NULL
)
801 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
805 if (lpDeviceID
== NULL
)
807 /* read the device instance id */
808 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
810 DevAdvPropInfo
->szDeviceID
,
819 /* copy the device instance id supplied by the caller */
820 wcscpy(DevAdvPropInfo
->szDeviceID
,
824 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
825 DevAdvPropInfo
->DeviceInfoData
= *DeviceInfoData
;
826 DevAdvPropInfo
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
827 DevAdvPropInfo
->CurrentDeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
829 DevAdvPropInfo
->hMachine
= hMachine
;
830 DevAdvPropInfo
->lpMachineName
= lpMachineName
;
831 DevAdvPropInfo
->szDevName
[0] = L
'\0';
832 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
834 DevAdvPropInfo
->IsAdmin
= IsUserAdmin();
835 DevAdvPropInfo
->DoDefaultDevAction
= ((dwFlags
& DPF_DEVICE_STATUS_ACTION
) != 0);
837 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
838 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
839 psh
.hwndParent
= hWndParent
;
840 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
842 DevAdvPropInfo
->PropertySheetType
= lpMachineName
!= NULL
?
843 DIGCDP_FLAG_REMOTE_ADVANCED
:
844 DIGCDP_FLAG_ADVANCED
;
846 /* find out how many property sheets we need */
847 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
848 &DevAdvPropInfo
->DeviceInfoData
,
852 DevAdvPropInfo
->PropertySheetType
) &&
855 DPRINT1("SetupDiGetClassDevPropertySheets unexpectedly returned TRUE!\n");
859 if (nPropSheets
!= 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
864 psh
.phpage
= HeapAlloc(GetProcessHeap(),
866 (nPropSheets
+ 1) * sizeof(HPROPSHEETPAGE
));
867 if (psh
.phpage
== NULL
)
872 /* add the "General" property sheet */
873 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
874 pspGeneral
.dwFlags
= PSP_DEFAULT
;
875 pspGeneral
.hInstance
= hDllInstance
;
876 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
877 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
878 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
879 psh
.phpage
[0] = pCreatePropertySheetPageW(&pspGeneral
);
880 if (psh
.phpage
[0] != NULL
)
885 DevAdvPropInfo
->nDevPropSheets
= nPropSheets
;
887 if (nPropSheets
!= 0)
889 DevAdvPropInfo
->DevPropSheets
= psh
.phpage
+ psh
.nPages
;
891 /* create the device property sheets */
892 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
893 &DevAdvPropInfo
->DeviceInfoData
,
895 nPropSheets
+ psh
.nPages
,
897 DevAdvPropInfo
->PropertySheetType
))
903 /* FIXME - add the "Driver" property sheet if necessary */
907 Ret
= pPropertySheetW(&psh
);
909 /* NOTE: no need to destroy the property sheets anymore! */
916 /* in case of failure the property sheets must be destroyed */
917 if (psh
.phpage
!= NULL
)
923 if (psh
.phpage
[i
] != NULL
)
925 pDestroyPropertySheetPage(psh
.phpage
[i
]);
931 if (DevAdvPropInfo
!= NULL
)
933 if (DevAdvPropInfo
->FreeDevPropSheets
)
935 /* don't free the array if it's the one allocated in
936 DisplayDeviceAdvancedProperties */
937 HeapFree(GetProcessHeap(),
939 DevAdvPropInfo
->DevPropSheets
);
942 if (DevAdvPropInfo
->CloseDevInst
)
944 /* close the device info set in case a new one was created */
945 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->DeviceInfoSet
);
948 if (DevAdvPropInfo
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
950 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->CurrentDeviceInfoSet
);
953 HeapFree(GetProcessHeap(),
958 if (psh
.phpage
!= NULL
)
960 HeapFree(GetProcessHeap(),
965 if (hMachine
!= NULL
)
967 CM_Disconnect_Machine(hMachine
);
974 /***************************************************************************
976 * DeviceAdvancedPropertiesW
979 * Invokes the device properties dialog, this version may add some property pages
983 * hWndParent: Handle to the parent window
984 * lpMachineName: Machine Name, NULL is the local machine
985 * lpDeviceID: Specifies the device whose properties are to be shown
988 * Always returns -1, a call to GetLastError returns 0 if successful
994 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL
,
995 IN LPCWSTR lpMachineName OPTIONAL
,
996 IN LPCWSTR lpDeviceID
)
999 SP_DEVINFO_DATA DevInfoData
;
1000 HINSTANCE hComCtl32
;
1003 if (lpDeviceID
== NULL
)
1005 SetLastError(ERROR_INVALID_PARAMETER
);
1009 /* dynamically load comctl32 */
1010 hComCtl32
= LoadAndInitComctl32();
1011 if (hComCtl32
!= NULL
)
1013 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1017 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1019 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1020 if (SetupDiOpenDeviceInfo(hDevInfo
,
1026 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1035 SetupDiDestroyDeviceInfoList(hDevInfo
);
1038 FreeLibrary(hComCtl32
);
1045 /***************************************************************************
1047 * DeviceAdvancedPropertiesA
1050 * Invokes the device properties dialog, this version may add some property pages
1054 * hWndParent: Handle to the parent window
1055 * lpMachineName: Machine Name, NULL is the local machine
1056 * lpDeviceID: Specifies the device whose properties are to be shown
1059 * Always returns -1, a call to GetLastError returns 0 if successful
1065 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL
,
1066 IN LPCSTR lpMachineName OPTIONAL
,
1067 IN LPCSTR lpDeviceID
)
1069 LPWSTR lpMachineNameW
= NULL
;
1070 LPWSTR lpDeviceIDW
= NULL
;
1073 if (lpMachineName
!= NULL
)
1075 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1081 if (lpDeviceID
!= NULL
)
1083 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1090 Ret
= DeviceAdvancedPropertiesW(hWndParent
,
1095 if (lpMachineNameW
!= NULL
)
1097 HeapFree(GetProcessHeap(),
1101 if (lpDeviceIDW
!= NULL
)
1103 HeapFree(GetProcessHeap(),
1112 /***************************************************************************
1114 * DevicePropertiesExA
1117 * Invokes the extended device properties dialog
1120 * hWndParent: Handle to the parent window
1121 * lpMachineName: Machine Name, NULL is the local machine
1122 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1123 * bShowDevMgr is nonzero
1124 * dwFlags: This parameter can be a combination of the following flags:
1125 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1126 * the default device status action button
1127 * to be clicked (Troubleshoot, Enable
1129 * bShowDevMgr: If non-zero it displays the device manager instead of
1130 * the advanced device property dialog
1133 * 1: if bShowDevMgr is non-zero and no error occured
1134 * -1: a call to GetLastError returns 0 if successful
1140 DevicePropertiesExA(IN HWND hWndParent OPTIONAL
,
1141 IN LPCSTR lpMachineName OPTIONAL
,
1142 IN LPCSTR lpDeviceID OPTIONAL
,
1143 IN DWORD dwFlags OPTIONAL
,
1144 IN BOOL bShowDevMgr
)
1146 LPWSTR lpMachineNameW
= NULL
;
1147 LPWSTR lpDeviceIDW
= NULL
;
1150 if (lpMachineName
!= NULL
)
1152 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1158 if (lpDeviceID
!= NULL
)
1160 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1167 Ret
= DevicePropertiesExW(hWndParent
,
1174 if (lpMachineNameW
!= NULL
)
1176 HeapFree(GetProcessHeap(),
1180 if (lpDeviceIDW
!= NULL
)
1182 HeapFree(GetProcessHeap(),
1191 /***************************************************************************
1193 * DevicePropertiesExW
1196 * Invokes the extended device properties dialog
1199 * hWndParent: Handle to the parent window
1200 * lpMachineName: Machine Name, NULL is the local machine
1201 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1202 * bShowDevMgr is nonzero
1203 * dwFlags: This parameter can be a combination of the following flags:
1204 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1205 * the default device status action button
1206 * to be clicked (Troubleshoot, Enable
1208 * bShowDevMgr: If non-zero it displays the device manager instead of
1209 * the advanced device property dialog
1212 * 1: if bShowDevMgr is non-zero and no error occured
1213 * -1: a call to GetLastError returns 0 if successful
1219 DevicePropertiesExW(IN HWND hWndParent OPTIONAL
,
1220 IN LPCWSTR lpMachineName OPTIONAL
,
1221 IN LPCWSTR lpDeviceID OPTIONAL
,
1222 IN DWORD dwFlags OPTIONAL
,
1223 IN BOOL bShowDevMgr
)
1227 if (dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
))
1229 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1230 dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
));
1231 SetLastError(ERROR_INVALID_FLAGS
);
1237 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1238 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1243 SP_DEVINFO_DATA DevInfoData
;
1244 HINSTANCE hComCtl32
;
1246 if (lpDeviceID
== NULL
)
1248 SetLastError(ERROR_INVALID_PARAMETER
);
1252 /* dynamically load comctl32 */
1253 hComCtl32
= LoadAndInitComctl32();
1254 if (hComCtl32
!= NULL
)
1256 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1260 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1262 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1263 if (SetupDiOpenDeviceInfo(hDevInfo
,
1269 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1278 SetupDiDestroyDeviceInfoList(hDevInfo
);
1281 FreeLibrary(hComCtl32
);