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
55 } HWCLASSDEVINFO
, *PHWCLASSDEVINFO
;
57 typedef struct _HARDWARE_PAGE_DATA
61 HINSTANCE hComCtl32
; /* only save this to keep track of the references */
62 INT DevListViewHeight
;
63 SP_CLASSIMAGELIST_DATA ClassImageListData
;
64 HWPAGE_DISPLAYMODE DisplayMode
;
66 /* parent window subclass info */
67 WNDPROC ParentOldWndProc
;
71 HWCLASSDEVINFO ClassDevInfo
[1];
72 /* struct may be dynamically expanded here! */
73 } HARDWARE_PAGE_DATA
, *PHARDWARE_PAGE_DATA
;
75 #define CX_TYPECOLUMN_WIDTH 80
78 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
85 /* set the list view style */
86 ListView_SetExtendedListViewStyle(hpd
->hWndDevList
,
87 LVS_EX_FULLROWSELECT
);
89 /* set the list view image list */
90 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
92 ListView_SetImageList(hpd
->hWndDevList
,
93 hpd
->ClassImageListData
.ImageList
,
97 GetClientRect(hpd
->hWndDevList
,
100 /* add the list view columns */
101 lvc
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
102 lvc
.fmt
= LVCFMT_LEFT
;
103 lvc
.pszText
= szColName
;
105 if (LoadString(hDllInstance
,
108 sizeof(szColName
) / sizeof(szColName
[0])))
110 lvc
.cx
= rcClient
.right
- CX_TYPECOLUMN_WIDTH
-
111 GetSystemMetrics(SM_CXVSCROLL
);
112 ListView_InsertColumn(hpd
->hWndDevList
,
116 if (LoadString(hDllInstance
,
119 sizeof(szColName
) / sizeof(szColName
[0])))
121 lvc
.cx
= CX_TYPECOLUMN_WIDTH
;
122 ListView_InsertColumn(hpd
->hWndDevList
,
130 DisplaySelectedDeviceProperties(IN PHARDWARE_PAGE_DATA hpd
)
132 PHWDEVINFO HwDevInfo
;
135 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
136 if (HwDevInfo
!= NULL
)
138 PWSTR szDeviceInstanceId
= NULL
;
139 DWORD DeviceInstanceIdLen
= 0;
141 /* find out how much size is needed for the buffer */
142 if (SetupDiGetDeviceInstanceId(HwDevInfo
->ClassDevInfo
->hDevInfo
,
143 &HwDevInfo
->DevInfoData
,
146 &DeviceInstanceIdLen
))
148 DPRINT1("SetupDiGetDeviceInterfaceDetail unexpectedly returned TRUE!\n");
152 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
157 szDeviceInstanceId
= HeapAlloc(GetProcessHeap(),
159 DeviceInstanceIdLen
* sizeof(WCHAR
));
160 if (szDeviceInstanceId
== NULL
)
165 /* read the device instance id */
166 if (!SetupDiGetDeviceInstanceId(HwDevInfo
->ClassDevInfo
->hDevInfo
,
167 &HwDevInfo
->DevInfoData
,
170 &DeviceInstanceIdLen
))
175 /* display the properties dialog */
176 Ret
= DeviceAdvancedProperties(hpd
->hWnd
,
178 szDeviceInstanceId
) >= 0;
181 if (szDeviceInstanceId
!= NULL
)
183 HeapFree(GetProcessHeap(),
194 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd
)
196 PHWDEVINFO HwDevInfo
;
197 HWND hBtnTroubleShoot
, hBtnProperties
;
199 hBtnTroubleShoot
= GetDlgItem(hpd
->hWnd
,
201 hBtnProperties
= GetDlgItem(hpd
->hWnd
,
204 HwDevInfo
= (PHWDEVINFO
)ListViewGetSelectedItemData(hpd
->hWndDevList
);
205 if (HwDevInfo
!= NULL
)
207 /* update static controls */
212 LPWSTR szFormatted
= NULL
;
214 /* get the manufacturer string */
215 if (!SetupDiGetDeviceRegistryProperty(HwDevInfo
->ClassDevInfo
->hDevInfo
,
216 &HwDevInfo
->DevInfoData
,
222 RegDataType
!= REG_SZ
)
225 LoadString(hDllInstance
,
228 sizeof(szBuffer
) / sizeof(szBuffer
[0]));
230 /* FIXME - check string for NULL termination! */
231 if (LoadAndFormatString(hDllInstance
,
236 SetDlgItemText(hpd
->hWnd
,
239 LocalFree((HLOCAL
)szFormatted
);
242 /* get the location string */
243 DataSize
= sizeof(szBuffer
);
244 cRet
= CM_Get_DevNode_Registry_Property(HwDevInfo
->DevInfoData
.DevInst
,
245 CM_DRP_LOCATION_INFORMATION
,
250 if (cRet
!= CR_SUCCESS
||
251 RegDataType
!= REG_SZ
)
254 LoadString(hDllInstance
,
257 sizeof(szBuffer
) / sizeof(szBuffer
[0]));
259 /* FIXME - check string for NULL termination! */
261 if (szBuffer
[0] >= L
'0' && szBuffer
[0] <= L
'9')
263 /* convert the string to an integer value and create a
265 ULONG ulLocation
= (ULONG
)wcstoul(szBuffer
,
268 if (LoadAndFormatString(hDllInstance
,
276 (sizeof(szBuffer
) / sizeof(szBuffer
[0])) - 1);
277 szBuffer
[(sizeof(szBuffer
) / sizeof(szBuffer
[0])) - 1] = L
'\0';
278 LocalFree((HLOCAL
)szFormatted
);
282 if (LoadAndFormatString(hDllInstance
,
287 SetDlgItemText(hpd
->hWnd
,
290 LocalFree((HLOCAL
)szFormatted
);
293 /* FIXME - get the device status text */
294 LoadString(hDllInstance
,
297 sizeof(szBuffer
) / sizeof(szBuffer
[0]));
299 if (LoadAndFormatString(hDllInstance
,
304 SetDlgItemText(hpd
->hWnd
,
307 LocalFree((HLOCAL
)szFormatted
);
312 /* clear static controls */
313 SetDlgItemText(hpd
->hWnd
,
316 SetDlgItemText(hpd
->hWnd
,
319 SetDlgItemText(hpd
->hWnd
,
324 EnableWindow(hBtnTroubleShoot
,
326 EnableWindow(hBtnProperties
,
332 FreeDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
334 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
336 ClassDevInfo
= hpd
->ClassDevInfo
;
337 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
339 /* free the device info set handles and structures */
340 while (ClassDevInfo
!= LastClassDevInfo
)
342 if (ClassDevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
344 SetupDiDestroyDeviceInfoList(ClassDevInfo
->hDevInfo
);
345 ClassDevInfo
->hDevInfo
= INVALID_HANDLE_VALUE
;
348 ClassDevInfo
->ItemCount
= 0;
349 ClassDevInfo
->ImageIndex
= 0;
351 if (ClassDevInfo
->HwDevInfo
!= NULL
)
353 HeapFree(GetProcessHeap(),
355 ClassDevInfo
->HwDevInfo
);
356 ClassDevInfo
->HwDevInfo
= NULL
;
365 BuildDevicesList(IN PHARDWARE_PAGE_DATA hpd
)
367 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
368 SP_DEVINFO_DATA DevInfoData
;
370 DevInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
372 ClassDevInfo
= hpd
->ClassDevInfo
;
373 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
375 while (ClassDevInfo
!= LastClassDevInfo
)
377 ClassDevInfo
->ImageIndex
= -1;
379 /* open a class device handle for the GUID we're processing */
380 ClassDevInfo
->hDevInfo
= SetupDiGetClassDevs(&ClassDevInfo
->Guid
,
384 if (ClassDevInfo
->hDevInfo
!= INVALID_HANDLE_VALUE
)
386 DWORD MemberIndex
= 0;
388 SetupDiGetClassImageIndex(&hpd
->ClassImageListData
,
390 &ClassDevInfo
->ImageIndex
);
392 /* enumerate all devices in the class */
393 while (SetupDiEnumDeviceInfo(ClassDevInfo
->hDevInfo
,
397 if (ClassDevInfo
->HwDevInfo
!= NULL
)
399 PHWDEVINFO HwNewDevInfo
= HeapReAlloc(GetProcessHeap(),
401 ClassDevInfo
->HwDevInfo
,
402 (ClassDevInfo
->ItemCount
+ 1) *
404 if (HwNewDevInfo
!= NULL
)
406 ClassDevInfo
->HwDevInfo
= HwNewDevInfo
;
410 DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
411 ClassDevInfo
->ItemCount
+ 1);
417 ClassDevInfo
->HwDevInfo
= HeapAlloc(GetProcessHeap(),
420 if (ClassDevInfo
->HwDevInfo
== NULL
)
422 DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
427 /* save all information for the current device */
428 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
].ClassDevInfo
= ClassDevInfo
;
429 ClassDevInfo
->HwDevInfo
[ClassDevInfo
->ItemCount
++].DevInfoData
= DevInfoData
;
439 FillDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd
)
441 PHWCLASSDEVINFO ClassDevInfo
, LastClassDevInfo
;
442 PHWDEVINFO HwDevInfo
, LastHwDevInfo
;
446 BuildDevicesList(hpd
);
448 ClassDevInfo
= hpd
->ClassDevInfo
;
449 LastClassDevInfo
= ClassDevInfo
+ hpd
->NumberOfGuids
;
451 while (ClassDevInfo
!= LastClassDevInfo
)
453 if (ClassDevInfo
->HwDevInfo
!= NULL
)
455 HwDevInfo
= ClassDevInfo
->HwDevInfo
;
456 LastHwDevInfo
= HwDevInfo
+ ClassDevInfo
->ItemCount
;
458 while (HwDevInfo
!= LastHwDevInfo
)
464 /* get the device name */
465 if ((SetupDiGetDeviceRegistryProperty(ClassDevInfo
->hDevInfo
,
466 &HwDevInfo
->DevInfoData
,
472 SetupDiGetDeviceRegistryProperty(ClassDevInfo
->hDevInfo
,
473 &HwDevInfo
->DevInfoData
,
479 RegDataType
== REG_SZ
)
481 /* FIXME - check string for NULL termination! */
483 li
.mask
= LVIF_PARAM
| LVIF_STATE
| LVIF_TEXT
| LVIF_IMAGE
;
484 li
.iItem
= ItemCount
;
486 li
.state
= (ItemCount
== 0 ? LVIS_SELECTED
: 0);
487 li
.stateMask
= LVIS_SELECTED
;
488 li
.pszText
= szBuffer
;
489 li
.iImage
= ClassDevInfo
->ImageIndex
;
490 li
.lParam
= (LPARAM
)HwDevInfo
;
492 iItem
= ListView_InsertItem(hpd
->hWndDevList
,
498 /* get the device type for the second column */
499 if (SetupDiGetClassDescription(&ClassDevInfo
->Guid
,
501 sizeof(szBuffer
) / sizeof(szBuffer
[0]),
508 ListView_SetItem(hpd
->hWndDevList
,
521 /* update the controls */
522 UpdateControlStates(hpd
);
528 ParentSubWndProc(IN HWND hwnd
,
533 PHARDWARE_PAGE_DATA hpd
;
535 hpd
= (PHARDWARE_PAGE_DATA
)GetProp(hwnd
,
536 L
"DevMgrSubClassInfo");
541 /* resize the hardware page */
542 SetWindowPos(hpd
->hWnd
,
551 /* pass the message the the old window proc */
552 return CallWindowProc(hpd
->ParentOldWndProc
,
560 /* this is not a good idea if the subclassed window was an ansi
561 window, but we failed finding out the previous window proc
562 so we can't use CallWindowProc. This should rarely - if ever -
565 return DefWindowProc(hwnd
,
574 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd
,
579 HWND hControl
, hButton
;
583 POINT ptMargin
= {0};
584 POINT ptMarginGroup
= {0};
586 /* use left margin of the IDC_DEVICES label as the right
587 margin of all controls outside the group box */
588 hControl
= GetDlgItem(hpd
->hWnd
,
590 GetWindowRect(hControl
,
592 MapWindowPoints(hControl
,
597 Width
= cx
- (2 * ptMargin
.x
);
599 if ((dwp
= BeginDeferWindowPos(8)))
601 /* rc already has the window rect of IDC_DEVICES! */
602 if (!(dwp
= DeferWindowPos(dwp
,
609 SWP_NOMOVE
| SWP_NOZORDER
)))
614 /* resize the devices list view control */
615 GetWindowRect(hpd
->hWndDevList
,
617 MapWindowPoints(hpd
->hWndDevList
,
621 y
= pt
.y
+ hpd
->DevListViewHeight
+ ptMargin
.y
;
622 if (!(dwp
= DeferWindowPos(dwp
,
628 hpd
->DevListViewHeight
,
629 SWP_NOMOVE
| SWP_NOZORDER
)))
634 /* resize the group box control */
635 hControl
= GetDlgItem(hpd
->hWnd
,
636 IDC_PROPERTIESGROUP
);
637 GetWindowRect(hControl
,
639 if (!(dwp
= DeferWindowPos(dwp
,
651 /* use left margin of the IDC_MANUFACTURER label as the right
652 margin of all controls inside the group box */
653 hControl
= GetDlgItem(hpd
->hWnd
,
655 GetWindowRect(hControl
,
657 MapWindowPoints(hControl
,
662 ptMarginGroup
.y
= ptMargin
.y
* 2;
663 Width
= cx
- (2 * ptMarginGroup
.x
);
664 y
+= ptMarginGroup
.y
;
665 if (!(dwp
= DeferWindowPos(dwp
,
676 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
678 /* resize the IDC_LOCATION label */
679 hControl
= GetDlgItem(hpd
->hWnd
,
681 GetWindowRect(hControl
,
683 if (!(dwp
= DeferWindowPos(dwp
,
694 y
+= rc
.bottom
- rc
.top
+ (ptMargin
.y
/ 2);
696 /* measure the size of the buttons */
697 hButton
= GetDlgItem(hpd
->hWnd
,
699 GetWindowRect(hButton
,
702 /* resize the IDC_STATUS label */
703 hControl
= GetDlgItem(hpd
->hWnd
,
705 GetWindowRect(hControl
,
707 if (!(dwp
= DeferWindowPos(dwp
,
713 cy
- y
- (3 * ptMargin
.y
) -
714 (rcButton
.bottom
- rcButton
.top
),
720 /* move the IDC_PROPERTIES button */
721 y
= cy
- (2 * ptMargin
.y
) - (rcButton
.bottom
- rcButton
.top
);
722 x
= cx
- ptMarginGroup
.x
- (rcButton
.right
- rcButton
.left
);
723 if (!(dwp
= DeferWindowPos(dwp
,
730 SWP_NOSIZE
| SWP_NOZORDER
)))
735 /* move the IDC_TROUBLESHOOT button */
736 hButton
= GetDlgItem(hpd
->hWnd
,
738 GetWindowRect(hButton
,
740 x
-= (ptMargin
.x
/ 2) + (rcButton
.right
- rcButton
.left
);
741 if (!(dwp
= DeferWindowPos(dwp
,
748 SWP_NOSIZE
| SWP_NOZORDER
)))
753 EndDeferWindowPos(dwp
);
759 EnableTroubleShoot(PHARDWARE_PAGE_DATA hpd
,
762 HWND hBtnTroubleShoot
= GetDlgItem(hpd
->hWnd
,
765 ShowWindow(hBtnTroubleShoot
,
766 Enable
? SW_SHOW
: SW_HIDE
);
772 HardwareDlgProc(IN HWND hwndDlg
,
777 PHARDWARE_PAGE_DATA hpd
;
779 hpd
= (PHARDWARE_PAGE_DATA
)GetWindowLongPtr(hwndDlg
,
782 if (hpd
!= NULL
|| uMsg
== WM_INITDIALOG
)
788 NMHDR
*pnmh
= (NMHDR
*)lParam
;
789 if (pnmh
->hwndFrom
== hpd
->hWndDevList
)
793 case LVN_ITEMCHANGED
:
795 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
)lParam
;
797 if ((pnmv
->uChanged
& LVIF_STATE
) &&
798 ((pnmv
->uOldState
& (LVIS_FOCUSED
| LVIS_SELECTED
)) ||
799 (pnmv
->uNewState
& (LVIS_FOCUSED
| LVIS_SELECTED
))))
801 UpdateControlStates(hpd
);
812 switch (LOWORD(wParam
))
814 case IDC_TROUBLESHOOT
:
816 /* FIXME - start the help using the command in the window text */
822 DisplaySelectedDeviceProperties(hpd
);
830 HardwareDlgResize(hpd
,
832 (INT
)HIWORD(lParam
));
837 LPCWSTR szWndText
= (LPCWSTR
)lParam
;
838 EnableTroubleShoot(hpd
,
839 (szWndText
!= NULL
&& szWndText
[0] != L
'\0'));
845 hpd
= (PHARDWARE_PAGE_DATA
)lParam
;
851 SetWindowLongPtr(hwndDlg
,
855 hpd
->ClassImageListData
.cbSize
= sizeof(SP_CLASSIMAGELIST_DATA
);
857 SetupDiGetClassImageList(&hpd
->ClassImageListData
);
859 /* calculate the size of the devices list view control */
860 hpd
->hWndDevList
= GetDlgItem(hwndDlg
,
862 if (hpd
->hWndDevList
!= NULL
)
865 GetClientRect(hpd
->hWndDevList
,
867 hpd
->DevListViewHeight
= rcClient
.bottom
;
869 if (hpd
->DisplayMode
== HWPD_LARGELIST
)
871 hpd
->DevListViewHeight
= (hpd
->DevListViewHeight
* 3) / 2;
875 /* subclass the parent window */
876 hWndParent
= GetAncestor(hwndDlg
,
878 if (hWndParent
!= NULL
)
882 if (GetClientRect(hWndParent
,
884 SetWindowPos(hwndDlg
,
892 /* subclass the parent window. This is not safe
893 if the parent window belongs to another thread! */
894 hpd
->ParentOldWndProc
= (WNDPROC
)SetWindowLongPtr(hWndParent
,
896 (LONG_PTR
)ParentSubWndProc
);
898 if (hpd
->ParentOldWndProc
!= NULL
&&
900 L
"DevMgrSubClassInfo",
903 hpd
->hWndParent
= hWndParent
;
908 /* initialize the devices list view control */
909 InitializeDevicesList(hpd
);
911 /* fill the devices list view control */
912 FillDevicesListViewControl(hpd
);
914 /* decide whether to show or hide the troubleshoot button */
915 EnableTroubleShoot(hpd
,
916 GetWindowTextLength(hwndDlg
) != 0);
923 /* free devices list */
924 FreeDevicesList(hpd
);
926 /* restore the old window proc of the subclassed parent window */
927 if (hpd
->hWndParent
!= NULL
&& hpd
->ParentOldWndProc
!= NULL
)
929 SetWindowLongPtr(hpd
->hWndParent
,
931 (LONG_PTR
)hpd
->ParentOldWndProc
);
934 if (hpd
->ClassImageListData
.ImageList
!= NULL
)
936 SetupDiDestroyClassImageList(&hpd
->ClassImageListData
);
939 /* free the reference to comctl32 */
940 FreeLibrary(hpd
->hComCtl32
);
941 hpd
->hComCtl32
= NULL
;
943 /* free the allocated resources */
944 HeapFree(GetProcessHeap(),
956 /***************************************************************************
958 * DeviceCreateHardwarePageEx
961 * Creates a hardware page
964 * hWndParent: Handle to the parent window
965 * lpGuids: An array of guids of devices that are to be listed
966 * uNumberOfGuids: Numbers of guids in the Guids array
967 * DisplayMode: Sets the size of the device list view control
970 * Returns the handle of the hardware page window that has been created or
975 DeviceCreateHardwarePageEx(IN HWND hWndParent
,
977 IN UINT uNumberOfGuids
,
978 IN HWPAGE_DISPLAYMODE DisplayMode
)
980 PHARDWARE_PAGE_DATA hpd
;
981 PINITCOMMONCONTROLS pInitCommonControls
;
983 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
984 zeroed because the initialization code assumes that in
986 hpd
= HeapAlloc(GetProcessHeap(),
988 FIELD_OFFSET(HARDWARE_PAGE_DATA
,
990 (uNumberOfGuids
* sizeof(HWCLASSDEVINFO
)));
996 hpd
->DisplayMode
= ((DisplayMode
> HWPD_MAX
) ? HWPD_STANDARDLIST
: DisplayMode
);
998 /* initialize the HARDWARE_PAGE_DATA structure */
999 hpd
->NumberOfGuids
= uNumberOfGuids
;
1004 hpd
->ClassDevInfo
[i
].hDevInfo
= INVALID_HANDLE_VALUE
;
1005 hpd
->ClassDevInfo
[i
].Guid
= lpGuids
[i
];
1008 /* load comctl32.dll dynamically */
1009 hpd
->hComCtl32
= LoadLibrary(TEXT("comctl32.dll"));
1010 if (hpd
->hComCtl32
== NULL
)
1015 /* initialize the common controls */
1016 pInitCommonControls
= (PINITCOMMONCONTROLS
)GetProcAddress(hpd
->hComCtl32
,
1017 "InitCommonControls");
1018 if (pInitCommonControls
== NULL
)
1022 pInitCommonControls();
1024 /* create the dialog */
1025 hWnd
= CreateDialogParam(hDllInstance
,
1026 MAKEINTRESOURCE(IDD_HARDWARE
),
1037 /* oops, something went wrong... */
1038 if (hpd
->hComCtl32
!= NULL
)
1040 FreeLibrary(hpd
->hComCtl32
);
1043 HeapFree(GetProcessHeap(),
1053 /***************************************************************************
1055 * DeviceCreateHardwarePage
1058 * Creates a hardware page
1061 * hWndParent: Handle to the parent window
1062 * lpGuid: Guid of the device
1065 * Returns the handle of the hardware page window that has been created or
1066 * NULL if it failed.
1075 DeviceCreateHardwarePage(IN HWND hWndParent
,
1078 return DeviceCreateHardwarePageEx(hWndParent
,