0b59ad86343bf979e57657d644ad1b3c1696ef7a
[reactos.git] / reactos / dll / win32 / devmgr / properties / advprop.cpp
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 *
21 * PROJECT: ReactOS devmgr.dll
22 * FILE: lib/devmgr/advprop.c
23 * PURPOSE: ReactOS Device Manager
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
25 * Ged Murphy <gedmurphy@reactos.org>
26 * UPDATE HISTORY:
27 * 04-04-2004 Created
28 */
29
30 #include "precomp.h"
31 #include "properties.h"
32 #include "resource.h"
33
34 #include <winver.h>
35
36
37 static UINT WINAPI
38 EnumDeviceDriverFilesCallback(IN PVOID Context,
39 IN UINT Notification,
40 IN UINT_PTR Param1,
41 IN UINT_PTR Param2)
42 {
43 LVITEM li;
44 PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext = (PENUMDRIVERFILES_CONTEXT)Context;
45
46 li.mask = LVIF_TEXT | LVIF_STATE;
47 li.iItem = EnumDriverFilesContext->nCount++;
48 li.iSubItem = 0;
49 li.state = (li.iItem == 0 ? LVIS_SELECTED : 0);
50 li.stateMask = LVIS_SELECTED;
51 li.pszText = (LPWSTR)Param1;
52 (void)ListView_InsertItem(EnumDriverFilesContext->hDriversListView,
53 &li);
54 return NO_ERROR;
55 }
56
57
58 static VOID
59 UpdateDriverDetailsDlg(IN HWND hwndDlg,
60 IN HWND hDriversListView,
61 IN PDEVADVPROP_INFO dap)
62 {
63 HDEVINFO DeviceInfoSet;
64 PSP_DEVINFO_DATA DeviceInfoData;
65 SP_DRVINFO_DATA DriverInfoData;
66 ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext;
67
68 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
69 {
70 DeviceInfoSet = dap->CurrentDeviceInfoSet;
71 DeviceInfoData = &dap->CurrentDeviceInfoData;
72 }
73 else
74 {
75 DeviceInfoSet = dap->DeviceInfoSet;
76 DeviceInfoData = &dap->DeviceInfoData;
77 }
78
79 /* set the device image */
80 SendDlgItemMessage(hwndDlg,
81 IDC_DEVICON,
82 STM_SETICON,
83 (WPARAM)dap->hDevIcon,
84 0);
85
86 /* set the device name edit control text */
87 SetDlgItemText(hwndDlg,
88 IDC_DEVNAME,
89 dap->szDevName);
90
91 /* fill the driver files list view */
92 EnumDriverFilesContext.hDriversListView = hDriversListView;
93 EnumDriverFilesContext.nCount = 0;
94
95 (void)ListView_DeleteAllItems(EnumDriverFilesContext.hDriversListView);
96 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
97 if (FindCurrentDriver(DeviceInfoSet,
98 DeviceInfoData,
99 &DriverInfoData) &&
100 SetupDiSetSelectedDriver(DeviceInfoSet,
101 DeviceInfoData,
102 &DriverInfoData))
103 {
104 HSPFILEQ queueHandle;
105
106 queueHandle = SetupOpenFileQueue();
107 if (queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE)
108 {
109 SP_DEVINSTALL_PARAMS DeviceInstallParams = {0};
110 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
111 if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
112 DeviceInfoData,
113 &DeviceInstallParams))
114 {
115 DeviceInstallParams.FileQueue = queueHandle;
116 DeviceInstallParams.Flags |= DI_NOVCP;
117
118 if (SetupDiSetDeviceInstallParams(DeviceInfoSet,
119 DeviceInfoData,
120 &DeviceInstallParams) &&
121 SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
122 DeviceInfoSet,
123 DeviceInfoData))
124 {
125 DWORD scanResult;
126 RECT rcClient;
127 LVCOLUMN lvc;
128
129 /* enumerate the driver files */
130 SetupScanFileQueue(queueHandle,
131 SPQ_SCAN_USE_CALLBACK,
132 NULL,
133 EnumDeviceDriverFilesCallback,
134 &EnumDriverFilesContext,
135 &scanResult);
136
137 /* update the list view column width */
138 GetClientRect(hDriversListView,
139 &rcClient);
140 lvc.mask = LVCF_WIDTH;
141 lvc.cx = rcClient.right;
142 (void)ListView_SetColumn(hDriversListView,
143 0,
144 &lvc);
145
146 /* highlight the first item from list */
147 if (ListView_GetSelectedCount(hDriversListView) != 0)
148 {
149 ListView_SetItemState(hDriversListView,
150 0,
151 LVIS_FOCUSED | LVIS_SELECTED,
152 LVIS_FOCUSED | LVIS_SELECTED);
153 }
154 }
155 }
156
157 SetupCloseFileQueue(queueHandle);
158 }
159 }
160 }
161
162
163 static VOID
164 UpdateDriverVersionInfoDetails(IN HWND hwndDlg,
165 IN LPCWSTR lpszDriverPath)
166 {
167 DWORD dwHandle;
168 DWORD dwVerInfoSize;
169 LPVOID lpData = NULL;
170 LPVOID lpInfo;
171 UINT uInfoLen;
172 DWORD dwLangId;
173 WCHAR szLangInfo[255];
174 WCHAR szLangPath[MAX_PATH];
175 LPWSTR lpCompanyName = NULL;
176 LPWSTR lpFileVersion = NULL;
177 LPWSTR lpLegalCopyright = NULL;
178 LPWSTR lpDigitalSigner = NULL;
179 UINT uBufLen;
180 WCHAR szNotAvailable[255];
181
182 /* extract version info from selected file */
183 dwVerInfoSize = GetFileVersionInfoSize(lpszDriverPath,
184 &dwHandle);
185 if (!dwVerInfoSize)
186 goto done;
187
188 lpData = HeapAlloc(GetProcessHeap(),
189 HEAP_ZERO_MEMORY,
190 dwVerInfoSize);
191 if (!lpData)
192 goto done;
193
194 if (!GetFileVersionInfo(lpszDriverPath,
195 dwHandle,
196 dwVerInfoSize,
197 lpData))
198 goto done;
199
200 if (!VerQueryValue(lpData,
201 L"\\VarFileInfo\\Translation",
202 &lpInfo,
203 &uInfoLen))
204 goto done;
205
206 dwLangId = *(LPDWORD)lpInfo;
207 swprintf(szLangInfo, L"\\StringFileInfo\\%04x%04x\\",
208 LOWORD(dwLangId), HIWORD(dwLangId));
209
210 /* read CompanyName */
211 wcscpy(szLangPath, szLangInfo);
212 wcscat(szLangPath, L"CompanyName");
213
214 VerQueryValue(lpData,
215 szLangPath,
216 (void **)&lpCompanyName,
217 (PUINT)&uBufLen);
218
219 /* read FileVersion */
220 wcscpy(szLangPath, szLangInfo);
221 wcscat(szLangPath, L"FileVersion");
222
223 VerQueryValue(lpData,
224 szLangPath,
225 (void **)&lpFileVersion,
226 (PUINT)&uBufLen);
227
228 /* read LegalTrademarks */
229 wcscpy(szLangPath, szLangInfo);
230 wcscat(szLangPath, L"LegalCopyright");
231
232 VerQueryValue(lpData,
233 szLangPath,
234 (void **)&lpLegalCopyright,
235 (PUINT)&uBufLen);
236
237 /* TODO: read digital signer info */
238
239 done:
240 if (!LoadString(hDllInstance,
241 IDS_NOTAVAILABLE,
242 szNotAvailable,
243 sizeof(szNotAvailable) / sizeof(WCHAR)))
244 {
245 wcscpy(szNotAvailable, L"n/a");
246 }
247
248 /* update labels */
249 if (!lpCompanyName)
250 lpCompanyName = szNotAvailable;
251 SetDlgItemText(hwndDlg,
252 IDC_FILEPROVIDER,
253 lpCompanyName);
254
255 if (!lpFileVersion)
256 lpFileVersion = szNotAvailable;
257 SetDlgItemText(hwndDlg,
258 IDC_FILEVERSION,
259 lpFileVersion);
260
261 if (!lpLegalCopyright)
262 lpLegalCopyright = szNotAvailable;
263 SetDlgItemText(hwndDlg,
264 IDC_FILECOPYRIGHT,
265 lpLegalCopyright);
266
267 if (!lpDigitalSigner)
268 lpDigitalSigner = szNotAvailable;
269 SetDlgItemText(hwndDlg,
270 IDC_DIGITALSIGNER,
271 lpDigitalSigner);
272
273 /* release version info */
274 if (lpData)
275 HeapFree(GetProcessHeap(),
276 0,
277 lpData);
278 }
279
280
281 static INT_PTR
282 CALLBACK
283 DriverDetailsDlgProc(IN HWND hwndDlg,
284 IN UINT uMsg,
285 IN WPARAM wParam,
286 IN LPARAM lParam)
287 {
288 PDEVADVPROP_INFO dap;
289 INT_PTR Ret = FALSE;
290
291 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
292 DWL_USER);
293
294 if (dap != NULL || uMsg == WM_INITDIALOG)
295 {
296 switch (uMsg)
297 {
298 case WM_COMMAND:
299 {
300 switch (LOWORD(wParam))
301 {
302 case IDOK:
303 case IDCANCEL:
304 {
305 EndDialog(hwndDlg,
306 IDOK);
307 break;
308 }
309 }
310 break;
311 }
312
313 case WM_CLOSE:
314 {
315 EndDialog(hwndDlg,
316 IDCANCEL);
317 break;
318 }
319
320 case WM_INITDIALOG:
321 {
322 LV_COLUMN lvc;
323 HWND hDriversListView;
324 WCHAR szBuffer[260];
325
326 dap = (PDEVADVPROP_INFO)lParam;
327 if (dap != NULL)
328 {
329 SetWindowLongPtr(hwndDlg,
330 DWL_USER,
331 (DWORD_PTR)dap);
332
333 hDriversListView = GetDlgItem(hwndDlg,
334 IDC_DRIVERFILES);
335
336 /* add a column to the list view control */
337 lvc.mask = LVCF_FMT | LVCF_WIDTH;
338 lvc.fmt = LVCFMT_LEFT;
339 lvc.cx = 0;
340 (void)ListView_InsertColumn(hDriversListView,
341 0,
342 &lvc);
343
344 UpdateDriverDetailsDlg(hwndDlg,
345 hDriversListView,
346 dap);
347
348 if (ListView_GetItemCount(hDriversListView) == 0)
349 {
350 if (LoadStringW(hDllInstance, IDS_NODRIVERS, szBuffer, _countof(szBuffer)))
351 MessageBoxW(hwndDlg, szBuffer, dap->szDevName, MB_OK);
352 EndDialog(hwndDlg, IDCANCEL);
353 }
354 }
355
356 Ret = TRUE;
357 break;
358 }
359
360 case WM_NOTIFY:
361 {
362 LPNMHDR pnmhdr = (LPNMHDR)lParam;
363
364 switch (pnmhdr->code)
365 {
366 case LVN_ITEMCHANGED:
367 {
368 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
369 HWND hDriversListView = GetDlgItem(hwndDlg,
370 IDC_DRIVERFILES);
371
372 if (ListView_GetSelectedCount(hDriversListView) == 0)
373 {
374 /* nothing is selected - empty the labels */
375 SetDlgItemText(hwndDlg,
376 IDC_FILEPROVIDER,
377 NULL);
378 SetDlgItemText(hwndDlg,
379 IDC_FILEVERSION,
380 NULL);
381 SetDlgItemText(hwndDlg,
382 IDC_FILECOPYRIGHT,
383 NULL);
384 SetDlgItemText(hwndDlg,
385 IDC_DIGITALSIGNER,
386 NULL);
387 }
388 else if (pnmv->uNewState != 0)
389 {
390 /* extract version info and update the labels */
391 WCHAR szDriverPath[MAX_PATH];
392
393 ListView_GetItemText(hDriversListView,
394 pnmv->iItem,
395 pnmv->iSubItem,
396 szDriverPath,
397 MAX_PATH);
398
399 UpdateDriverVersionInfoDetails(hwndDlg,
400 szDriverPath);
401 }
402 }
403 }
404 break;
405 }
406 }
407 }
408
409 return Ret;
410 }
411
412
413 static
414 VOID
415 UpdateDriver(
416 IN HWND hwndDlg,
417 IN PDEVADVPROP_INFO dap)
418 {
419 TOKEN_PRIVILEGES Privileges;
420 HANDLE hToken;
421 DWORD dwReboot;
422 BOOL NeedReboot = FALSE;
423
424 // Better use InstallDevInst:
425 // BOOL
426 // WINAPI
427 // InstallDevInst(
428 // HWND hWnd,
429 // LPWSTR wszDeviceId,
430 // BOOL bUpdate,
431 // DWORD *dwReboot);
432 // See: http://comp.os.ms-windows.programmer.win32.narkive.com/J8FTd4KK/signature-of-undocumented-installdevinstex
433
434 if (!InstallDevInst(hwndDlg, dap->szDeviceID, TRUE, &dwReboot))
435 return;
436
437 if (NeedReboot == FALSE)
438 return;
439
440 //FIXME: load text from resource file
441 if (MessageBoxW(hwndDlg, L"Reboot now?", L"Reboot required", MB_YESNO | MB_ICONQUESTION) != IDYES)
442 return;
443
444 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
445 {
446 ERR("OpenProcessToken failed\n");
447 return;
448 }
449
450 /* Get the LUID for the Shutdown privilege */
451 if (!LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &Privileges.Privileges[0].Luid))
452 {
453 ERR("LookupPrivilegeValue failed\n");
454 CloseHandle(hToken);
455 return;
456 }
457
458 /* Assign the Shutdown privilege to our process */
459 Privileges.PrivilegeCount = 1;
460 Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
461
462 if (!AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL))
463 {
464 ERR("AdjustTokenPrivileges failed\n");
465 CloseHandle(hToken);
466 return;
467 }
468
469 /* Finally shut down the system */
470 if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
471 {
472 ERR("ExitWindowsEx failed\n");
473 CloseHandle(hToken);
474 }
475 }
476
477
478 static VOID
479 UpdateDriverDlg(IN HWND hwndDlg,
480 IN PDEVADVPROP_INFO dap)
481 {
482 HDEVINFO DeviceInfoSet;
483 PSP_DEVINFO_DATA DeviceInfoData;
484
485 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
486 {
487 DeviceInfoSet = dap->CurrentDeviceInfoSet;
488 DeviceInfoData = &dap->CurrentDeviceInfoData;
489 }
490 else
491 {
492 DeviceInfoSet = dap->DeviceInfoSet;
493 DeviceInfoData = &dap->DeviceInfoData;
494 }
495
496 /* set the device image */
497 SendDlgItemMessage(hwndDlg,
498 IDC_DEVICON,
499 STM_SETICON,
500 (WPARAM)dap->hDevIcon,
501 0);
502
503 /* set the device name edit control text */
504 SetDlgItemText(hwndDlg,
505 IDC_DEVNAME,
506 dap->szDevName);
507
508 /* query the driver provider */
509 if (GetDriverProviderString(DeviceInfoSet,
510 DeviceInfoData,
511 dap->szTemp,
512 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
513 {
514 SetDlgItemText(hwndDlg,
515 IDC_DRVPROVIDER,
516 dap->szTemp);
517 }
518
519 /* query the driver date */
520 if (GetDriverDateString(DeviceInfoSet,
521 DeviceInfoData,
522 dap->szTemp,
523 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
524 {
525 SetDlgItemText(hwndDlg,
526 IDC_DRVDATE,
527 dap->szTemp);
528 }
529
530 /* query the driver version */
531 if (GetDriverVersionString(DeviceInfoSet,
532 DeviceInfoData,
533 dap->szTemp,
534 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
535 {
536 SetDlgItemText(hwndDlg,
537 IDC_DRVVERSION,
538 dap->szTemp);
539 }
540 }
541
542
543 static INT_PTR
544 CALLBACK
545 AdvProcDriverDlgProc(IN HWND hwndDlg,
546 IN UINT uMsg,
547 IN WPARAM wParam,
548 IN LPARAM lParam)
549 {
550 PDEVADVPROP_INFO dap;
551 INT_PTR Ret = FALSE;
552
553 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
554 DWL_USER);
555
556 if (dap != NULL || uMsg == WM_INITDIALOG)
557 {
558 switch (uMsg)
559 {
560 case WM_COMMAND:
561 {
562 switch (LOWORD(wParam))
563 {
564 case IDC_DRIVERDETAILS:
565 DialogBoxParam(hDllInstance,
566 MAKEINTRESOURCE(IDD_DRIVERDETAILS),
567 hwndDlg,
568 DriverDetailsDlgProc,
569 (ULONG_PTR)dap);
570 break;
571
572 case IDC_UPDATEDRIVER:
573 UpdateDriver(hwndDlg, dap);
574 break;
575 }
576 break;
577 }
578
579 case WM_NOTIFY:
580 {
581 NMHDR *hdr = (NMHDR*)lParam;
582 switch (hdr->code)
583 {
584 case PSN_APPLY:
585 break;
586 }
587 break;
588 }
589
590 case WM_INITDIALOG:
591 {
592 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
593 if (dap != NULL)
594 {
595 SetWindowLongPtr(hwndDlg,
596 DWL_USER,
597 (DWORD_PTR)dap);
598
599 UpdateDriverDlg(hwndDlg,
600 dap);
601 }
602 Ret = TRUE;
603 break;
604 }
605 }
606 }
607
608 return Ret;
609 }
610
611
612 static VOID
613 SetListViewText(HWND hwnd,
614 INT iItem,
615 LPCWSTR lpText)
616 {
617 LVITEM li;
618
619 li.mask = LVIF_TEXT | LVIF_STATE;
620 li.iItem = iItem;
621 li.iSubItem = 0;
622 li.state = 0; //(li.iItem == 0 ? LVIS_SELECTED : 0);
623 li.stateMask = LVIS_SELECTED;
624 li.pszText = (LPWSTR)lpText;
625 (void)ListView_InsertItem(hwnd,
626 &li);
627 }
628
629
630 static VOID
631 UpdateDetailsDlg(IN HWND hwndDlg,
632 IN PDEVADVPROP_INFO dap)
633 {
634 HWND hwndComboBox;
635 HWND hwndListView;
636 LV_COLUMN lvc;
637 RECT rcClient;
638
639 UINT i;
640 UINT Properties[] =
641 {
642 IDS_PROP_DEVICEID,
643 IDS_PROP_HARDWAREIDS,
644 IDS_PROP_COMPATIBLEIDS,
645 IDS_PROP_MATCHINGDEVICEID,
646 IDS_PROP_SERVICE,
647 IDS_PROP_ENUMERATOR,
648 IDS_PROP_CAPABILITIES,
649 IDS_PROP_DEVNODEFLAGS,
650 IDS_PROP_CONFIGFLAGS,
651 IDS_PROP_CSCONFIGFLAGS,
652 IDS_PROP_EJECTIONRELATIONS,
653 IDS_PROP_REMOVALRELATIONS,
654 IDS_PROP_BUSRELATIONS,
655 IDS_PROP_DEVUPPERFILTERS,
656 IDS_PROP_DEVLOWERFILTERS,
657 IDS_PROP_CLASSUPPERFILTERS,
658 IDS_PROP_CLASSLOWERFILTERS,
659 IDS_PROP_CLASSINSTALLER,
660 IDS_PROP_CLASSCOINSTALLER,
661 IDS_PROP_DEVICECOINSTALLER,
662 IDS_PROP_FIRMWAREREVISION,
663 IDS_PROP_CURRENTPOWERSTATE,
664 IDS_PROP_POWERCAPABILITIES,
665 IDS_PROP_POWERSTATEMAPPINGS
666 };
667
668
669 /* set the device image */
670 SendDlgItemMessage(hwndDlg,
671 IDC_DEVICON,
672 STM_SETICON,
673 (WPARAM)dap->hDevIcon,
674 0);
675
676 /* set the device name edit control text */
677 SetDlgItemText(hwndDlg,
678 IDC_DEVNAME,
679 dap->szDevName);
680
681
682 hwndComboBox = GetDlgItem(hwndDlg,
683 IDC_DETAILSPROPNAME);
684
685 hwndListView = GetDlgItem(hwndDlg,
686 IDC_DETAILSPROPVALUE);
687
688 for (i = 0; i != sizeof(Properties) / sizeof(Properties[0]); i++)
689 {
690 /* fill in the device usage combo box */
691 if (LoadString(hDllInstance,
692 Properties[i],
693 dap->szTemp,
694 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
695 {
696 SendMessage(hwndComboBox,
697 CB_ADDSTRING,
698 0,
699 (LPARAM)dap->szTemp);
700 }
701 }
702
703
704 GetClientRect(hwndListView,
705 &rcClient);
706
707 /* add a column to the list view control */
708 lvc.mask = LVCF_FMT | LVCF_WIDTH;
709 lvc.fmt = LVCFMT_LEFT;
710 lvc.cx = rcClient.right;
711 (void)ListView_InsertColumn(hwndListView,
712 0,
713 &lvc);
714
715 SendMessage(hwndComboBox,
716 CB_SETCURSEL,
717 0,
718 0);
719
720 SetListViewText(hwndListView, 0, dap->szDeviceID);
721
722 SetFocus(hwndComboBox);
723 }
724
725
726 static VOID
727 DisplayDevicePropertyText(IN PDEVADVPROP_INFO dap,
728 IN HWND hwndListView,
729 IN DWORD dwProperty)
730 {
731 HDEVINFO DeviceInfoSet;
732 PSP_DEVINFO_DATA DeviceInfoData;
733 DWORD dwType;
734 DWORD dwSize;
735 DWORD dwValue;
736 LPBYTE lpBuffer;
737 LPWSTR lpStr;
738 INT len;
739 INT index;
740
741 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
742 {
743 DeviceInfoSet = dap->CurrentDeviceInfoSet;
744 DeviceInfoData = &dap->CurrentDeviceInfoData;
745 }
746 else
747 {
748 DeviceInfoSet = dap->DeviceInfoSet;
749 DeviceInfoData = &dap->DeviceInfoData;
750 }
751
752 dwSize = 0;
753 SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
754 DeviceInfoData,
755 dwProperty,
756 &dwType,
757 NULL,
758 0,
759 &dwSize);
760 if (dwSize == 0)
761 {
762 if (GetLastError() != ERROR_FILE_NOT_FOUND)
763 {
764 swprintf(dap->szTemp, L"Error: Getting the size failed! (Error: %ld)", GetLastError());
765 SetListViewText(hwndListView, 0, dap->szTemp);
766 }
767 return;
768 }
769
770 if (dwType == REG_SZ)
771 dwSize += sizeof(WCHAR);
772
773 lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
774 HEAP_ZERO_MEMORY,
775 dwSize);
776 if (lpBuffer == NULL)
777 {
778 SetListViewText(hwndListView, 0, L"Error: Allocating the buffer failed!");
779 return;
780 }
781
782 if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
783 DeviceInfoData,
784 dwProperty,
785 &dwType,
786 lpBuffer,
787 dwSize,
788 &dwSize))
789 {
790 if (dwType == REG_SZ)
791 {
792 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
793 }
794 else if (dwType == REG_MULTI_SZ)
795 {
796 lpStr = (LPWSTR)lpBuffer;
797 index = 0;
798 while (*lpStr != 0)
799 {
800 len = wcslen(lpStr) + 1;
801
802 SetListViewText(hwndListView, index, lpStr);
803
804 lpStr += len;
805 index++;
806 }
807 }
808 else if (dwType == REG_DWORD)
809 {
810 dwValue = *(DWORD *) lpBuffer;
811
812 switch (dwProperty)
813 {
814 case SPDRP_CAPABILITIES:
815 index = 0;
816 if (dwValue & CM_DEVCAP_LOCKSUPPORTED)
817 SetListViewText(hwndListView, index++, L"CM_DEVCAP_LOCKSUPPORTED");
818 if (dwValue & CM_DEVCAP_EJECTSUPPORTED)
819 SetListViewText(hwndListView, index++, L"CM_DEVCAP_EJECTSUPPORTED");
820 if (dwValue & CM_DEVCAP_REMOVABLE)
821 SetListViewText(hwndListView, index++, L"CM_DEVCAP_REMOVABLE");
822 if (dwValue & CM_DEVCAP_DOCKDEVICE)
823 SetListViewText(hwndListView, index++, L"CM_DEVCAP_DOCKDEVICE");
824 if (dwValue & CM_DEVCAP_UNIQUEID)
825 SetListViewText(hwndListView, index++, L"CM_DEVCAP_UNIQUEID");
826 if (dwValue & CM_DEVCAP_SILENTINSTALL)
827 SetListViewText(hwndListView, index++, L"CM_DEVCAP_SILENTINSTALL");
828 if (dwValue & CM_DEVCAP_RAWDEVICEOK)
829 SetListViewText(hwndListView, index++, L"CM_DEVCAP_RAWDEVICEOK");
830 if (dwValue & CM_DEVCAP_SURPRISEREMOVALOK)
831 SetListViewText(hwndListView, index++, L"CM_DEVCAP_SURPRISEREMOVALOK");
832 if (dwValue & CM_DEVCAP_HARDWAREDISABLED)
833 SetListViewText(hwndListView, index++, L"CM_DEVCAP_HARDWAREDISABLED");
834 if (dwValue & CM_DEVCAP_NONDYNAMIC)
835 SetListViewText(hwndListView, index++, L"CM_DEVCAP_NONDYNAMIC");
836 break;
837
838 case SPDRP_CONFIGFLAGS:
839 index = 0;
840 if (dwValue & CONFIGFLAG_DISABLED)
841 SetListViewText(hwndListView, index++, L"CONFIGFLAG_DISABLED");
842 if (dwValue & CONFIGFLAG_REMOVED)
843 SetListViewText(hwndListView, index++, L"CONFIGFLAG_REMOVED");
844 if (dwValue & CONFIGFLAG_MANUAL_INSTALL)
845 SetListViewText(hwndListView, index++, L"CONFIGFLAG_MANUAL_INSTALL");
846 if (dwValue & CONFIGFLAG_IGNORE_BOOT_LC)
847 SetListViewText(hwndListView, index++, L"CONFIGFLAG_IGNORE_BOOT_LC");
848 if (dwValue & CONFIGFLAG_NET_BOOT)
849 SetListViewText(hwndListView, index++, L"CONFIGFLAG_NET_BOOT");
850 if (dwValue & CONFIGFLAG_REINSTALL)
851 SetListViewText(hwndListView, index++, L"CONFIGFLAG_REINSTALL");
852 if (dwValue & CONFIGFLAG_FAILEDINSTALL)
853 SetListViewText(hwndListView, index++, L"CONFIGFLAG_FAILEDINSTALL");
854 if (dwValue & CONFIGFLAG_CANTSTOPACHILD)
855 SetListViewText(hwndListView, index++, L"CONFIGFLAG_CANTSTOPACHILD");
856 if (dwValue & CONFIGFLAG_OKREMOVEROM)
857 SetListViewText(hwndListView, index++, L"CONFIGFLAG_OKREMOVEROM");
858 if (dwValue & CONFIGFLAG_NOREMOVEEXIT)
859 SetListViewText(hwndListView, index++, L"CONFIGFLAG_NOREMOVEEXIT");
860 break;
861
862 default:
863 swprintf(dap->szTemp, L"0x%08lx", dwValue);
864 SetListViewText(hwndListView, 0, dap->szTemp);
865 break;
866 }
867 }
868 else
869 {
870 SetListViewText(hwndListView, 0, L"Error: Unsupported value type!");
871
872 }
873 }
874 else
875 {
876 SetListViewText(hwndListView, 0, L"Error: Retrieving the value failed!");
877 }
878
879 HeapFree(GetProcessHeap(),
880 0,
881 lpBuffer);
882 }
883
884 static VOID
885 DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,
886 IN HWND hwndListView)
887 {
888 DWORD dwStatus = 0;
889 DWORD dwProblem = 0;
890 INT index;
891
892 CM_Get_DevNode_Status_Ex(&dwStatus,
893 &dwProblem,
894 dap->DeviceInfoData.DevInst,
895 0,
896 dap->hMachine);
897
898 index = 0;
899 if (dwStatus & DN_ROOT_ENUMERATED)
900 SetListViewText(hwndListView, index++, L"DN_ROOT_ENUMERATED");
901 if (dwStatus & DN_DRIVER_LOADED)
902 SetListViewText(hwndListView, index++, L"DN_DRIVER_LOADED");
903 if (dwStatus & DN_ENUM_LOADED)
904 SetListViewText(hwndListView, index++, L"DN_ENUM_LOADED");
905 if (dwStatus & DN_STARTED)
906 SetListViewText(hwndListView, index++, L"DN_STARTED");
907 if (dwStatus & DN_MANUAL)
908 SetListViewText(hwndListView, index++, L"DN_MANUAL");
909 if (dwStatus & DN_NEED_TO_ENUM)
910 SetListViewText(hwndListView, index++, L"DN_NEED_TO_ENUM");
911 if (dwStatus & DN_DRIVER_BLOCKED)
912 SetListViewText(hwndListView, index++, L"DN_DRIVER_BLOCKED");
913 if (dwStatus & DN_HARDWARE_ENUM)
914 SetListViewText(hwndListView, index++, L"DN_HARDWARE_ENUM");
915 if (dwStatus & DN_NEED_RESTART)
916 SetListViewText(hwndListView, index++, L"DN_NEED_RESTART");
917 if (dwStatus & DN_CHILD_WITH_INVALID_ID)
918 SetListViewText(hwndListView, index++, L"DN_CHILD_WITH_INVALID_ID");
919 if (dwStatus & DN_HAS_PROBLEM)
920 SetListViewText(hwndListView, index++, L"DN_HAS_PROBLEM");
921 if (dwStatus & DN_FILTERED)
922 SetListViewText(hwndListView, index++, L"DN_FILTERED");
923 if (dwStatus & DN_LEGACY_DRIVER)
924 SetListViewText(hwndListView, index++, L"DN_LEGACY_DRIVER");
925 if (dwStatus & DN_DISABLEABLE)
926 SetListViewText(hwndListView, index++, L"DN_DISABLEABLE");
927 if (dwStatus & DN_REMOVABLE)
928 SetListViewText(hwndListView, index++, L"DN_REMOVABLE");
929 if (dwStatus & DN_PRIVATE_PROBLEM)
930 SetListViewText(hwndListView, index++, L"DN_PRIVATE_PROBLEM");
931 if (dwStatus & DN_MF_PARENT)
932 SetListViewText(hwndListView, index++, L"DN_MF_PARENT");
933 if (dwStatus & DN_MF_CHILD)
934 SetListViewText(hwndListView, index++, L"DN_MF_CHILD");
935 if (dwStatus & DN_WILL_BE_REMOVED)
936 SetListViewText(hwndListView, index++, L"DN_WILL_BE_REMOVED");
937
938 if (dwStatus & DN_NOT_FIRST_TIMEE)
939 SetListViewText(hwndListView, index++, L"DN_NOT_FIRST_TIMEE");
940 if (dwStatus & DN_STOP_FREE_RES)
941 SetListViewText(hwndListView, index++, L"DN_STOP_FREE_RES");
942 if (dwStatus & DN_REBAL_CANDIDATE)
943 SetListViewText(hwndListView, index++, L"DN_REBAL_CANDIDATE");
944 if (dwStatus & DN_BAD_PARTIAL)
945 SetListViewText(hwndListView, index++, L"DN_BAD_PARTIAL");
946 if (dwStatus & DN_NT_ENUMERATOR)
947 SetListViewText(hwndListView, index++, L"DN_NT_ENUMERATOR");
948 if (dwStatus & DN_NT_DRIVER)
949 SetListViewText(hwndListView, index++, L"DN_NT_DRIVER");
950
951 if (dwStatus & DN_NEEDS_LOCKING)
952 SetListViewText(hwndListView, index++, L"DN_NEEDS_LOCKING");
953 if (dwStatus & DN_ARM_WAKEUP)
954 SetListViewText(hwndListView, index++, L"DN_ARM_WAKEUP");
955 if (dwStatus & DN_APM_ENUMERATOR)
956 SetListViewText(hwndListView, index++, L"DN_APM_ENUMERATOR");
957 if (dwStatus & DN_APM_DRIVER)
958 SetListViewText(hwndListView, index++, L"DN_APM_DRIVER");
959 if (dwStatus & DN_SILENT_INSTALL)
960 SetListViewText(hwndListView, index++, L"DN_SILENT_INSTALL");
961 if (dwStatus & DN_NO_SHOW_IN_DM)
962 SetListViewText(hwndListView, index++, L"DN_NO_SHOW_IN_DM");
963 if (dwStatus & DN_BOOT_LOG_PROB)
964 SetListViewText(hwndListView, index++, L"DN_BOOT_LOG_PROB");
965
966 // swprintf(dap->szTemp, L"0x%08x", dwStatus);
967 // SetListViewText(hwndListView, 0, dap->szTemp);
968 }
969
970
971 static VOID
972 DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
973 IN HWND hwndListView)
974 {
975 PSP_DEVINFO_DATA DeviceInfoData;
976
977 DWORD dwType = 0;
978 WCHAR szBuffer[256];
979 DWORD dwSize = 256 * sizeof(WCHAR);
980
981 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
982 {
983 DeviceInfoData = &dap->CurrentDeviceInfoData;
984 }
985 else
986 {
987 DeviceInfoData = &dap->DeviceInfoData;
988 }
989
990 CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
991 CM_DRP_ENUMERATOR_NAME,
992 &dwType,
993 &szBuffer,
994 &dwSize,
995 0,
996 dap->hMachine);
997
998 SetListViewText(hwndListView, 0, szBuffer);
999 }
1000
1001
1002 static VOID
1003 DisplayCsFlags(IN PDEVADVPROP_INFO dap,
1004 IN HWND hwndListView)
1005 {
1006 DWORD dwValue = 0;
1007 INT index;
1008
1009 CM_Get_HW_Prof_Flags_Ex(dap->szDevName,
1010 0, /* current hardware profile */
1011 &dwValue,
1012 0,
1013 dap->hMachine);
1014
1015 index = 0;
1016 if (dwValue & CSCONFIGFLAG_DISABLED)
1017 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DISABLED");
1018
1019 if (dwValue & CSCONFIGFLAG_DO_NOT_CREATE)
1020 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_CREATE");
1021
1022 if (dwValue & CSCONFIGFLAG_DO_NOT_START)
1023 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_START");
1024 }
1025
1026
1027 static VOID
1028 DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
1029 IN HWND hwndListView)
1030 {
1031 HDEVINFO DeviceInfoSet;
1032 PSP_DEVINFO_DATA DeviceInfoData;
1033 WCHAR szBuffer[256];
1034 HKEY hKey;
1035 DWORD dwSize;
1036 DWORD dwType;
1037
1038 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1039 {
1040 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1041 DeviceInfoData = &dap->CurrentDeviceInfoData;
1042 }
1043 else
1044 {
1045 DeviceInfoSet = dap->DeviceInfoSet;
1046 DeviceInfoData = &dap->DeviceInfoData;
1047 }
1048
1049 hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1050 DeviceInfoData,
1051 DICS_FLAG_GLOBAL,
1052 0,
1053 DIREG_DRV,
1054 KEY_QUERY_VALUE);
1055 if (hKey != INVALID_HANDLE_VALUE)
1056 {
1057 dwSize = 256 * sizeof(WCHAR);
1058 if (RegQueryValueEx(hKey,
1059 L"MatchingDeviceId",
1060 NULL,
1061 &dwType,
1062 (LPBYTE)szBuffer,
1063 &dwSize) == ERROR_SUCCESS)
1064 {
1065 SetListViewText(hwndListView, 0, szBuffer);
1066 }
1067
1068 RegCloseKey(hKey);
1069 }
1070 }
1071
1072
1073 static VOID
1074 DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,
1075 IN HWND hwndListView)
1076 {
1077 HDEVINFO DeviceInfoSet;
1078 PSP_DEVINFO_DATA DeviceInfoData;
1079 WCHAR szClassGuid[45];
1080 HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
1081 DWORD dwSize;
1082 DWORD dwType;
1083 LPBYTE lpBuffer = NULL;
1084 LPWSTR lpStr;
1085 INT index;
1086 INT len;
1087 LONG lError;
1088
1089 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1090 {
1091 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1092 DeviceInfoData = &dap->CurrentDeviceInfoData;
1093 }
1094 else
1095 {
1096 DeviceInfoSet = dap->DeviceInfoSet;
1097 DeviceInfoData = &dap->DeviceInfoData;
1098 }
1099
1100 dwSize = 45 * sizeof(WCHAR);
1101 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1102 DeviceInfoData,
1103 SPDRP_CLASSGUID,
1104 &dwType,
1105 (LPBYTE)szClassGuid,
1106 dwSize,
1107 &dwSize))
1108 return;
1109
1110 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1111 L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
1112 0,
1113 GENERIC_READ,
1114 &hKey);
1115 if (lError != ERROR_SUCCESS)
1116 return;
1117
1118 dwSize = 0;
1119 lError = RegQueryValueEx(hKey,
1120 szClassGuid,
1121 NULL,
1122 &dwType,
1123 NULL,
1124 &dwSize);
1125 if (lError != ERROR_SUCCESS)
1126 goto done;
1127
1128 if (dwSize == 0)
1129 goto done;
1130
1131 lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1132 HEAP_ZERO_MEMORY,
1133 dwSize);
1134
1135 RegQueryValueEx(hKey,
1136 szClassGuid,
1137 NULL,
1138 &dwType,
1139 lpBuffer,
1140 &dwSize);
1141
1142 lpStr = (LPWSTR)lpBuffer;
1143 index = 0;
1144 while (*lpStr != 0)
1145 {
1146 len = wcslen(lpStr) + 1;
1147
1148 SetListViewText(hwndListView, index, lpStr);
1149
1150 lpStr += len;
1151 index++;
1152 }
1153
1154 done:
1155 if (lpBuffer != NULL)
1156 HeapFree(GetProcessHeap(), 0, lpBuffer);
1157
1158 if (hKey != INVALID_HANDLE_VALUE)
1159 RegCloseKey(hKey);
1160 }
1161
1162
1163 static VOID
1164 DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
1165 IN HWND hwndListView)
1166 {
1167 HDEVINFO DeviceInfoSet;
1168 PSP_DEVINFO_DATA DeviceInfoData;
1169 HKEY hKey;
1170 DWORD dwSize;
1171 DWORD dwType;
1172 LPBYTE lpBuffer;
1173 LPWSTR lpStr;
1174 INT index;
1175 INT len;
1176
1177 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1178 {
1179 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1180 DeviceInfoData = &dap->CurrentDeviceInfoData;
1181 }
1182 else
1183 {
1184 DeviceInfoSet = dap->DeviceInfoSet;
1185 DeviceInfoData = &dap->DeviceInfoData;
1186 }
1187
1188 hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1189 DeviceInfoData,
1190 DICS_FLAG_GLOBAL,
1191 0,
1192 DIREG_DRV,
1193 KEY_QUERY_VALUE);
1194 if (hKey != INVALID_HANDLE_VALUE)
1195 {
1196 dwSize = 0;
1197 if (RegQueryValueEx(hKey,
1198 L"CoInstallers32",
1199 NULL,
1200 &dwType,
1201 NULL,
1202 &dwSize) == ERROR_SUCCESS &&
1203 dwSize > 0)
1204 {
1205
1206 lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1207 HEAP_ZERO_MEMORY,
1208 dwSize);
1209
1210 RegQueryValueEx(hKey,
1211 L"CoInstallers32",
1212 NULL,
1213 &dwType,
1214 lpBuffer,
1215 &dwSize);
1216
1217 lpStr = (LPWSTR)lpBuffer;
1218 index = 0;
1219 while (*lpStr != 0)
1220 {
1221 len = wcslen(lpStr) + 1;
1222
1223 SetListViewText(hwndListView, index, lpStr);
1224
1225 lpStr += len;
1226 index++;
1227 }
1228
1229 HeapFree(GetProcessHeap(),
1230 0,
1231 lpBuffer);
1232 }
1233
1234 RegCloseKey(hKey);
1235 }
1236 }
1237
1238
1239 static VOID
1240 DisplayClassProperties(IN PDEVADVPROP_INFO dap,
1241 IN HWND hwndListView,
1242 IN LPCWSTR lpProperty)
1243 {
1244 HDEVINFO DeviceInfoSet;
1245 PSP_DEVINFO_DATA DeviceInfoData;
1246 WCHAR szClassGuid[45];
1247 DWORD dwSize;
1248 DWORD dwType;
1249 HKEY hKey;
1250 GUID ClassGuid;
1251 LPBYTE lpBuffer;
1252 LPWSTR lpStr;
1253 INT index = 0;
1254 INT len;
1255
1256 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1257 {
1258 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1259 DeviceInfoData = &dap->CurrentDeviceInfoData;
1260 }
1261 else
1262 {
1263 DeviceInfoSet = dap->DeviceInfoSet;
1264 DeviceInfoData = &dap->DeviceInfoData;
1265 }
1266
1267 dwSize = 45 * sizeof(WCHAR);
1268 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1269 DeviceInfoData,
1270 SPDRP_CLASSGUID,
1271 &dwType,
1272 (LPBYTE)szClassGuid,
1273 dwSize,
1274 &dwSize))
1275 return;
1276
1277 pSetupGuidFromString(szClassGuid,
1278 &ClassGuid);
1279
1280 hKey = SetupDiOpenClassRegKey(&ClassGuid,
1281 KEY_QUERY_VALUE);
1282 if (hKey != INVALID_HANDLE_VALUE)
1283 {
1284 dwSize = 0;
1285 if (RegQueryValueEx(hKey,
1286 lpProperty,
1287 NULL,
1288 &dwType,
1289 NULL,
1290 &dwSize) == ERROR_SUCCESS &&
1291 dwSize > 0)
1292 {
1293 lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(),
1294 HEAP_ZERO_MEMORY,
1295 dwSize);
1296
1297 RegQueryValueEx(hKey,
1298 lpProperty,
1299 NULL,
1300 &dwType,
1301 lpBuffer,
1302 &dwSize);
1303
1304 if (dwType == REG_SZ)
1305 {
1306 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
1307 }
1308 else if (dwType == REG_MULTI_SZ)
1309 {
1310 lpStr = (LPWSTR)lpBuffer;
1311 index = 0;
1312 while (*lpStr != 0)
1313 {
1314 len = wcslen(lpStr) + 1;
1315
1316 SetListViewText(hwndListView, index, lpStr);
1317
1318 lpStr += len;
1319 index++;
1320 }
1321 }
1322
1323 HeapFree(GetProcessHeap(),
1324 0,
1325 lpBuffer);
1326 }
1327
1328 RegCloseKey(hKey);
1329 }
1330 }
1331
1332
1333 static VOID
1334 DisplayDeviceRelations(
1335 IN PDEVADVPROP_INFO dap,
1336 IN HWND hwndListView,
1337 IN ULONG ulFlags)
1338 {
1339 ULONG ulLength = 0;
1340 LPWSTR pszBuffer = NULL, pszStr;
1341 INT index = 0, len;
1342 CONFIGRET ret;
1343
1344 ret = CM_Get_Device_ID_List_Size_ExW(&ulLength,
1345 dap->szDeviceID,
1346 ulFlags,
1347 NULL);
1348 if (ret != CR_SUCCESS)
1349 return;
1350
1351 pszBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(),
1352 HEAP_ZERO_MEMORY,
1353 ulLength * sizeof(WCHAR));
1354 if (pszBuffer == NULL)
1355 return;
1356
1357 ret = CM_Get_Device_ID_List_ExW(dap->szDeviceID,
1358 pszBuffer,
1359 ulLength,
1360 ulFlags,
1361 NULL);
1362 if (ret != CR_SUCCESS)
1363 {
1364 HeapFree(GetProcessHeap(), 0, pszBuffer);
1365 return;
1366 }
1367
1368 pszStr = pszBuffer;
1369 index = 0;
1370 while (*pszStr != 0)
1371 {
1372 len = wcslen(pszStr) + 1;
1373
1374 SetListViewText(hwndListView, index, pszStr);
1375
1376 pszStr += len;
1377 index++;
1378 }
1379
1380 HeapFree(GetProcessHeap(), 0, pszBuffer);
1381 }
1382
1383
1384 static VOID
1385 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
1386 IN HWND hwndComboBox,
1387 IN HWND hwndListView)
1388 {
1389 INT Index;
1390
1391 Index = (INT)SendMessage(hwndComboBox,
1392 CB_GETCURSEL,
1393 0,
1394 0);
1395 if (Index == CB_ERR)
1396 return;
1397
1398 (void)ListView_DeleteAllItems(hwndListView);
1399
1400 switch (Index)
1401 {
1402 case 0:
1403 SetListViewText(hwndListView, 0, dap->szDeviceID);
1404 break;
1405
1406 case 1: /* Hardware ID */
1407 DisplayDevicePropertyText(dap,
1408 hwndListView,
1409 SPDRP_HARDWAREID);
1410 break;
1411
1412 case 2: /* Compatible IDs */
1413 DisplayDevicePropertyText(dap,
1414 hwndListView,
1415 SPDRP_COMPATIBLEIDS);
1416 break;
1417
1418 case 3: /* Matching ID */
1419 DisplayMatchingDeviceId(dap,
1420 hwndListView);
1421 break;
1422
1423 case 4: /* Service */
1424 DisplayDevicePropertyText(dap,
1425 hwndListView,
1426 SPDRP_SERVICE);
1427 break;
1428
1429 case 5: /* Enumerator */
1430 DisplayDevNodeEnumerator(dap,
1431 hwndListView);
1432 break;
1433
1434 case 6: /* Capabilities */
1435 DisplayDevicePropertyText(dap,
1436 hwndListView,
1437 SPDRP_CAPABILITIES);
1438 break;
1439
1440 case 7: /* Devnode Flags */
1441 DisplayDevNodeFlags(dap,
1442 hwndListView);
1443 break;
1444
1445 case 8: /* Config Flags */
1446 DisplayDevicePropertyText(dap,
1447 hwndListView,
1448 SPDRP_CONFIGFLAGS);
1449 break;
1450
1451 case 9: /* CSConfig Flags */
1452 DisplayCsFlags(dap,
1453 hwndListView);
1454 break;
1455
1456 case 10: /* Ejection relation */
1457 DisplayDeviceRelations(dap,
1458 hwndListView,
1459 CM_GETIDLIST_FILTER_EJECTRELATIONS);
1460 break;
1461
1462 case 11: /* Removal relations */
1463 DisplayDeviceRelations(dap,
1464 hwndListView,
1465 CM_GETIDLIST_FILTER_REMOVALRELATIONS);
1466 break;
1467
1468 case 12: /* Bus relation */
1469 DisplayDeviceRelations(dap,
1470 hwndListView,
1471 CM_GETIDLIST_FILTER_BUSRELATIONS);
1472 break;
1473
1474 case 13: /* Device Upper Filters */
1475 DisplayDevicePropertyText(dap,
1476 hwndListView,
1477 SPDRP_UPPERFILTERS);
1478 break;
1479
1480 case 14: /* Device Lower Filters */
1481 DisplayDevicePropertyText(dap,
1482 hwndListView,
1483 SPDRP_LOWERFILTERS);
1484 break;
1485
1486 case 15: /* Class Upper Filters */
1487 DisplayClassProperties(dap,
1488 hwndListView,
1489 L"UpperFilters");
1490 break;
1491
1492 case 16: /* Class Lower Filters */
1493 DisplayClassProperties(dap,
1494 hwndListView,
1495 L"LowerFilters");
1496 break;
1497
1498 case 17: /* Class Installer */
1499 DisplayClassProperties(dap,
1500 hwndListView,
1501 L"Installer32");
1502 break;
1503
1504 case 18: /* Class Coinstaller */
1505 DisplayClassCoinstallers(dap,
1506 hwndListView);
1507 break;
1508
1509 case 19: /* Device Coinstaller */
1510 DisplayDeviceCoinstallers(dap,
1511 hwndListView);
1512 break;
1513
1514 #if 0
1515 case 20: /* Firmware Revision */
1516 break;
1517
1518 case 21: /* Current Power State */
1519 break;
1520
1521 case 20: /* Power Capabilities */
1522 break;
1523
1524 case 21: /* Power State Mappings */
1525 break;
1526 #endif
1527
1528 default:
1529 SetListViewText(hwndListView, 0, L"<Not implemented yet>");
1530 break;
1531 }
1532 }
1533
1534
1535 static INT_PTR
1536 CALLBACK
1537 AdvProcDetailsDlgProc(IN HWND hwndDlg,
1538 IN UINT uMsg,
1539 IN WPARAM wParam,
1540 IN LPARAM lParam)
1541 {
1542 PDEVADVPROP_INFO dap;
1543 INT_PTR Ret = FALSE;
1544
1545 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1546 DWL_USER);
1547
1548 if (dap != NULL || uMsg == WM_INITDIALOG)
1549 {
1550 switch (uMsg)
1551 {
1552 case WM_COMMAND:
1553 {
1554 switch (LOWORD(wParam))
1555 {
1556 case IDC_DETAILSPROPNAME:
1557 if (HIWORD(wParam) == CBN_SELCHANGE)
1558 {
1559 DisplayDeviceProperties(dap,
1560 GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
1561 GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
1562 }
1563 break;
1564 }
1565 break;
1566 }
1567
1568 case WM_NOTIFY:
1569 {
1570 NMHDR *hdr = (NMHDR*)lParam;
1571 switch (hdr->code)
1572 {
1573 case PSN_APPLY:
1574 break;
1575 }
1576 break;
1577 }
1578
1579 case WM_INITDIALOG:
1580 {
1581 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1582 if (dap != NULL)
1583 {
1584 SetWindowLongPtr(hwndDlg,
1585 DWL_USER,
1586 (DWORD_PTR)dap);
1587
1588 UpdateDetailsDlg(hwndDlg,
1589 dap);
1590 }
1591 Ret = TRUE;
1592 break;
1593 }
1594 }
1595 }
1596
1597 return Ret;
1598 }
1599
1600
1601 static VOID
1602 InitDevUsageActions(IN HWND hwndDlg,
1603 IN HWND hComboBox,
1604 IN PDEVADVPROP_INFO dap)
1605 {
1606 INT Index;
1607 UINT i;
1608 UINT Actions[] =
1609 {
1610 IDS_ENABLEDEVICE,
1611 IDS_DISABLEDEVICE,
1612 };
1613
1614 for (i = 0;
1615 i != sizeof(Actions) / sizeof(Actions[0]);
1616 i++)
1617 {
1618 /* fill in the device usage combo box */
1619 if (LoadString(hDllInstance,
1620 Actions[i],
1621 dap->szTemp,
1622 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1623 {
1624 Index = (INT)SendMessage(hComboBox,
1625 CB_ADDSTRING,
1626 0,
1627 (LPARAM)dap->szTemp);
1628 if (Index != CB_ERR)
1629 {
1630 SendMessage(hComboBox,
1631 CB_SETITEMDATA,
1632 (WPARAM)Index,
1633 (LPARAM)Actions[i]);
1634
1635 switch (Actions[i])
1636 {
1637 case IDS_ENABLEDEVICE:
1638 if (dap->DeviceStarted)
1639 {
1640 SendMessage(hComboBox,
1641 CB_SETCURSEL,
1642 (WPARAM)Index,
1643 0);
1644 }
1645 break;
1646
1647 case IDS_DISABLEDEVICE:
1648 if (!dap->DeviceStarted)
1649 {
1650 SendMessage(hComboBox,
1651 CB_SETCURSEL,
1652 (WPARAM)Index,
1653 0);
1654 }
1655 break;
1656
1657 default:
1658 break;
1659 }
1660 }
1661 }
1662 }
1663 }
1664
1665
1666 static UINT
1667 GetSelectedUsageAction(IN HWND hComboBox)
1668 {
1669 INT Index;
1670 UINT Ret = 0;
1671
1672 Index = (INT)SendMessage(hComboBox,
1673 CB_GETCURSEL,
1674 0,
1675 0);
1676 if (Index != CB_ERR)
1677 {
1678 INT iRet = (INT) SendMessage(hComboBox,
1679 CB_GETITEMDATA,
1680 (WPARAM)Index,
1681 0);
1682 if (iRet != CB_ERR)
1683 {
1684 Ret = (UINT)iRet;
1685 }
1686 }
1687
1688 return Ret;
1689 }
1690
1691
1692 static BOOL
1693 ApplyGeneralSettings(IN HWND hwndDlg,
1694 IN PDEVADVPROP_INFO dap)
1695 {
1696 BOOL Ret = FALSE;
1697
1698 if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
1699 {
1700 UINT SelectedUsageAction;
1701 BOOL NeedReboot = FALSE;
1702
1703 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
1704 IDC_DEVUSAGE));
1705 switch (SelectedUsageAction)
1706 {
1707 case IDS_ENABLEDEVICE:
1708 if (!dap->DeviceStarted)
1709 {
1710 Ret = EnableDevice(dap->DeviceInfoSet,
1711 &dap->DeviceInfoData,
1712 TRUE,
1713 0,
1714 &NeedReboot);
1715 }
1716 break;
1717
1718 case IDS_DISABLEDEVICE:
1719 if (dap->DeviceStarted)
1720 {
1721 Ret = EnableDevice(dap->DeviceInfoSet,
1722 &dap->DeviceInfoData,
1723 FALSE,
1724 0,
1725 &NeedReboot);
1726 }
1727 break;
1728
1729 default:
1730 break;
1731 }
1732
1733 if (Ret)
1734 {
1735 if (NeedReboot)
1736 {
1737 /* make PropertySheet() return PSM_REBOOTSYSTEM */
1738 PropSheet_RebootSystem(hwndDlg);
1739 }
1740 }
1741 else
1742 {
1743 /* FIXME - display an error message */
1744 FIXME("Failed to enable/disable device! LastError: %d\n",
1745 GetLastError());
1746 }
1747 }
1748 else
1749 Ret = !dap->DeviceUsageChanged;
1750
1751 /* disable the apply button */
1752 PropSheet_UnChanged(GetParent(hwndDlg),
1753 hwndDlg);
1754 dap->DeviceUsageChanged = FALSE;
1755 return Ret;
1756 }
1757
1758
1759 static VOID
1760 UpdateDevInfo(IN HWND hwndDlg,
1761 IN PDEVADVPROP_INFO dap,
1762 IN BOOL ReOpen)
1763 {
1764 HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
1765 CONFIGRET cr;
1766 ULONG Status, ProblemNumber;
1767 SP_DEVINSTALL_PARAMS_W InstallParams;
1768 UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
1769 BOOL bFlag, bDevActionAvailable = TRUE;
1770 BOOL bDrvInstalled = FALSE;
1771 DWORD iPage;
1772 HDEVINFO DeviceInfoSet = NULL;
1773 PSP_DEVINFO_DATA DeviceInfoData = NULL;
1774 PROPSHEETHEADER psh;
1775 DWORD nDriverPages = 0;
1776 BOOL RecalcPages = FALSE;
1777
1778 hPropSheetDlg = GetParent(hwndDlg);
1779
1780 if (dap->PageInitialized)
1781 {
1782 /* switch to the General page */
1783 PropSheet_SetCurSelByID(hPropSheetDlg,
1784 IDD_DEVICEGENERAL);
1785
1786 /* remove and destroy the existing device property sheet pages */
1787 if (dap->DevPropSheets != NULL)
1788 {
1789 for (iPage = 0;
1790 iPage != dap->nDevPropSheets;
1791 iPage++)
1792 {
1793 if (dap->DevPropSheets[iPage] != NULL)
1794 {
1795 PropSheet_RemovePage(hPropSheetDlg,
1796 (WPARAM) -1,
1797 dap->DevPropSheets[iPage]);
1798 RecalcPages = TRUE;
1799 }
1800 }
1801 }
1802 }
1803
1804 iPage = 0;
1805
1806 if (dap->FreeDevPropSheets)
1807 {
1808 /* don't free the array if it's the one allocated in
1809 DisplayDeviceAdvancedProperties */
1810 HeapFree(GetProcessHeap(),
1811 0,
1812 dap->DevPropSheets);
1813
1814 dap->FreeDevPropSheets = FALSE;
1815 }
1816
1817 dap->DevPropSheets = NULL;
1818 dap->nDevPropSheets = 0;
1819
1820 if (ReOpen)
1821 {
1822 /* create a new device info set and re-open the device */
1823 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1824 {
1825 SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
1826 }
1827
1828 dap->ParentDevInst = 0;
1829 dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
1830 hwndDlg,
1831 dap->lpMachineName,
1832 NULL);
1833 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1834 {
1835 if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
1836 dap->szDeviceID,
1837 hwndDlg,
1838 0,
1839 &dap->CurrentDeviceInfoData))
1840 {
1841 if (dap->CloseDevInst)
1842 {
1843 SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
1844 }
1845
1846 dap->CloseDevInst = TRUE;
1847 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
1848 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
1849 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1850 }
1851 else
1852 goto GetParentNode;
1853 }
1854 else
1855 {
1856 GetParentNode:
1857 /* get the parent node from the initial devinst */
1858 CM_Get_Parent_Ex(&dap->ParentDevInst,
1859 dap->DeviceInfoData.DevInst,
1860 0,
1861 dap->hMachine);
1862 }
1863
1864 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1865 {
1866 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1867 DeviceInfoData = &dap->CurrentDeviceInfoData;
1868 }
1869 else
1870 {
1871 DeviceInfoSet = dap->DeviceInfoSet;
1872 DeviceInfoData = &dap->DeviceInfoData;
1873 }
1874 }
1875 else
1876 {
1877 DeviceInfoSet = dap->DeviceInfoSet;
1878 DeviceInfoData = &dap->DeviceInfoData;
1879 }
1880
1881 dap->HasDriverPage = FALSE;
1882 dap->HasResourcePage = FALSE;
1883 dap->HasPowerPage = FALSE;
1884 if (IsDriverInstalled(DeviceInfoData->DevInst,
1885 dap->hMachine,
1886 &bDrvInstalled) &&
1887 bDrvInstalled)
1888 {
1889 if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
1890 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
1891 DIF_ADDPROPERTYPAGE_ADVANCED),
1892 DeviceInfoSet,
1893 DeviceInfoData))
1894 {
1895 /* get install params */
1896 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1897 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
1898 DeviceInfoData,
1899 &InstallParams))
1900 {
1901 /* zero the flags */
1902 InstallParams.Flags = 0;
1903 }
1904
1905 dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
1906 dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
1907 dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
1908 }
1909 }
1910
1911 /* get the device icon */
1912 if (dap->hDevIcon != NULL)
1913 {
1914 DestroyIcon(dap->hDevIcon);
1915 dap->hDevIcon = NULL;
1916 }
1917 if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
1918 &dap->hDevIcon,
1919 NULL))
1920 {
1921 dap->hDevIcon = NULL;
1922 }
1923
1924 /* get the device name */
1925 if (GetDeviceDescriptionString(DeviceInfoSet,
1926 DeviceInfoData,
1927 dap->szDevName,
1928 sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
1929 {
1930 PropSheet_SetTitle(hPropSheetDlg,
1931 PSH_PROPTITLE,
1932 dap->szDevName);
1933 }
1934
1935 /* set the device image */
1936 SendDlgItemMessage(hwndDlg,
1937 IDC_DEVICON,
1938 STM_SETICON,
1939 (WPARAM)dap->hDevIcon,
1940 0);
1941
1942 /* set the device name edit control text */
1943 SetDlgItemText(hwndDlg,
1944 IDC_DEVNAME,
1945 dap->szDevName);
1946
1947 /* set the device type edit control text */
1948 if (GetDeviceTypeString(DeviceInfoData,
1949 dap->szTemp,
1950 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1951 {
1952 SetDlgItemText(hwndDlg,
1953 IDC_DEVTYPE,
1954 dap->szTemp);
1955 }
1956
1957 /* set the device manufacturer edit control text */
1958 if (GetDeviceManufacturerString(DeviceInfoSet,
1959 DeviceInfoData,
1960 dap->szTemp,
1961 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1962 {
1963 SetDlgItemText(hwndDlg,
1964 IDC_DEVMANUFACTURER,
1965 dap->szTemp);
1966 }
1967
1968 /* set the device location edit control text */
1969 if (GetDeviceLocationString(DeviceInfoSet,
1970 DeviceInfoData,
1971 dap->ParentDevInst,
1972 dap->szTemp,
1973 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1974 {
1975 SetDlgItemText(hwndDlg,
1976 IDC_DEVLOCATION,
1977 dap->szTemp);
1978 }
1979
1980 /* set the device status edit control text */
1981 if (GetDeviceStatusString(DeviceInfoData->DevInst,
1982 dap->hMachine,
1983 dap->szTemp,
1984 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1985 {
1986 SetDlgItemText(hwndDlg,
1987 IDC_DEVSTATUS,
1988 dap->szTemp);
1989 }
1990
1991 /* set the device troubleshoot button text and disable it if necessary */
1992 hDevProbBtn = GetDlgItem(hwndDlg,
1993 IDC_DEVPROBLEM);
1994 cr = CM_Get_DevNode_Status_Ex(&Status,
1995 &ProblemNumber,
1996 DeviceInfoData->DevInst,
1997 0,
1998 dap->hMachine);
1999 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
2000 {
2001 switch (ProblemNumber)
2002 {
2003 case CM_PROB_DEVLOADER_FAILED:
2004 {
2005 /* FIXME - only if it's not a root bus devloader,
2006 disable the button otherwise */
2007 TroubleShootStrId = IDS_UPDATEDRV;
2008 break;
2009 }
2010
2011 case CM_PROB_OUT_OF_MEMORY:
2012 case CM_PROB_ENTRY_IS_WRONG_TYPE:
2013 case CM_PROB_LACKED_ARBITRATOR:
2014 case CM_PROB_FAILED_START:
2015 case CM_PROB_LIAR:
2016 case CM_PROB_UNKNOWN_RESOURCE:
2017 {
2018 TroubleShootStrId = IDS_UPDATEDRV;
2019 break;
2020 }
2021
2022 case CM_PROB_BOOT_CONFIG_CONFLICT:
2023 case CM_PROB_NORMAL_CONFLICT:
2024 case CM_PROB_REENUMERATION:
2025 {
2026 /* FIXME - Troubleshoot conflict */
2027 break;
2028 }
2029
2030 case CM_PROB_FAILED_FILTER:
2031 case CM_PROB_REINSTALL:
2032 case CM_PROB_FAILED_INSTALL:
2033 {
2034 TroubleShootStrId = IDS_REINSTALLDRV;
2035 break;
2036 }
2037
2038 case CM_PROB_DEVLOADER_NOT_FOUND:
2039 {
2040 /* FIXME - 4 cases:
2041 1) if it's a missing system devloader:
2042 - disable the button (Reinstall Driver)
2043 2) if it's not a system devloader but still missing:
2044 - Reinstall Driver
2045 3) if it's not a system devloader but the file can be found:
2046 - Update Driver
2047 4) if it's a missing or empty software key
2048 - Update Driver
2049 */
2050 break;
2051 }
2052
2053 case CM_PROB_INVALID_DATA:
2054 case CM_PROB_PARTIAL_LOG_CONF:
2055 case CM_PROB_NO_VALID_LOG_CONF:
2056 case CM_PROB_HARDWARE_DISABLED:
2057 case CM_PROB_CANT_SHARE_IRQ:
2058 case CM_PROB_TRANSLATION_FAILED:
2059 case CM_PROB_SYSTEM_SHUTDOWN:
2060 case CM_PROB_PHANTOM:
2061 bDevActionAvailable = FALSE;
2062 break;
2063
2064 case CM_PROB_NOT_VERIFIED:
2065 case CM_PROB_DEVICE_NOT_THERE:
2066 /* FIXME - search hardware */
2067 break;
2068
2069 case CM_PROB_NEED_RESTART:
2070 case CM_PROB_WILL_BE_REMOVED:
2071 case CM_PROB_MOVED:
2072 case CM_PROB_TOO_EARLY:
2073 case CM_PROB_DISABLED_SERVICE:
2074 TroubleShootStrId = IDS_REBOOT;
2075 break;
2076
2077 case CM_PROB_REGISTRY:
2078 /* FIXME - check registry? */
2079 break;
2080
2081 case CM_PROB_DISABLED:
2082 /* if device was disabled by the user: */
2083 TroubleShootStrId = IDS_ENABLEDEV;
2084 /* FIXME - otherwise disable button because the device was
2085 disabled by the system*/
2086 break;
2087
2088 case CM_PROB_DEVLOADER_NOT_READY:
2089 /* FIXME - if it's a graphics adapter:
2090 - if it's a a secondary adapter and the main adapter
2091 couldn't be found
2092 - disable button
2093 - else
2094 - Properties
2095 - else
2096 - Update driver
2097 */
2098 break;
2099
2100 case CM_PROB_FAILED_ADD:
2101 TroubleShootStrId = IDS_PROPERTIES;
2102 break;
2103 }
2104 }
2105
2106 if (LoadString(hDllInstance,
2107 TroubleShootStrId,
2108 dap->szTemp,
2109 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
2110 {
2111 SetWindowText(hDevProbBtn,
2112 dap->szTemp);
2113 }
2114 EnableWindow(hDevProbBtn,
2115 dap->IsAdmin && bDevActionAvailable);
2116
2117 /* check if the device can be enabled/disabled */
2118 hDevUsage = GetDlgItem(hwndDlg,
2119 IDC_DEVUSAGE);
2120
2121 dap->CanDisable = FALSE;
2122 dap->DeviceStarted = FALSE;
2123
2124 if (CanDisableDevice(DeviceInfoData->DevInst,
2125 dap->hMachine,
2126 &bFlag))
2127 {
2128 dap->CanDisable = bFlag;
2129 }
2130
2131 if (IsDeviceStarted(DeviceInfoData->DevInst,
2132 dap->hMachine,
2133 &bFlag))
2134 {
2135 dap->DeviceStarted = bFlag;
2136 }
2137
2138 /* enable/disable the device usage controls */
2139 EnableWindow(GetDlgItem(hwndDlg,
2140 IDC_DEVUSAGELABEL),
2141 dap->CanDisable && dap->IsAdmin);
2142 EnableWindow(hDevUsage,
2143 dap->CanDisable && dap->IsAdmin);
2144
2145 /* clear the combobox */
2146 SendMessage(hDevUsage,
2147 CB_RESETCONTENT,
2148 0,
2149 0);
2150 if (dap->CanDisable)
2151 {
2152 InitDevUsageActions(hwndDlg,
2153 hDevUsage,
2154 dap);
2155 }
2156
2157 /* find out how many new device property sheets to add.
2158 fake a PROPSHEETHEADER structure, we don't plan to
2159 call PropertySheet again!*/
2160 psh.dwSize = sizeof(PROPSHEETHEADER);
2161 psh.dwFlags = 0;
2162 psh.nPages = 0;
2163
2164 /* get the number of device property sheets for the device */
2165 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2166 DeviceInfoData,
2167 &psh,
2168 0,
2169 &nDriverPages,
2170 dap->PropertySheetType) &&
2171 nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2172 {
2173 dap->nDevPropSheets += nDriverPages;
2174 }
2175 else
2176 {
2177 nDriverPages = 0;
2178 }
2179
2180 /* include the driver page */
2181 if (dap->HasDriverPage)
2182 dap->nDevPropSheets++;
2183
2184 /* include the details page */
2185 if (dap->Extended)
2186 dap->nDevPropSheets++;
2187
2188 if (dap->HasResourcePage)
2189 dap->nDevPropSheets++;
2190
2191 /* add the device property sheets */
2192 if (dap->nDevPropSheets != 0)
2193 {
2194 dap->DevPropSheets = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2195 HEAP_ZERO_MEMORY,
2196 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
2197 if (dap->DevPropSheets != NULL)
2198 {
2199 if (nDriverPages != 0)
2200 {
2201 psh.phpage = dap->DevPropSheets;
2202
2203 /* query the device property sheet pages to add */
2204 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2205 DeviceInfoData,
2206 &psh,
2207 dap->nDevPropSheets,
2208 NULL,
2209 dap->PropertySheetType))
2210 {
2211 /* add the property sheets */
2212 for (iPage = 0;
2213 iPage < nDriverPages;
2214 iPage++)
2215 {
2216 if (PropSheet_AddPage(hPropSheetDlg,
2217 dap->DevPropSheets[iPage]))
2218 {
2219 RecalcPages = TRUE;
2220 }
2221 }
2222
2223 dap->FreeDevPropSheets = TRUE;
2224 }
2225 else
2226 {
2227 /* cleanup, we were unable to get the device property sheets */
2228 iPage = nDriverPages;
2229 dap->nDevPropSheets -= nDriverPages;
2230 nDriverPages = 0;
2231 }
2232 }
2233 else
2234 iPage = 0;
2235
2236 /* add the driver page if necessary */
2237 if (dap->HasDriverPage)
2238 {
2239 PROPSHEETPAGE pspDriver = {0};
2240 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2241 pspDriver.dwFlags = PSP_DEFAULT;
2242 pspDriver.hInstance = hDllInstance;
2243 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
2244 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
2245 pspDriver.lParam = (LPARAM)dap;
2246 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2247 if (dap->DevPropSheets[iPage] != NULL)
2248 {
2249 if (PropSheet_AddPage(hPropSheetDlg,
2250 dap->DevPropSheets[iPage]))
2251 {
2252 iPage++;
2253 RecalcPages = TRUE;
2254 }
2255 else
2256 {
2257 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2258 dap->DevPropSheets[iPage] = NULL;
2259 }
2260 }
2261 }
2262
2263 if (dap->Extended)
2264 {
2265 /* Add the details page */
2266 PROPSHEETPAGE pspDetails = {0};
2267 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
2268 pspDetails.dwFlags = PSP_DEFAULT;
2269 pspDetails.hInstance = hDllInstance;
2270 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
2271 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
2272 pspDetails.lParam = (LPARAM)dap;
2273 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
2274 if (dap->DevPropSheets[iPage] != NULL)
2275 {
2276 if (PropSheet_AddPage(hPropSheetDlg,
2277 dap->DevPropSheets[iPage]))
2278 {
2279 iPage++;
2280 RecalcPages = TRUE;
2281 }
2282 else
2283 {
2284 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2285 dap->DevPropSheets[iPage] = NULL;
2286 }
2287 }
2288 }
2289
2290 if (dap->HasResourcePage)
2291 {
2292 PROPSHEETPAGE pspDriver = {0};
2293 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2294 pspDriver.dwFlags = PSP_DEFAULT;
2295 pspDriver.hInstance = hDllInstance;
2296 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
2297 pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
2298 pspDriver.lParam = (LPARAM)dap;
2299 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2300 if (dap->DevPropSheets[iPage] != NULL)
2301 {
2302 if (PropSheet_AddPage(hPropSheetDlg,
2303 dap->DevPropSheets[iPage]))
2304 {
2305 iPage++;
2306 RecalcPages = TRUE;
2307 }
2308 else
2309 {
2310 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2311 dap->DevPropSheets[iPage] = NULL;
2312 }
2313 }
2314 }
2315 /* FIXME: Add the power page */
2316 }
2317 else
2318 dap->nDevPropSheets = 0;
2319 }
2320
2321 if (RecalcPages)
2322 {
2323 PropSheet_RecalcPageSizes(hPropSheetDlg);
2324 }
2325
2326 /* finally, disable the apply button */
2327 PropSheet_UnChanged(hPropSheetDlg,
2328 hwndDlg);
2329 dap->DeviceUsageChanged = FALSE;
2330 }
2331
2332
2333 static LRESULT
2334 CALLBACK
2335 DlgParentSubWndProc(IN HWND hwnd,
2336 IN UINT uMsg,
2337 IN WPARAM wParam,
2338 IN LPARAM lParam)
2339 {
2340 PDEVADVPROP_INFO dap;
2341
2342 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
2343 L"DevMgrDevChangeSub");
2344 if (dap != NULL)
2345 {
2346 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
2347 {
2348 SendMessage(dap->hWndGeneralPage,
2349 WM_DEVICECHANGE,
2350 wParam,
2351 lParam);
2352 }
2353
2354 /* pass the message the the old window proc */
2355 return CallWindowProc(dap->ParentOldWndProc,
2356 hwnd,
2357 uMsg,
2358 wParam,
2359 lParam);
2360 }
2361 else
2362 {
2363 /* this is not a good idea if the subclassed window was an ansi
2364 window, but we failed finding out the previous window proc
2365 so we can't use CallWindowProc. This should rarely - if ever -
2366 happen. */
2367
2368 return DefWindowProc(hwnd,
2369 uMsg,
2370 wParam,
2371 lParam);
2372 }
2373 }
2374
2375
2376 static INT_PTR
2377 CALLBACK
2378 AdvPropGeneralDlgProc(IN HWND hwndDlg,
2379 IN UINT uMsg,
2380 IN WPARAM wParam,
2381 IN LPARAM lParam)
2382 {
2383 PDEVADVPROP_INFO dap;
2384 INT_PTR Ret = FALSE;
2385
2386 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
2387 DWL_USER);
2388
2389 if (dap != NULL || uMsg == WM_INITDIALOG)
2390 {
2391 switch (uMsg)
2392 {
2393 case WM_COMMAND:
2394 {
2395 switch (LOWORD(wParam))
2396 {
2397 case IDC_DEVUSAGE:
2398 {
2399 if (HIWORD(wParam) == CBN_SELCHANGE)
2400 {
2401 PropSheet_Changed(GetParent(hwndDlg),
2402 hwndDlg);
2403 dap->DeviceUsageChanged = TRUE;
2404 }
2405 break;
2406 }
2407
2408 case IDC_DEVPROBLEM:
2409 {
2410 if (dap->IsAdmin)
2411 {
2412 /* display the device problem wizard */
2413 ShowDeviceProblemWizard(hwndDlg,
2414 dap->DeviceInfoSet,
2415 &dap->DeviceInfoData,
2416 dap->hMachine);
2417 }
2418 break;
2419 }
2420 }
2421 break;
2422 }
2423
2424 case WM_NOTIFY:
2425 {
2426 NMHDR *hdr = (NMHDR*)lParam;
2427 switch (hdr->code)
2428 {
2429 case PSN_APPLY:
2430 ApplyGeneralSettings(hwndDlg,
2431 dap);
2432 break;
2433 }
2434 break;
2435 }
2436
2437 case WM_INITDIALOG:
2438 {
2439 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2440 if (dap != NULL)
2441 {
2442 HWND hWndParent;
2443
2444 dap->hWndGeneralPage = hwndDlg;
2445
2446 SetWindowLongPtr(hwndDlg,
2447 DWL_USER,
2448 (DWORD_PTR)dap);
2449
2450 /* subclass the parent window to always receive
2451 WM_DEVICECHANGE messages */
2452 hWndParent = GetParent(hwndDlg);
2453 if (hWndParent != NULL)
2454 {
2455 /* subclass the parent window. This is not safe
2456 if the parent window belongs to another thread! */
2457 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
2458 GWLP_WNDPROC,
2459 (LONG_PTR)DlgParentSubWndProc);
2460
2461 if (dap->ParentOldWndProc != NULL &&
2462 SetProp(hWndParent,
2463 L"DevMgrDevChangeSub",
2464 (HANDLE)dap))
2465 {
2466 dap->hWndParent = hWndParent;
2467 }
2468 }
2469
2470 /* do not call UpdateDevInfo directly in here because it modifies
2471 the pages of the property sheet! */
2472 PostMessage(hwndDlg,
2473 PM_INITIALIZE,
2474 0,
2475 0);
2476 }
2477 Ret = TRUE;
2478 break;
2479 }
2480
2481 case WM_DEVICECHANGE:
2482 {
2483 /* FIXME - don't call UpdateDevInfo for all events */
2484 UpdateDevInfo(hwndDlg,
2485 dap,
2486 TRUE);
2487 Ret = TRUE;
2488 break;
2489 }
2490
2491 case PM_INITIALIZE:
2492 {
2493 UpdateDevInfo(hwndDlg,
2494 dap,
2495 FALSE);
2496 dap->PageInitialized = TRUE;
2497 break;
2498 }
2499
2500 case WM_DESTROY:
2501 {
2502 /* restore the old window proc of the subclassed parent window */
2503 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
2504 {
2505 if (SetWindowLongPtr(dap->hWndParent,
2506 GWLP_WNDPROC,
2507 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
2508 {
2509 RemoveProp(dap->hWndParent,
2510 L"DevMgrDevChangeSub");
2511 }
2512 }
2513 break;
2514 }
2515 }
2516 }
2517
2518 return Ret;
2519 }
2520
2521
2522 INT_PTR
2523 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
2524 IN LPCWSTR lpDeviceID OPTIONAL,
2525 IN HDEVINFO DeviceInfoSet,
2526 IN PSP_DEVINFO_DATA DeviceInfoData,
2527 IN HINSTANCE hComCtl32,
2528 IN LPCWSTR lpMachineName,
2529 IN DWORD dwFlags)
2530 {
2531 PROPSHEETHEADER psh = {0};
2532 PROPSHEETPAGE pspGeneral = {0};
2533 PPROPERTYSHEETW pPropertySheetW;
2534 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
2535 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
2536 PDEVADVPROP_INFO DevAdvPropInfo;
2537 HMACHINE hMachine = NULL;
2538 DWORD DevIdSize = 0;
2539 INT_PTR Ret = -1;
2540
2541 /* we don't want to statically link against comctl32, so find the
2542 functions we need dynamically */
2543 pPropertySheetW =
2544 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
2545 "PropertySheetW");
2546 pCreatePropertySheetPageW =
2547 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
2548 "CreatePropertySheetPageW");
2549 pDestroyPropertySheetPage =
2550 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
2551 "DestroyPropertySheetPage");
2552 if (pPropertySheetW == NULL ||
2553 pCreatePropertySheetPageW == NULL ||
2554 pDestroyPropertySheetPage == NULL)
2555 {
2556 return -1;
2557 }
2558
2559 if (lpDeviceID == NULL)
2560 {
2561 /* find out how much size is needed for the device id */
2562 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
2563 DeviceInfoData,
2564 NULL,
2565 0,
2566 &DevIdSize))
2567 {
2568 ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
2569 return -1;
2570 }
2571
2572 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2573 {
2574 return -1;
2575 }
2576 }
2577 else
2578 {
2579 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
2580 }
2581
2582 if (lpMachineName != NULL && lpMachineName[0] != L'\0')
2583 {
2584 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
2585 &hMachine);
2586 if (cr != CR_SUCCESS)
2587 {
2588 return -1;
2589 }
2590 }
2591
2592 /* create the internal structure associated with the "General",
2593 "Driver", ... pages */
2594 DevAdvPropInfo = (PDEVADVPROP_INFO)HeapAlloc(GetProcessHeap(),
2595 HEAP_ZERO_MEMORY,
2596 FIELD_OFFSET(DEVADVPROP_INFO,
2597 szDeviceID) +
2598 (DevIdSize * sizeof(WCHAR)));
2599 if (DevAdvPropInfo == NULL)
2600 {
2601 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2602 goto Cleanup;
2603 }
2604
2605 if (lpDeviceID == NULL)
2606 {
2607 /* read the device instance id */
2608 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
2609 DeviceInfoData,
2610 DevAdvPropInfo->szDeviceID,
2611 DevIdSize,
2612 NULL))
2613 {
2614 goto Cleanup;
2615 }
2616 }
2617 else
2618 {
2619 /* copy the device instance id supplied by the caller */
2620 wcscpy(DevAdvPropInfo->szDeviceID,
2621 lpDeviceID);
2622 }
2623
2624 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
2625 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
2626 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2627 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2628
2629 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
2630 DevAdvPropInfo->hMachine = hMachine;
2631 DevAdvPropInfo->lpMachineName = lpMachineName;
2632 DevAdvPropInfo->szDevName[0] = L'\0';
2633 DevAdvPropInfo->hComCtl32 = hComCtl32;
2634 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
2635 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
2636
2637 DevAdvPropInfo->IsAdmin = TRUE;// IsUserAdmin();
2638 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
2639 DevAdvPropInfo->Extended = ((dwFlags & DPF_EXTENDED) != 0);
2640
2641 psh.dwSize = sizeof(PROPSHEETHEADER);
2642 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2643 psh.hwndParent = hWndParent;
2644 psh.pszCaption = DevAdvPropInfo->szDevName;
2645
2646 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2647 DIGCDP_FLAG_REMOTE_ADVANCED :
2648 DIGCDP_FLAG_ADVANCED;
2649
2650 psh.phpage = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2651 HEAP_ZERO_MEMORY,
2652 1 * sizeof(HPROPSHEETPAGE));
2653 if (psh.phpage == NULL)
2654 {
2655 goto Cleanup;
2656 }
2657
2658 /* add the "General" property sheet */
2659 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2660 pspGeneral.dwFlags = PSP_DEFAULT;
2661 pspGeneral.hInstance = hDllInstance;
2662 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2663 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2664 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2665 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2666 if (psh.phpage[psh.nPages] != NULL)
2667 {
2668 psh.nPages++;
2669 }
2670
2671 DevAdvPropInfo->nDevPropSheets = psh.nPages;
2672
2673 if (psh.nPages != 0)
2674 {
2675 Ret = pPropertySheetW(&psh);
2676
2677 /* NOTE: no need to destroy the property sheets anymore! */
2678 }
2679 else
2680 {
2681 UINT i;
2682
2683 Cleanup:
2684 /* in case of failure the property sheets must be destroyed */
2685 if (psh.phpage != NULL)
2686 {
2687 for (i = 0;
2688 i < psh.nPages;
2689 i++)
2690 {
2691 if (psh.phpage[i] != NULL)
2692 {
2693 pDestroyPropertySheetPage(psh.phpage[i]);
2694 }
2695 }
2696 }
2697 }
2698
2699 if (DevAdvPropInfo != NULL)
2700 {
2701 if (DevAdvPropInfo->FreeDevPropSheets)
2702 {
2703 /* don't free the array if it's the one allocated in
2704 DisplayDeviceAdvancedProperties */
2705 HeapFree(GetProcessHeap(),
2706 0,
2707 DevAdvPropInfo->DevPropSheets);
2708 }
2709
2710 if (DevAdvPropInfo->CloseDevInst)
2711 {
2712 /* close the device info set in case a new one was created */
2713 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2714 }
2715
2716 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2717 {
2718 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2719 }
2720
2721 if (DevAdvPropInfo->hDevIcon != NULL)
2722 {
2723 DestroyIcon(DevAdvPropInfo->hDevIcon);
2724 }
2725
2726 HeapFree(GetProcessHeap(),
2727 0,
2728 DevAdvPropInfo);
2729 }
2730
2731 if (psh.phpage != NULL)
2732 {
2733 HeapFree(GetProcessHeap(),
2734 0,
2735 psh.phpage);
2736 }
2737
2738 if (hMachine != NULL)
2739 {
2740 CM_Disconnect_Machine(hMachine);
2741 }
2742
2743 return Ret;
2744 }