fac1f52f69a46ed97986bbe82ab3f83d37d4ec17
[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 ImageIndex;
53 INT ItemCount;
54 PHWDEVINFO HwDevInfo;
55 } HWCLASSDEVINFO, *PHWCLASSDEVINFO;
56
57 typedef struct _HARDWARE_PAGE_DATA
58 {
59 HWND hWnd;
60 HWND hWndDevList;
61 HINSTANCE hComCtl32; /* only save this to keep track of the references */
62 INT DevListViewHeight;
63 SP_CLASSIMAGELIST_DATA ClassImageListData;
64 HWPAGE_DISPLAYMODE DisplayMode;
65
66 /* parent window subclass info */
67 WNDPROC ParentOldWndProc;
68 HWND hWndParent;
69
70 UINT NumberOfGuids;
71 HWCLASSDEVINFO ClassDevInfo[1];
72 /* struct may be dynamically expanded here! */
73 } HARDWARE_PAGE_DATA, *PHARDWARE_PAGE_DATA;
74
75 #define CX_TYPECOLUMN_WIDTH 80
76
77 static VOID
78 InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd)
79 {
80 LVCOLUMN lvc;
81 RECT rcClient;
82 WCHAR szColName[255];
83 int iCol = 0;
84
85 /* set the list view style */
86 ListView_SetExtendedListViewStyle(hpd->hWndDevList,
87 LVS_EX_FULLROWSELECT);
88
89 /* set the list view image list */
90 if (hpd->ClassImageListData.ImageList != NULL)
91 {
92 ListView_SetImageList(hpd->hWndDevList,
93 hpd->ClassImageListData.ImageList,
94 LVSIL_SMALL);
95 }
96
97 GetClientRect(hpd->hWndDevList,
98 &rcClient);
99
100 /* add the list view columns */
101 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
102 lvc.fmt = LVCFMT_LEFT;
103 lvc.pszText = szColName;
104
105 if (LoadString(hDllInstance,
106 IDS_NAME,
107 szColName,
108 sizeof(szColName) / sizeof(szColName[0])))
109 {
110 lvc.cx = rcClient.right - CX_TYPECOLUMN_WIDTH -
111 GetSystemMetrics(SM_CXVSCROLL);
112 ListView_InsertColumn(hpd->hWndDevList,
113 iCol++,
114 &lvc);
115 }
116 if (LoadString(hDllInstance,
117 IDS_TYPE,
118 szColName,
119 sizeof(szColName) / sizeof(szColName[0])))
120 {
121 lvc.cx = CX_TYPECOLUMN_WIDTH;
122 ListView_InsertColumn(hpd->hWndDevList,
123 iCol++,
124 &lvc);
125 }
126 }
127
128
129 static VOID
130 UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd)
131 {
132 PHWDEVINFO HwDevInfo;
133 HWND hBtnTroubleShoot, hBtnProperties;
134 DWORD RegDataType;
135
136 hBtnTroubleShoot = GetDlgItem(hpd->hWnd,
137 IDC_TROUBLESHOOT);
138 hBtnProperties = GetDlgItem(hpd->hWnd,
139 IDC_PROPERTIES);
140
141 HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
142 if (HwDevInfo != NULL)
143 {
144 /* update static controls */
145 WCHAR szBuffer[256];
146 LPWSTR szFormatted = NULL;
147
148 if (!SetupDiGetDeviceRegistryProperty(HwDevInfo->ClassDevInfo->hDevInfo,
149 &HwDevInfo->DevInfoData,
150 SPDRP_MFG,
151 &RegDataType,
152 (PBYTE)szBuffer,
153 sizeof(szBuffer),
154 NULL) ||
155 RegDataType != REG_SZ)
156 {
157 /* FIXME - check string for NULL termination! */
158 szBuffer[0] = L'\0';
159 }
160 if (LoadAndFormatString(hDllInstance,
161 IDS_MANUFACTURER,
162 &szFormatted,
163 szBuffer) != 0)
164 {
165 SetDlgItemText(hpd->hWnd,
166 IDC_MANUFACTURER,
167 szFormatted);
168 LocalFree((HLOCAL)szFormatted);
169 }
170
171 /* FIXME - Display location and status */
172 }
173 else
174 {
175 /* clear static controls */
176 SetDlgItemText(hpd->hWnd,
177 IDC_MANUFACTURER,
178 NULL);
179 SetDlgItemText(hpd->hWnd,
180 IDC_LOCATION,
181 NULL);
182 SetDlgItemText(hpd->hWnd,
183 IDC_STATUS,
184 NULL);
185 }
186
187 EnableWindow(hBtnTroubleShoot,
188 HwDevInfo != NULL);
189 EnableWindow(hBtnTroubleShoot,
190 hBtnProperties != NULL);
191 }
192
193 static VOID
194 FreeDevicesList(IN PHARDWARE_PAGE_DATA hpd)
195 {
196 PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
197
198 ClassDevInfo = hpd->ClassDevInfo;
199 LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
200
201 /* free the device info set handles */
202 while (ClassDevInfo != LastClassDevInfo)
203 {
204 if (ClassDevInfo->hDevInfo != INVALID_HANDLE_VALUE)
205 {
206 SetupDiDestroyDeviceInfoList(ClassDevInfo->hDevInfo);
207 }
208 ClassDevInfo->hDevInfo = NULL;
209 ClassDevInfo->ItemCount = 0;
210 ClassDevInfo->ImageIndex = 0;
211
212 if (ClassDevInfo->HwDevInfo != NULL)
213 {
214 HeapFree(GetProcessHeap(),
215 0,
216 ClassDevInfo->HwDevInfo);
217 ClassDevInfo->HwDevInfo = NULL;
218 }
219
220 ClassDevInfo++;
221 }
222 }
223
224
225 static VOID
226 BuildDevicesList(IN PHARDWARE_PAGE_DATA hpd)
227 {
228 PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
229 SP_DEVINFO_DATA DevInfoData;
230
231 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
232
233 ClassDevInfo = hpd->ClassDevInfo;
234 LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
235
236 while (ClassDevInfo != LastClassDevInfo)
237 {
238 ClassDevInfo->ImageIndex = -1;
239 ClassDevInfo->hDevInfo = SetupDiGetClassDevs(&ClassDevInfo->Guid,
240 NULL,
241 hpd->hWnd,
242 DIGCF_PRESENT);
243 if (ClassDevInfo->hDevInfo != INVALID_HANDLE_VALUE)
244 {
245 DWORD MemberIndex = 0;
246
247 SetupDiGetClassImageIndex(&hpd->ClassImageListData,
248 &ClassDevInfo->Guid,
249 &ClassDevInfo->ImageIndex);
250
251 while (SetupDiEnumDeviceInfo(ClassDevInfo->hDevInfo,
252 MemberIndex++,
253 &DevInfoData))
254 {
255 if (ClassDevInfo->HwDevInfo != NULL)
256 {
257 PHWDEVINFO HwNewDevInfo = HeapReAlloc(GetProcessHeap(),
258 0,
259 ClassDevInfo->HwDevInfo,
260 (ClassDevInfo->ItemCount + 1) *
261 sizeof(HWDEVINFO));
262 if (HwNewDevInfo != NULL)
263 {
264 ClassDevInfo->HwDevInfo = HwNewDevInfo;
265 }
266 else
267 {
268 DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
269 ClassDevInfo->ItemCount + 1);
270 break;
271 }
272 }
273 else
274 {
275 ClassDevInfo->HwDevInfo = HeapAlloc(GetProcessHeap(),
276 0,
277 sizeof(HWDEVINFO));
278 if (ClassDevInfo->HwDevInfo == NULL)
279 {
280 DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
281 break;
282 }
283 }
284
285 ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount].ClassDevInfo = ClassDevInfo;
286 ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount++].DevInfoData = DevInfoData;
287 }
288 }
289
290 ClassDevInfo++;
291 }
292 }
293
294
295 static VOID
296 FillDevicesList(IN PHARDWARE_PAGE_DATA hpd)
297 {
298 PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
299 PHWDEVINFO HwDevInfo, LastHwDevInfo;
300 WCHAR szBuffer[255];
301 INT ItemCount = 0;
302
303 BuildDevicesList(hpd);
304
305 ClassDevInfo = hpd->ClassDevInfo;
306 LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
307
308 while (ClassDevInfo != LastClassDevInfo)
309 {
310 if (ClassDevInfo->HwDevInfo != NULL)
311 {
312 HwDevInfo = ClassDevInfo->HwDevInfo;
313 LastHwDevInfo = HwDevInfo + ClassDevInfo->ItemCount;
314
315 while (HwDevInfo != LastHwDevInfo)
316 {
317 DWORD RegDataType;
318 INT iItem;
319 LVITEM li;
320
321 if ((SetupDiGetDeviceRegistryProperty(ClassDevInfo->hDevInfo,
322 &HwDevInfo->DevInfoData,
323 SPDRP_FRIENDLYNAME,
324 &RegDataType,
325 (PBYTE)szBuffer,
326 sizeof(szBuffer),
327 NULL) ||
328 SetupDiGetDeviceRegistryProperty(ClassDevInfo->hDevInfo,
329 &HwDevInfo->DevInfoData,
330 SPDRP_DEVICEDESC,
331 &RegDataType,
332 (PBYTE)szBuffer,
333 sizeof(szBuffer),
334 NULL)) &&
335 RegDataType == REG_SZ)
336 {
337 /* FIXME - check string for NULL termination! */
338
339 li.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT | LVIF_IMAGE;
340 li.iItem = ItemCount;
341 li.iSubItem = 0;
342 li.state = (ItemCount == 0 ? LVIS_SELECTED : 0);
343 li.stateMask = LVIS_SELECTED;
344 li.pszText = szBuffer;
345 li.iImage = ClassDevInfo->ImageIndex;
346 li.lParam = (LPARAM)HwDevInfo;
347
348 iItem = ListView_InsertItem(hpd->hWndDevList,
349 &li);
350 if (iItem != -1)
351 {
352 ItemCount++;
353
354 if (SetupDiGetClassDescription(&ClassDevInfo->Guid,
355 szBuffer,
356 sizeof(szBuffer) / sizeof(szBuffer[0]),
357 NULL))
358 {
359 li.mask = LVIF_TEXT;
360 li.iItem = iItem;
361 li.iSubItem = 1;
362
363 ListView_SetItem(hpd->hWndDevList,
364 &li);
365 }
366 }
367 }
368
369 HwDevInfo++;
370 }
371 }
372
373 ClassDevInfo++;
374 }
375
376 /* update the controls */
377 UpdateControlStates(hpd);
378 }
379
380
381 static LRESULT
382 CALLBACK
383 ParentSubWndProc(IN HWND hwnd,
384 IN UINT uMsg,
385 IN WPARAM wParam,
386 IN LPARAM lParam)
387 {
388 PHARDWARE_PAGE_DATA hpd;
389
390 hpd = (PHARDWARE_PAGE_DATA)GetProp(hwnd,
391 L"DevMgrSubClassInfo");
392 if (hpd != NULL)
393 {
394 if (uMsg == WM_SIZE)
395 {
396 /* resize the hardware page */
397 SetWindowPos(hpd->hWnd,
398 NULL,
399 0,
400 0,
401 LOWORD(lParam),
402 HIWORD(lParam),
403 SWP_NOZORDER);
404 }
405
406 /* pass the message the the old window proc */
407 return CallWindowProc(hpd->ParentOldWndProc,
408 hwnd,
409 uMsg,
410 wParam,
411 lParam);
412 }
413 else
414 {
415 /* this is not a good idea if the subclassed window was an ansi
416 window, but we failed finding out the previous window proc
417 so we can't use CallWindowProc. This should rarely - if ever -
418 happen. */
419
420 return DefWindowProc(hwnd,
421 uMsg,
422 wParam,
423 lParam);
424 }
425 }
426
427
428 static VOID
429 HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd,
430 IN INT cx,
431 IN INT cy)
432 {
433 HDWP dwp;
434 HWND hControl, hButton;
435 INT Width, x, y;
436 RECT rc, rcButton;
437 POINT pt = {0};
438 POINT ptMargin = {0};
439 POINT ptMarginGroup = {0};
440
441 /* use left margin of the IDC_DEVICES label as the right
442 margin of all controls outside the group box */
443 hControl = GetDlgItem(hpd->hWnd,
444 IDC_DEVICES);
445 GetWindowRect(hControl,
446 &rc);
447 MapWindowPoints(hControl,
448 hpd->hWnd,
449 &ptMargin,
450 1);
451
452 Width = cx - (2 * ptMargin.x);
453
454 if ((dwp = BeginDeferWindowPos(8)))
455 {
456 /* rc already has the window rect of IDC_DEVICES! */
457 if (!(dwp = DeferWindowPos(dwp,
458 hControl,
459 NULL,
460 0,
461 0,
462 Width,
463 rc.bottom - rc.top,
464 SWP_NOMOVE | SWP_NOZORDER)))
465 {
466 return;
467 }
468
469 /* resize the devices list view control */
470 GetWindowRect(hpd->hWndDevList,
471 &rc);
472 MapWindowPoints(hpd->hWndDevList,
473 hpd->hWnd,
474 &pt,
475 1);
476 y = pt.y + hpd->DevListViewHeight + ptMargin.y;
477 if (!(dwp = DeferWindowPos(dwp,
478 hpd->hWndDevList,
479 NULL,
480 0,
481 0,
482 Width,
483 hpd->DevListViewHeight,
484 SWP_NOMOVE | SWP_NOZORDER)))
485 {
486 return;
487 }
488
489 /* resize the group box control */
490 hControl = GetDlgItem(hpd->hWnd,
491 IDC_PROPERTIESGROUP);
492 GetWindowRect(hControl,
493 &rc);
494 if (!(dwp = DeferWindowPos(dwp,
495 hControl,
496 NULL,
497 ptMargin.x,
498 y,
499 Width,
500 cy - y - ptMargin.y,
501 SWP_NOZORDER)))
502 {
503 return;
504 }
505
506 /* use left margin of the IDC_MANUFACTURER label as the right
507 margin of all controls inside the group box */
508 hControl = GetDlgItem(hpd->hWnd,
509 IDC_MANUFACTURER);
510 GetWindowRect(hControl,
511 &rc);
512 MapWindowPoints(hControl,
513 hpd->hWnd,
514 &ptMarginGroup,
515 1);
516
517 ptMarginGroup.y = ptMargin.y * 2;
518 Width = cx - (2 * ptMarginGroup.x);
519 y += ptMarginGroup.y;
520 if (!(dwp = DeferWindowPos(dwp,
521 hControl,
522 NULL,
523 ptMarginGroup.x,
524 y,
525 Width,
526 rc.bottom - rc.top,
527 SWP_NOZORDER)))
528 {
529 return;
530 }
531 y += rc.bottom - rc.top + (ptMargin.y / 2);
532
533 /* resize the IDC_LOCATION label */
534 hControl = GetDlgItem(hpd->hWnd,
535 IDC_LOCATION);
536 GetWindowRect(hControl,
537 &rc);
538 if (!(dwp = DeferWindowPos(dwp,
539 hControl,
540 NULL,
541 ptMarginGroup.x,
542 y,
543 Width,
544 rc.bottom - rc.top,
545 SWP_NOZORDER)))
546 {
547 return;
548 }
549 y += rc.bottom - rc.top + (ptMargin.y / 2);
550
551 /* measure the size of the buttons */
552 hButton = GetDlgItem(hpd->hWnd,
553 IDC_PROPERTIES);
554 GetWindowRect(hButton,
555 &rcButton);
556
557 /* resize the IDC_STATUS label */
558 hControl = GetDlgItem(hpd->hWnd,
559 IDC_STATUS);
560 GetWindowRect(hControl,
561 &rc);
562 if (!(dwp = DeferWindowPos(dwp,
563 hControl,
564 NULL,
565 ptMarginGroup.x,
566 y,
567 Width,
568 cy - y - (3 * ptMargin.y) -
569 (rcButton.bottom - rcButton.top),
570 SWP_NOZORDER)))
571 {
572 return;
573 }
574
575 /* move the IDC_PROPERTIES button */
576 y = cy - (2 * ptMargin.y) - (rcButton.bottom - rcButton.top);
577 x = cx - ptMarginGroup.x - (rcButton.right - rcButton.left);
578 if (!(dwp = DeferWindowPos(dwp,
579 hButton,
580 NULL,
581 x,
582 y,
583 0,
584 0,
585 SWP_NOSIZE | SWP_NOZORDER)))
586 {
587 return;
588 }
589
590 /* move the IDC_TROUBLESHOOT button */
591 hButton = GetDlgItem(hpd->hWnd,
592 IDC_TROUBLESHOOT);
593 GetWindowRect(hButton,
594 &rcButton);
595 x -= (ptMargin.x / 2) + (rcButton.right - rcButton.left);
596 if (!(dwp = DeferWindowPos(dwp,
597 hButton,
598 NULL,
599 x,
600 y,
601 0,
602 0,
603 SWP_NOSIZE | SWP_NOZORDER)))
604 {
605 return;
606 }
607
608 EndDeferWindowPos(dwp);
609 }
610 }
611
612
613 static VOID
614 EnableTroubleShoot(PHARDWARE_PAGE_DATA hpd,
615 BOOL Enable)
616 {
617 HWND hBtnTroubleShoot = GetDlgItem(hpd->hWnd,
618 IDC_TROUBLESHOOT);
619
620 ShowWindow(hBtnTroubleShoot,
621 Enable ? SW_SHOW : SW_HIDE);
622 }
623
624
625 static INT_PTR
626 CALLBACK
627 HardwareDlgProc(IN HWND hwndDlg,
628 IN UINT uMsg,
629 IN WPARAM wParam,
630 IN LPARAM lParam)
631 {
632 PHARDWARE_PAGE_DATA hpd;
633
634 hpd = (PHARDWARE_PAGE_DATA)GetWindowLongPtr(hwndDlg,
635 DWL_USER);
636
637 if (hpd != NULL || uMsg == WM_INITDIALOG)
638 {
639 switch (uMsg)
640 {
641 case WM_NOTIFY:
642 {
643 NMHDR *pnmh = (NMHDR*)lParam;
644 if (pnmh->hwndFrom == hpd->hWndDevList)
645 {
646 switch (pnmh->code)
647 {
648 case LVN_ITEMCHANGED:
649 {
650 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
651
652 if ((pnmv->uChanged & LVIF_STATE) &&
653 ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
654 (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
655 {
656 UpdateControlStates(hpd);
657 }
658 break;
659 }
660 }
661 }
662 break;
663 }
664
665 case WM_SIZE:
666 HardwareDlgResize(hpd,
667 (INT)LOWORD(lParam),
668 (INT)HIWORD(lParam));
669 break;
670
671 case WM_SETTEXT:
672 {
673 LPCWSTR szWndText = (LPCWSTR)lParam;
674 EnableTroubleShoot(hpd,
675 (szWndText != NULL && szWndText[0] != L'\0'));
676 break;
677 }
678
679 case WM_INITDIALOG:
680 {
681 hpd = (PHARDWARE_PAGE_DATA)lParam;
682 if (hpd != NULL)
683 {
684 HWND hWndParent;
685
686 hpd->hWnd = hwndDlg;
687 SetWindowLongPtr(hwndDlg,
688 DWL_USER,
689 (DWORD_PTR)hpd);
690
691 hpd->ClassImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
692
693 SetupDiGetClassImageList(&hpd->ClassImageListData);
694
695 /* calculate the size of the devices list view control */
696 hpd->hWndDevList = GetDlgItem(hwndDlg,
697 IDC_LV_DEVICES);
698 if (hpd->hWndDevList != NULL)
699 {
700 RECT rcClient;
701 GetClientRect(hpd->hWndDevList,
702 &rcClient);
703 hpd->DevListViewHeight = rcClient.bottom;
704
705 if (hpd->DisplayMode == HWPD_LARGELIST)
706 {
707 hpd->DevListViewHeight = (hpd->DevListViewHeight * 3) / 2;
708 }
709 }
710
711 /* subclass the parent window */
712 hWndParent = GetAncestor(hwndDlg,
713 GA_PARENT);
714 if (hWndParent != NULL)
715 {
716 RECT rcClient;
717
718 if (GetClientRect(hWndParent,
719 &rcClient) &&
720 SetWindowPos(hwndDlg,
721 NULL,
722 0,
723 0,
724 rcClient.right,
725 rcClient.bottom,
726 SWP_NOZORDER))
727 {
728 /* subclass the parent window. This is not safe
729 if the parent window belongs to another thread! */
730 hpd->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
731 GWLP_WNDPROC,
732 (LONG_PTR)ParentSubWndProc);
733
734 if (hpd->ParentOldWndProc != NULL &&
735 SetProp(hWndParent,
736 L"DevMgrSubClassInfo",
737 (HANDLE)hpd))
738 {
739 hpd->hWndParent = hWndParent;
740 }
741 }
742 }
743
744 /* initialize the devices list view control */
745 InitializeDevicesList(hpd);
746
747 /* fill the devices list view control */
748 FillDevicesList(hpd);
749
750 /* decide whether to show or hide the troubleshoot button */
751 EnableTroubleShoot(hpd,
752 GetWindowTextLength(hwndDlg) != 0);
753 }
754 break;
755 }
756
757 case WM_DESTROY:
758 {
759 /* free devices list */
760 FreeDevicesList(hpd);
761
762 /* restore the old window proc of the subclassed parent window */
763 if (hpd->hWndParent != NULL && hpd->ParentOldWndProc != NULL)
764 {
765 SetWindowLongPtr(hpd->hWndParent,
766 GWLP_WNDPROC,
767 (LONG_PTR)hpd->ParentOldWndProc);
768 }
769
770 if (hpd->ClassImageListData.ImageList != NULL)
771 {
772 SetupDiDestroyClassImageList(&hpd->ClassImageListData);
773 }
774
775 /* free the reference to comctl32 */
776 FreeLibrary(hpd->hComCtl32);
777 hpd->hComCtl32 = NULL;
778
779 /* free the allocated resources */
780 HeapFree(GetProcessHeap(),
781 0,
782 hpd);
783 break;
784 }
785 }
786 }
787
788 return FALSE;
789 }
790
791
792 /***************************************************************************
793 * NAME EXPORTED
794 * DeviceCreateHardwarePageEx
795 *
796 * DESCRIPTION
797 * Creates a hardware page
798 *
799 * ARGUMENTS
800 * hWndParent: Handle to the parent window
801 * lpGuids: An array of guids of devices that are to be listed
802 * uNumberOfGuids: Numbers of guids in the Guids array
803 * Unknown: Unknown parameter, see NOTEs
804 *
805 * RETURN VALUE
806 * Returns the handle of the hardware page window that has been created or
807 * NULL if it failed.
808 *
809 * REVISIONS
810 * 13-05-2005 first working version (Sebastian Gasiorek <zebasoftis@gmail.com>)
811 *
812 * TODO
813 * missing: device icon in list view, Troubleshoot button, device properties,
814 * status description,
815 * devices should be visible afer PSN_SETACTIVE message
816 *
817 */
818 HWND
819 WINAPI
820 DeviceCreateHardwarePageEx(IN HWND hWndParent,
821 IN LPGUID lpGuids,
822 IN UINT uNumberOfGuids,
823 IN HWPAGE_DISPLAYMODE DisplayMode)
824 {
825 PHARDWARE_PAGE_DATA hpd;
826 PINITCOMMONCONTROLS pInitCommonControls;
827
828 /* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
829 zeroed because the initialization code assumes that in
830 failure cases! */
831 hpd = HeapAlloc(GetProcessHeap(),
832 HEAP_ZERO_MEMORY,
833 FIELD_OFFSET(HARDWARE_PAGE_DATA,
834 ClassDevInfo) +
835 (uNumberOfGuids * sizeof(HWCLASSDEVINFO)));
836 if (hpd != NULL)
837 {
838 HWND hWnd;
839 UINT i;
840
841 hpd->DisplayMode = ((DisplayMode > HWPD_MAX) ? HWPD_STANDARDLIST : DisplayMode);
842
843 /* initialize the HARDWARE_PAGE_DATA structure */
844 hpd->NumberOfGuids = uNumberOfGuids;
845 for (i = 0;
846 i < uNumberOfGuids;
847 i++)
848 {
849 hpd->ClassDevInfo[i].Guid = lpGuids[i];
850 }
851
852 /* load comctl32.dll dynamically */
853 hpd->hComCtl32 = LoadLibrary(TEXT("comctl32.dll"));
854 if (hpd->hComCtl32 == NULL)
855 {
856 goto Cleanup;
857 }
858
859 /* initialize the common controls */
860 pInitCommonControls = (PINITCOMMONCONTROLS)GetProcAddress(hpd->hComCtl32,
861 "InitCommonControls");
862 if (pInitCommonControls == NULL)
863 {
864 goto Cleanup;
865 }
866 pInitCommonControls();
867
868 /* create the dialog */
869 hWnd = CreateDialogParam(hDllInstance,
870 MAKEINTRESOURCE(IDD_HARDWARE),
871 hWndParent,
872 HardwareDlgProc,
873 (LPARAM)hpd);
874 if (hWnd != NULL)
875 {
876 return hWnd;
877 }
878 else
879 {
880 Cleanup:
881 /* oops, something went wrong... */
882 if (hpd->hComCtl32 != NULL)
883 {
884 FreeLibrary(hpd->hComCtl32);
885 }
886
887 HeapFree(GetProcessHeap(),
888 0,
889 hpd);
890 }
891 }
892
893 return NULL;
894 }
895
896
897 /***************************************************************************
898 * NAME EXPORTED
899 * DeviceCreateHardwarePage
900 *
901 * DESCRIPTION
902 * Creates a hardware page
903 *
904 * ARGUMENTS
905 * hWndParent: Handle to the parent window
906 * lpGuid: Guid of the device
907 *
908 * RETURN VALUE
909 * Returns the handle of the hardware page window that has been created or
910 * NULL if it failed.
911 *
912 * REVISIONS
913 *
914 * NOTE
915 *
916 */
917 HWND
918 WINAPI
919 DeviceCreateHardwarePage(IN HWND hWndParent,
920 IN LPGUID lpGuid)
921 {
922 return DeviceCreateHardwarePageEx(hWndParent,
923 lpGuid,
924 1,
925 HWPD_LARGELIST);
926 }