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
;
43 HDEVINFO DeviceInfoSet
;
44 SP_DEVINFO_DATA DeviceInfoData
;
45 HDEVINFO CurrentDeviceInfoSet
;
46 SP_DEVINFO_DATA CurrentDeviceInfoData
;
47 DEVINST ParentDevInst
;
49 LPCWSTR lpMachineName
;
53 DWORD PropertySheetType
;
55 HPROPSHEETPAGE
*DevPropSheets
;
57 BOOL FreeDevPropSheets
: 1;
59 BOOL DeviceStarted
: 1;
60 BOOL DeviceUsageChanged
: 1;
61 BOOL CloseDevInst
: 1;
63 BOOL DoDefaultDevAction
: 1;
68 /* struct may be dynamically expanded here! */
69 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
73 InitDevUsageActions(IN HWND hwndDlg
,
75 IN PDEVADVPROP_INFO dap
)
86 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
89 /* fill in the device usage combo box */
90 if (LoadString(hDllInstance
,
93 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
95 Index
= (INT
)SendMessage(hComboBox
,
101 SendMessage(hComboBox
,
108 case IDS_ENABLEDEVICE
:
109 if (dap
->DeviceStarted
)
111 SendMessage(hComboBox
,
118 case IDS_DISABLEDEVICE
:
119 if (!dap
->DeviceStarted
)
121 SendMessage(hComboBox
,
138 GetSelectedUsageAction(IN HWND hComboBox
)
143 Index
= (INT
)SendMessage(hComboBox
,
149 INT iRet
= SendMessage(hComboBox
,
164 ApplyGeneralSettings(IN HWND hwndDlg
,
165 IN PDEVADVPROP_INFO dap
)
169 if (dap
->DeviceUsageChanged
&& dap
->IsAdmin
&& dap
->CanDisable
)
171 UINT SelectedUsageAction
;
172 BOOL NeedReboot
= FALSE
;
174 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
176 switch (SelectedUsageAction
)
178 case IDS_ENABLEDEVICE
:
179 if (!dap
->DeviceStarted
)
181 Ret
= EnableDevice(dap
->DeviceInfoSet
,
182 &dap
->DeviceInfoData
,
189 case IDS_DISABLEDEVICE
:
190 if (dap
->DeviceStarted
)
192 Ret
= EnableDevice(dap
->DeviceInfoSet
,
193 &dap
->DeviceInfoData
,
208 /* make PropertySheet() return PSM_REBOOTSYSTEM */
209 PropSheet_RebootSystem(hwndDlg
);
214 /* FIXME - display an error message */
215 DPRINT1("Failed to enable/disable device! LastError: %d\n",
220 Ret
= !dap
->DeviceUsageChanged
;
222 /* disable the apply button */
223 PropSheet_UnChanged(GetParent(hwndDlg
),
225 dap
->DeviceUsageChanged
= FALSE
;
231 UpdateDevInfo(IN HWND hwndDlg
,
232 IN PDEVADVPROP_INFO dap
,
236 HWND hDevUsage
, hPropSheetDlg
, hDevProbBtn
;
238 ULONG Status
, ProblemNumber
;
239 UINT TroubleShootStrId
= IDS_TROUBLESHOOTDEV
;
240 BOOL bFlag
, bDevActionAvailable
= TRUE
;
242 HDEVINFO DeviceInfoSet
= NULL
;
243 PSP_DEVINFO_DATA DeviceInfoData
= NULL
;
245 hPropSheetDlg
= GetParent(hwndDlg
);
251 /* switch to the General page */
252 PropSheet_SetCurSelByID(hPropSheetDlg
,
255 /* remove and destroy the existing device property sheet pages */
257 i
!= dap
->nDevPropSheets
;
260 PropSheet_RemovePage(hPropSheetDlg
,
262 dap
->DevPropSheets
[i
]);
265 if (dap
->FreeDevPropSheets
)
267 /* don't free the array if it's the one allocated in
268 DisplayDeviceAdvancedProperties */
269 HeapFree(GetProcessHeap(),
273 dap
->FreeDevPropSheets
= FALSE
;
276 dap
->DevPropSheets
= NULL
;
277 dap
->nDevPropSheets
= 0;
279 /* create a new device info set and re-open the device */
280 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
282 SetupDiDestroyDeviceInfoList(dap
->CurrentDeviceInfoSet
);
285 dap
->ParentDevInst
= 0;
286 dap
->CurrentDeviceInfoSet
= SetupDiCreateDeviceInfoListEx(NULL
,
290 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
292 if (SetupDiOpenDeviceInfo(dap
->CurrentDeviceInfoSet
,
296 &dap
->CurrentDeviceInfoData
))
298 if (dap
->CloseDevInst
)
300 SetupDiDestroyDeviceInfoList(dap
->DeviceInfoSet
);
303 dap
->CloseDevInst
= TRUE
;
304 dap
->DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
305 dap
->DeviceInfoData
= dap
->CurrentDeviceInfoData
;
306 dap
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
314 /* get the parent node from the initial devinst */
315 CM_Get_Parent_Ex(&dap
->ParentDevInst
,
316 dap
->DeviceInfoData
.DevInst
,
321 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
323 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
324 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
328 DeviceInfoSet
= dap
->DeviceInfoSet
;
329 DeviceInfoData
= &dap
->DeviceInfoData
;
332 /* find out how many new device property sheets to add.
333 fake a PROPSHEETHEADER structure, we don't plan to
334 call PropertySheet again!*/
335 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
339 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
343 &dap
->nDevPropSheets
,
344 dap
->PropertySheetType
) &&
345 dap
->nDevPropSheets
!= 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
347 dap
->DevPropSheets
= HeapAlloc(GetProcessHeap(),
349 dap
->nDevPropSheets
* sizeof(HPROPSHEETPAGE
));
350 if (dap
->DevPropSheets
!= NULL
)
352 psh
.phpage
= dap
->DevPropSheets
;
354 /* query the new property sheet pages to add */
355 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
360 dap
->PropertySheetType
))
362 /* add the property sheets */
365 i
!= dap
->nDevPropSheets
;
368 PropSheet_AddPage(hPropSheetDlg
,
369 dap
->DevPropSheets
[i
]);
372 dap
->FreeDevPropSheets
= TRUE
;
376 /* cleanup, we were unable to get the device property sheets */
377 HeapFree(GetProcessHeap(),
381 dap
->nDevPropSheets
= 0;
382 dap
->DevPropSheets
= NULL
;
386 dap
->nDevPropSheets
= 0;
391 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
393 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
394 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
398 DeviceInfoSet
= dap
->DeviceInfoSet
;
399 DeviceInfoData
= &dap
->DeviceInfoData
;
403 /* get the device name */
404 if (GetDeviceDescriptionString(DeviceInfoSet
,
407 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
409 PropSheet_SetTitle(GetParent(hwndDlg
),
414 /* set the device image */
415 if (SetupDiLoadClassIcon(&DeviceInfoData
->ClassGuid
,
419 HICON hOldIcon
= (HICON
)SendDlgItemMessage(hwndDlg
,
424 if (hOldIcon
!= NULL
)
426 DestroyIcon(hOldIcon
);
430 /* set the device name edit control text */
431 SetDlgItemText(hwndDlg
,
435 /* set the device type edit control text */
436 if (GetDeviceTypeString(DeviceInfoData
,
438 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
440 SetDlgItemText(hwndDlg
,
445 /* set the device manufacturer edit control text */
446 if (GetDeviceManufacturerString(DeviceInfoSet
,
449 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
451 SetDlgItemText(hwndDlg
,
456 /* set the device location edit control text */
457 if (GetDeviceLocationString(DeviceInfoData
->DevInst
,
460 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
462 SetDlgItemText(hwndDlg
,
467 /* set the device status edit control text */
468 if (GetDeviceStatusString(DeviceInfoData
->DevInst
,
471 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
473 SetDlgItemText(hwndDlg
,
478 /* set the device troubleshoot button text and disable it if necessary */
479 hDevProbBtn
= GetDlgItem(hwndDlg
,
481 cr
= CM_Get_DevNode_Status_Ex(&Status
,
483 DeviceInfoData
->DevInst
,
486 if (cr
== CR_SUCCESS
&& (Status
& DN_HAS_PROBLEM
))
488 switch (ProblemNumber
)
490 case CM_PROB_DEVLOADER_FAILED
:
492 /* FIXME - only if it's not a root bus devloader,
493 disable the button otherwise */
494 TroubleShootStrId
= IDS_UPDATEDRV
;
498 case CM_PROB_OUT_OF_MEMORY
:
499 case CM_PROB_ENTRY_IS_WRONG_TYPE
:
500 case CM_PROB_LACKED_ARBITRATOR
:
501 case CM_PROB_FAILED_START
:
503 case CM_PROB_UNKNOWN_RESOURCE
:
505 TroubleShootStrId
= IDS_UPDATEDRV
;
509 case CM_PROB_BOOT_CONFIG_CONFLICT
:
510 case CM_PROB_NORMAL_CONFLICT
:
511 case CM_PROB_REENUMERATION
:
513 /* FIXME - Troubleshoot conflict */
517 case CM_PROB_FAILED_FILTER
:
518 case CM_PROB_REINSTALL
:
519 case CM_PROB_FAILED_INSTALL
:
521 TroubleShootStrId
= IDS_REINSTALLDRV
;
525 case CM_PROB_DEVLOADER_NOT_FOUND
:
528 1) if it's a missing system devloader:
529 - disable the button (Reinstall Driver)
530 2) if it's not a system devloader but still missing:
532 3) if it's not a system devloader but the file can be found:
534 4) if it's a missing or empty software key
540 case CM_PROB_INVALID_DATA
:
541 case CM_PROB_PARTIAL_LOG_CONF
:
542 case CM_PROB_NO_VALID_LOG_CONF
:
543 case CM_PROB_HARDWARE_DISABLED
:
544 case CM_PROB_CANT_SHARE_IRQ
:
545 case CM_PROB_TRANSLATION_FAILED
:
546 case CM_PROB_SYSTEM_SHUTDOWN
:
547 case CM_PROB_PHANTOM
:
548 bDevActionAvailable
= FALSE
;
551 case CM_PROB_NOT_VERIFIED
:
552 case CM_PROB_DEVICE_NOT_THERE
:
553 /* FIXME - search hardware */
556 case CM_PROB_NEED_RESTART
:
557 case CM_PROB_WILL_BE_REMOVED
:
559 case CM_PROB_TOO_EARLY
:
560 case CM_PROB_DISABLED_SERVICE
:
561 TroubleShootStrId
= IDS_REBOOT
;
564 case CM_PROB_REGISTRY
:
565 /* FIXME - check registry? */
568 case CM_PROB_DISABLED
:
569 /* if device was disabled by the user: */
570 TroubleShootStrId
= IDS_ENABLEDEV
;
571 /* FIXME - otherwise disable button because the device was
572 disabled by the system*/
575 case CM_PROB_DEVLOADER_NOT_READY
:
576 /* FIXME - if it's a graphics adapter:
577 - if it's a a secondary adapter and the main adapter
587 case CM_PROB_FAILED_ADD
:
588 TroubleShootStrId
= IDS_PROPERTIES
;
593 if (LoadString(hDllInstance
,
596 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])) != 0)
598 SetWindowText(hDevProbBtn
,
601 EnableWindow(hDevProbBtn
,
602 dap
->IsAdmin
&& bDevActionAvailable
);
604 /* check if the device can be enabled/disabled */
605 hDevUsage
= GetDlgItem(hwndDlg
,
608 dap
->CanDisable
= FALSE
;
609 dap
->DeviceStarted
= FALSE
;
611 if (CanDisableDevice(DeviceInfoData
->DevInst
,
615 dap
->CanDisable
= bFlag
;
618 if (IsDeviceStarted(DeviceInfoData
->DevInst
,
622 dap
->DeviceStarted
= bFlag
;
625 /* enable/disable the device usage controls */
626 EnableWindow(GetDlgItem(hwndDlg
,
628 dap
->CanDisable
&& dap
->IsAdmin
);
629 EnableWindow(hDevUsage
,
630 dap
->CanDisable
&& dap
->IsAdmin
);
632 /* clear the combobox */
633 SendMessage(hDevUsage
,
639 InitDevUsageActions(hwndDlg
,
644 /* finally, disable the apply button */
645 PropSheet_UnChanged(hPropSheetDlg
,
647 dap
->DeviceUsageChanged
= FALSE
;
653 DlgParentSubWndProc(IN HWND hwnd
,
658 PDEVADVPROP_INFO dap
;
660 dap
= (PDEVADVPROP_INFO
)GetProp(hwnd
,
661 L
"DevMgrDevChangeSub");
664 if (uMsg
== WM_DEVICECHANGE
&& !IsWindowVisible(dap
->hWndGeneralPage
))
666 SendMessage(dap
->hWndGeneralPage
,
672 /* pass the message the the old window proc */
673 return CallWindowProc(dap
->ParentOldWndProc
,
681 /* this is not a good idea if the subclassed window was an ansi
682 window, but we failed finding out the previous window proc
683 so we can't use CallWindowProc. This should rarely - if ever -
686 return DefWindowProc(hwnd
,
696 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
701 PDEVADVPROP_INFO dap
;
704 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
707 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
713 switch (LOWORD(wParam
))
717 if (HIWORD(wParam
) == CBN_SELCHANGE
)
719 PropSheet_Changed(GetParent(hwndDlg
),
721 dap
->DeviceUsageChanged
= TRUE
;
730 /* display the device problem wizard */
731 ShowDeviceProblemWizard(hwndDlg
,
733 &dap
->DeviceInfoData
,
744 NMHDR
*hdr
= (NMHDR
*)lParam
;
748 ApplyGeneralSettings(hwndDlg
,
757 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
762 dap
->hWndGeneralPage
= hwndDlg
;
764 SetWindowLongPtr(hwndDlg
,
768 /* subclass the parent window to always receive
769 WM_DEVICECHANGE messages */
770 hWndParent
= GetParent(hwndDlg
);
771 if (hWndParent
!= NULL
)
773 /* subclass the parent window. This is not safe
774 if the parent window belongs to another thread! */
775 dap
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
777 (LONG_PTR
)DlgParentSubWndProc
);
779 if (dap
->ParentOldWndProc
!= NULL
&&
781 L
"DevMgrDevChangeSub",
784 dap
->hWndParent
= hWndParent
;
788 UpdateDevInfo(hwndDlg
,
796 case WM_DEVICECHANGE
:
798 /* FIXME - don't call UpdateDevInfo for all events */
799 UpdateDevInfo(hwndDlg
,
810 /* restore the old window proc of the subclassed parent window */
811 if (dap
->hWndParent
!= NULL
&& dap
->ParentOldWndProc
!= NULL
)
813 SetWindowLongPtr(dap
->hWndParent
,
815 (LONG_PTR
)dap
->ParentOldWndProc
);
818 /* destroy the device icon */
819 hDevIcon
= (HICON
)SendDlgItemMessage(hwndDlg
,
824 if (hDevIcon
!= NULL
)
826 DestroyIcon(hDevIcon
);
838 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
839 IN LPCWSTR lpDeviceID OPTIONAL
,
840 IN HDEVINFO DeviceInfoSet
,
841 IN PSP_DEVINFO_DATA DeviceInfoData
,
842 IN HINSTANCE hComCtl32
,
843 IN LPCWSTR lpMachineName
,
846 PROPSHEETHEADER psh
= {0};
847 PROPSHEETPAGE pspGeneral
= {0};
848 DWORD nPropSheets
= 0;
849 PPROPERTYSHEETW pPropertySheetW
;
850 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
851 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
852 PDEVADVPROP_INFO DevAdvPropInfo
;
853 HMACHINE hMachine
= NULL
;
857 /* we don't want to statically link against comctl32, so find the
858 functions we need dynamically */
860 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
862 pCreatePropertySheetPageW
=
863 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
864 "CreatePropertySheetPageW");
865 pDestroyPropertySheetPage
=
866 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
867 "DestroyPropertySheetPage");
868 if (pPropertySheetW
== NULL
||
869 pCreatePropertySheetPageW
== NULL
||
870 pDestroyPropertySheetPage
== NULL
)
875 if (lpDeviceID
== NULL
)
877 /* find out how much size is needed for the device id */
878 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
884 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
888 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
895 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
898 if (lpMachineName
!= NULL
)
900 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
902 if (cr
!= CR_SUCCESS
)
908 /* create the internal structure associated with the "General",
909 "Driver", ... pages */
910 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
912 FIELD_OFFSET(DEVADVPROP_INFO
,
914 (DevIdSize
* sizeof(WCHAR
)));
915 if (DevAdvPropInfo
== NULL
)
917 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
921 if (lpDeviceID
== NULL
)
923 /* read the device instance id */
924 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
926 DevAdvPropInfo
->szDeviceID
,
935 /* copy the device instance id supplied by the caller */
936 wcscpy(DevAdvPropInfo
->szDeviceID
,
940 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
941 DevAdvPropInfo
->DeviceInfoData
= *DeviceInfoData
;
942 DevAdvPropInfo
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
943 DevAdvPropInfo
->CurrentDeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
945 DevAdvPropInfo
->hMachine
= hMachine
;
946 DevAdvPropInfo
->lpMachineName
= lpMachineName
;
947 DevAdvPropInfo
->szDevName
[0] = L
'\0';
948 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
950 DevAdvPropInfo
->IsAdmin
= IsUserAdmin();
951 DevAdvPropInfo
->DoDefaultDevAction
= ((dwFlags
& DPF_DEVICE_STATUS_ACTION
) != 0);
953 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
954 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
955 psh
.hwndParent
= hWndParent
;
956 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
958 DevAdvPropInfo
->PropertySheetType
= lpMachineName
!= NULL
?
959 DIGCDP_FLAG_REMOTE_ADVANCED
:
960 DIGCDP_FLAG_ADVANCED
;
962 /* find out how many property sheets we need */
963 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
964 &DevAdvPropInfo
->DeviceInfoData
,
968 DevAdvPropInfo
->PropertySheetType
) &&
971 DPRINT1("SetupDiGetClassDevPropertySheets unexpectedly returned TRUE!\n");
975 if (nPropSheets
!= 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
980 psh
.phpage
= HeapAlloc(GetProcessHeap(),
982 (nPropSheets
+ 1) * sizeof(HPROPSHEETPAGE
));
983 if (psh
.phpage
== NULL
)
988 /* add the "General" property sheet */
989 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
990 pspGeneral
.dwFlags
= PSP_DEFAULT
;
991 pspGeneral
.hInstance
= hDllInstance
;
992 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
993 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
994 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
995 psh
.phpage
[0] = pCreatePropertySheetPageW(&pspGeneral
);
996 if (psh
.phpage
[0] != NULL
)
1001 DevAdvPropInfo
->nDevPropSheets
= nPropSheets
;
1003 if (nPropSheets
!= 0)
1005 DevAdvPropInfo
->DevPropSheets
= psh
.phpage
+ psh
.nPages
;
1007 /* create the device property sheets */
1008 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
1009 &DevAdvPropInfo
->DeviceInfoData
,
1011 nPropSheets
+ psh
.nPages
,
1013 DevAdvPropInfo
->PropertySheetType
))
1019 /* FIXME - add the "Driver" property sheet if necessary */
1021 if (psh
.nPages
!= 0)
1023 Ret
= pPropertySheetW(&psh
);
1025 /* NOTE: no need to destroy the property sheets anymore! */
1032 /* in case of failure the property sheets must be destroyed */
1033 if (psh
.phpage
!= NULL
)
1039 if (psh
.phpage
[i
] != NULL
)
1041 pDestroyPropertySheetPage(psh
.phpage
[i
]);
1047 if (DevAdvPropInfo
!= NULL
)
1049 if (DevAdvPropInfo
->FreeDevPropSheets
)
1051 /* don't free the array if it's the one allocated in
1052 DisplayDeviceAdvancedProperties */
1053 HeapFree(GetProcessHeap(),
1055 DevAdvPropInfo
->DevPropSheets
);
1058 if (DevAdvPropInfo
->CloseDevInst
)
1060 /* close the device info set in case a new one was created */
1061 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->DeviceInfoSet
);
1064 if (DevAdvPropInfo
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
1066 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->CurrentDeviceInfoSet
);
1069 HeapFree(GetProcessHeap(),
1074 if (psh
.phpage
!= NULL
)
1076 HeapFree(GetProcessHeap(),
1081 if (hMachine
!= NULL
)
1083 CM_Disconnect_Machine(hMachine
);
1090 /***************************************************************************
1092 * DeviceAdvancedPropertiesW
1095 * Invokes the device properties dialog, this version may add some property pages
1099 * hWndParent: Handle to the parent window
1100 * lpMachineName: Machine Name, NULL is the local machine
1101 * lpDeviceID: Specifies the device whose properties are to be shown
1104 * Always returns -1, a call to GetLastError returns 0 if successful
1110 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL
,
1111 IN LPCWSTR lpMachineName OPTIONAL
,
1112 IN LPCWSTR lpDeviceID
)
1115 SP_DEVINFO_DATA DevInfoData
;
1116 HINSTANCE hComCtl32
;
1119 if (lpDeviceID
== NULL
)
1121 SetLastError(ERROR_INVALID_PARAMETER
);
1125 /* dynamically load comctl32 */
1126 hComCtl32
= LoadAndInitComctl32();
1127 if (hComCtl32
!= NULL
)
1129 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1133 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1135 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1136 if (SetupDiOpenDeviceInfo(hDevInfo
,
1142 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1151 SetupDiDestroyDeviceInfoList(hDevInfo
);
1154 FreeLibrary(hComCtl32
);
1161 /***************************************************************************
1163 * DeviceAdvancedPropertiesA
1166 * Invokes the device properties dialog, this version may add some property pages
1170 * hWndParent: Handle to the parent window
1171 * lpMachineName: Machine Name, NULL is the local machine
1172 * lpDeviceID: Specifies the device whose properties are to be shown
1175 * Always returns -1, a call to GetLastError returns 0 if successful
1181 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL
,
1182 IN LPCSTR lpMachineName OPTIONAL
,
1183 IN LPCSTR lpDeviceID
)
1185 LPWSTR lpMachineNameW
= NULL
;
1186 LPWSTR lpDeviceIDW
= NULL
;
1189 if (lpMachineName
!= NULL
)
1191 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1197 if (lpDeviceID
!= NULL
)
1199 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1206 Ret
= DeviceAdvancedPropertiesW(hWndParent
,
1211 if (lpMachineNameW
!= NULL
)
1213 HeapFree(GetProcessHeap(),
1217 if (lpDeviceIDW
!= NULL
)
1219 HeapFree(GetProcessHeap(),
1228 /***************************************************************************
1230 * DevicePropertiesExA
1233 * Invokes the extended device properties dialog
1236 * hWndParent: Handle to the parent window
1237 * lpMachineName: Machine Name, NULL is the local machine
1238 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1239 * bShowDevMgr is nonzero
1240 * dwFlags: This parameter can be a combination of the following flags:
1241 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1242 * the default device status action button
1243 * to be clicked (Troubleshoot, Enable
1245 * bShowDevMgr: If non-zero it displays the device manager instead of
1246 * the advanced device property dialog
1249 * 1: if bShowDevMgr is non-zero and no error occured
1250 * -1: a call to GetLastError returns 0 if successful
1256 DevicePropertiesExA(IN HWND hWndParent OPTIONAL
,
1257 IN LPCSTR lpMachineName OPTIONAL
,
1258 IN LPCSTR lpDeviceID OPTIONAL
,
1259 IN DWORD dwFlags OPTIONAL
,
1260 IN BOOL bShowDevMgr
)
1262 LPWSTR lpMachineNameW
= NULL
;
1263 LPWSTR lpDeviceIDW
= NULL
;
1266 if (lpMachineName
!= NULL
)
1268 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1274 if (lpDeviceID
!= NULL
)
1276 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1283 Ret
= DevicePropertiesExW(hWndParent
,
1290 if (lpMachineNameW
!= NULL
)
1292 HeapFree(GetProcessHeap(),
1296 if (lpDeviceIDW
!= NULL
)
1298 HeapFree(GetProcessHeap(),
1307 /***************************************************************************
1309 * DevicePropertiesExW
1312 * Invokes the extended device properties dialog
1315 * hWndParent: Handle to the parent window
1316 * lpMachineName: Machine Name, NULL is the local machine
1317 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1318 * bShowDevMgr is nonzero
1319 * dwFlags: This parameter can be a combination of the following flags:
1320 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1321 * the default device status action button
1322 * to be clicked (Troubleshoot, Enable
1324 * bShowDevMgr: If non-zero it displays the device manager instead of
1325 * the advanced device property dialog
1328 * 1: if bShowDevMgr is non-zero and no error occured
1329 * -1: a call to GetLastError returns 0 if successful
1335 DevicePropertiesExW(IN HWND hWndParent OPTIONAL
,
1336 IN LPCWSTR lpMachineName OPTIONAL
,
1337 IN LPCWSTR lpDeviceID OPTIONAL
,
1338 IN DWORD dwFlags OPTIONAL
,
1339 IN BOOL bShowDevMgr
)
1343 if (dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
))
1345 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1346 dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
));
1347 SetLastError(ERROR_INVALID_FLAGS
);
1353 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1354 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1359 SP_DEVINFO_DATA DevInfoData
;
1360 HINSTANCE hComCtl32
;
1362 if (lpDeviceID
== NULL
)
1364 SetLastError(ERROR_INVALID_PARAMETER
);
1368 /* dynamically load comctl32 */
1369 hComCtl32
= LoadAndInitComctl32();
1370 if (hComCtl32
!= NULL
)
1372 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1376 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1378 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1379 if (SetupDiOpenDeviceInfo(hDevInfo
,
1385 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1394 SetupDiDestroyDeviceInfoList(hDevInfo
);
1397 FreeLibrary(hComCtl32
);