fixed some resizing bugs
[reactos.git] / reactos / lib / devmgr / hwpage.c
1 /*
2 * ReactOS Device Manager Applet
3 * Copyright (C) 2004 - 2005 ReactOS Team
4 *
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.
9 *
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.
14 *
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
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/hwpage.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
25 * UPDATE HISTORY:
26 * 04-04-2004 Created
27 */
28 #include <precomp.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33 typedef VOID (WINAPI *PINITCOMMONCONTROLS)(VOID);
34
35 typedef enum
36 {
37 HWPD_STANDARDLIST = 0,
38 HWPD_LARGELIST,
39 HWPD_MAX = HWPD_LARGELIST
40 } HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
41
42 typedef struct _HWDEVINFO
43 {
44 struct _HWCLASSDEVINFO *ClassDevInfo;
45 SP_DEVINFO_DATA DevInfoData;
46 } HWDEVINFO, *PHWDEVINFO;
47
48 typedef struct _HWCLASSDEVINFO
49 {
50 GUID Guid;
51 HDEVINFO hDevInfo;
52 INT ItemCount;
53 PHWDEVINFO HwDevInfo;
54 } HWCLASSDEVINFO, *PHWCLASSDEVINFO;
55
56 typedef struct _HARDWARE_PAGE_DATA
57 {
58 HWND hWnd;
59 HWND hWndDevList;
60 HINSTANCE hComCtl32; /* only save this to keep track of the references */
61 INT DevListViewHeight;
62 SP_CLASSIMAGELIST_DATA ClassImageListData;
63 HWPAGE_DISPLAYMODE DisplayMode;
64
65 /* parent window subclass info */
66 WNDPROC ParentOldWndProc;
67 HWND hWndParent;
68
69 UINT NumberOfGuids;
70 HWCLASSDEVINFO ClassDevInfo[1];
71 /* struct may be dynamically expanded here! */
72 } HARDWARE_PAGE_DATA, *PHARDWARE_PAGE_DATA;
73
74 #define CX_TYPECOLUMN_WIDTH 80
75
76 static VOID
77 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd)
78 {
79 LVCOLUMN lvc;
80 RECT rcClient;
81 WCHAR szColName[255];
82 int iCol = 0;
83
84 /* set the list view style */
85 ListView_SetExtendedListViewStyle(hpd->hWndDevList,
86 LVS_EX_FULLROWSELECT);
87
88 /* set the list view image list */
89 if (hpd->ClassImageListData.ImageList != NULL)
90 {
91 ListView_SetImageList(hpd->hWndDevList,
92 hpd->ClassImageListData.ImageList,
93 LVSIL_SMALL);
94 }
95
96 GetClientRect(hpd->hWndDevList,
97 &rcClient);
98
99 /* add the list view columns */
100 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
101 lvc.fmt = LVCFMT_LEFT;
102 lvc.pszText = szColName;
103
104 if (LoadString(hDllInstance,
105 IDS_NAME,
106 szColName,
107 sizeof(szColName) / sizeof(szColName[0])))
108 {
109 lvc.cx = rcClient.right - CX_TYPECOLUMN_WIDTH -
110 GetSystemMetrics(SM_CXVSCROLL);
111 ListView_InsertColumn(hpd->hWndDevList,
112 iCol++,
113 &lvc);
114 }
115 if (LoadString(hDllInstance,
116 IDS_TYPE,
117 szColName,
118 sizeof(szColName) / sizeof(szColName[0])))
119 {
120 lvc.cx = CX_TYPECOLUMN_WIDTH;
121 ListView_InsertColumn(hpd->hWndDevList,
122 iCol++,
123 &lvc);
124 }
125 }
126
127
128 static VOID
129 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd)
130 {
131 PHWDEVINFO HwDevInfo;
132
133 HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
134 if (HwDevInfo != NULL)
135 {
136 /* FIXME - update static controls and enable buttons */
137 }
138 else
139 {
140 /* FIXME - clear static controls and disable buttons */
141 }
142 }
143
144
145 static VOID
146 FillDevicesList(IN PHARDWARE_PAGE_DATA hpd)
147 {
148 PHWCLASSDEVINFO DevInfo, LastDevInfo;
149 SP_DEVINFO_DATA DevInfoData;
150 WCHAR szBuffer[255];
151 INT ItemCount = 0;
152
153 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
154
155 DevInfo = hpd->ClassDevInfo;
156 LastDevInfo = DevInfo + hpd->NumberOfGuids;
157
158 while (DevInfo != LastDevInfo)
159 {
160 INT ImageIndex = -1;
161
162 DevInfo->hDevInfo = SetupDiGetClassDevs(&DevInfo->Guid,
163 NULL,
164 hpd->hWnd,
165 DIGCF_PRESENT);
166 if (DevInfo->hDevInfo != INVALID_HANDLE_VALUE)
167 {
168 LVITEM li;
169 DWORD MemberIndex = 0;
170
171 SetupDiGetClassImageIndex(&hpd->ClassImageListData,
172 &DevInfo->Guid,
173 &ImageIndex);
174
175 while (SetupDiEnumDeviceInfo(DevInfo->hDevInfo,
176 MemberIndex++,
177 &DevInfoData))
178 {
179 DWORD RegDataType;
180 INT iItem;
181
182 if (DevInfo->HwDevInfo != NULL)
183 {
184 PHWDEVINFO HwNewDevInfo = HeapReAlloc(GetProcessHeap(),
185 0,
186 DevInfo->HwDevInfo,
187 (DevInfo->ItemCount + 1) *
188 sizeof(HWDEVINFO));
189 if (HwNewDevInfo != NULL)
190 {
191 DevInfo->HwDevInfo = HwNewDevInfo;
192 }
193 else
194 {
195 DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
196 DevInfo->ItemCount + 1);
197 break;
198 }
199 }
200 else
201 {
202 DevInfo->HwDevInfo = HeapAlloc(GetProcessHeap(),
203 0,
204 sizeof(HWDEVINFO));
205 if (DevInfo->HwDevInfo == NULL)
206 {
207 DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
208 break;
209 }
210 }
211
212 DevInfo->HwDevInfo[DevInfo->ItemCount].ClassDevInfo = DevInfo;
213 DevInfo->HwDevInfo[DevInfo->ItemCount++].DevInfoData = DevInfoData;
214
215 if ((SetupDiGetDeviceRegistryProperty(DevInfo->hDevInfo,
216 &DevInfoData,
217 SPDRP_FRIENDLYNAME,
218 &RegDataType,
219 (PBYTE)szBuffer,
220 sizeof(szBuffer),
221 NULL) ||
222 SetupDiGetDeviceRegistryProperty(DevInfo->hDevInfo,
223 &DevInfoData,
224 SPDRP_DEVICEDESC,
225 &RegDataType,
226 (PBYTE)szBuffer,
227 sizeof(szBuffer),
228 NULL)) &&
229 RegDataType == REG_SZ)
230 {
231 /* FIXME - check string for NULL termination! */
232
233 li.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT | LVIF_IMAGE;
234 li.iItem = ItemCount;
235 li.iSubItem = 0;
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];
241
242 iItem = ListView_InsertItem(hpd->hWndDevList,
243 &li);
244 if (iItem != -1)
245 {
246 ItemCount++;
247
248 if (SetupDiGetClassDescription(&DevInfo->Guid,
249 szBuffer,
250 sizeof(szBuffer) / sizeof(szBuffer[0]),
251 NULL))
252 {
253 li.mask = LVIF_TEXT;
254 li.iItem = iItem;
255 li.iSubItem = 1;
256
257 ListView_SetItem(hpd->hWndDevList,
258 &li);
259 }
260 }
261 }
262 }
263 }
264
265 DevInfo++;
266 }
267
268 /* update the controls */
269 UpdateControlStates(hpd);
270 }
271
272
273 static LRESULT
274 CALLBACK
275 ParentSubWndProc(IN HWND hwnd,
276 IN UINT uMsg,
277 IN WPARAM wParam,
278 IN LPARAM lParam)
279 {
280 PHARDWARE_PAGE_DATA hpd;
281
282 hpd = (PHARDWARE_PAGE_DATA)GetProp(hwnd,
283 L"DevMgrSubClassInfo");
284 if (hpd != NULL)
285 {
286 if (uMsg == WM_SIZE)
287 {
288 /* resize the hardware page */
289 SetWindowPos(hpd->hWnd,
290 NULL,
291 0,
292 0,
293 LOWORD(lParam),
294 HIWORD(lParam),
295 SWP_NOZORDER);
296 }
297
298 /* pass the message the the old window proc */
299 return CallWindowProc(hpd->ParentOldWndProc,
300 hwnd,
301 uMsg,
302 wParam,
303 lParam);
304 }
305 else
306 {
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 -
310 happen. */
311
312 return DefWindowProc(hwnd,
313 uMsg,
314 wParam,
315 lParam);
316 }
317 }
318
319
320 static VOID
321 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd,
322 IN INT cx,
323 IN INT cy)
324 {
325 HDWP dwp;
326 HWND hControl, hButton;
327 INT Width, x, y;
328 RECT rc, rcButton;
329 POINT pt = {0};
330 POINT ptMargin = {0};
331 POINT ptMarginGroup = {0};
332
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,
336 IDC_DEVICES);
337 GetWindowRect(hControl,
338 &rc);
339 MapWindowPoints(hControl,
340 hpd->hWnd,
341 &ptMargin,
342 1);
343
344 Width = cx - (2 * ptMargin.x);
345
346 if ((dwp = BeginDeferWindowPos(8)))
347 {
348 /* rc already has the window rect of IDC_DEVICES! */
349 if (!(dwp = DeferWindowPos(dwp,
350 hControl,
351 NULL,
352 0,
353 0,
354 Width,
355 rc.bottom - rc.top,
356 SWP_NOMOVE | SWP_NOZORDER)))
357 {
358 return;
359 }
360
361 /* resize the devices list view control */
362 GetWindowRect(hpd->hWndDevList,
363 &rc);
364 MapWindowPoints(hpd->hWndDevList,
365 hpd->hWnd,
366 &pt,
367 1);
368 y = pt.y + hpd->DevListViewHeight + ptMargin.y;
369 if (!(dwp = DeferWindowPos(dwp,
370 hpd->hWndDevList,
371 NULL,
372 0,
373 0,
374 Width,
375 hpd->DevListViewHeight,
376 SWP_NOMOVE | SWP_NOZORDER)))
377 {
378 return;
379 }
380
381 /* resize the group box control */
382 hControl = GetDlgItem(hpd->hWnd,
383 IDC_PROPERTIESGROUP);
384 GetWindowRect(hControl,
385 &rc);
386 if (!(dwp = DeferWindowPos(dwp,
387 hControl,
388 NULL,
389 ptMargin.x,
390 y,
391 Width,
392 cy - y - ptMargin.y,
393 SWP_NOZORDER)))
394 {
395 return;
396 }
397
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,
401 IDC_MANUFACTURER);
402 GetWindowRect(hControl,
403 &rc);
404 MapWindowPoints(hControl,
405 hpd->hWnd,
406 &ptMarginGroup,
407 1);
408
409 ptMarginGroup.y = ptMargin.y * 2;
410 Width = cx - (2 * ptMarginGroup.x);
411 y += ptMarginGroup.y;
412 if (!(dwp = DeferWindowPos(dwp,
413 hControl,
414 NULL,
415 ptMarginGroup.x,
416 y,
417 Width,
418 rc.bottom - rc.top,
419 SWP_NOZORDER)))
420 {
421 return;
422 }
423 y += rc.bottom - rc.top + (ptMargin.y / 2);
424
425 /* resize the IDC_LOCATION label */
426 hControl = GetDlgItem(hpd->hWnd,
427 IDC_LOCATION);
428 GetWindowRect(hControl,
429 &rc);
430 if (!(dwp = DeferWindowPos(dwp,
431 hControl,
432 NULL,
433 ptMarginGroup.x,
434 y,
435 Width,
436 rc.bottom - rc.top,
437 SWP_NOZORDER)))
438 {
439 return;
440 }
441 y += rc.bottom - rc.top + (ptMargin.y / 2);
442
443 /* measure the size of the buttons */
444 hButton = GetDlgItem(hpd->hWnd,
445 IDC_PROPERTIES);
446 GetWindowRect(hButton,
447 &rcButton);
448
449 /* resize the IDC_STATUS label */
450 hControl = GetDlgItem(hpd->hWnd,
451 IDC_STATUS);
452 GetWindowRect(hControl,
453 &rc);
454 if (!(dwp = DeferWindowPos(dwp,
455 hControl,
456 NULL,
457 ptMarginGroup.x,
458 y,
459 Width,
460 cy - y - (3 * ptMargin.y) -
461 (rcButton.bottom - rcButton.top),
462 SWP_NOZORDER)))
463 {
464 return;
465 }
466
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,
471 hButton,
472 NULL,
473 x,
474 y,
475 0,
476 0,
477 SWP_NOSIZE | SWP_NOZORDER)))
478 {
479 return;
480 }
481
482 /* move the IDC_TROUBLESHOOT button */
483 hButton = GetDlgItem(hpd->hWnd,
484 IDC_TROUBLESHOOT);
485 GetWindowRect(hButton,
486 &rcButton);
487 x -= (ptMargin.x / 2) + (rcButton.right - rcButton.left);
488 if (!(dwp = DeferWindowPos(dwp,
489 hButton,
490 NULL,
491 x,
492 y,
493 0,
494 0,
495 SWP_NOSIZE | SWP_NOZORDER)))
496 {
497 return;
498 }
499
500 EndDeferWindowPos(dwp);
501 }
502 }
503
504
505 static INT_PTR
506 CALLBACK
507 HardwareDlgProc(IN HWND hwndDlg,
508 IN UINT uMsg,
509 IN WPARAM wParam,
510 IN LPARAM lParam)
511 {
512 PHARDWARE_PAGE_DATA hpd;
513
514 hpd = (PHARDWARE_PAGE_DATA)GetWindowLongPtr(hwndDlg,
515 DWL_USER);
516
517 if (hpd != NULL || uMsg == WM_INITDIALOG)
518 {
519 switch (uMsg)
520 {
521 case WM_NOTIFY:
522 {
523 NMHDR *pnmh = (NMHDR*)lParam;
524 if (pnmh->hwndFrom == hpd->hWndDevList)
525 {
526 switch (pnmh->code)
527 {
528 case LVN_ITEMCHANGED:
529 {
530 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
531
532 if ((pnmv->uChanged & LVIF_STATE) &&
533 ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
534 (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
535 {
536 UpdateControlStates(hpd);
537 }
538 break;
539 }
540 }
541 }
542 break;
543 }
544
545 case WM_SIZE:
546 HardwareDlgResize(hpd,
547 (INT)LOWORD(lParam),
548 (INT)HIWORD(lParam));
549 break;
550
551 case WM_INITDIALOG:
552 {
553 hpd = (PHARDWARE_PAGE_DATA)lParam;
554 if (hpd != NULL)
555 {
556 HWND hWndParent;
557
558 hpd->hWnd = hwndDlg;
559 SetWindowLongPtr(hwndDlg,
560 DWL_USER,
561 (DWORD_PTR)hpd);
562
563 hpd->ClassImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
564
565 SetupDiGetClassImageList(&hpd->ClassImageListData);
566
567 /* calculate the size of the devices list view control */
568 hpd->hWndDevList = GetDlgItem(hwndDlg,
569 IDC_LV_DEVICES);
570 if (hpd->hWndDevList != NULL)
571 {
572 RECT rcClient;
573 GetClientRect(hpd->hWndDevList,
574 &rcClient);
575 hpd->DevListViewHeight = rcClient.bottom;
576
577 if (hpd->DisplayMode == HWPD_LARGELIST)
578 {
579 hpd->DevListViewHeight = (hpd->DevListViewHeight * 3) / 2;
580 }
581 }
582
583 /* subclass the parent window */
584 hWndParent = GetAncestor(hwndDlg,
585 GA_PARENT);
586 if (hWndParent != NULL)
587 {
588 RECT rcClient;
589
590 if (GetClientRect(hWndParent,
591 &rcClient) &&
592 SetWindowPos(hwndDlg,
593 NULL,
594 0,
595 0,
596 rcClient.right,
597 rcClient.bottom,
598 SWP_NOZORDER))
599 {
600 /* subclass the parent window. This is not safe
601 if the parent window belongs to another thread! */
602 hpd->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
603 GWLP_WNDPROC,
604 (LONG_PTR)ParentSubWndProc);
605
606 if (hpd->ParentOldWndProc != NULL &&
607 SetProp(hWndParent,
608 L"DevMgrSubClassInfo",
609 (HANDLE)hpd))
610 {
611 hpd->hWndParent = hWndParent;
612 }
613 }
614 }
615
616 /* initialize the devices list view control */
617 InitializeDevicesList(hpd);
618
619 /* fill the devices list view control */
620 FillDevicesList(hpd);
621 }
622 break;
623 }
624
625 case WM_DESTROY:
626 {
627 UINT i;
628
629 /* free the device info set handles */
630 for (i = 0;
631 i < hpd->NumberOfGuids;
632 i++)
633 {
634 SetupDiDestroyDeviceInfoList(hpd->ClassDevInfo[i].hDevInfo);
635 if (hpd->ClassDevInfo[i].HwDevInfo != NULL)
636 {
637 HeapFree(GetProcessHeap(),
638 0,
639 hpd->ClassDevInfo[i].HwDevInfo);
640 }
641 }
642
643 /* restore the old window proc of the subclassed parent window */
644 if (hpd->hWndParent != NULL && hpd->ParentOldWndProc != NULL)
645 {
646 SetWindowLongPtr(hpd->hWndParent,
647 GWLP_WNDPROC,
648 (LONG_PTR)hpd->ParentOldWndProc);
649 }
650
651 if (hpd->ClassImageListData.ImageList != NULL)
652 {
653 SetupDiDestroyClassImageList(&hpd->ClassImageListData);
654 }
655
656 /* free the reference to comctl32 */
657 FreeLibrary(hpd->hComCtl32);
658 hpd->hComCtl32 = NULL;
659
660 /* free the allocated resources */
661 HeapFree(GetProcessHeap(),
662 0,
663 hpd);
664 break;
665 }
666 }
667 }
668
669 return FALSE;
670 }
671
672
673 /***************************************************************************
674 * NAME EXPORTED
675 * DeviceCreateHardwarePageEx
676 *
677 * DESCRIPTION
678 * Creates a hardware page
679 *
680 * ARGUMENTS
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
685 *
686 * RETURN VALUE
687 * Returns the handle of the hardware page window that has been created or
688 * NULL if it failed.
689 *
690 * REVISIONS
691 * 13-05-2005 first working version (Sebastian Gasiorek <zebasoftis@gmail.com>)
692 *
693 * TODO
694 * missing: device icon in list view, Troubleshoot button, device properties,
695 * status description,
696 * devices should be visible afer PSN_SETACTIVE message
697 *
698 */
699 HWND
700 WINAPI
701 DeviceCreateHardwarePageEx(IN HWND hWndParent,
702 IN LPGUID lpGuids,
703 IN UINT uNumberOfGuids,
704 IN HWPAGE_DISPLAYMODE DisplayMode)
705 {
706 PHARDWARE_PAGE_DATA hpd;
707 PINITCOMMONCONTROLS pInitCommonControls;
708
709 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
710 zeroed because the initialization code assumes that in
711 failure cases! */
712 hpd = HeapAlloc(GetProcessHeap(),
713 HEAP_ZERO_MEMORY,
714 FIELD_OFFSET(HARDWARE_PAGE_DATA,
715 ClassDevInfo) +
716 (uNumberOfGuids * sizeof(HWCLASSDEVINFO)));
717 if (hpd != NULL)
718 {
719 HWND hWnd;
720 UINT i;
721
722 hpd->DisplayMode = ((DisplayMode > HWPD_MAX) ? HWPD_STANDARDLIST : DisplayMode);
723
724 /* initialize the HARDWARE_PAGE_DATA structure */
725 hpd->NumberOfGuids = uNumberOfGuids;
726 for (i = 0;
727 i < uNumberOfGuids;
728 i++)
729 {
730 hpd->ClassDevInfo[i].Guid = lpGuids[i];
731 }
732
733 /* load comctl32.dll dynamically */
734 hpd->hComCtl32 = LoadLibrary(TEXT("comctl32.dll"));
735 if (hpd->hComCtl32 == NULL)
736 {
737 goto Cleanup;
738 }
739
740 /* initialize the common controls */
741 pInitCommonControls = (PINITCOMMONCONTROLS)GetProcAddress(hpd->hComCtl32,
742 "InitCommonControls");
743 if (pInitCommonControls == NULL)
744 {
745 goto Cleanup;
746 }
747 pInitCommonControls();
748
749 /* create the dialog */
750 hWnd = CreateDialogParam(hDllInstance,
751 MAKEINTRESOURCE(IDD_HARDWARE),
752 hWndParent,
753 HardwareDlgProc,
754 (LPARAM)hpd);
755 if (hWnd != NULL)
756 {
757 return hWnd;
758 }
759 else
760 {
761 Cleanup:
762 /* oops, something went wrong... */
763 if (hpd->hComCtl32 != NULL)
764 {
765 FreeLibrary(hpd->hComCtl32);
766 }
767
768 HeapFree(GetProcessHeap(),
769 0,
770 hpd);
771 }
772 }
773
774 return NULL;
775 }
776
777
778 /***************************************************************************
779 * NAME EXPORTED
780 * DeviceCreateHardwarePage
781 *
782 * DESCRIPTION
783 * Creates a hardware page
784 *
785 * ARGUMENTS
786 * hWndParent: Handle to the parent window
787 * lpGuid: Guid of the device
788 *
789 * RETURN VALUE
790 * Returns the handle of the hardware page window that has been created or
791 * NULL if it failed.
792 *
793 * REVISIONS
794 *
795 * NOTE
796 *
797 */
798 HWND
799 WINAPI
800 DeviceCreateHardwarePage(IN HWND hWndParent,
801 IN LPGUID lpGuid)
802 {
803 return DeviceCreateHardwarePageEx(hWndParent,
804 lpGuid,
805 1,
806 HWPD_LARGELIST);
807 }