2 * ReactOS Device Manager Applet
3 * Copyright (C) 2004 - 2005 ReactOS Team
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* $Id: hwpage.c 19599 2005-11-26 02:12:58Z weiden $
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/advprop.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 typedef INT_PTR (WINAPI
*PPROPERTYSHEETW
)(LPCPROPSHEETHEADERW
);
34 typedef HPROPSHEETPAGE (WINAPI
*PCREATEPROPERTYSHEETPAGEW
)(LPCPROPSHEETPAGEW
);
35 typedef BOOL (WINAPI
*PDESTROYPROPERTYSHEETPAGE
)(HPROPSHEETPAGE
);
37 typedef struct _DEVADVPROP_INFO
41 WNDPROC ParentOldWndProc
;
44 HDEVINFO DeviceInfoSet
;
45 SP_DEVINFO_DATA DeviceInfoData
;
46 HDEVINFO CurrentDeviceInfoSet
;
47 SP_DEVINFO_DATA CurrentDeviceInfoData
;
48 DEVINST ParentDevInst
;
50 LPCWSTR lpMachineName
;
53 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
54 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
56 DWORD PropertySheetType
;
58 HPROPSHEETPAGE
*DevPropSheets
;
60 BOOL FreeDevPropSheets
: 1;
62 BOOL DeviceStarted
: 1;
63 BOOL DeviceUsageChanged
: 1;
64 BOOL CloseDevInst
: 1;
66 BOOL DoDefaultDevAction
: 1;
67 BOOL PageInitialized
: 1;
68 BOOL ShowRemotePages
: 1;
69 BOOL HasDriverPage
: 1;
70 BOOL HasResourcePage
: 1;
71 BOOL HasPowerPage
: 1;
76 /* struct may be dynamically expanded here! */
77 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
79 #define PM_INITIALIZE (WM_APP + 0x101)
84 AdvProcDriverDlgProc(IN HWND hwndDlg
,
92 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
95 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
101 NMHDR
*hdr
= (NMHDR
*)lParam
;
112 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
115 SetWindowLongPtr(hwndDlg
,
119 /* set the device image */
120 SendDlgItemMessage(hwndDlg
,
123 (WPARAM
)dap
->hDevIcon
,
126 /* set the device name edit control text */
127 SetDlgItemText(hwndDlg
,
142 InitDevUsageActions(IN HWND hwndDlg
,
144 IN PDEVADVPROP_INFO dap
)
155 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
158 /* fill in the device usage combo box */
159 if (LoadString(hDllInstance
,
162 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
164 Index
= (INT
)SendMessage(hComboBox
,
167 (LPARAM
)dap
->szTemp
);
170 SendMessage(hComboBox
,
177 case IDS_ENABLEDEVICE
:
178 if (dap
->DeviceStarted
)
180 SendMessage(hComboBox
,
187 case IDS_DISABLEDEVICE
:
188 if (!dap
->DeviceStarted
)
190 SendMessage(hComboBox
,
207 GetSelectedUsageAction(IN HWND hComboBox
)
212 Index
= (INT
)SendMessage(hComboBox
,
218 INT iRet
= SendMessage(hComboBox
,
233 ApplyGeneralSettings(IN HWND hwndDlg
,
234 IN PDEVADVPROP_INFO dap
)
238 if (dap
->DeviceUsageChanged
&& dap
->IsAdmin
&& dap
->CanDisable
)
240 UINT SelectedUsageAction
;
241 BOOL NeedReboot
= FALSE
;
243 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
245 switch (SelectedUsageAction
)
247 case IDS_ENABLEDEVICE
:
248 if (!dap
->DeviceStarted
)
250 Ret
= EnableDevice(dap
->DeviceInfoSet
,
251 &dap
->DeviceInfoData
,
258 case IDS_DISABLEDEVICE
:
259 if (dap
->DeviceStarted
)
261 Ret
= EnableDevice(dap
->DeviceInfoSet
,
262 &dap
->DeviceInfoData
,
277 /* make PropertySheet() return PSM_REBOOTSYSTEM */
278 PropSheet_RebootSystem(hwndDlg
);
283 /* FIXME - display an error message */
284 DPRINT1("Failed to enable/disable device! LastError: %d\n",
289 Ret
= !dap
->DeviceUsageChanged
;
291 /* disable the apply button */
292 PropSheet_UnChanged(GetParent(hwndDlg
),
294 dap
->DeviceUsageChanged
= FALSE
;
300 UpdateDevInfo(IN HWND hwndDlg
,
301 IN PDEVADVPROP_INFO dap
,
304 HWND hDevUsage
, hPropSheetDlg
, hDevProbBtn
;
306 ULONG Status
, ProblemNumber
;
307 SP_DEVINSTALL_PARAMS_W InstallParams
;
308 UINT TroubleShootStrId
= IDS_TROUBLESHOOTDEV
;
309 BOOL bFlag
, bDevActionAvailable
= TRUE
;
310 BOOL bDrvInstalled
= FALSE
;
312 HDEVINFO DeviceInfoSet
= NULL
;
313 PSP_DEVINFO_DATA DeviceInfoData
= NULL
;
315 DWORD nDriverPages
= 0;
317 hPropSheetDlg
= GetParent(hwndDlg
);
319 if (dap
->PageInitialized
)
321 /* switch to the General page */
322 PropSheet_SetCurSelByID(hPropSheetDlg
,
325 /* remove and destroy the existing device property sheet pages */
326 if (dap
->DevPropSheets
!= NULL
)
329 iPage
!= dap
->nDevPropSheets
;
332 if (dap
->DevPropSheets
[iPage
] != NULL
)
334 PropSheet_RemovePage(hPropSheetDlg
,
336 dap
->DevPropSheets
[iPage
]);
344 if (dap
->FreeDevPropSheets
)
346 /* don't free the array if it's the one allocated in
347 DisplayDeviceAdvancedProperties */
348 HeapFree(GetProcessHeap(),
352 dap
->FreeDevPropSheets
= FALSE
;
355 dap
->DevPropSheets
= NULL
;
356 dap
->nDevPropSheets
= 0;
360 /* create a new device info set and re-open the device */
361 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
363 SetupDiDestroyDeviceInfoList(dap
->CurrentDeviceInfoSet
);
366 dap
->ParentDevInst
= 0;
367 dap
->CurrentDeviceInfoSet
= SetupDiCreateDeviceInfoListEx(NULL
,
371 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
373 if (SetupDiOpenDeviceInfo(dap
->CurrentDeviceInfoSet
,
377 &dap
->CurrentDeviceInfoData
))
379 if (dap
->CloseDevInst
)
381 SetupDiDestroyDeviceInfoList(dap
->DeviceInfoSet
);
384 dap
->CloseDevInst
= TRUE
;
385 dap
->DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
386 dap
->DeviceInfoData
= dap
->CurrentDeviceInfoData
;
387 dap
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
395 /* get the parent node from the initial devinst */
396 CM_Get_Parent_Ex(&dap
->ParentDevInst
,
397 dap
->DeviceInfoData
.DevInst
,
402 if (dap
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
404 DeviceInfoSet
= dap
->CurrentDeviceInfoSet
;
405 DeviceInfoData
= &dap
->CurrentDeviceInfoData
;
409 DeviceInfoSet
= dap
->DeviceInfoSet
;
410 DeviceInfoData
= &dap
->DeviceInfoData
;
415 DeviceInfoSet
= dap
->DeviceInfoSet
;
416 DeviceInfoData
= &dap
->DeviceInfoData
;
419 dap
->HasDriverPage
= FALSE
;
420 dap
->HasResourcePage
= FALSE
;
421 dap
->HasPowerPage
= FALSE
;
422 if (IsDriverInstalled(DeviceInfoData
->DevInst
,
427 if (SetupDiCallClassInstaller((dap
->ShowRemotePages
?
428 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
429 DIF_ADDPROPERTYPAGE_ADVANCED
),
433 /* get install params */
434 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
435 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
,
440 InstallParams
.Flags
= 0;
443 dap
->HasDriverPage
= !(InstallParams
.Flags
& DI_DRIVERPAGE_ADDED
);
444 dap
->HasResourcePage
= !(InstallParams
.Flags
& DI_RESOURCEPAGE_ADDED
);
445 dap
->HasPowerPage
= !(InstallParams
.Flags
& DI_FLAGSEX_POWERPAGE_ADDED
);
449 /* get the device icon */
450 if (dap
->hDevIcon
!= NULL
)
452 DestroyIcon(dap
->hDevIcon
);
453 dap
->hDevIcon
= NULL
;
455 if (!SetupDiLoadClassIcon(&DeviceInfoData
->ClassGuid
,
459 dap
->hDevIcon
= NULL
;
462 /* get the device name */
463 if (GetDeviceDescriptionString(DeviceInfoSet
,
466 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
468 PropSheet_SetTitle(hPropSheetDlg
,
473 /* set the device image */
474 SendDlgItemMessage(hwndDlg
,
477 (WPARAM
)dap
->hDevIcon
,
480 /* set the device name edit control text */
481 SetDlgItemText(hwndDlg
,
485 /* set the device type edit control text */
486 if (GetDeviceTypeString(DeviceInfoData
,
488 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
490 SetDlgItemText(hwndDlg
,
495 /* set the device manufacturer edit control text */
496 if (GetDeviceManufacturerString(DeviceInfoSet
,
499 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
501 SetDlgItemText(hwndDlg
,
506 /* set the device location edit control text */
507 if (GetDeviceLocationString(DeviceInfoData
->DevInst
,
510 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
512 SetDlgItemText(hwndDlg
,
517 /* set the device status edit control text */
518 if (GetDeviceStatusString(DeviceInfoData
->DevInst
,
521 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
523 SetDlgItemText(hwndDlg
,
528 /* set the device troubleshoot button text and disable it if necessary */
529 hDevProbBtn
= GetDlgItem(hwndDlg
,
531 cr
= CM_Get_DevNode_Status_Ex(&Status
,
533 DeviceInfoData
->DevInst
,
536 if (cr
== CR_SUCCESS
&& (Status
& DN_HAS_PROBLEM
))
538 switch (ProblemNumber
)
540 case CM_PROB_DEVLOADER_FAILED
:
542 /* FIXME - only if it's not a root bus devloader,
543 disable the button otherwise */
544 TroubleShootStrId
= IDS_UPDATEDRV
;
548 case CM_PROB_OUT_OF_MEMORY
:
549 case CM_PROB_ENTRY_IS_WRONG_TYPE
:
550 case CM_PROB_LACKED_ARBITRATOR
:
551 case CM_PROB_FAILED_START
:
553 case CM_PROB_UNKNOWN_RESOURCE
:
555 TroubleShootStrId
= IDS_UPDATEDRV
;
559 case CM_PROB_BOOT_CONFIG_CONFLICT
:
560 case CM_PROB_NORMAL_CONFLICT
:
561 case CM_PROB_REENUMERATION
:
563 /* FIXME - Troubleshoot conflict */
567 case CM_PROB_FAILED_FILTER
:
568 case CM_PROB_REINSTALL
:
569 case CM_PROB_FAILED_INSTALL
:
571 TroubleShootStrId
= IDS_REINSTALLDRV
;
575 case CM_PROB_DEVLOADER_NOT_FOUND
:
578 1) if it's a missing system devloader:
579 - disable the button (Reinstall Driver)
580 2) if it's not a system devloader but still missing:
582 3) if it's not a system devloader but the file can be found:
584 4) if it's a missing or empty software key
590 case CM_PROB_INVALID_DATA
:
591 case CM_PROB_PARTIAL_LOG_CONF
:
592 case CM_PROB_NO_VALID_LOG_CONF
:
593 case CM_PROB_HARDWARE_DISABLED
:
594 case CM_PROB_CANT_SHARE_IRQ
:
595 case CM_PROB_TRANSLATION_FAILED
:
596 case CM_PROB_SYSTEM_SHUTDOWN
:
597 case CM_PROB_PHANTOM
:
598 bDevActionAvailable
= FALSE
;
601 case CM_PROB_NOT_VERIFIED
:
602 case CM_PROB_DEVICE_NOT_THERE
:
603 /* FIXME - search hardware */
606 case CM_PROB_NEED_RESTART
:
607 case CM_PROB_WILL_BE_REMOVED
:
609 case CM_PROB_TOO_EARLY
:
610 case CM_PROB_DISABLED_SERVICE
:
611 TroubleShootStrId
= IDS_REBOOT
;
614 case CM_PROB_REGISTRY
:
615 /* FIXME - check registry? */
618 case CM_PROB_DISABLED
:
619 /* if device was disabled by the user: */
620 TroubleShootStrId
= IDS_ENABLEDEV
;
621 /* FIXME - otherwise disable button because the device was
622 disabled by the system*/
625 case CM_PROB_DEVLOADER_NOT_READY
:
626 /* FIXME - if it's a graphics adapter:
627 - if it's a a secondary adapter and the main adapter
637 case CM_PROB_FAILED_ADD
:
638 TroubleShootStrId
= IDS_PROPERTIES
;
643 if (LoadString(hDllInstance
,
646 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])) != 0)
648 SetWindowText(hDevProbBtn
,
651 EnableWindow(hDevProbBtn
,
652 dap
->IsAdmin
&& bDevActionAvailable
);
654 /* check if the device can be enabled/disabled */
655 hDevUsage
= GetDlgItem(hwndDlg
,
658 dap
->CanDisable
= FALSE
;
659 dap
->DeviceStarted
= FALSE
;
661 if (CanDisableDevice(DeviceInfoData
->DevInst
,
665 dap
->CanDisable
= bFlag
;
668 if (IsDeviceStarted(DeviceInfoData
->DevInst
,
672 dap
->DeviceStarted
= bFlag
;
675 /* enable/disable the device usage controls */
676 EnableWindow(GetDlgItem(hwndDlg
,
678 dap
->CanDisable
&& dap
->IsAdmin
);
679 EnableWindow(hDevUsage
,
680 dap
->CanDisable
&& dap
->IsAdmin
);
682 /* clear the combobox */
683 SendMessage(hDevUsage
,
689 InitDevUsageActions(hwndDlg
,
694 /* find out how many new device property sheets to add.
695 fake a PROPSHEETHEADER structure, we don't plan to
696 call PropertySheet again!*/
697 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
701 /* get the number of device property sheets for the device */
702 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
707 dap
->PropertySheetType
) &&
708 nDriverPages
!= 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
710 dap
->nDevPropSheets
+= nDriverPages
;
717 /* include the driver page */
718 if (dap
->HasDriverPage
)
719 dap
->nDevPropSheets
++;
721 /* add the device property sheets */
722 if (dap
->nDevPropSheets
!= 0)
724 dap
->DevPropSheets
= HeapAlloc(GetProcessHeap(),
726 dap
->nDevPropSheets
* sizeof(HPROPSHEETPAGE
));
727 if (dap
->DevPropSheets
!= NULL
)
729 if (nDriverPages
!= 0)
731 psh
.phpage
= dap
->DevPropSheets
;
733 /* query the device property sheet pages to add */
734 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
739 dap
->PropertySheetType
))
741 /* add the property sheets */
743 iPage
!= nDriverPages
;
746 PropSheet_AddPage(hPropSheetDlg
,
747 dap
->DevPropSheets
[iPage
]);
750 dap
->FreeDevPropSheets
= TRUE
;
754 /* cleanup, we were unable to get the device property sheets */
755 dap
->nDevPropSheets
-= nDriverPages
;
757 if (dap
->nDevPropSheets
== 0)
759 HeapFree(GetProcessHeap(),
762 dap
->DevPropSheets
= NULL
;
767 /* add the driver page if necessary */
768 if (dap
->HasDriverPage
)
770 PROPSHEETPAGE pspDriver
= {0};
771 pspDriver
.dwSize
= sizeof(PROPSHEETPAGE
);
772 pspDriver
.dwFlags
= PSP_DEFAULT
;
773 pspDriver
.hInstance
= hDllInstance
;
774 pspDriver
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEDRIVER
);
775 pspDriver
.pfnDlgProc
= AdvProcDriverDlgProc
;
776 pspDriver
.lParam
= (LPARAM
)dap
;
777 dap
->DevPropSheets
[iPage
] = dap
->pCreatePropertySheetPageW(&pspDriver
);
778 if (dap
->DevPropSheets
[iPage
] != NULL
)
780 if (PropSheet_AddPage(hPropSheetDlg
,
781 dap
->DevPropSheets
[iPage
]))
787 dap
->pDestroyPropertySheetPage(dap
->DevPropSheets
[iPage
]);
793 dap
->nDevPropSheets
= 0;
796 /* finally, disable the apply button */
797 PropSheet_UnChanged(hPropSheetDlg
,
799 dap
->DeviceUsageChanged
= FALSE
;
805 DlgParentSubWndProc(IN HWND hwnd
,
810 PDEVADVPROP_INFO dap
;
812 dap
= (PDEVADVPROP_INFO
)GetProp(hwnd
,
813 L
"DevMgrDevChangeSub");
816 if (uMsg
== WM_DEVICECHANGE
&& !IsWindowVisible(dap
->hWndGeneralPage
))
818 SendMessage(dap
->hWndGeneralPage
,
824 /* pass the message the the old window proc */
825 return CallWindowProc(dap
->ParentOldWndProc
,
833 /* this is not a good idea if the subclassed window was an ansi
834 window, but we failed finding out the previous window proc
835 so we can't use CallWindowProc. This should rarely - if ever -
838 return DefWindowProc(hwnd
,
848 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
853 PDEVADVPROP_INFO dap
;
856 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
859 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
865 switch (LOWORD(wParam
))
869 if (HIWORD(wParam
) == CBN_SELCHANGE
)
871 PropSheet_Changed(GetParent(hwndDlg
),
873 dap
->DeviceUsageChanged
= TRUE
;
882 /* display the device problem wizard */
883 ShowDeviceProblemWizard(hwndDlg
,
885 &dap
->DeviceInfoData
,
896 NMHDR
*hdr
= (NMHDR
*)lParam
;
900 ApplyGeneralSettings(hwndDlg
,
909 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
914 dap
->hWndGeneralPage
= hwndDlg
;
916 SetWindowLongPtr(hwndDlg
,
920 /* subclass the parent window to always receive
921 WM_DEVICECHANGE messages */
922 hWndParent
= GetParent(hwndDlg
);
923 if (hWndParent
!= NULL
)
925 /* subclass the parent window. This is not safe
926 if the parent window belongs to another thread! */
927 dap
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
929 (LONG_PTR
)DlgParentSubWndProc
);
931 if (dap
->ParentOldWndProc
!= NULL
&&
933 L
"DevMgrDevChangeSub",
936 dap
->hWndParent
= hWndParent
;
940 /* do not call UpdateDevInfo directly in here because it modifies
941 the pages of the property sheet! */
951 case WM_DEVICECHANGE
:
953 /* FIXME - don't call UpdateDevInfo for all events */
954 UpdateDevInfo(hwndDlg
,
963 UpdateDevInfo(hwndDlg
,
966 dap
->PageInitialized
= TRUE
;
972 /* restore the old window proc of the subclassed parent window */
973 if (dap
->hWndParent
!= NULL
&& dap
->ParentOldWndProc
!= NULL
)
975 if (SetWindowLongPtr(dap
->hWndParent
,
977 (LONG_PTR
)dap
->ParentOldWndProc
) == (LONG_PTR
)DlgParentSubWndProc
)
979 RemoveProp(dap
->hWndParent
,
980 L
"DevMgrDevChangeSub");
993 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
994 IN LPCWSTR lpDeviceID OPTIONAL
,
995 IN HDEVINFO DeviceInfoSet
,
996 IN PSP_DEVINFO_DATA DeviceInfoData
,
997 IN HINSTANCE hComCtl32
,
998 IN LPCWSTR lpMachineName
,
1001 PROPSHEETHEADER psh
= {0};
1002 PROPSHEETPAGE pspGeneral
= {0};
1003 PPROPERTYSHEETW pPropertySheetW
;
1004 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
1005 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
1006 PDEVADVPROP_INFO DevAdvPropInfo
;
1007 HMACHINE hMachine
= NULL
;
1008 DWORD DevIdSize
= 0;
1011 /* we don't want to statically link against comctl32, so find the
1012 functions we need dynamically */
1014 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
1016 pCreatePropertySheetPageW
=
1017 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
1018 "CreatePropertySheetPageW");
1019 pDestroyPropertySheetPage
=
1020 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
1021 "DestroyPropertySheetPage");
1022 if (pPropertySheetW
== NULL
||
1023 pCreatePropertySheetPageW
== NULL
||
1024 pDestroyPropertySheetPage
== NULL
)
1029 if (lpDeviceID
== NULL
)
1031 /* find out how much size is needed for the device id */
1032 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1038 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1042 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1049 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
1052 if (lpMachineName
!= NULL
)
1054 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
1056 if (cr
!= CR_SUCCESS
)
1062 /* create the internal structure associated with the "General",
1063 "Driver", ... pages */
1064 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
1066 FIELD_OFFSET(DEVADVPROP_INFO
,
1068 (DevIdSize
* sizeof(WCHAR
)));
1069 if (DevAdvPropInfo
== NULL
)
1071 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1075 if (lpDeviceID
== NULL
)
1077 /* read the device instance id */
1078 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
1080 DevAdvPropInfo
->szDeviceID
,
1089 /* copy the device instance id supplied by the caller */
1090 wcscpy(DevAdvPropInfo
->szDeviceID
,
1094 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
1095 DevAdvPropInfo
->DeviceInfoData
= *DeviceInfoData
;
1096 DevAdvPropInfo
->CurrentDeviceInfoSet
= INVALID_HANDLE_VALUE
;
1097 DevAdvPropInfo
->CurrentDeviceInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1099 DevAdvPropInfo
->ShowRemotePages
= (lpMachineName
!= NULL
&& lpMachineName
[0] != L
'\0');
1100 DevAdvPropInfo
->hMachine
= hMachine
;
1101 DevAdvPropInfo
->lpMachineName
= lpMachineName
;
1102 DevAdvPropInfo
->szDevName
[0] = L
'\0';
1103 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
1104 DevAdvPropInfo
->pCreatePropertySheetPageW
= pCreatePropertySheetPageW
;
1105 DevAdvPropInfo
->pDestroyPropertySheetPage
= pDestroyPropertySheetPage
;
1107 DevAdvPropInfo
->IsAdmin
= IsUserAdmin();
1108 DevAdvPropInfo
->DoDefaultDevAction
= ((dwFlags
& DPF_DEVICE_STATUS_ACTION
) != 0);
1110 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1111 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
1112 psh
.hwndParent
= hWndParent
;
1113 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
1115 DevAdvPropInfo
->PropertySheetType
= DevAdvPropInfo
->ShowRemotePages
?
1116 DIGCDP_FLAG_REMOTE_ADVANCED
:
1117 DIGCDP_FLAG_ADVANCED
;
1119 psh
.phpage
= HeapAlloc(GetProcessHeap(),
1121 1 * sizeof(HPROPSHEETPAGE
));
1122 if (psh
.phpage
== NULL
)
1127 /* add the "General" property sheet */
1128 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
1129 pspGeneral
.dwFlags
= PSP_DEFAULT
;
1130 pspGeneral
.hInstance
= hDllInstance
;
1131 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
1132 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
1133 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
1134 psh
.phpage
[psh
.nPages
] = pCreatePropertySheetPageW(&pspGeneral
);
1135 if (psh
.phpage
[psh
.nPages
] != NULL
)
1140 DevAdvPropInfo
->nDevPropSheets
= psh
.nPages
;
1142 if (psh
.nPages
!= 0)
1144 Ret
= pPropertySheetW(&psh
);
1146 /* NOTE: no need to destroy the property sheets anymore! */
1153 /* in case of failure the property sheets must be destroyed */
1154 if (psh
.phpage
!= NULL
)
1160 if (psh
.phpage
[i
] != NULL
)
1162 pDestroyPropertySheetPage(psh
.phpage
[i
]);
1168 if (DevAdvPropInfo
!= NULL
)
1170 if (DevAdvPropInfo
->FreeDevPropSheets
)
1172 /* don't free the array if it's the one allocated in
1173 DisplayDeviceAdvancedProperties */
1174 HeapFree(GetProcessHeap(),
1176 DevAdvPropInfo
->DevPropSheets
);
1179 if (DevAdvPropInfo
->CloseDevInst
)
1181 /* close the device info set in case a new one was created */
1182 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->DeviceInfoSet
);
1185 if (DevAdvPropInfo
->CurrentDeviceInfoSet
!= INVALID_HANDLE_VALUE
)
1187 SetupDiDestroyDeviceInfoList(DevAdvPropInfo
->CurrentDeviceInfoSet
);
1190 if (DevAdvPropInfo
->hDevIcon
!= NULL
)
1192 DestroyIcon(DevAdvPropInfo
->hDevIcon
);
1195 HeapFree(GetProcessHeap(),
1200 if (psh
.phpage
!= NULL
)
1202 HeapFree(GetProcessHeap(),
1207 if (hMachine
!= NULL
)
1209 CM_Disconnect_Machine(hMachine
);
1216 /***************************************************************************
1218 * DeviceAdvancedPropertiesW
1221 * Invokes the device properties dialog, this version may add some property pages
1225 * hWndParent: Handle to the parent window
1226 * lpMachineName: Machine Name, NULL is the local machine
1227 * lpDeviceID: Specifies the device whose properties are to be shown
1230 * Always returns -1, a call to GetLastError returns 0 if successful
1236 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL
,
1237 IN LPCWSTR lpMachineName OPTIONAL
,
1238 IN LPCWSTR lpDeviceID
)
1241 SP_DEVINFO_DATA DevInfoData
;
1242 HINSTANCE hComCtl32
;
1245 if (lpDeviceID
== NULL
)
1247 SetLastError(ERROR_INVALID_PARAMETER
);
1251 /* dynamically load comctl32 */
1252 hComCtl32
= LoadAndInitComctl32();
1253 if (hComCtl32
!= NULL
)
1255 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1259 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1261 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1262 if (SetupDiOpenDeviceInfo(hDevInfo
,
1268 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1277 SetupDiDestroyDeviceInfoList(hDevInfo
);
1280 FreeLibrary(hComCtl32
);
1287 /***************************************************************************
1289 * DeviceAdvancedPropertiesA
1292 * Invokes the device properties dialog, this version may add some property pages
1296 * hWndParent: Handle to the parent window
1297 * lpMachineName: Machine Name, NULL is the local machine
1298 * lpDeviceID: Specifies the device whose properties are to be shown
1301 * Always returns -1, a call to GetLastError returns 0 if successful
1307 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL
,
1308 IN LPCSTR lpMachineName OPTIONAL
,
1309 IN LPCSTR lpDeviceID
)
1311 LPWSTR lpMachineNameW
= NULL
;
1312 LPWSTR lpDeviceIDW
= NULL
;
1315 if (lpMachineName
!= NULL
)
1317 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1323 if (lpDeviceID
!= NULL
)
1325 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1332 Ret
= DeviceAdvancedPropertiesW(hWndParent
,
1337 if (lpMachineNameW
!= NULL
)
1339 HeapFree(GetProcessHeap(),
1343 if (lpDeviceIDW
!= NULL
)
1345 HeapFree(GetProcessHeap(),
1354 /***************************************************************************
1356 * DevicePropertiesExA
1359 * Invokes the extended device properties dialog
1362 * hWndParent: Handle to the parent window
1363 * lpMachineName: Machine Name, NULL is the local machine
1364 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1365 * bShowDevMgr is nonzero
1366 * dwFlags: This parameter can be a combination of the following flags:
1367 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1368 * the default device status action button
1369 * to be clicked (Troubleshoot, Enable
1371 * bShowDevMgr: If non-zero it displays the device manager instead of
1372 * the advanced device property dialog
1375 * 1: if bShowDevMgr is non-zero and no error occured
1376 * -1: a call to GetLastError returns 0 if successful
1382 DevicePropertiesExA(IN HWND hWndParent OPTIONAL
,
1383 IN LPCSTR lpMachineName OPTIONAL
,
1384 IN LPCSTR lpDeviceID OPTIONAL
,
1385 IN DWORD dwFlags OPTIONAL
,
1386 IN BOOL bShowDevMgr
)
1388 LPWSTR lpMachineNameW
= NULL
;
1389 LPWSTR lpDeviceIDW
= NULL
;
1392 if (lpMachineName
!= NULL
)
1394 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
1400 if (lpDeviceID
!= NULL
)
1402 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
1409 Ret
= DevicePropertiesExW(hWndParent
,
1416 if (lpMachineNameW
!= NULL
)
1418 HeapFree(GetProcessHeap(),
1422 if (lpDeviceIDW
!= NULL
)
1424 HeapFree(GetProcessHeap(),
1433 /***************************************************************************
1435 * DevicePropertiesExW
1438 * Invokes the extended device properties dialog
1441 * hWndParent: Handle to the parent window
1442 * lpMachineName: Machine Name, NULL is the local machine
1443 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1444 * bShowDevMgr is nonzero
1445 * dwFlags: This parameter can be a combination of the following flags:
1446 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1447 * the default device status action button
1448 * to be clicked (Troubleshoot, Enable
1450 * bShowDevMgr: If non-zero it displays the device manager instead of
1451 * the advanced device property dialog
1454 * 1: if bShowDevMgr is non-zero and no error occured
1455 * -1: a call to GetLastError returns 0 if successful
1461 DevicePropertiesExW(IN HWND hWndParent OPTIONAL
,
1462 IN LPCWSTR lpMachineName OPTIONAL
,
1463 IN LPCWSTR lpDeviceID OPTIONAL
,
1464 IN DWORD dwFlags OPTIONAL
,
1465 IN BOOL bShowDevMgr
)
1469 if (dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
))
1471 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1472 dwFlags
& ~(DPF_UNKNOWN
| DPF_DEVICE_STATUS_ACTION
));
1473 SetLastError(ERROR_INVALID_FLAGS
);
1479 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1480 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1485 SP_DEVINFO_DATA DevInfoData
;
1486 HINSTANCE hComCtl32
;
1488 if (lpDeviceID
== NULL
)
1490 SetLastError(ERROR_INVALID_PARAMETER
);
1494 /* dynamically load comctl32 */
1495 hComCtl32
= LoadAndInitComctl32();
1496 if (hComCtl32
!= NULL
)
1498 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
1502 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
1504 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1505 if (SetupDiOpenDeviceInfo(hDevInfo
,
1511 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
1520 SetupDiDestroyDeviceInfoList(hDevInfo
);
1523 FreeLibrary(hComCtl32
);