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 INT DevListViewHeight
;
62 SP_CLASSIMAGELIST_DATA ClassImageListData
;
63 HWPAGE_DISPLAYMODE DisplayMode
;
65 /* parent window subclass info */
66 WNDPROC ParentOldWndProc
;
70 HWCLASSDEVINFO ClassDevInfo
[1];
71 /* struct may be dynamically expanded here! */
72 } HARDWARE_PAGE_DATA
, *PHARDWARE_PAGE_DATA
;
74 #define CX_TYPECOLUMN_WIDTH 80
77 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
84 /* set the list view style */
85 ListView_SetExtendedListViewStyle(hpd
->hWndDevList
,
86 LVS_EX_FULLROWSELECT
);
88 /* set the list view image list */
89 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
91 ListView_SetImageList(hpd
->hWndDevList
,
92 hpd
->ClassImageListData
.ImageList
,
96 GetClientRect(hpd
->hWndDevList
,
99 /* add the list view columns */
100 lvc
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
101 lvc
.fmt
= LVCFMT_LEFT
;
102 lvc
.pszText
= szColName
;
104 if (LoadString(hDllInstance
,
107 sizeof(szColName
) / sizeof(szColName
[0])))
109 lvc
.cx
= rcClient
.right
- CX_TYPECOLUMN_WIDTH
-
110 GetSystemMetrics(SM_CXVSCROLL
);
111 ListView_InsertColumn(hpd
->hWndDevList
,
115 if (LoadString(hDllInstance
,
118 sizeof(szColName
) / sizeof(szColName
[0])))
120 lvc
.cx
= CX_TYPECOLUMN_WIDTH
;
121 ListView_InsertColumn(hpd
->hWndDevList
,
129 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd
)
131 PHWDEVINFO HwDevInfo
;
133 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
134 if (HwDevInfo
!= NULL
)
136 /* FIXME - update static controls and enable buttons */
140 /* FIXME - clear static controls and disable buttons */
146 FillDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
148 PHWCLASSDEVINFO DevInfo
, LastDevInfo
;
149 SP_DEVINFO_DATA DevInfoData
;
153 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
155 DevInfo
= hpd
->ClassDevInfo
;
156 LastDevInfo
= DevInfo
+ hpd
->NumberOfGuids
;
158 while (DevInfo
!= LastDevInfo
)
162 DevInfo
->hDevInfo
= SetupDiGetClassDevs(&DevInfo
->Guid
,
166 if (DevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
169 DWORD MemberIndex
= 0;
171 SetupDiGetClassImageIndex(&hpd
->ClassImageListData
,
175 while (SetupDiEnumDeviceInfo(DevInfo
->hDevInfo
,
182 if (DevInfo
->HwDevInfo
!= NULL
)
184 PHWDEVINFO HwNewDevInfo
= HeapReAlloc(GetProcessHeap(),
187 (DevInfo
->ItemCount
+ 1) *
189 if (HwNewDevInfo
!= NULL
)
191 DevInfo
->HwDevInfo
= HwNewDevInfo
;
195 DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
196 DevInfo
->ItemCount
+ 1);
202 DevInfo
->HwDevInfo
= HeapAlloc(GetProcessHeap(),
205 if (DevInfo
->HwDevInfo
== NULL
)
207 DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
212 DevInfo
->HwDevInfo
[DevInfo
->ItemCount
].ClassDevInfo
= DevInfo
;
213 DevInfo
->HwDevInfo
[DevInfo
->ItemCount
++].DevInfoData
= DevInfoData
;
215 if ((SetupDiGetDeviceRegistryProperty(DevInfo
->hDevInfo
,
222 SetupDiGetDeviceRegistryProperty(DevInfo
->hDevInfo
,
229 RegDataType
== REG_SZ
)
231 /* FIXME - check string for NULL termination! */
233 li
.mask
= LVIF_PARAM
| LVIF_STATE
| LVIF_TEXT
| LVIF_IMAGE
;
234 li
.iItem
= ItemCount
;
236 li
.state
= (ItemCount
== 0 ? LVIS_SELECTED
: 0);
237 li
.stateMask
= LVIS_SELECTED
;
238 li
.pszText
= szBuffer
;
239 li
.iImage
= ImageIndex
;
240 li
.lParam
= (LPARAM
)&DevInfo
->HwDevInfo
[DevInfo
->ItemCount
- 1];
242 iItem
= ListView_InsertItem(hpd
->hWndDevList
,
248 if (SetupDiGetClassDescription(&DevInfo
->Guid
,
250 sizeof(szBuffer
) / sizeof(szBuffer
[0]),
257 ListView_SetItem(hpd
->hWndDevList
,
268 /* update the controls */
269 UpdateControlStates(hpd
);
275 ParentSubWndProc(IN HWND hwnd
,
280 PHARDWARE_PAGE_DATA hpd
;
282 hpd
= (PHARDWARE_PAGE_DATA
)GetProp(hwnd
,
283 L
"DevMgrSubClassInfo");
288 /* resize the hardware page */
289 SetWindowPos(hpd
->hWnd
,
298 /* pass the message the the old window proc */
299 return CallWindowProc(hpd
->ParentOldWndProc
,
307 /* this is not a good idea if the subclassed window was an ansi
308 window, but we failed finding out the previous window proc
309 so we can't use CallWindowProc. This should rarely - if ever -
312 return DefWindowProc(hwnd
,
321 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd
,
326 HWND hControl
, hButton
;
330 POINT ptMargin
= {0};
331 POINT ptMarginGroup
= {0};
333 /* use left margin of the IDC_DEVICES label as the right
334 margin of all controls outside the group box */
335 hControl
= GetDlgItem(hpd
->hWnd
,
337 GetWindowRect(hControl
,
339 MapWindowPoints(hControl
,
344 Width
= cx
- (2 * ptMargin
.x
);
346 if ((dwp
= BeginDeferWindowPos(8)))
348 /* rc already has the window rect of IDC_DEVICES! */
349 if (!(dwp
= DeferWindowPos(dwp
,
356 SWP_NOMOVE
| SWP_NOZORDER
)))
361 /* resize the devices list view control */
362 GetWindowRect(hpd
->hWndDevList
,
364 MapWindowPoints(hpd
->hWndDevList
,
368 y
= pt
.y
+ hpd
->DevListViewHeight
+ ptMargin
.y
;
369 if (!(dwp
= DeferWindowPos(dwp
,
375 hpd
->DevListViewHeight
,
376 SWP_NOMOVE
| SWP_NOZORDER
)))
381 /* resize the group box control */
382 hControl
= GetDlgItem(hpd
->hWnd
,
383 IDC_PROPERTIESGROUP
);
384 GetWindowRect(hControl
,
386 if (!(dwp
= DeferWindowPos(dwp
,
398 /* use left margin of the IDC_MANUFACTURER label as the right
399 margin of all controls inside the group box */
400 hControl
= GetDlgItem(hpd
->hWnd
,
402 GetWindowRect(hControl
,
404 MapWindowPoints(hControl
,
409 ptMarginGroup
.y
= ptMargin
.y
* 2;
410 Width
= cx
- (2 * ptMarginGroup
.x
);
411 y
+= ptMarginGroup
.y
;
412 if (!(dwp
= DeferWindowPos(dwp
,
423 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
425 /* resize the IDC_LOCATION label */
426 hControl
= GetDlgItem(hpd
->hWnd
,
428 GetWindowRect(hControl
,
430 if (!(dwp
= DeferWindowPos(dwp
,
441 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
443 /* measure the size of the buttons */
444 hButton
= GetDlgItem(hpd
->hWnd
,
446 GetWindowRect(hButton
,
449 /* resize the IDC_STATUS label */
450 hControl
= GetDlgItem(hpd
->hWnd
,
452 GetWindowRect(hControl
,
454 if (!(dwp
= DeferWindowPos(dwp
,
460 cy
- y
- (3 * ptMargin
.y
) -
461 (rcButton
.bottom
- rcButton
.top
),
467 /* move the IDC_PROPERTIES button */
468 y
= cy
- (2 * ptMargin
.y
) - (rcButton
.bottom
- rcButton
.top
);
469 x
= cx
- ptMarginGroup
.x
- (rcButton
.right
- rcButton
.left
);
470 if (!(dwp
= DeferWindowPos(dwp
,
477 SWP_NOSIZE
| SWP_NOZORDER
)))
482 /* move the IDC_TROUBLESHOOT button */
483 hButton
= GetDlgItem(hpd
->hWnd
,
485 GetWindowRect(hButton
,
487 x
-= (ptMargin
.x
/ 2) + (rcButton
.right
- rcButton
.left
);
488 if (!(dwp
= DeferWindowPos(dwp
,
495 SWP_NOSIZE
| SWP_NOZORDER
)))
500 EndDeferWindowPos(dwp
);
507 HardwareDlgProc(IN HWND hwndDlg
,
512 PHARDWARE_PAGE_DATA hpd
;
514 hpd
= (PHARDWARE_PAGE_DATA
)GetWindowLongPtr(hwndDlg
,
517 if (hpd
!= NULL
|| uMsg
== WM_INITDIALOG
)
523 NMHDR
*pnmh
= (NMHDR
*)lParam
;
524 if (pnmh
->hwndFrom
== hpd
->hWndDevList
)
528 case LVN_ITEMCHANGED
:
530 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
)lParam
;
532 if ((pnmv
->uChanged
& LVIF_STATE
) &&
533 ((pnmv
->uOldState
& (LVIS_FOCUSED
| LVIS_SELECTED
)) ||
534 (pnmv
->uNewState
& (LVIS_FOCUSED
| LVIS_SELECTED
))))
536 UpdateControlStates(hpd
);
546 HardwareDlgResize(hpd
,
548 (INT
)HIWORD(lParam
));
553 hpd
= (PHARDWARE_PAGE_DATA
)lParam
;
559 SetWindowLongPtr(hwndDlg
,
563 hpd
->ClassImageListData
.cbSize
= sizeof(SP_CLASSIMAGELIST_DATA
);
565 SetupDiGetClassImageList(&hpd
->ClassImageListData
);
567 /* calculate the size of the devices list view control */
568 hpd
->hWndDevList
= GetDlgItem(hwndDlg
,
570 if (hpd
->hWndDevList
!= NULL
)
573 GetClientRect(hpd
->hWndDevList
,
575 hpd
->DevListViewHeight
= rcClient
.bottom
;
577 if (hpd
->DisplayMode
== HWPD_LARGELIST
)
579 hpd
->DevListViewHeight
= (hpd
->DevListViewHeight
* 3) / 2;
583 /* subclass the parent window */
584 hWndParent
= GetAncestor(hwndDlg
,
586 if (hWndParent
!= NULL
)
590 if (GetClientRect(hWndParent
,
592 SetWindowPos(hwndDlg
,
600 /* subclass the parent window. This is not safe
601 if the parent window belongs to another thread! */
602 hpd
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
604 (LONG_PTR
)ParentSubWndProc
);
606 if (hpd
->ParentOldWndProc
!= NULL
&&
608 L
"DevMgrSubClassInfo",
611 hpd
->hWndParent
= hWndParent
;
616 /* initialize the devices list view control */
617 InitializeDevicesList(hpd
);
619 /* fill the devices list view control */
620 FillDevicesList(hpd
);
629 /* free the device info set handles */
631 i
< hpd
->NumberOfGuids
;
634 SetupDiDestroyDeviceInfoList(hpd
->ClassDevInfo
[i
].hDevInfo
);
635 if (hpd
->ClassDevInfo
[i
].HwDevInfo
!= NULL
)
637 HeapFree(GetProcessHeap(),
639 hpd
->ClassDevInfo
[i
].HwDevInfo
);
643 /* restore the old window proc of the subclassed parent window */
644 if (hpd
->hWndParent
!= NULL
&& hpd
->ParentOldWndProc
!= NULL
)
646 SetWindowLongPtr(hpd
->hWndParent
,
648 (LONG_PTR
)hpd
->ParentOldWndProc
);
651 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
653 SetupDiDestroyClassImageList(&hpd
->ClassImageListData
);
656 /* free the reference to comctl32 */
657 FreeLibrary(hpd
->hComCtl32
);
658 hpd
->hComCtl32
= NULL
;
660 /* free the allocated resources */
661 HeapFree(GetProcessHeap(),
673 /***************************************************************************
675 * DeviceCreateHardwarePageEx
678 * Creates a hardware page
681 * hWndParent: Handle to the parent window
682 * lpGuids: An array of guids of devices that are to be listed
683 * uNumberOfGuids: Numbers of guids in the Guids array
684 * Unknown: Unknown parameter, see NOTEs
687 * Returns the handle of the hardware page window that has been created or
691 * 13-05-2005 first working version (Sebastian Gasiorek <zebasoftis@gmail.com>)
694 * missing: device icon in list view, Troubleshoot button, device properties,
695 * status description,
696 * devices should be visible afer PSN_SETACTIVE message
701 DeviceCreateHardwarePageEx(IN HWND hWndParent
,
703 IN UINT uNumberOfGuids
,
704 IN HWPAGE_DISPLAYMODE DisplayMode
)
706 PHARDWARE_PAGE_DATA hpd
;
707 PINITCOMMONCONTROLS pInitCommonControls
;
709 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
710 zeroed because the initialization code assumes that in
712 hpd
= HeapAlloc(GetProcessHeap(),
714 FIELD_OFFSET(HARDWARE_PAGE_DATA
,
716 (uNumberOfGuids
* sizeof(HWCLASSDEVINFO
)));
722 hpd
->DisplayMode
= ((DisplayMode
> HWPD_MAX
) ? HWPD_STANDARDLIST
: DisplayMode
);
724 /* initialize the HARDWARE_PAGE_DATA structure */
725 hpd
->NumberOfGuids
= uNumberOfGuids
;
730 hpd
->ClassDevInfo
[i
].Guid
= lpGuids
[i
];
733 /* load comctl32.dll dynamically */
734 hpd
->hComCtl32
= LoadLibrary(TEXT("comctl32.dll"));
735 if (hpd
->hComCtl32
== NULL
)
740 /* initialize the common controls */
741 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hpd
->hComCtl32
,
742 "InitCommonControls");
743 if (pInitCommonControls
== NULL
)
747 pInitCommonControls();
749 /* create the dialog */
750 hWnd
= CreateDialogParam(hDllInstance
,
751 MAKEINTRESOURCE(IDD_HARDWARE
),
762 /* oops, something went wrong... */
763 if (hpd
->hComCtl32
!= NULL
)
765 FreeLibrary(hpd
->hComCtl32
);
768 HeapFree(GetProcessHeap(),
778 /***************************************************************************
780 * DeviceCreateHardwarePage
783 * Creates a hardware page
786 * hWndParent: Handle to the parent window
787 * lpGuid: Guid of the device
790 * Returns the handle of the hardware page window that has been created or
800 DeviceCreateHardwarePage(IN HWND hWndParent
,
803 return DeviceCreateHardwarePageEx(hWndParent
,