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
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 struct _HWDEVINFO
35 struct _HWCLASSDEVINFO
*ClassDevInfo
;
36 SP_DEVINFO_DATA DevInfoData
;
38 } HWDEVINFO
, *PHWDEVINFO
;
40 typedef struct _HWCLASSDEVINFO
47 } HWCLASSDEVINFO
, *PHWCLASSDEVINFO
;
49 typedef struct _HARDWARE_PAGE_DATA
53 HINSTANCE hComCtl32
; /* only save this to keep track of the references */
54 INT DevListViewHeight
;
55 SP_CLASSIMAGELIST_DATA ClassImageListData
;
56 HWPAGE_DISPLAYMODE DisplayMode
;
58 /* parent window subclass info */
59 WNDPROC ParentOldWndProc
;
63 HWCLASSDEVINFO ClassDevInfo
[1];
64 /* struct may be dynamically expanded here! */
65 } HARDWARE_PAGE_DATA
, *PHARDWARE_PAGE_DATA
;
67 #define CX_TYPECOLUMN_WIDTH 80
70 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
77 /* set the list view style */
78 (void)ListView_SetExtendedListViewStyle(hpd
->hWndDevList
,
79 LVS_EX_FULLROWSELECT
);
81 /* set the list view image list */
82 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
84 (void)ListView_SetImageList(hpd
->hWndDevList
,
85 hpd
->ClassImageListData
.ImageList
,
89 GetClientRect(hpd
->hWndDevList
,
92 /* add the list view columns */
93 lvc
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
94 lvc
.fmt
= LVCFMT_LEFT
;
95 lvc
.pszText
= szColName
;
97 if (LoadString(hDllInstance
,
100 sizeof(szColName
) / sizeof(szColName
[0])))
102 lvc
.cx
= rcClient
.right
- CX_TYPECOLUMN_WIDTH
-
103 GetSystemMetrics(SM_CXVSCROLL
);
104 (void)ListView_InsertColumn(hpd
->hWndDevList
,
108 if (LoadString(hDllInstance
,
111 sizeof(szColName
) / sizeof(szColName
[0])))
113 lvc
.cx
= CX_TYPECOLUMN_WIDTH
;
114 (void)ListView_InsertColumn(hpd
->hWndDevList
,
122 DisplaySelectedDeviceProperties(IN PHARDWARE_PAGE_DATA hpd
)
124 PHWDEVINFO HwDevInfo
;
125 SP_DEVINFO_DATA DevInfoData
;
128 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
129 if (HwDevInfo
!= NULL
)
131 /* make a copy of the SP_DEVINFO_DATA structure on the stack, it may
132 become invalid in case the devices are updated */
133 DevInfoData
= HwDevInfo
->DevInfoData
;
135 /* display the advanced properties */
136 Ret
= DisplayDeviceAdvancedProperties(hpd
->hWnd
,
138 HwDevInfo
->ClassDevInfo
->hDevInfo
,
150 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd
)
152 PHWDEVINFO HwDevInfo
;
153 HWND hBtnTroubleShoot
, hBtnProperties
;
155 hBtnTroubleShoot
= GetDlgItem(hpd
->hWnd
,
157 hBtnProperties
= GetDlgItem(hpd
->hWnd
,
160 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
161 if (HwDevInfo
!= NULL
)
163 /* update static controls */
165 LPWSTR szFormatted
= NULL
;
167 /* get the manufacturer string */
168 if (GetDeviceManufacturerString(HwDevInfo
->ClassDevInfo
->hDevInfo
,
169 &HwDevInfo
->DevInfoData
,
171 sizeof(szBuffer
) / sizeof(szBuffer
[0])) &&
172 LoadAndFormatString(hDllInstance
,
177 SetDlgItemText(hpd
->hWnd
,
180 LocalFree((HLOCAL
)szFormatted
);
183 /* get the location string */
184 if (GetDeviceLocationString(HwDevInfo
->ClassDevInfo
->hDevInfo
,
185 &HwDevInfo
->DevInfoData
,
188 sizeof(szBuffer
) / sizeof(szBuffer
[0])) &&
189 LoadAndFormatString(hDllInstance
,
194 SetDlgItemText(hpd
->hWnd
,
197 LocalFree((HLOCAL
)szFormatted
);
200 if (GetDeviceStatusString(HwDevInfo
->DevInfoData
.DevInst
,
203 sizeof(szBuffer
) / sizeof(szBuffer
[0])) &&
204 LoadAndFormatString(hDllInstance
,
209 SetDlgItemText(hpd
->hWnd
,
212 LocalFree((HLOCAL
)szFormatted
);
217 /* clear static controls */
218 SetDlgItemText(hpd
->hWnd
,
221 SetDlgItemText(hpd
->hWnd
,
224 SetDlgItemText(hpd
->hWnd
,
229 EnableWindow(hBtnTroubleShoot
,
231 EnableWindow(hBtnProperties
,
237 FreeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
239 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
241 ClassDevInfo
= hpd
->ClassDevInfo
;
242 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
244 /* free the device info set handles and structures */
245 while (ClassDevInfo
!= LastClassDevInfo
)
247 if (ClassDevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
249 SetupDiDestroyDeviceInfoList(ClassDevInfo
->hDevInfo
);
250 ClassDevInfo
->hDevInfo
= INVALID_HANDLE_VALUE
;
253 ClassDevInfo
->ItemCount
= 0;
254 ClassDevInfo
->ImageIndex
= 0;
256 if (ClassDevInfo
->HwDevInfo
!= NULL
)
258 HeapFree(GetProcessHeap(),
260 ClassDevInfo
->HwDevInfo
);
261 ClassDevInfo
->HwDevInfo
= NULL
;
270 BuildDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
272 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
273 SP_DEVINFO_DATA DevInfoData
;
275 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
277 ClassDevInfo
= hpd
->ClassDevInfo
;
278 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
280 while (ClassDevInfo
!= LastClassDevInfo
)
282 ClassDevInfo
->ImageIndex
= -1;
284 /* open a class device handle for the GUID we're processing */
285 ClassDevInfo
->hDevInfo
= SetupDiGetClassDevs(&ClassDevInfo
->Guid
,
288 DIGCF_PRESENT
| DIGCF_PROFILE
);
289 if (ClassDevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
291 DWORD MemberIndex
= 0;
293 SetupDiGetClassImageIndex(&hpd
->ClassImageListData
,
295 &ClassDevInfo
->ImageIndex
);
297 /* enumerate all devices in the class */
298 while (SetupDiEnumDeviceInfo(ClassDevInfo
->hDevInfo
,
302 BOOL HideDevice
= FALSE
;
304 if (ClassDevInfo
->HwDevInfo
!= NULL
)
306 PHWDEVINFO HwNewDevInfo
= HeapReAlloc(GetProcessHeap(),
308 ClassDevInfo
->HwDevInfo
,
309 (ClassDevInfo
->ItemCount
+ 1) *
311 if (HwNewDevInfo
!= NULL
)
313 ClassDevInfo
->HwDevInfo
= HwNewDevInfo
;
317 DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
318 ClassDevInfo
->ItemCount
+ 1);
324 ClassDevInfo
->HwDevInfo
= HeapAlloc(GetProcessHeap(),
327 if (ClassDevInfo
->HwDevInfo
== NULL
)
329 DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
334 /* Find out if the device should be hidden by default */
335 IsDeviceHidden(DevInfoData
.DevInst
,
339 /* save all information for the current device */
340 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
].ClassDevInfo
= ClassDevInfo
;
341 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
].DevInfoData
= DevInfoData
;
342 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
++].HideDevice
= HideDevice
;
352 DeviceIdMatch(IN HDEVINFO DeviceInfoSet
,
353 IN PSP_DEVINFO_DATA DeviceInfoData
,
354 IN LPCWSTR lpDeviceId
)
357 LPWSTR lpQueriedDeviceId
;
360 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet
,
365 GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
367 if (DevIdLen
== wcslen(lpDeviceId
) + 1)
369 lpQueriedDeviceId
= HeapAlloc(GetProcessHeap(),
371 DevIdLen
* sizeof(WCHAR
));
372 if (lpQueriedDeviceId
!= NULL
)
374 if (SetupDiGetDeviceInstanceId(DeviceInfoSet
,
380 Ret
= (wcscmp(lpDeviceId
,
381 lpQueriedDeviceId
) == 0);
384 HeapFree(GetProcessHeap(),
396 FillDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd
,
397 IN LPCWSTR lpSelectDeviceId OPTIONAL
,
398 IN GUID
*SelectedClassGuid OPTIONAL
)
400 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
401 PHWDEVINFO HwDevInfo
, LastHwDevInfo
;
403 BOOL SelectedInClass
;
406 BuildDevicesList(hpd
);
408 ClassDevInfo
= hpd
->ClassDevInfo
;
409 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
411 while (ClassDevInfo
!= LastClassDevInfo
)
413 if (ClassDevInfo
->HwDevInfo
!= NULL
)
415 HwDevInfo
= ClassDevInfo
->HwDevInfo
;
416 LastHwDevInfo
= HwDevInfo
+ ClassDevInfo
->ItemCount
;
418 SelectedInClass
= (SelectedClassGuid
!= NULL
&&
419 IsEqualGUID(SelectedClassGuid
,
420 &ClassDevInfo
->Guid
));
421 while (HwDevInfo
!= LastHwDevInfo
)
426 /* get the device name */
427 if (!HwDevInfo
->HideDevice
&&
428 GetDeviceDescriptionString(ClassDevInfo
->hDevInfo
,
429 &HwDevInfo
->DevInfoData
,
431 sizeof(szBuffer
) / sizeof(szBuffer
[0])))
433 li
.mask
= LVIF_PARAM
| LVIF_STATE
| LVIF_TEXT
| LVIF_IMAGE
;
434 li
.iItem
= ItemCount
;
435 if ((ItemCount
== 0 && lpSelectDeviceId
== NULL
) ||
437 DeviceIdMatch(ClassDevInfo
->hDevInfo
,
438 &HwDevInfo
->DevInfoData
,
441 li
.state
= LVIS_SELECTED
;
443 li
.stateMask
= LVIS_SELECTED
;
444 li
.pszText
= szBuffer
;
445 li
.iImage
= ClassDevInfo
->ImageIndex
;
446 li
.lParam
= (LPARAM
)HwDevInfo
;
448 iItem
= ListView_InsertItem(hpd
->hWndDevList
,
454 /* get the device type for the second column */
455 if (GetDeviceTypeString(&HwDevInfo
->DevInfoData
,
457 sizeof(szBuffer
) / sizeof(szBuffer
[0])))
463 (void)ListView_SetItem(hpd
->hWndDevList
,
476 /* update the controls */
477 UpdateControlStates(hpd
);
482 UpdateDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd
)
484 PHWDEVINFO HwDevInfo
;
485 GUID SelectedClassGuid
= {0};
486 LPWSTR lpDeviceId
= NULL
;
488 /* if a device currently is selected, remember the device id so we can
489 select the device after the update if still present */
490 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
491 if (HwDevInfo
!= NULL
)
494 if (!SetupDiGetDeviceInstanceId(HwDevInfo
->ClassDevInfo
->hDevInfo
,
495 &HwDevInfo
->DevInfoData
,
499 GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
501 SelectedClassGuid
= HwDevInfo
->DevInfoData
.ClassGuid
;
502 lpDeviceId
= HeapAlloc(GetProcessHeap(),
504 DevIdLen
* sizeof(WCHAR
));
505 if (lpDeviceId
!= NULL
&&
506 !SetupDiGetDeviceInstanceId(HwDevInfo
->ClassDevInfo
->hDevInfo
,
507 &HwDevInfo
->DevInfoData
,
512 HeapFree(GetProcessHeap(),
520 /* clear the devices list view control */
521 (void)ListView_DeleteAllItems(hpd
->hWndDevList
);
523 /* free the device list */
524 FreeDevicesList(hpd
);
526 /* build rebuild the device list and fill the list box again */
527 FillDevicesListViewControl(hpd
,
529 (lpDeviceId
!= NULL
?
533 if (lpDeviceId
!= NULL
)
535 HeapFree(GetProcessHeap(),
544 ParentSubWndProc(IN HWND hwnd
,
549 PHARDWARE_PAGE_DATA hpd
;
551 hpd
= (PHARDWARE_PAGE_DATA
)GetProp(hwnd
,
552 L
"DevMgrSubClassInfo");
557 /* resize the hardware page */
558 SetWindowPos(hpd
->hWnd
,
566 else if (uMsg
== WM_DEVICECHANGE
&& IsWindowVisible(hpd
->hWnd
))
568 /* forward a WM_DEVICECHANGE message to the hardware
569 page which wouldn't get the message itself as it is
571 SendMessage(hpd
->hWnd
,
577 /* pass the message the the old window proc */
578 return CallWindowProc(hpd
->ParentOldWndProc
,
586 /* this is not a good idea if the subclassed window was an ansi
587 window, but we failed finding out the previous window proc
588 so we can't use CallWindowProc. This should rarely - if ever -
591 return DefWindowProc(hwnd
,
600 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd
,
605 HWND hControl
, hButton
;
609 POINT ptMargin
= {0};
610 POINT ptMarginGroup
= {0};
612 /* use left margin of the IDC_DEVICES label as the right
613 margin of all controls outside the group box */
614 hControl
= GetDlgItem(hpd
->hWnd
,
616 GetWindowRect(hControl
,
618 MapWindowPoints(hControl
,
623 Width
= cx
- (2 * ptMargin
.x
);
625 if ((dwp
= BeginDeferWindowPos(8)))
627 /* rc already has the window rect of IDC_DEVICES! */
628 if (!(dwp
= DeferWindowPos(dwp
,
635 SWP_NOMOVE
| SWP_NOZORDER
)))
640 /* resize the devices list view control */
641 GetWindowRect(hpd
->hWndDevList
,
643 MapWindowPoints(hpd
->hWndDevList
,
647 y
= pt
.y
+ hpd
->DevListViewHeight
+ ptMargin
.y
;
648 if (!(dwp
= DeferWindowPos(dwp
,
654 hpd
->DevListViewHeight
,
655 SWP_NOMOVE
| SWP_NOZORDER
)))
660 /* resize the group box control */
661 hControl
= GetDlgItem(hpd
->hWnd
,
662 IDC_PROPERTIESGROUP
);
663 GetWindowRect(hControl
,
665 if (!(dwp
= DeferWindowPos(dwp
,
677 /* use left margin of the IDC_MANUFACTURER label as the right
678 margin of all controls inside the group box */
679 hControl
= GetDlgItem(hpd
->hWnd
,
681 GetWindowRect(hControl
,
683 MapWindowPoints(hControl
,
688 ptMarginGroup
.y
= ptMargin
.y
* 2;
689 Width
= cx
- (2 * ptMarginGroup
.x
);
690 y
+= ptMarginGroup
.y
;
691 if (!(dwp
= DeferWindowPos(dwp
,
702 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
704 /* resize the IDC_LOCATION label */
705 hControl
= GetDlgItem(hpd
->hWnd
,
707 GetWindowRect(hControl
,
709 if (!(dwp
= DeferWindowPos(dwp
,
720 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
722 /* measure the size of the buttons */
723 hButton
= GetDlgItem(hpd
->hWnd
,
725 GetWindowRect(hButton
,
728 /* resize the IDC_STATUS label */
729 hControl
= GetDlgItem(hpd
->hWnd
,
731 GetWindowRect(hControl
,
733 if (!(dwp
= DeferWindowPos(dwp
,
739 cy
- y
- (3 * ptMargin
.y
) -
740 (rcButton
.bottom
- rcButton
.top
),
746 /* move the IDC_PROPERTIES button */
747 y
= cy
- (2 * ptMargin
.y
) - (rcButton
.bottom
- rcButton
.top
);
748 x
= cx
- ptMarginGroup
.x
- (rcButton
.right
- rcButton
.left
);
749 if (!(dwp
= DeferWindowPos(dwp
,
756 SWP_NOSIZE
| SWP_NOZORDER
)))
761 /* move the IDC_TROUBLESHOOT button */
762 hButton
= GetDlgItem(hpd
->hWnd
,
764 GetWindowRect(hButton
,
766 x
-= (ptMargin
.x
/ 2) + (rcButton
.right
- rcButton
.left
);
767 if (!(dwp
= DeferWindowPos(dwp
,
774 SWP_NOSIZE
| SWP_NOZORDER
)))
779 EndDeferWindowPos(dwp
);
785 EnableTroubleShoot(PHARDWARE_PAGE_DATA hpd
,
788 HWND hBtnTroubleShoot
= GetDlgItem(hpd
->hWnd
,
791 ShowWindow(hBtnTroubleShoot
,
792 Enable
? SW_SHOW
: SW_HIDE
);
798 HardwareDlgProc(IN HWND hwndDlg
,
803 PHARDWARE_PAGE_DATA hpd
;
806 hpd
= (PHARDWARE_PAGE_DATA
)GetWindowLongPtr(hwndDlg
,
809 if (hpd
!= NULL
|| uMsg
== WM_INITDIALOG
)
815 NMHDR
*pnmh
= (NMHDR
*)lParam
;
816 if (pnmh
->hwndFrom
== hpd
->hWndDevList
)
820 case LVN_ITEMCHANGED
:
822 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
)lParam
;
824 if ((pnmv
->uChanged
& LVIF_STATE
) &&
825 ((pnmv
->uOldState
& (LVIS_FOCUSED
| LVIS_SELECTED
)) ||
826 (pnmv
->uNewState
& (LVIS_FOCUSED
| LVIS_SELECTED
))))
828 UpdateControlStates(hpd
);
835 DisplaySelectedDeviceProperties(hpd
);
845 switch (LOWORD(wParam
))
847 case IDC_TROUBLESHOOT
:
849 /* FIXME - start the help using the command in the window text */
855 DisplaySelectedDeviceProperties(hpd
);
863 HardwareDlgResize(hpd
,
865 (INT
)HIWORD(lParam
));
870 LPCWSTR szWndText
= (LPCWSTR
)lParam
;
871 EnableTroubleShoot(hpd
,
872 (szWndText
!= NULL
&& szWndText
[0] != L
'\0'));
876 case WM_DEVICECHANGE
:
878 /* FIXME - don't call UpdateDevicesListViewControl for all events */
879 UpdateDevicesListViewControl(hpd
);
886 hpd
= (PHARDWARE_PAGE_DATA
)lParam
;
892 SetWindowLongPtr(hwndDlg
,
896 hpd
->ClassImageListData
.cbSize
= sizeof(SP_CLASSIMAGELIST_DATA
);
898 SetupDiGetClassImageList(&hpd
->ClassImageListData
);
900 /* calculate the size of the devices list view control */
901 hpd
->hWndDevList
= GetDlgItem(hwndDlg
,
903 if (hpd
->hWndDevList
!= NULL
)
906 GetClientRect(hpd
->hWndDevList
,
908 hpd
->DevListViewHeight
= rcClient
.bottom
;
910 if (hpd
->DisplayMode
== HWPD_LARGELIST
)
912 hpd
->DevListViewHeight
= (hpd
->DevListViewHeight
* 3) / 2;
916 /* subclass the parent window */
917 hWndParent
= GetAncestor(hwndDlg
,
919 if (hWndParent
!= NULL
)
923 if (GetClientRect(hWndParent
,
925 SetWindowPos(hwndDlg
,
933 /* subclass the parent window. This is not safe
934 if the parent window belongs to another thread! */
935 hpd
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
937 (LONG_PTR
)ParentSubWndProc
);
939 if (hpd
->ParentOldWndProc
!= NULL
&&
941 L
"DevMgrSubClassInfo",
944 hpd
->hWndParent
= hWndParent
;
949 /* initialize the devices list view control */
950 InitializeDevicesList(hpd
);
952 /* fill the devices list view control */
953 FillDevicesListViewControl(hpd
,
957 /* decide whether to show or hide the troubleshoot button */
958 EnableTroubleShoot(hpd
,
959 GetWindowTextLength(hwndDlg
) != 0);
967 /* zero hpd pointer in window data, because it can be used later (WM_DESTROY has not to be last message) */
968 SetWindowLongPtr(hwndDlg
, DWL_USER
, (DWORD_PTR
)NULL
);
970 /* free devices list */
971 FreeDevicesList(hpd
);
973 /* restore the old window proc of the subclassed parent window */
974 if (hpd
->hWndParent
!= NULL
&& hpd
->ParentOldWndProc
!= NULL
)
976 SetWindowLongPtr(hpd
->hWndParent
,
978 (LONG_PTR
)hpd
->ParentOldWndProc
);
981 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
983 SetupDiDestroyClassImageList(&hpd
->ClassImageListData
);
986 /* free the reference to comctl32 */
987 FreeLibrary(hpd
->hComCtl32
);
988 hpd
->hComCtl32
= NULL
;
990 /* free the allocated resources */
991 HeapFree(GetProcessHeap(),
1003 /***************************************************************************
1005 * DeviceCreateHardwarePageEx
1008 * Creates a hardware page
1011 * hWndParent: Handle to the parent window
1012 * lpGuids: An array of guids of devices that are to be listed
1013 * uNumberOfGuids: Numbers of guids in the Guids array
1014 * DisplayMode: Sets the size of the device list view control
1017 * Returns the handle of the hardware page window that has been created or
1018 * NULL if it failed.
1024 DeviceCreateHardwarePageEx(IN HWND hWndParent
,
1026 IN UINT uNumberOfGuids
,
1027 IN HWPAGE_DISPLAYMODE DisplayMode
)
1029 PHARDWARE_PAGE_DATA hpd
;
1031 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
1032 zeroed because the initialization code assumes that in
1034 hpd
= HeapAlloc(GetProcessHeap(),
1036 FIELD_OFFSET(HARDWARE_PAGE_DATA
,
1037 ClassDevInfo
[uNumberOfGuids
]));
1043 hpd
->DisplayMode
= ((DisplayMode
> HWPD_MAX
) ? HWPD_STANDARDLIST
: DisplayMode
);
1045 /* initialize the HARDWARE_PAGE_DATA structure */
1046 hpd
->NumberOfGuids
= uNumberOfGuids
;
1051 hpd
->ClassDevInfo
[i
].hDevInfo
= INVALID_HANDLE_VALUE
;
1052 hpd
->ClassDevInfo
[i
].Guid
= lpGuids
[i
];
1055 /* load comctl32.dll dynamically */
1056 hpd
->hComCtl32
= LoadAndInitComctl32();
1057 if (hpd
->hComCtl32
== NULL
)
1062 /* create the dialog */
1063 hWnd
= CreateDialogParam(hDllInstance
,
1064 MAKEINTRESOURCE(IDD_HARDWARE
),
1075 /* oops, something went wrong... */
1076 if (hpd
->hComCtl32
!= NULL
)
1078 FreeLibrary(hpd
->hComCtl32
);
1081 HeapFree(GetProcessHeap(),
1091 /***************************************************************************
1093 * DeviceCreateHardwarePage
1096 * Creates a hardware page
1099 * hWndParent: Handle to the parent window
1100 * lpGuid: Guid of the device
1103 * Returns the handle of the hardware page window that has been created or
1104 * NULL if it failed.
1110 DeviceCreateHardwarePage(IN HWND hWndParent
,
1113 return DeviceCreateHardwarePageEx(hWndParent
,