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