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
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/hwpage.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 typedef VOID (WINAPI
*PINITCOMMONCONTROLS
)(VOID
);
37 HWPD_STANDARDLIST
= 0,
39 HWPD_MAX
= HWPD_LARGELIST
40 } HWPAGE_DISPLAYMODE
, *PHWPAGE_DISPLAYMODE
;
42 typedef struct _HWDEVINFO
44 struct _HWCLASSDEVINFO
*ClassDevInfo
;
45 SP_DEVINFO_DATA DevInfoData
;
46 } HWDEVINFO
, *PHWDEVINFO
;
48 typedef struct _HWCLASSDEVINFO
54 } HWCLASSDEVINFO
, *PHWCLASSDEVINFO
;
56 typedef struct _HARDWARE_PAGE_DATA
60 HINSTANCE hComCtl32
; /* only save this to keep track of the references */
61 SP_CLASSIMAGELIST_DATA ClassImageListData
;
62 HWPAGE_DISPLAYMODE DisplayMode
;
64 /* parent window subclass info */
65 WNDPROC ParentOldWndProc
;
69 HWCLASSDEVINFO ClassDevInfo
[1];
70 /* struct may be dynamically expanded here! */
71 } HARDWARE_PAGE_DATA
, *PHARDWARE_PAGE_DATA
;
73 #define CX_TYPECOLUMN_WIDTH 80
76 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
83 /* set the list view style */
84 ListView_SetExtendedListViewStyle(hpd
->hWndDevList
,
85 LVS_EX_FULLROWSELECT
);
87 /* set the list view image list */
88 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
90 ListView_SetImageList(hpd
->hWndDevList
,
91 hpd
->ClassImageListData
.ImageList
,
95 GetClientRect(hpd
->hWndDevList
,
98 /* add the list view columns */
99 lvc
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
100 lvc
.fmt
= LVCFMT_LEFT
;
101 lvc
.pszText
= szColName
;
103 if (LoadString(hDllInstance
,
106 sizeof(szColName
) / sizeof(szColName
[0])))
108 lvc
.cx
= rcClient
.right
- CX_TYPECOLUMN_WIDTH
-
109 GetSystemMetrics(SM_CXVSCROLL
);
110 ListView_InsertColumn(hpd
->hWndDevList
,
114 if (LoadString(hDllInstance
,
117 sizeof(szColName
) / sizeof(szColName
[0])))
119 lvc
.cx
= CX_TYPECOLUMN_WIDTH
;
120 ListView_InsertColumn(hpd
->hWndDevList
,
128 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd
)
130 PHWDEVINFO HwDevInfo
;
132 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
133 if (HwDevInfo
!= NULL
)
135 /* FIXME - update static controls and enable buttons */
139 /* FIXME - clear static controls and disable buttons */
145 FillDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
147 PHWCLASSDEVINFO DevInfo
, LastDevInfo
;
148 SP_DEVINFO_DATA DevInfoData
;
152 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
154 DevInfo
= hpd
->ClassDevInfo
;
155 LastDevInfo
= DevInfo
+ hpd
->NumberOfGuids
;
157 while (DevInfo
!= LastDevInfo
)
161 DevInfo
->hDevInfo
= SetupDiGetClassDevs(&DevInfo
->Guid
,
165 if (DevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
168 DWORD MemberIndex
= 0;
170 SetupDiGetClassImageIndex(&hpd
->ClassImageListData
,
174 while (SetupDiEnumDeviceInfo(DevInfo
->hDevInfo
,
181 if (DevInfo
->HwDevInfo
!= NULL
)
183 PHWDEVINFO HwNewDevInfo
= HeapReAlloc(GetProcessHeap(),
186 (DevInfo
->ItemCount
+ 1) *
188 if (HwNewDevInfo
!= NULL
)
190 DevInfo
->HwDevInfo
= HwNewDevInfo
;
191 DevInfo
->HwDevInfo
[DevInfo
->ItemCount
].ClassDevInfo
= DevInfo
;
192 DevInfo
->HwDevInfo
[DevInfo
->ItemCount
++].DevInfoData
= DevInfoData
;
196 DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
197 DevInfo
->ItemCount
+ 1);
203 DevInfo
->HwDevInfo
= HeapAlloc(GetProcessHeap(),
206 if (DevInfo
->HwDevInfo
!= NULL
)
208 DevInfo
->HwDevInfo
[DevInfo
->ItemCount
].ClassDevInfo
= DevInfo
;
209 DevInfo
->HwDevInfo
[DevInfo
->ItemCount
++].DevInfoData
= DevInfoData
;
213 DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
218 if ((SetupDiGetDeviceRegistryProperty(DevInfo
->hDevInfo
,
225 SetupDiGetDeviceRegistryProperty(DevInfo
->hDevInfo
,
232 RegDataType
== REG_SZ
)
234 /* FIXME - check string for NULL termination! */
236 li
.mask
= LVIF_PARAM
| LVIF_STATE
| LVIF_TEXT
| LVIF_IMAGE
;
237 li
.iItem
= ItemCount
;
239 li
.state
= (ItemCount
== 0 ? LVIS_SELECTED
: 0);
240 li
.stateMask
= LVIS_SELECTED
;
241 li
.pszText
= szBuffer
;
242 li
.iImage
= ImageIndex
;
243 li
.lParam
= (LPARAM
)&DevInfo
->HwDevInfo
[DevInfo
->ItemCount
- 1];
245 iItem
= ListView_InsertItem(hpd
->hWndDevList
,
251 if (SetupDiGetClassDescription(&DevInfo
->Guid
,
253 sizeof(szBuffer
) / sizeof(szBuffer
[0]),
260 ListView_SetItem(hpd
->hWndDevList
,
271 /* update the controls */
272 UpdateControlStates(hpd
);
278 ParentSubWndProc(IN HWND hwnd
,
283 PHARDWARE_PAGE_DATA hpd
;
285 hpd
= (PHARDWARE_PAGE_DATA
)GetProp(hwnd
,
286 L
"DevMgrSubClassInfo");
291 /* resize the hardware page */
292 SetWindowPos(hpd
->hWnd
,
301 /* pass the message the the old window proc */
302 return CallWindowProc(hpd
->ParentOldWndProc
,
310 /* this is not a good idea if the subclassed window was an ansi
311 window, but we failed finding out the previous window proc
312 so we can't use CallWindowProc. This should rarely - if ever -
315 return DefWindowProc(hwnd
,
324 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd
,
329 HWND hControl
, hButton
;
330 INT Width
, x
, y
, TopBias
= 0;
333 POINT ptMargin
= {0};
334 POINT ptMarginGroup
= {0};
336 /* use left margin of the IDC_DEVICES label as the right
337 margin of all controls outside the group box */
338 hControl
= GetDlgItem(hpd
->hWnd
,
340 GetWindowRect(hControl
,
342 MapWindowPoints(hControl
,
347 Width
= cx
- (2 * ptMargin
.x
);
349 if ((dwp
= BeginDeferWindowPos(8)))
351 /* rc already has the window rect of IDC_DEVICES! */
352 if (!(dwp
= DeferWindowPos(dwp
,
359 SWP_NOMOVE
| SWP_NOZORDER
)))
364 /* resize the devices list view control */
365 GetWindowRect(hpd
->hWndDevList
,
367 MapWindowPoints(hpd
->hWndDevList
,
371 if (hpd
->DisplayMode
== HWPD_LARGELIST
)
373 /* increase the size of the list view control by 2/3 */
374 TopBias
= ((rc
.bottom
- rc
.top
) * 2) / 3;
376 y
= pt
.y
+ TopBias
+ rc
.bottom
- rc
.top
+ ptMargin
.y
;
377 if (!(dwp
= DeferWindowPos(dwp
,
383 rc
.bottom
- rc
.top
+ TopBias
,
384 SWP_NOMOVE
| SWP_NOZORDER
)))
389 /* resize the group box control */
390 hControl
= GetDlgItem(hpd
->hWnd
,
391 IDC_PROPERTIESGROUP
);
392 GetWindowRect(hControl
,
394 if (!(dwp
= DeferWindowPos(dwp
,
406 /* use left margin of the IDC_MANUFACTURER label as the right
407 margin of all controls inside the group box */
408 hControl
= GetDlgItem(hpd
->hWnd
,
410 GetWindowRect(hControl
,
412 MapWindowPoints(hControl
,
417 ptMarginGroup
.y
= ptMargin
.y
* 2;
418 Width
= cx
- (2 * ptMarginGroup
.x
);
419 y
+= ptMarginGroup
.y
;
420 if (!(dwp
= DeferWindowPos(dwp
,
431 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
433 /* resize the IDC_LOCATION label */
434 hControl
= GetDlgItem(hpd
->hWnd
,
436 GetWindowRect(hControl
,
438 if (!(dwp
= DeferWindowPos(dwp
,
449 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
451 /* measure the size of the buttons */
452 hButton
= GetDlgItem(hpd
->hWnd
,
454 GetWindowRect(hButton
,
457 /* resize the IDC_STATUS label */
458 hControl
= GetDlgItem(hpd
->hWnd
,
460 GetWindowRect(hControl
,
462 if (!(dwp
= DeferWindowPos(dwp
,
468 cy
- y
- (3 * ptMargin
.y
) -
469 (rcButton
.bottom
- rcButton
.top
),
475 /* move the IDC_PROPERTIES button */
476 y
= cy
- (2 * ptMargin
.y
) - (rcButton
.bottom
- rcButton
.top
);
477 x
= cx
- ptMarginGroup
.x
- (rcButton
.right
- rcButton
.left
);
478 if (!(dwp
= DeferWindowPos(dwp
,
485 SWP_NOSIZE
| SWP_NOZORDER
)))
490 /* move the IDC_TROUBLESHOOT button */
491 hButton
= GetDlgItem(hpd
->hWnd
,
493 GetWindowRect(hButton
,
495 x
-= (ptMargin
.x
/ 2) + (rcButton
.right
- rcButton
.left
);
496 if (!(dwp
= DeferWindowPos(dwp
,
503 SWP_NOSIZE
| SWP_NOZORDER
)))
508 EndDeferWindowPos(dwp
);
515 HardwareDlgProc(IN HWND hwndDlg
,
520 PHARDWARE_PAGE_DATA hpd
;
522 hpd
= (PHARDWARE_PAGE_DATA
)GetWindowLongPtr(hwndDlg
,
525 if (hpd
!= NULL
|| uMsg
== WM_INITDIALOG
)
531 NMHDR
*pnmh
= (NMHDR
*)lParam
;
532 if (pnmh
->hwndFrom
== hpd
->hWndDevList
)
536 case LVN_ITEMCHANGED
:
538 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
)lParam
;
540 if ((pnmv
->uChanged
& LVIF_STATE
) &&
541 ((pnmv
->uOldState
& (LVIS_FOCUSED
| LVIS_SELECTED
)) ||
542 (pnmv
->uNewState
& (LVIS_FOCUSED
| LVIS_SELECTED
))))
544 UpdateControlStates(hpd
);
554 HardwareDlgResize(hpd
,
556 (INT
)HIWORD(lParam
));
561 hpd
= (PHARDWARE_PAGE_DATA
)lParam
;
567 SetWindowLongPtr(hwndDlg
,
571 hpd
->ClassImageListData
.cbSize
= sizeof(SP_CLASSIMAGELIST_DATA
);
573 SetupDiGetClassImageList(&hpd
->ClassImageListData
);
575 hpd
->hWndDevList
= GetDlgItem(hwndDlg
,
578 /* subclass the parent window */
579 hWndParent
= GetAncestor(hwndDlg
,
581 if (hWndParent
!= NULL
)
585 if (GetClientRect(hWndParent
,
587 SetWindowPos(hwndDlg
,
595 /* subclass the parent window. This is not safe
596 if the parent window belongs to another thread! */
597 hpd
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
599 (LONG_PTR
)ParentSubWndProc
);
601 if (hpd
->ParentOldWndProc
!= NULL
&&
603 L
"DevMgrSubClassInfo",
606 hpd
->hWndParent
= hWndParent
;
611 /* initialize the devices list view control */
612 InitializeDevicesList(hpd
);
614 /* fill the devices list view control */
615 FillDevicesList(hpd
);
624 /* free the device info set handles */
626 i
< hpd
->NumberOfGuids
;
629 SetupDiDestroyDeviceInfoList(hpd
->ClassDevInfo
[i
].hDevInfo
);
630 if (hpd
->ClassDevInfo
[i
].HwDevInfo
!= NULL
)
632 HeapFree(GetProcessHeap(),
634 hpd
->ClassDevInfo
[i
].HwDevInfo
);
638 /* restore the old window proc of the subclassed parent window */
639 if (hpd
->hWndParent
!= NULL
&& hpd
->ParentOldWndProc
!= NULL
)
641 SetWindowLongPtr(hpd
->hWndParent
,
643 (LONG_PTR
)hpd
->ParentOldWndProc
);
646 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
648 SetupDiDestroyClassImageList(&hpd
->ClassImageListData
);
651 /* free the reference to comctl32 */
652 FreeLibrary(hpd
->hComCtl32
);
653 hpd
->hComCtl32
= NULL
;
655 /* free the allocated resources */
656 HeapFree(GetProcessHeap(),
668 /***************************************************************************
670 * DeviceCreateHardwarePageEx
673 * Creates a hardware page
676 * hWndParent: Handle to the parent window
677 * lpGuids: An array of guids of devices that are to be listed
678 * uNumberOfGuids: Numbers of guids in the Guids array
679 * Unknown: Unknown parameter, see NOTEs
682 * Returns the handle of the hardware page window that has been created or
686 * 13-05-2005 first working version (Sebastian Gasiorek <zebasoftis@gmail.com>)
689 * missing: device icon in list view, Troubleshoot button, device properties,
690 * status description,
691 * devices should be visible afer PSN_SETACTIVE message
696 DeviceCreateHardwarePageEx(IN HWND hWndParent
,
698 IN UINT uNumberOfGuids
,
699 IN HWPAGE_DISPLAYMODE DisplayMode
)
701 PHARDWARE_PAGE_DATA hpd
;
702 PINITCOMMONCONTROLS pInitCommonControls
;
704 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
705 zeroed because the initialization code assumes that in
707 hpd
= HeapAlloc(GetProcessHeap(),
709 FIELD_OFFSET(HARDWARE_PAGE_DATA
,
711 (uNumberOfGuids
* sizeof(HWCLASSDEVINFO
)));
717 hpd
->DisplayMode
= ((DisplayMode
> HWPD_MAX
) ? HWPD_STANDARDLIST
: DisplayMode
);
719 /* initialize the HARDWARE_PAGE_DATA structure */
720 hpd
->NumberOfGuids
= uNumberOfGuids
;
725 hpd
->ClassDevInfo
[i
].Guid
= lpGuids
[i
];
728 /* load comctl32.dll dynamically */
729 hpd
->hComCtl32
= LoadLibrary(TEXT("comctl32.dll"));
730 if (hpd
->hComCtl32
== NULL
)
735 /* initialize the common controls */
736 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hpd
->hComCtl32
,
737 "InitCommonControls");
738 if (pInitCommonControls
== NULL
)
742 pInitCommonControls();
744 /* create the dialog */
745 hWnd
= CreateDialogParam(hDllInstance
,
746 MAKEINTRESOURCE(IDD_HARDWARE
),
757 /* oops, something went wrong... */
758 if (hpd
->hComCtl32
!= NULL
)
760 FreeLibrary(hpd
->hComCtl32
);
763 HeapFree(GetProcessHeap(),
773 /***************************************************************************
775 * DeviceCreateHardwarePage
778 * Creates a hardware page
781 * hWndParent: Handle to the parent window
782 * lpGuid: Guid of the device
785 * Returns the handle of the hardware page window that has been created or
796 DeviceCreateHardwarePage(IN HWND hWndParent
,
799 return DeviceCreateHardwarePageEx(hWndParent
,