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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * PROJECT: ReactOS devmgr.dll
21 * FILE: lib/devmgr/hwpage.c
22 * PURPOSE: ReactOS Device Manager
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
31 typedef struct _HWDEVINFO
33 struct _HWCLASSDEVINFO
*ClassDevInfo
;
34 SP_DEVINFO_DATA DevInfoData
;
36 } HWDEVINFO
, *PHWDEVINFO
;
38 typedef struct _HWCLASSDEVINFO
45 } HWCLASSDEVINFO
, *PHWCLASSDEVINFO
;
47 typedef struct _HARDWARE_PAGE_DATA
51 HINSTANCE hComCtl32
; /* only save this to keep track of the references */
52 INT DevListViewHeight
;
53 SP_CLASSIMAGELIST_DATA ClassImageListData
;
54 HWPAGE_DISPLAYMODE DisplayMode
;
56 /* parent window subclass info */
57 WNDPROC ParentOldWndProc
;
61 HWCLASSDEVINFO ClassDevInfo
[1];
62 /* struct may be dynamically expanded here! */
63 } HARDWARE_PAGE_DATA
, *PHARDWARE_PAGE_DATA
;
65 #define CX_TYPECOLUMN_WIDTH 80
68 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
75 /* set the list view style */
76 (void)ListView_SetExtendedListViewStyle(hpd
->hWndDevList
,
77 LVS_EX_FULLROWSELECT
);
79 /* set the list view image list */
80 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
82 (void)ListView_SetImageList(hpd
->hWndDevList
,
83 hpd
->ClassImageListData
.ImageList
,
87 GetClientRect(hpd
->hWndDevList
,
90 /* add the list view columns */
91 lvc
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
92 lvc
.fmt
= LVCFMT_LEFT
;
93 lvc
.pszText
= szColName
;
95 if (LoadString(hDllInstance
,
98 sizeof(szColName
) / sizeof(szColName
[0])))
100 lvc
.cx
= rcClient
.right
- CX_TYPECOLUMN_WIDTH
-
101 GetSystemMetrics(SM_CXVSCROLL
);
102 (void)ListView_InsertColumn(hpd
->hWndDevList
,
106 if (LoadString(hDllInstance
,
109 sizeof(szColName
) / sizeof(szColName
[0])))
111 lvc
.cx
= CX_TYPECOLUMN_WIDTH
;
112 (void)ListView_InsertColumn(hpd
->hWndDevList
,
120 DisplaySelectedDeviceProperties(IN PHARDWARE_PAGE_DATA hpd
)
122 PHWDEVINFO HwDevInfo
;
123 SP_DEVINFO_DATA DevInfoData
;
126 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
127 if (HwDevInfo
!= NULL
)
129 /* make a copy of the SP_DEVINFO_DATA structure on the stack, it may
130 become invalid in case the devices are updated */
131 DevInfoData
= HwDevInfo
->DevInfoData
;
133 /* display the advanced properties */
134 Ret
= DisplayDeviceAdvancedProperties(hpd
->hWnd
,
136 HwDevInfo
->ClassDevInfo
->hDevInfo
,
148 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd
)
150 PHWDEVINFO HwDevInfo
;
151 HWND hBtnTroubleShoot
, hBtnProperties
;
153 hBtnTroubleShoot
= GetDlgItem(hpd
->hWnd
,
155 hBtnProperties
= GetDlgItem(hpd
->hWnd
,
158 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
159 if (HwDevInfo
!= NULL
)
161 /* update static controls */
163 LPWSTR szFormatted
= NULL
;
165 /* get the manufacturer string */
166 if (GetDeviceManufacturerString(HwDevInfo
->ClassDevInfo
->hDevInfo
,
167 &HwDevInfo
->DevInfoData
,
169 sizeof(szBuffer
) / sizeof(szBuffer
[0])) &&
170 LoadAndFormatString(hDllInstance
,
175 SetDlgItemText(hpd
->hWnd
,
178 LocalFree((HLOCAL
)szFormatted
);
181 /* get the location string */
182 if (GetDeviceLocationString(HwDevInfo
->ClassDevInfo
->hDevInfo
,
183 &HwDevInfo
->DevInfoData
,
186 sizeof(szBuffer
) / sizeof(szBuffer
[0])) &&
187 LoadAndFormatString(hDllInstance
,
192 SetDlgItemText(hpd
->hWnd
,
195 LocalFree((HLOCAL
)szFormatted
);
198 if (GetDeviceStatusString(HwDevInfo
->DevInfoData
.DevInst
,
201 sizeof(szBuffer
) / sizeof(szBuffer
[0])) &&
202 LoadAndFormatString(hDllInstance
,
207 SetDlgItemText(hpd
->hWnd
,
210 LocalFree((HLOCAL
)szFormatted
);
215 /* clear static controls */
216 SetDlgItemText(hpd
->hWnd
,
219 SetDlgItemText(hpd
->hWnd
,
222 SetDlgItemText(hpd
->hWnd
,
227 EnableWindow(hBtnTroubleShoot
,
229 EnableWindow(hBtnProperties
,
235 FreeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
237 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
239 ClassDevInfo
= hpd
->ClassDevInfo
;
240 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
242 /* free the device info set handles and structures */
243 while (ClassDevInfo
!= LastClassDevInfo
)
245 if (ClassDevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
247 SetupDiDestroyDeviceInfoList(ClassDevInfo
->hDevInfo
);
248 ClassDevInfo
->hDevInfo
= INVALID_HANDLE_VALUE
;
251 ClassDevInfo
->ItemCount
= 0;
252 ClassDevInfo
->ImageIndex
= 0;
254 if (ClassDevInfo
->HwDevInfo
!= NULL
)
256 HeapFree(GetProcessHeap(),
258 ClassDevInfo
->HwDevInfo
);
259 ClassDevInfo
->HwDevInfo
= NULL
;
268 BuildDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
270 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
271 SP_DEVINFO_DATA DevInfoData
;
273 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
275 ClassDevInfo
= hpd
->ClassDevInfo
;
276 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
278 while (ClassDevInfo
!= LastClassDevInfo
)
280 ClassDevInfo
->ImageIndex
= -1;
282 /* open a class device handle for the GUID we're processing */
283 ClassDevInfo
->hDevInfo
= SetupDiGetClassDevs(&ClassDevInfo
->Guid
,
286 DIGCF_PRESENT
| DIGCF_PROFILE
);
287 if (ClassDevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
289 DWORD MemberIndex
= 0;
291 SetupDiGetClassImageIndex(&hpd
->ClassImageListData
,
293 &ClassDevInfo
->ImageIndex
);
295 /* enumerate all devices in the class */
296 while (SetupDiEnumDeviceInfo(ClassDevInfo
->hDevInfo
,
300 BOOL HideDevice
= FALSE
;
302 if (ClassDevInfo
->HwDevInfo
!= NULL
)
304 PHWDEVINFO HwNewDevInfo
= HeapReAlloc(GetProcessHeap(),
306 ClassDevInfo
->HwDevInfo
,
307 (ClassDevInfo
->ItemCount
+ 1) *
309 if (HwNewDevInfo
!= NULL
)
311 ClassDevInfo
->HwDevInfo
= HwNewDevInfo
;
315 ERR("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
316 ClassDevInfo
->ItemCount
+ 1);
322 ClassDevInfo
->HwDevInfo
= HeapAlloc(GetProcessHeap(),
325 if (ClassDevInfo
->HwDevInfo
== NULL
)
327 ERR("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
332 /* Find out if the device should be hidden by default */
333 IsDeviceHidden(DevInfoData
.DevInst
,
337 /* save all information for the current device */
338 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
].ClassDevInfo
= ClassDevInfo
;
339 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
].DevInfoData
= DevInfoData
;
340 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
++].HideDevice
= HideDevice
;
350 DeviceIdMatch(IN HDEVINFO DeviceInfoSet
,
351 IN PSP_DEVINFO_DATA DeviceInfoData
,
352 IN LPCWSTR lpDeviceId
)
355 LPWSTR lpQueriedDeviceId
;
358 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
363 GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
365 if (DevIdLen
== wcslen(lpDeviceId
) + 1)
367 lpQueriedDeviceId
= HeapAlloc(GetProcessHeap(),
369 DevIdLen
* sizeof(WCHAR
));
370 if (lpQueriedDeviceId
!= NULL
)
372 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
378 Ret
= (wcscmp(lpDeviceId
,
379 lpQueriedDeviceId
) == 0);
382 HeapFree(GetProcessHeap(),
394 FillDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd
,
395 IN LPCWSTR lpSelectDeviceId OPTIONAL
,
396 IN GUID
*SelectedClassGuid OPTIONAL
)
398 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
399 PHWDEVINFO HwDevInfo
, LastHwDevInfo
;
401 BOOL SelectedInClass
;
404 BuildDevicesList(hpd
);
406 ClassDevInfo
= hpd
->ClassDevInfo
;
407 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
409 while (ClassDevInfo
!= LastClassDevInfo
)
411 if (ClassDevInfo
->HwDevInfo
!= NULL
)
413 HwDevInfo
= ClassDevInfo
->HwDevInfo
;
414 LastHwDevInfo
= HwDevInfo
+ ClassDevInfo
->ItemCount
;
416 SelectedInClass
= (SelectedClassGuid
!= NULL
&&
417 IsEqualGUID(SelectedClassGuid
,
418 &ClassDevInfo
->Guid
));
419 while (HwDevInfo
!= LastHwDevInfo
)
424 /* get the device name */
425 if (!HwDevInfo
->HideDevice
&&
426 GetDeviceDescriptionString(ClassDevInfo
->hDevInfo
,
427 &HwDevInfo
->DevInfoData
,
429 sizeof(szBuffer
) / sizeof(szBuffer
[0])))
431 li
.mask
= LVIF_PARAM
| LVIF_STATE
| LVIF_TEXT
| LVIF_IMAGE
;
432 li
.iItem
= ItemCount
;
433 if ((ItemCount
== 0 && lpSelectDeviceId
== NULL
) ||
435 DeviceIdMatch(ClassDevInfo
->hDevInfo
,
436 &HwDevInfo
->DevInfoData
,
439 li
.state
= LVIS_SELECTED
;
441 li
.stateMask
= LVIS_SELECTED
;
442 li
.pszText
= szBuffer
;
443 li
.iImage
= ClassDevInfo
->ImageIndex
;
444 li
.lParam
= (LPARAM
)HwDevInfo
;
446 iItem
= ListView_InsertItem(hpd
->hWndDevList
,
452 /* get the device type for the second column */
453 if (GetDeviceTypeString(&HwDevInfo
->DevInfoData
,
455 sizeof(szBuffer
) / sizeof(szBuffer
[0])))
461 (void)ListView_SetItem(hpd
->hWndDevList
,
474 /* update the controls */
475 UpdateControlStates(hpd
);
480 UpdateDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd
)
482 PHWDEVINFO HwDevInfo
;
483 GUID SelectedClassGuid
= {0};
484 LPWSTR lpDeviceId
= NULL
;
486 /* if a device currently is selected, remember the device id so we can
487 select the device after the update if still present */
488 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
489 if (HwDevInfo
!= NULL
)
492 if (!SetupDiGetDeviceInstanceId(HwDevInfo
->ClassDevInfo
->hDevInfo
,
493 &HwDevInfo
->DevInfoData
,
497 GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
499 SelectedClassGuid
= HwDevInfo
->DevInfoData
.ClassGuid
;
500 lpDeviceId
= HeapAlloc(GetProcessHeap(),
502 DevIdLen
* sizeof(WCHAR
));
503 if (lpDeviceId
!= NULL
&&
504 !SetupDiGetDeviceInstanceId(HwDevInfo
->ClassDevInfo
->hDevInfo
,
505 &HwDevInfo
->DevInfoData
,
510 HeapFree(GetProcessHeap(),
518 /* clear the devices list view control */
519 (void)ListView_DeleteAllItems(hpd
->hWndDevList
);
521 /* free the device list */
522 FreeDevicesList(hpd
);
524 /* build rebuild the device list and fill the list box again */
525 FillDevicesListViewControl(hpd
,
527 (lpDeviceId
!= NULL
?
531 if (lpDeviceId
!= NULL
)
533 HeapFree(GetProcessHeap(),
542 ParentSubWndProc(IN HWND hwnd
,
547 PHARDWARE_PAGE_DATA hpd
;
549 hpd
= (PHARDWARE_PAGE_DATA
)GetProp(hwnd
,
550 L
"DevMgrSubClassInfo");
555 /* resize the hardware page */
556 SetWindowPos(hpd
->hWnd
,
564 else if (uMsg
== WM_DEVICECHANGE
&& IsWindowVisible(hpd
->hWnd
))
566 /* forward a WM_DEVICECHANGE message to the hardware
567 page which wouldn't get the message itself as it is
569 SendMessage(hpd
->hWnd
,
575 /* pass the message the the old window proc */
576 return CallWindowProc(hpd
->ParentOldWndProc
,
584 /* this is not a good idea if the subclassed window was an ansi
585 window, but we failed finding out the previous window proc
586 so we can't use CallWindowProc. This should rarely - if ever -
589 return DefWindowProc(hwnd
,
598 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd
,
603 HWND hControl
, hButton
;
607 POINT ptMargin
= {0};
608 POINT ptMarginGroup
= {0};
610 /* use left margin of the IDC_DEVICES label as the right
611 margin of all controls outside the group box */
612 hControl
= GetDlgItem(hpd
->hWnd
,
614 GetWindowRect(hControl
,
616 MapWindowPoints(hControl
,
621 Width
= cx
- (2 * ptMargin
.x
);
623 if ((dwp
= BeginDeferWindowPos(8)))
625 /* rc already has the window rect of IDC_DEVICES! */
626 if (!(dwp
= DeferWindowPos(dwp
,
633 SWP_NOMOVE
| SWP_NOZORDER
)))
638 /* resize the devices list view control */
639 GetWindowRect(hpd
->hWndDevList
,
641 MapWindowPoints(hpd
->hWndDevList
,
645 y
= pt
.y
+ hpd
->DevListViewHeight
+ ptMargin
.y
;
646 if (!(dwp
= DeferWindowPos(dwp
,
652 hpd
->DevListViewHeight
,
653 SWP_NOMOVE
| SWP_NOZORDER
)))
658 /* resize the group box control */
659 hControl
= GetDlgItem(hpd
->hWnd
,
660 IDC_PROPERTIESGROUP
);
661 GetWindowRect(hControl
,
663 if (!(dwp
= DeferWindowPos(dwp
,
675 /* use left margin of the IDC_MANUFACTURER label as the right
676 margin of all controls inside the group box */
677 hControl
= GetDlgItem(hpd
->hWnd
,
679 GetWindowRect(hControl
,
681 MapWindowPoints(hControl
,
686 ptMarginGroup
.y
= ptMargin
.y
* 2;
687 Width
= cx
- (2 * ptMarginGroup
.x
);
688 y
+= ptMarginGroup
.y
;
689 if (!(dwp
= DeferWindowPos(dwp
,
700 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
702 /* resize the IDC_LOCATION label */
703 hControl
= GetDlgItem(hpd
->hWnd
,
705 GetWindowRect(hControl
,
707 if (!(dwp
= DeferWindowPos(dwp
,
718 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
720 /* measure the size of the buttons */
721 hButton
= GetDlgItem(hpd
->hWnd
,
723 GetWindowRect(hButton
,
726 /* resize the IDC_STATUS label */
727 hControl
= GetDlgItem(hpd
->hWnd
,
729 GetWindowRect(hControl
,
731 if (!(dwp
= DeferWindowPos(dwp
,
737 cy
- y
- (3 * ptMargin
.y
) -
738 (rcButton
.bottom
- rcButton
.top
),
744 /* move the IDC_PROPERTIES button */
745 y
= cy
- (2 * ptMargin
.y
) - (rcButton
.bottom
- rcButton
.top
);
746 x
= cx
- ptMarginGroup
.x
- (rcButton
.right
- rcButton
.left
);
747 if (!(dwp
= DeferWindowPos(dwp
,
754 SWP_NOSIZE
| SWP_NOZORDER
)))
759 /* move the IDC_TROUBLESHOOT button */
760 hButton
= GetDlgItem(hpd
->hWnd
,
762 GetWindowRect(hButton
,
764 x
-= (ptMargin
.x
/ 2) + (rcButton
.right
- rcButton
.left
);
765 if (!(dwp
= DeferWindowPos(dwp
,
772 SWP_NOSIZE
| SWP_NOZORDER
)))
777 EndDeferWindowPos(dwp
);
783 EnableTroubleShoot(PHARDWARE_PAGE_DATA hpd
,
786 HWND hBtnTroubleShoot
= GetDlgItem(hpd
->hWnd
,
789 ShowWindow(hBtnTroubleShoot
,
790 Enable
? SW_SHOW
: SW_HIDE
);
796 HardwareDlgProc(IN HWND hwndDlg
,
801 PHARDWARE_PAGE_DATA hpd
;
804 hpd
= (PHARDWARE_PAGE_DATA
)GetWindowLongPtr(hwndDlg
,
807 if (hpd
!= NULL
|| uMsg
== WM_INITDIALOG
)
813 NMHDR
*pnmh
= (NMHDR
*)lParam
;
814 if (pnmh
->hwndFrom
== hpd
->hWndDevList
)
818 case LVN_ITEMCHANGED
:
820 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
)lParam
;
822 if ((pnmv
->uChanged
& LVIF_STATE
) &&
823 ((pnmv
->uOldState
& (LVIS_FOCUSED
| LVIS_SELECTED
)) ||
824 (pnmv
->uNewState
& (LVIS_FOCUSED
| LVIS_SELECTED
))))
826 UpdateControlStates(hpd
);
833 DisplaySelectedDeviceProperties(hpd
);
843 switch (LOWORD(wParam
))
845 case IDC_TROUBLESHOOT
:
847 /* FIXME - start the help using the command in the window text */
853 DisplaySelectedDeviceProperties(hpd
);
861 HardwareDlgResize(hpd
,
863 (INT
)HIWORD(lParam
));
868 LPCWSTR szWndText
= (LPCWSTR
)lParam
;
869 EnableTroubleShoot(hpd
,
870 (szWndText
!= NULL
&& szWndText
[0] != L
'\0'));
874 case WM_DEVICECHANGE
:
876 /* FIXME - don't call UpdateDevicesListViewControl for all events */
877 UpdateDevicesListViewControl(hpd
);
884 hpd
= (PHARDWARE_PAGE_DATA
)lParam
;
890 SetWindowLongPtr(hwndDlg
,
894 hpd
->ClassImageListData
.cbSize
= sizeof(SP_CLASSIMAGELIST_DATA
);
896 SetupDiGetClassImageList(&hpd
->ClassImageListData
);
898 /* calculate the size of the devices list view control */
899 hpd
->hWndDevList
= GetDlgItem(hwndDlg
,
901 if (hpd
->hWndDevList
!= NULL
)
904 GetClientRect(hpd
->hWndDevList
,
906 hpd
->DevListViewHeight
= rcClient
.bottom
;
908 if (hpd
->DisplayMode
== HWPD_LARGELIST
)
910 hpd
->DevListViewHeight
= (hpd
->DevListViewHeight
* 3) / 2;
914 /* subclass the parent window */
915 hWndParent
= GetAncestor(hwndDlg
,
917 if (hWndParent
!= NULL
)
921 if (GetClientRect(hWndParent
,
923 SetWindowPos(hwndDlg
,
931 /* subclass the parent window. This is not safe
932 if the parent window belongs to another thread! */
933 hpd
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
935 (LONG_PTR
)ParentSubWndProc
);
937 if (hpd
->ParentOldWndProc
!= NULL
&&
939 L
"DevMgrSubClassInfo",
942 hpd
->hWndParent
= hWndParent
;
947 /* initialize the devices list view control */
948 InitializeDevicesList(hpd
);
950 /* fill the devices list view control */
951 FillDevicesListViewControl(hpd
,
955 /* decide whether to show or hide the troubleshoot button */
956 EnableTroubleShoot(hpd
,
957 GetWindowTextLength(hwndDlg
) != 0);
965 /* zero hpd pointer in window data, because it can be used later (WM_DESTROY has not to be last message) */
966 SetWindowLongPtr(hwndDlg
, DWL_USER
, (DWORD_PTR
)NULL
);
968 /* free devices list */
969 FreeDevicesList(hpd
);
971 /* restore the old window proc of the subclassed parent window */
972 if (hpd
->hWndParent
!= NULL
&& hpd
->ParentOldWndProc
!= NULL
)
974 SetWindowLongPtr(hpd
->hWndParent
,
976 (LONG_PTR
)hpd
->ParentOldWndProc
);
979 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
981 SetupDiDestroyClassImageList(&hpd
->ClassImageListData
);
984 /* free the reference to comctl32 */
985 FreeLibrary(hpd
->hComCtl32
);
986 hpd
->hComCtl32
= NULL
;
988 /* free the allocated resources */
989 HeapFree(GetProcessHeap(),
1001 /***************************************************************************
1003 * DeviceCreateHardwarePageEx
1006 * Creates a hardware page
1009 * hWndParent: Handle to the parent window
1010 * lpGuids: An array of guids of devices that are to be listed
1011 * uNumberOfGuids: Numbers of guids in the Guids array
1012 * DisplayMode: Sets the size of the device list view control
1015 * Returns the handle of the hardware page window that has been created or
1016 * NULL if it failed.
1022 DeviceCreateHardwarePageEx(IN HWND hWndParent
,
1024 IN UINT uNumberOfGuids
,
1025 IN HWPAGE_DISPLAYMODE DisplayMode
)
1027 PHARDWARE_PAGE_DATA hpd
;
1029 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
1030 zeroed because the initialization code assumes that in
1032 hpd
= HeapAlloc(GetProcessHeap(),
1034 FIELD_OFFSET(HARDWARE_PAGE_DATA
,
1035 ClassDevInfo
[uNumberOfGuids
]));
1041 hpd
->DisplayMode
= ((DisplayMode
> HWPD_MAX
) ? HWPD_STANDARDLIST
: DisplayMode
);
1043 /* initialize the HARDWARE_PAGE_DATA structure */
1044 hpd
->NumberOfGuids
= uNumberOfGuids
;
1049 hpd
->ClassDevInfo
[i
].hDevInfo
= INVALID_HANDLE_VALUE
;
1050 hpd
->ClassDevInfo
[i
].Guid
= lpGuids
[i
];
1053 /* load comctl32.dll dynamically */
1054 hpd
->hComCtl32
= LoadAndInitComctl32();
1055 if (hpd
->hComCtl32
== NULL
)
1060 /* create the dialog */
1061 hWnd
= CreateDialogParam(hDllInstance
,
1062 MAKEINTRESOURCE(IDD_HARDWARE
),
1068 HeapFree(GetProcessHeap(), 0, hpd
);
1074 /* oops, something went wrong... */
1075 if (hpd
->hComCtl32
!= NULL
)
1077 FreeLibrary(hpd
->hComCtl32
);
1080 HeapFree(GetProcessHeap(),
1090 /***************************************************************************
1092 * DeviceCreateHardwarePage
1095 * Creates a hardware page
1098 * hWndParent: Handle to the parent window
1099 * lpGuid: Guid of the device
1102 * Returns the handle of the hardware page window that has been created or
1103 * NULL if it failed.
1109 DeviceCreateHardwarePage(IN HWND hWndParent
,
1112 return DeviceCreateHardwarePageEx(hWndParent
,