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