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
46 HDEVINFO DeviceInfoSet
;
47 PSP_DEVINFO_DATA DeviceInfoData
;
55 /* struct may be dynamically expanded here! */
56 } DEVADVPROP_INFO
, *PDEVADVPROP_INFO
;
60 InitDevUsageActions(IN HWND hwndDlg
,
62 IN PDEVADVPROP_INFO dap
)
69 DEVENABLEACTION Action
;
72 {IDS_ENABLEDEVICE
, DEA_ENABLE
},
73 {IDS_DISABLEDEVICE
, DEA_DISABLE
},
77 i
!= sizeof(Actions
) / sizeof(Actions
[0]);
80 /* fill in the device usage combo box */
81 if (LoadString(hDllInstance
,
84 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
86 Index
= (INT
)SendMessage(hComboBox
,
92 SendMessage(hComboBox
,
95 (LPARAM
)Actions
[i
].Action
);
97 switch (Actions
[i
].Action
)
100 if (dap
->DeviceEnabled
)
102 SendMessage(hComboBox
,
110 if (!dap
->DeviceEnabled
)
112 SendMessage(hComboBox
,
128 static DEVENABLEACTION
129 GetSelectedUsageAction(IN HWND hComboBox
)
132 DEVENABLEACTION Ret
= DEA_UNKNOWN
;
134 Index
= (INT
)SendMessage(hComboBox
,
140 INT iRet
= SendMessage(hComboBox
,
144 if (iRet
!= CB_ERR
&& iRet
< (INT
)DEA_UNKNOWN
)
146 Ret
= (DEVENABLEACTION
)iRet
;
155 ApplyGeneralSettings(IN HWND hwndDlg
,
156 IN PDEVADVPROP_INFO dap
)
158 DEVENABLEACTION SelectedUsageAction
;
160 SelectedUsageAction
= GetSelectedUsageAction(GetDlgItem(hwndDlg
,
162 if (SelectedUsageAction
!= DEA_UNKNOWN
)
164 switch (SelectedUsageAction
)
167 if (!dap
->DeviceEnabled
)
169 /* FIXME - enable device */
174 if (dap
->DeviceEnabled
)
176 /* FIXME - disable device */
184 /* disable the apply button */
185 PropSheet_UnChanged(GetParent(hwndDlg
),
192 UpdateDevInfo(IN HWND hwndDlg
,
193 IN PDEVADVPROP_INFO dap
,
194 IN BOOL ReOpenDevice
)
201 /* note, we ignore the fact that SetupDiOpenDeviceInfo could fail here,
202 in case of failure we're still going to query information from it even
203 though those calls are going to fail. But they return readable strings
204 even in that case. */
205 SetupDiOpenDeviceInfo(dap
->DeviceInfoSet
,
209 dap
->DeviceInfoData
);
212 /* get the device name */
213 if (GetDeviceDescriptionString(dap
->DeviceInfoSet
,
216 sizeof(dap
->szDevName
) / sizeof(dap
->szDevName
[0])))
218 PropSheet_SetTitle(GetParent(hwndDlg
),
223 /* set the device image */
224 if (SetupDiLoadClassIcon(&dap
->DeviceInfoData
->ClassGuid
,
228 HICON hOldIcon
= (HICON
)SendDlgItemMessage(hwndDlg
,
233 if (hOldIcon
!= NULL
)
235 DestroyIcon(hOldIcon
);
239 /* set the device name edit control text */
240 SetDlgItemText(hwndDlg
,
244 /* set the device type edit control text */
245 if (GetDeviceTypeString(dap
->DeviceInfoData
,
247 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
249 SetDlgItemText(hwndDlg
,
254 /* set the device manufacturer edit control text */
255 if (GetDeviceManufacturerString(dap
->DeviceInfoSet
,
258 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
260 SetDlgItemText(hwndDlg
,
265 /* set the device location edit control text */
266 if (GetDeviceLocationString(dap
->DeviceInfoData
->DevInst
,
268 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
270 SetDlgItemText(hwndDlg
,
275 /* set the device status edit control text */
276 if (GetDeviceStatusString(dap
->DeviceInfoData
->DevInst
,
279 sizeof(dap
->szTemp
) / sizeof(dap
->szTemp
[0])))
281 SetDlgItemText(hwndDlg
,
286 /* check if the device can be enabled/disabled */
287 hDevUsage
= GetDlgItem(hwndDlg
,
290 if (!CanDisableDevice(dap
->DeviceInfoData
->DevInst
,
294 dap
->CanDisable
= FALSE
;
297 if (!IsDeviceEnabled(dap
->DeviceInfoData
->DevInst
,
299 &dap
->DeviceEnabled
))
301 dap
->DeviceEnabled
= FALSE
;
304 /* enable/disable the device usage controls */
305 EnableWindow(GetDlgItem(hwndDlg
,
308 EnableWindow(hDevUsage
,
311 /* clear the combobox */
312 SendMessage(hDevUsage
,
318 InitDevUsageActions(hwndDlg
,
323 /* finally, disable the apply button */
324 PropSheet_UnChanged(GetParent(hwndDlg
),
331 AdvPropGeneralDlgProc(IN HWND hwndDlg
,
336 PDEVADVPROP_INFO dap
;
339 dap
= (PDEVADVPROP_INFO
)GetWindowLongPtr(hwndDlg
,
342 if (dap
!= NULL
|| uMsg
== WM_INITDIALOG
)
348 switch (LOWORD(wParam
))
352 if (HIWORD(wParam
) == CBN_SELCHANGE
)
354 PropSheet_Changed(GetParent(hwndDlg
),
365 NMHDR
*hdr
= (NMHDR
*)lParam
;
369 ApplyGeneralSettings(hwndDlg
,
378 dap
= (PDEVADVPROP_INFO
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
381 SetWindowLongPtr(hwndDlg
,
385 UpdateDevInfo(hwndDlg
,
393 case WM_DEVICECHANGE
:
395 /* FIXME - don't call UpdateDevInfo in all events */
396 UpdateDevInfo(hwndDlg
,
406 /* destroy the device icon */
407 hDevIcon
= (HICON
)SendDlgItemMessage(hwndDlg
,
412 if (hDevIcon
!= NULL
)
414 DestroyIcon(hDevIcon
);
426 DisplayDeviceAdvancedProperties(IN HWND hWndParent
,
427 IN LPCWSTR lpDeviceID OPTIONAL
,
428 IN HDEVINFO DeviceInfoSet
,
429 IN PSP_DEVINFO_DATA DeviceInfoData
,
430 IN HINSTANCE hComCtl32
,
431 IN LPCWSTR lpMachineName
)
433 PROPSHEETHEADER psh
= {0};
434 PROPSHEETPAGE pspGeneral
= {0};
435 DWORD nPropSheets
= 0;
436 PPROPERTYSHEETW pPropertySheetW
;
437 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW
;
438 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage
;
439 PDEVADVPROP_INFO DevAdvPropInfo
;
440 DWORD PropertySheetType
;
441 HANDLE hMachine
= NULL
;
445 /* we don't want to statically link against comctl32, so find the
446 functions we need dynamically */
448 (PPROPERTYSHEETW
)GetProcAddress(hComCtl32
,
450 pCreatePropertySheetPageW
=
451 (PCREATEPROPERTYSHEETPAGEW
)GetProcAddress(hComCtl32
,
452 "CreatePropertySheetPageW");
453 pDestroyPropertySheetPage
=
454 (PDESTROYPROPERTYSHEETPAGE
)GetProcAddress(hComCtl32
,
455 "DestroyPropertySheetPage");
456 if (pPropertySheetW
== NULL
||
457 pCreatePropertySheetPageW
== NULL
||
458 pDestroyPropertySheetPage
== NULL
)
463 if (lpDeviceID
== NULL
)
465 /* find out how much size is needed for the device id */
466 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
472 DPRINT1("SetupDiGetDeviceInterfaceDetail unexpectedly returned TRUE!\n");
476 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
483 DevIdSize
= (DWORD
)wcslen(lpDeviceID
) + 1;
486 if (lpMachineName
!= NULL
)
488 CONFIGRET cr
= CM_Connect_Machine(lpMachineName
,
490 if (cr
!= CR_SUCCESS
)
496 /* create the internal structure associated with the "General",
497 "Driver", ... pages */
498 DevAdvPropInfo
= HeapAlloc(GetProcessHeap(),
500 FIELD_OFFSET(DEVADVPROP_INFO
,
502 (DevIdSize
* sizeof(WCHAR
)));
503 if (DevAdvPropInfo
== NULL
)
508 if (lpDeviceID
== NULL
)
510 /* read the device instance id */
511 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
513 DevAdvPropInfo
->szDeviceID
,
521 DevAdvPropInfo
->DeviceInfoSet
= DeviceInfoSet
;
522 DevAdvPropInfo
->DeviceInfoData
= DeviceInfoData
;
523 DevAdvPropInfo
->hComCtl32
= hComCtl32
;
524 DevAdvPropInfo
->hMachine
= hMachine
;
525 DevAdvPropInfo
->szDevName
[0] = L
'\0';
527 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
528 psh
.dwFlags
= PSH_PROPTITLE
| PSH_NOAPPLYNOW
;
529 psh
.hwndParent
= hWndParent
;
530 psh
.pszCaption
= DevAdvPropInfo
->szDevName
;
532 PropertySheetType
= lpMachineName
!= NULL
?
533 DIGCDP_FLAG_REMOTE_ADVANCED
:
534 DIGCDP_FLAG_ADVANCED
;
536 /* find out how many property sheets we need */
537 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
542 PropertySheetType
) &&
545 DPRINT1("SetupDiGetClassDevPropertySheets unexpectedly returned TRUE!\n");
549 if (nPropSheets
!= 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
554 psh
.phpage
= HeapAlloc(GetProcessHeap(),
556 (nPropSheets
+ 1) * sizeof(HPROPSHEETPAGE
));
557 if (psh
.phpage
== NULL
)
562 /* add the "General" property sheet */
563 pspGeneral
.dwSize
= sizeof(PROPSHEETPAGE
);
564 pspGeneral
.dwFlags
= PSP_DEFAULT
;
565 pspGeneral
.hInstance
= hDllInstance
;
566 pspGeneral
.pszTemplate
= (LPCWSTR
)MAKEINTRESOURCE(IDD_DEVICEGENERAL
);
567 pspGeneral
.pfnDlgProc
= AdvPropGeneralDlgProc
;
568 pspGeneral
.lParam
= (LPARAM
)DevAdvPropInfo
;
569 psh
.phpage
[0] = pCreatePropertySheetPageW(&pspGeneral
);
570 if (psh
.phpage
[0] != NULL
)
575 if (nPropSheets
!= 0)
577 /* create the device property sheets */
578 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet
,
581 nPropSheets
+ psh
.nPages
,
589 /* FIXME - add the "Driver" property sheet if necessary */
593 Ret
= pPropertySheetW(&psh
);
595 /* NOTE: no need to destroy the property sheets anymore! */
602 /* in case of failure the property sheets must be destroyed */
607 if (psh
.phpage
[i
] != NULL
)
609 pDestroyPropertySheetPage(psh
.phpage
[i
]);
614 HeapFree(GetProcessHeap(),
618 HeapFree(GetProcessHeap(),
622 if (hMachine
!= NULL
)
624 CM_Disconnect_Machine(hMachine
);
631 /***************************************************************************
633 * DeviceAdvancedPropertiesW
636 * Invokes the device properties dialog, this version may add some property pages
640 * hWndParent: Handle to the parent window
641 * lpMachineName: Machine Name, NULL is the local machine
642 * lpDeviceID: Specifies the device whose properties are to be shown
645 * -1: if errors occured
655 DeviceAdvancedPropertiesW(HWND hWndParent
,
656 LPCWSTR lpMachineName
,
660 SP_DEVINFO_DATA DevInfoData
;
664 /* dynamically load comctl32 */
665 hComCtl32
= LoadAndInitComctl32();
666 if (hComCtl32
!= NULL
)
668 if (lpMachineName
!= NULL
)
670 hDevInfo
= SetupDiCreateDeviceInfoListEx(NULL
,
677 hDevInfo
= SetupDiCreateDeviceInfoList(NULL
,
681 if (hDevInfo
!= INVALID_HANDLE_VALUE
)
683 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
684 if (SetupDiOpenDeviceInfo(hDevInfo
,
690 Ret
= DisplayDeviceAdvancedProperties(hWndParent
,
698 SetupDiDestroyDeviceInfoList(hDevInfo
);
701 FreeLibrary(hComCtl32
);
708 /***************************************************************************
710 * DeviceAdvancedPropertiesA
713 * Invokes the device properties dialog, this version may add some property pages
717 * hWndParent: Handle to the parent window
718 * lpMachineName: Machine Name, NULL is the local machine
719 * lpDeviceID: Specifies the device whose properties are to be shown
722 * -1: if errors occured
732 DeviceAdvancedPropertiesA(HWND hWndParent
,
733 LPCSTR lpMachineName
,
736 LPWSTR lpMachineNameW
= NULL
;
737 LPWSTR lpDeviceIDW
= NULL
;
740 if (lpMachineName
!= NULL
)
742 if (!(lpMachineNameW
= ConvertMultiByteToUnicode(lpMachineName
,
748 if (lpDeviceID
!= NULL
)
750 if (!(lpDeviceIDW
= ConvertMultiByteToUnicode(lpDeviceID
,
757 Ret
= DeviceAdvancedPropertiesW(hWndParent
,
762 if (lpMachineNameW
!= NULL
)
764 HeapFree(GetProcessHeap(),
768 if (lpDeviceIDW
!= NULL
)
770 HeapFree(GetProcessHeap(),