[PRINTING]
[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
1343 CONFIGRET ret;
1344
1345 ret = CM_Get_Device_ID_List_Size_ExW(&ulLength,
1346 dap->szDeviceID,
1347 ulFlags,
1348 NULL);
1349 if (ret != CR_SUCCESS)
1350 return;
1351
1352 pszBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(),
1353 HEAP_ZERO_MEMORY,
1354 ulLength);
1355 if (pszBuffer == NULL)
1356 return;
1357
1358 ret = CM_Get_Device_ID_List_ExW(dap->szDeviceID,
1359 pszBuffer,
1360 ulLength,
1361 ulFlags,
1362 NULL);
1363 if (ret != CR_SUCCESS)
1364 {
1365 HeapFree(GetProcessHeap(), 0, pszBuffer);
1366 return;
1367 }
1368
1369 pszStr = pszBuffer;
1370 index = 0;
1371 while (*pszStr != 0)
1372 {
1373 len = wcslen(pszStr) + 1;
1374
1375 SetListViewText(hwndListView, index, pszStr);
1376
1377 pszStr += len;
1378 index++;
1379 }
1380
1381 HeapFree(GetProcessHeap(), 0, pszBuffer);
1382 }
1383
1384
1385 static VOID
1386 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
1387 IN HWND hwndComboBox,
1388 IN HWND hwndListView)
1389 {
1390 INT Index;
1391
1392 Index = (INT)SendMessage(hwndComboBox,
1393 CB_GETCURSEL,
1394 0,
1395 0);
1396 if (Index == CB_ERR)
1397 return;
1398
1399 (void)ListView_DeleteAllItems(hwndListView);
1400
1401 switch (Index)
1402 {
1403 case 0:
1404 SetListViewText(hwndListView, 0, dap->szDeviceID);
1405 break;
1406
1407 case 1: /* Hardware ID */
1408 DisplayDevicePropertyText(dap,
1409 hwndListView,
1410 SPDRP_HARDWAREID);
1411 break;
1412
1413 case 2: /* Compatible IDs */
1414 DisplayDevicePropertyText(dap,
1415 hwndListView,
1416 SPDRP_COMPATIBLEIDS);
1417 break;
1418
1419 case 3: /* Matching ID */
1420 DisplayMatchingDeviceId(dap,
1421 hwndListView);
1422 break;
1423
1424 case 4: /* Service */
1425 DisplayDevicePropertyText(dap,
1426 hwndListView,
1427 SPDRP_SERVICE);
1428 break;
1429
1430 case 5: /* Enumerator */
1431 DisplayDevNodeEnumerator(dap,
1432 hwndListView);
1433 break;
1434
1435 case 6: /* Capabilities */
1436 DisplayDevicePropertyText(dap,
1437 hwndListView,
1438 SPDRP_CAPABILITIES);
1439 break;
1440
1441 case 7: /* Devnode Flags */
1442 DisplayDevNodeFlags(dap,
1443 hwndListView);
1444 break;
1445
1446 case 8: /* Config Flags */
1447 DisplayDevicePropertyText(dap,
1448 hwndListView,
1449 SPDRP_CONFIGFLAGS);
1450 break;
1451
1452 case 9: /* CSConfig Flags */
1453 DisplayCsFlags(dap,
1454 hwndListView);
1455 break;
1456
1457 case 10: /* Ejection relation */
1458 DisplayDeviceRelations(dap,
1459 hwndListView,
1460 CM_GETIDLIST_FILTER_EJECTRELATIONS);
1461 break;
1462
1463 case 11: /* Removal relations */
1464 DisplayDeviceRelations(dap,
1465 hwndListView,
1466 CM_GETIDLIST_FILTER_REMOVALRELATIONS);
1467 break;
1468
1469 case 12: /* Bus relation */
1470 DisplayDeviceRelations(dap,
1471 hwndListView,
1472 CM_GETIDLIST_FILTER_BUSRELATIONS);
1473 break;
1474
1475 case 13: /* Device Upper Filters */
1476 DisplayDevicePropertyText(dap,
1477 hwndListView,
1478 SPDRP_UPPERFILTERS);
1479 break;
1480
1481 case 14: /* Device Lower Filters */
1482 DisplayDevicePropertyText(dap,
1483 hwndListView,
1484 SPDRP_LOWERFILTERS);
1485 break;
1486
1487 case 15: /* Class Upper Filters */
1488 DisplayClassProperties(dap,
1489 hwndListView,
1490 L"UpperFilters");
1491 break;
1492
1493 case 16: /* Class Lower Filters */
1494 DisplayClassProperties(dap,
1495 hwndListView,
1496 L"LowerFilters");
1497 break;
1498
1499 case 17: /* Class Installer */
1500 DisplayClassProperties(dap,
1501 hwndListView,
1502 L"Installer32");
1503 break;
1504
1505 case 18: /* Class Coinstaller */
1506 DisplayClassCoinstallers(dap,
1507 hwndListView);
1508 break;
1509
1510 case 19: /* Device Coinstaller */
1511 DisplayDeviceCoinstallers(dap,
1512 hwndListView);
1513 break;
1514
1515 #if 0
1516 case 20: /* Firmware Revision */
1517 break;
1518
1519 case 21: /* Current Power State */
1520 break;
1521
1522 case 20: /* Power Capabilities */
1523 break;
1524
1525 case 21: /* Power State Mappings */
1526 break;
1527 #endif
1528
1529 default:
1530 SetListViewText(hwndListView, 0, L"<Not implemented yet>");
1531 break;
1532 }
1533 }
1534
1535
1536 static INT_PTR
1537 CALLBACK
1538 AdvProcDetailsDlgProc(IN HWND hwndDlg,
1539 IN UINT uMsg,
1540 IN WPARAM wParam,
1541 IN LPARAM lParam)
1542 {
1543 PDEVADVPROP_INFO dap;
1544 INT_PTR Ret = FALSE;
1545
1546 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1547 DWL_USER);
1548
1549 if (dap != NULL || uMsg == WM_INITDIALOG)
1550 {
1551 switch (uMsg)
1552 {
1553 case WM_COMMAND:
1554 {
1555 switch (LOWORD(wParam))
1556 {
1557 case IDC_DETAILSPROPNAME:
1558 if (HIWORD(wParam) == CBN_SELCHANGE)
1559 {
1560 DisplayDeviceProperties(dap,
1561 GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
1562 GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
1563 }
1564 break;
1565 }
1566 break;
1567 }
1568
1569 case WM_NOTIFY:
1570 {
1571 NMHDR *hdr = (NMHDR*)lParam;
1572 switch (hdr->code)
1573 {
1574 case PSN_APPLY:
1575 break;
1576 }
1577 break;
1578 }
1579
1580 case WM_INITDIALOG:
1581 {
1582 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1583 if (dap != NULL)
1584 {
1585 SetWindowLongPtr(hwndDlg,
1586 DWL_USER,
1587 (DWORD_PTR)dap);
1588
1589 UpdateDetailsDlg(hwndDlg,
1590 dap);
1591 }
1592 Ret = TRUE;
1593 break;
1594 }
1595 }
1596 }
1597
1598 return Ret;
1599 }
1600
1601
1602 static VOID
1603 InitDevUsageActions(IN HWND hwndDlg,
1604 IN HWND hComboBox,
1605 IN PDEVADVPROP_INFO dap)
1606 {
1607 INT Index;
1608 UINT i;
1609 UINT Actions[] =
1610 {
1611 IDS_ENABLEDEVICE,
1612 IDS_DISABLEDEVICE,
1613 };
1614
1615 for (i = 0;
1616 i != sizeof(Actions) / sizeof(Actions[0]);
1617 i++)
1618 {
1619 /* fill in the device usage combo box */
1620 if (LoadString(hDllInstance,
1621 Actions[i],
1622 dap->szTemp,
1623 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1624 {
1625 Index = (INT)SendMessage(hComboBox,
1626 CB_ADDSTRING,
1627 0,
1628 (LPARAM)dap->szTemp);
1629 if (Index != CB_ERR)
1630 {
1631 SendMessage(hComboBox,
1632 CB_SETITEMDATA,
1633 (WPARAM)Index,
1634 (LPARAM)Actions[i]);
1635
1636 switch (Actions[i])
1637 {
1638 case IDS_ENABLEDEVICE:
1639 if (dap->DeviceStarted)
1640 {
1641 SendMessage(hComboBox,
1642 CB_SETCURSEL,
1643 (WPARAM)Index,
1644 0);
1645 }
1646 break;
1647
1648 case IDS_DISABLEDEVICE:
1649 if (!dap->DeviceStarted)
1650 {
1651 SendMessage(hComboBox,
1652 CB_SETCURSEL,
1653 (WPARAM)Index,
1654 0);
1655 }
1656 break;
1657
1658 default:
1659 break;
1660 }
1661 }
1662 }
1663 }
1664 }
1665
1666
1667 static UINT
1668 GetSelectedUsageAction(IN HWND hComboBox)
1669 {
1670 INT Index;
1671 UINT Ret = 0;
1672
1673 Index = (INT)SendMessage(hComboBox,
1674 CB_GETCURSEL,
1675 0,
1676 0);
1677 if (Index != CB_ERR)
1678 {
1679 INT iRet = (INT) SendMessage(hComboBox,
1680 CB_GETITEMDATA,
1681 (WPARAM)Index,
1682 0);
1683 if (iRet != CB_ERR)
1684 {
1685 Ret = (UINT)iRet;
1686 }
1687 }
1688
1689 return Ret;
1690 }
1691
1692
1693 static BOOL
1694 ApplyGeneralSettings(IN HWND hwndDlg,
1695 IN PDEVADVPROP_INFO dap)
1696 {
1697 BOOL Ret = FALSE;
1698
1699 if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
1700 {
1701 UINT SelectedUsageAction;
1702 BOOL NeedReboot = FALSE;
1703
1704 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
1705 IDC_DEVUSAGE));
1706 switch (SelectedUsageAction)
1707 {
1708 case IDS_ENABLEDEVICE:
1709 if (!dap->DeviceStarted)
1710 {
1711 Ret = EnableDevice(dap->DeviceInfoSet,
1712 &dap->DeviceInfoData,
1713 TRUE,
1714 0,
1715 &NeedReboot);
1716 }
1717 break;
1718
1719 case IDS_DISABLEDEVICE:
1720 if (dap->DeviceStarted)
1721 {
1722 Ret = EnableDevice(dap->DeviceInfoSet,
1723 &dap->DeviceInfoData,
1724 FALSE,
1725 0,
1726 &NeedReboot);
1727 }
1728 break;
1729
1730 default:
1731 break;
1732 }
1733
1734 if (Ret)
1735 {
1736 if (NeedReboot)
1737 {
1738 /* make PropertySheet() return PSM_REBOOTSYSTEM */
1739 PropSheet_RebootSystem(hwndDlg);
1740 }
1741 }
1742 else
1743 {
1744 /* FIXME - display an error message */
1745 FIXME("Failed to enable/disable device! LastError: %d\n",
1746 GetLastError());
1747 }
1748 }
1749 else
1750 Ret = !dap->DeviceUsageChanged;
1751
1752 /* disable the apply button */
1753 PropSheet_UnChanged(GetParent(hwndDlg),
1754 hwndDlg);
1755 dap->DeviceUsageChanged = FALSE;
1756 return Ret;
1757 }
1758
1759
1760 static VOID
1761 UpdateDevInfo(IN HWND hwndDlg,
1762 IN PDEVADVPROP_INFO dap,
1763 IN BOOL ReOpen)
1764 {
1765 HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
1766 CONFIGRET cr;
1767 ULONG Status, ProblemNumber;
1768 SP_DEVINSTALL_PARAMS_W InstallParams;
1769 UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
1770 BOOL bFlag, bDevActionAvailable = TRUE;
1771 BOOL bDrvInstalled = FALSE;
1772 DWORD iPage;
1773 HDEVINFO DeviceInfoSet = NULL;
1774 PSP_DEVINFO_DATA DeviceInfoData = NULL;
1775 PROPSHEETHEADER psh;
1776 DWORD nDriverPages = 0;
1777 BOOL RecalcPages = FALSE;
1778
1779 hPropSheetDlg = GetParent(hwndDlg);
1780
1781 if (dap->PageInitialized)
1782 {
1783 /* switch to the General page */
1784 PropSheet_SetCurSelByID(hPropSheetDlg,
1785 IDD_DEVICEGENERAL);
1786
1787 /* remove and destroy the existing device property sheet pages */
1788 if (dap->DevPropSheets != NULL)
1789 {
1790 for (iPage = 0;
1791 iPage != dap->nDevPropSheets;
1792 iPage++)
1793 {
1794 if (dap->DevPropSheets[iPage] != NULL)
1795 {
1796 PropSheet_RemovePage(hPropSheetDlg,
1797 (WPARAM) -1,
1798 dap->DevPropSheets[iPage]);
1799 RecalcPages = TRUE;
1800 }
1801 }
1802 }
1803 }
1804
1805 iPage = 0;
1806
1807 if (dap->FreeDevPropSheets)
1808 {
1809 /* don't free the array if it's the one allocated in
1810 DisplayDeviceAdvancedProperties */
1811 HeapFree(GetProcessHeap(),
1812 0,
1813 dap->DevPropSheets);
1814
1815 dap->FreeDevPropSheets = FALSE;
1816 }
1817
1818 dap->DevPropSheets = NULL;
1819 dap->nDevPropSheets = 0;
1820
1821 if (ReOpen)
1822 {
1823 /* create a new device info set and re-open the device */
1824 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1825 {
1826 SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
1827 }
1828
1829 dap->ParentDevInst = 0;
1830 dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
1831 hwndDlg,
1832 dap->lpMachineName,
1833 NULL);
1834 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1835 {
1836 if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
1837 dap->szDeviceID,
1838 hwndDlg,
1839 0,
1840 &dap->CurrentDeviceInfoData))
1841 {
1842 if (dap->CloseDevInst)
1843 {
1844 SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
1845 }
1846
1847 dap->CloseDevInst = TRUE;
1848 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
1849 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
1850 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1851 }
1852 else
1853 goto GetParentNode;
1854 }
1855 else
1856 {
1857 GetParentNode:
1858 /* get the parent node from the initial devinst */
1859 CM_Get_Parent_Ex(&dap->ParentDevInst,
1860 dap->DeviceInfoData.DevInst,
1861 0,
1862 dap->hMachine);
1863 }
1864
1865 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1866 {
1867 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1868 DeviceInfoData = &dap->CurrentDeviceInfoData;
1869 }
1870 else
1871 {
1872 DeviceInfoSet = dap->DeviceInfoSet;
1873 DeviceInfoData = &dap->DeviceInfoData;
1874 }
1875 }
1876 else
1877 {
1878 DeviceInfoSet = dap->DeviceInfoSet;
1879 DeviceInfoData = &dap->DeviceInfoData;
1880 }
1881
1882 dap->HasDriverPage = FALSE;
1883 dap->HasResourcePage = FALSE;
1884 dap->HasPowerPage = FALSE;
1885 if (IsDriverInstalled(DeviceInfoData->DevInst,
1886 dap->hMachine,
1887 &bDrvInstalled) &&
1888 bDrvInstalled)
1889 {
1890 if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
1891 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
1892 DIF_ADDPROPERTYPAGE_ADVANCED),
1893 DeviceInfoSet,
1894 DeviceInfoData))
1895 {
1896 /* get install params */
1897 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1898 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
1899 DeviceInfoData,
1900 &InstallParams))
1901 {
1902 /* zero the flags */
1903 InstallParams.Flags = 0;
1904 }
1905
1906 dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
1907 dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
1908 dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
1909 }
1910 }
1911
1912 /* get the device icon */
1913 if (dap->hDevIcon != NULL)
1914 {
1915 DestroyIcon(dap->hDevIcon);
1916 dap->hDevIcon = NULL;
1917 }
1918 if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
1919 &dap->hDevIcon,
1920 NULL))
1921 {
1922 dap->hDevIcon = NULL;
1923 }
1924
1925 /* get the device name */
1926 if (GetDeviceDescriptionString(DeviceInfoSet,
1927 DeviceInfoData,
1928 dap->szDevName,
1929 sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
1930 {
1931 PropSheet_SetTitle(hPropSheetDlg,
1932 PSH_PROPTITLE,
1933 dap->szDevName);
1934 }
1935
1936 /* set the device image */
1937 SendDlgItemMessage(hwndDlg,
1938 IDC_DEVICON,
1939 STM_SETICON,
1940 (WPARAM)dap->hDevIcon,
1941 0);
1942
1943 /* set the device name edit control text */
1944 SetDlgItemText(hwndDlg,
1945 IDC_DEVNAME,
1946 dap->szDevName);
1947
1948 /* set the device type edit control text */
1949 if (GetDeviceTypeString(DeviceInfoData,
1950 dap->szTemp,
1951 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1952 {
1953 SetDlgItemText(hwndDlg,
1954 IDC_DEVTYPE,
1955 dap->szTemp);
1956 }
1957
1958 /* set the device manufacturer edit control text */
1959 if (GetDeviceManufacturerString(DeviceInfoSet,
1960 DeviceInfoData,
1961 dap->szTemp,
1962 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1963 {
1964 SetDlgItemText(hwndDlg,
1965 IDC_DEVMANUFACTURER,
1966 dap->szTemp);
1967 }
1968
1969 /* set the device location edit control text */
1970 if (GetDeviceLocationString(DeviceInfoSet,
1971 DeviceInfoData,
1972 dap->ParentDevInst,
1973 dap->szTemp,
1974 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1975 {
1976 SetDlgItemText(hwndDlg,
1977 IDC_DEVLOCATION,
1978 dap->szTemp);
1979 }
1980
1981 /* set the device status edit control text */
1982 if (GetDeviceStatusString(DeviceInfoData->DevInst,
1983 dap->hMachine,
1984 dap->szTemp,
1985 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1986 {
1987 SetDlgItemText(hwndDlg,
1988 IDC_DEVSTATUS,
1989 dap->szTemp);
1990 }
1991
1992 /* set the device troubleshoot button text and disable it if necessary */
1993 hDevProbBtn = GetDlgItem(hwndDlg,
1994 IDC_DEVPROBLEM);
1995 cr = CM_Get_DevNode_Status_Ex(&Status,
1996 &ProblemNumber,
1997 DeviceInfoData->DevInst,
1998 0,
1999 dap->hMachine);
2000 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
2001 {
2002 switch (ProblemNumber)
2003 {
2004 case CM_PROB_DEVLOADER_FAILED:
2005 {
2006 /* FIXME - only if it's not a root bus devloader,
2007 disable the button otherwise */
2008 TroubleShootStrId = IDS_UPDATEDRV;
2009 break;
2010 }
2011
2012 case CM_PROB_OUT_OF_MEMORY:
2013 case CM_PROB_ENTRY_IS_WRONG_TYPE:
2014 case CM_PROB_LACKED_ARBITRATOR:
2015 case CM_PROB_FAILED_START:
2016 case CM_PROB_LIAR:
2017 case CM_PROB_UNKNOWN_RESOURCE:
2018 {
2019 TroubleShootStrId = IDS_UPDATEDRV;
2020 break;
2021 }
2022
2023 case CM_PROB_BOOT_CONFIG_CONFLICT:
2024 case CM_PROB_NORMAL_CONFLICT:
2025 case CM_PROB_REENUMERATION:
2026 {
2027 /* FIXME - Troubleshoot conflict */
2028 break;
2029 }
2030
2031 case CM_PROB_FAILED_FILTER:
2032 case CM_PROB_REINSTALL:
2033 case CM_PROB_FAILED_INSTALL:
2034 {
2035 TroubleShootStrId = IDS_REINSTALLDRV;
2036 break;
2037 }
2038
2039 case CM_PROB_DEVLOADER_NOT_FOUND:
2040 {
2041 /* FIXME - 4 cases:
2042 1) if it's a missing system devloader:
2043 - disable the button (Reinstall Driver)
2044 2) if it's not a system devloader but still missing:
2045 - Reinstall Driver
2046 3) if it's not a system devloader but the file can be found:
2047 - Update Driver
2048 4) if it's a missing or empty software key
2049 - Update Driver
2050 */
2051 break;
2052 }
2053
2054 case CM_PROB_INVALID_DATA:
2055 case CM_PROB_PARTIAL_LOG_CONF:
2056 case CM_PROB_NO_VALID_LOG_CONF:
2057 case CM_PROB_HARDWARE_DISABLED:
2058 case CM_PROB_CANT_SHARE_IRQ:
2059 case CM_PROB_TRANSLATION_FAILED:
2060 case CM_PROB_SYSTEM_SHUTDOWN:
2061 case CM_PROB_PHANTOM:
2062 bDevActionAvailable = FALSE;
2063 break;
2064
2065 case CM_PROB_NOT_VERIFIED:
2066 case CM_PROB_DEVICE_NOT_THERE:
2067 /* FIXME - search hardware */
2068 break;
2069
2070 case CM_PROB_NEED_RESTART:
2071 case CM_PROB_WILL_BE_REMOVED:
2072 case CM_PROB_MOVED:
2073 case CM_PROB_TOO_EARLY:
2074 case CM_PROB_DISABLED_SERVICE:
2075 TroubleShootStrId = IDS_REBOOT;
2076 break;
2077
2078 case CM_PROB_REGISTRY:
2079 /* FIXME - check registry? */
2080 break;
2081
2082 case CM_PROB_DISABLED:
2083 /* if device was disabled by the user: */
2084 TroubleShootStrId = IDS_ENABLEDEV;
2085 /* FIXME - otherwise disable button because the device was
2086 disabled by the system*/
2087 break;
2088
2089 case CM_PROB_DEVLOADER_NOT_READY:
2090 /* FIXME - if it's a graphics adapter:
2091 - if it's a a secondary adapter and the main adapter
2092 couldn't be found
2093 - disable button
2094 - else
2095 - Properties
2096 - else
2097 - Update driver
2098 */
2099 break;
2100
2101 case CM_PROB_FAILED_ADD:
2102 TroubleShootStrId = IDS_PROPERTIES;
2103 break;
2104 }
2105 }
2106
2107 if (LoadString(hDllInstance,
2108 TroubleShootStrId,
2109 dap->szTemp,
2110 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
2111 {
2112 SetWindowText(hDevProbBtn,
2113 dap->szTemp);
2114 }
2115 EnableWindow(hDevProbBtn,
2116 dap->IsAdmin && bDevActionAvailable);
2117
2118 /* check if the device can be enabled/disabled */
2119 hDevUsage = GetDlgItem(hwndDlg,
2120 IDC_DEVUSAGE);
2121
2122 dap->CanDisable = FALSE;
2123 dap->DeviceStarted = FALSE;
2124
2125 if (CanDisableDevice(DeviceInfoData->DevInst,
2126 dap->hMachine,
2127 &bFlag))
2128 {
2129 dap->CanDisable = bFlag;
2130 }
2131
2132 if (IsDeviceStarted(DeviceInfoData->DevInst,
2133 dap->hMachine,
2134 &bFlag))
2135 {
2136 dap->DeviceStarted = bFlag;
2137 }
2138
2139 /* enable/disable the device usage controls */
2140 EnableWindow(GetDlgItem(hwndDlg,
2141 IDC_DEVUSAGELABEL),
2142 dap->CanDisable && dap->IsAdmin);
2143 EnableWindow(hDevUsage,
2144 dap->CanDisable && dap->IsAdmin);
2145
2146 /* clear the combobox */
2147 SendMessage(hDevUsage,
2148 CB_RESETCONTENT,
2149 0,
2150 0);
2151 if (dap->CanDisable)
2152 {
2153 InitDevUsageActions(hwndDlg,
2154 hDevUsage,
2155 dap);
2156 }
2157
2158 /* find out how many new device property sheets to add.
2159 fake a PROPSHEETHEADER structure, we don't plan to
2160 call PropertySheet again!*/
2161 psh.dwSize = sizeof(PROPSHEETHEADER);
2162 psh.dwFlags = 0;
2163 psh.nPages = 0;
2164
2165 /* get the number of device property sheets for the device */
2166 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2167 DeviceInfoData,
2168 &psh,
2169 0,
2170 &nDriverPages,
2171 dap->PropertySheetType) &&
2172 nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2173 {
2174 dap->nDevPropSheets += nDriverPages;
2175 }
2176 else
2177 {
2178 nDriverPages = 0;
2179 }
2180
2181 /* include the driver page */
2182 if (dap->HasDriverPage)
2183 dap->nDevPropSheets++;
2184
2185 /* include the details page */
2186 if (dap->Extended)
2187 dap->nDevPropSheets++;
2188
2189 if (dap->HasResourcePage)
2190 dap->nDevPropSheets++;
2191
2192 /* add the device property sheets */
2193 if (dap->nDevPropSheets != 0)
2194 {
2195 dap->DevPropSheets = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2196 HEAP_ZERO_MEMORY,
2197 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
2198 if (dap->DevPropSheets != NULL)
2199 {
2200 if (nDriverPages != 0)
2201 {
2202 psh.phpage = dap->DevPropSheets;
2203
2204 /* query the device property sheet pages to add */
2205 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2206 DeviceInfoData,
2207 &psh,
2208 dap->nDevPropSheets,
2209 NULL,
2210 dap->PropertySheetType))
2211 {
2212 /* add the property sheets */
2213 for (iPage = 0;
2214 iPage < nDriverPages;
2215 iPage++)
2216 {
2217 if (PropSheet_AddPage(hPropSheetDlg,
2218 dap->DevPropSheets[iPage]))
2219 {
2220 RecalcPages = TRUE;
2221 }
2222 }
2223
2224 dap->FreeDevPropSheets = TRUE;
2225 }
2226 else
2227 {
2228 /* cleanup, we were unable to get the device property sheets */
2229 iPage = nDriverPages;
2230 dap->nDevPropSheets -= nDriverPages;
2231 nDriverPages = 0;
2232 }
2233 }
2234 else
2235 iPage = 0;
2236
2237 /* add the driver page if necessary */
2238 if (dap->HasDriverPage)
2239 {
2240 PROPSHEETPAGE pspDriver = {0};
2241 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2242 pspDriver.dwFlags = PSP_DEFAULT;
2243 pspDriver.hInstance = hDllInstance;
2244 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
2245 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
2246 pspDriver.lParam = (LPARAM)dap;
2247 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2248 if (dap->DevPropSheets[iPage] != NULL)
2249 {
2250 if (PropSheet_AddPage(hPropSheetDlg,
2251 dap->DevPropSheets[iPage]))
2252 {
2253 iPage++;
2254 RecalcPages = TRUE;
2255 }
2256 else
2257 {
2258 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2259 dap->DevPropSheets[iPage] = NULL;
2260 }
2261 }
2262 }
2263
2264 if (dap->Extended)
2265 {
2266 /* Add the details page */
2267 PROPSHEETPAGE pspDetails = {0};
2268 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
2269 pspDetails.dwFlags = PSP_DEFAULT;
2270 pspDetails.hInstance = hDllInstance;
2271 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
2272 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
2273 pspDetails.lParam = (LPARAM)dap;
2274 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
2275 if (dap->DevPropSheets[iPage] != NULL)
2276 {
2277 if (PropSheet_AddPage(hPropSheetDlg,
2278 dap->DevPropSheets[iPage]))
2279 {
2280 iPage++;
2281 RecalcPages = TRUE;
2282 }
2283 else
2284 {
2285 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2286 dap->DevPropSheets[iPage] = NULL;
2287 }
2288 }
2289 }
2290
2291 if (dap->HasResourcePage)
2292 {
2293 PROPSHEETPAGE pspDriver = {0};
2294 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2295 pspDriver.dwFlags = PSP_DEFAULT;
2296 pspDriver.hInstance = hDllInstance;
2297 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
2298 pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
2299 pspDriver.lParam = (LPARAM)dap;
2300 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2301 if (dap->DevPropSheets[iPage] != NULL)
2302 {
2303 if (PropSheet_AddPage(hPropSheetDlg,
2304 dap->DevPropSheets[iPage]))
2305 {
2306 iPage++;
2307 RecalcPages = TRUE;
2308 }
2309 else
2310 {
2311 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2312 dap->DevPropSheets[iPage] = NULL;
2313 }
2314 }
2315 }
2316 /* FIXME: Add the power page */
2317 }
2318 else
2319 dap->nDevPropSheets = 0;
2320 }
2321
2322 if (RecalcPages)
2323 {
2324 PropSheet_RecalcPageSizes(hPropSheetDlg);
2325 }
2326
2327 /* finally, disable the apply button */
2328 PropSheet_UnChanged(hPropSheetDlg,
2329 hwndDlg);
2330 dap->DeviceUsageChanged = FALSE;
2331 }
2332
2333
2334 static LRESULT
2335 CALLBACK
2336 DlgParentSubWndProc(IN HWND hwnd,
2337 IN UINT uMsg,
2338 IN WPARAM wParam,
2339 IN LPARAM lParam)
2340 {
2341 PDEVADVPROP_INFO dap;
2342
2343 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
2344 L"DevMgrDevChangeSub");
2345 if (dap != NULL)
2346 {
2347 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
2348 {
2349 SendMessage(dap->hWndGeneralPage,
2350 WM_DEVICECHANGE,
2351 wParam,
2352 lParam);
2353 }
2354
2355 /* pass the message the the old window proc */
2356 return CallWindowProc(dap->ParentOldWndProc,
2357 hwnd,
2358 uMsg,
2359 wParam,
2360 lParam);
2361 }
2362 else
2363 {
2364 /* this is not a good idea if the subclassed window was an ansi
2365 window, but we failed finding out the previous window proc
2366 so we can't use CallWindowProc. This should rarely - if ever -
2367 happen. */
2368
2369 return DefWindowProc(hwnd,
2370 uMsg,
2371 wParam,
2372 lParam);
2373 }
2374 }
2375
2376
2377 static INT_PTR
2378 CALLBACK
2379 AdvPropGeneralDlgProc(IN HWND hwndDlg,
2380 IN UINT uMsg,
2381 IN WPARAM wParam,
2382 IN LPARAM lParam)
2383 {
2384 PDEVADVPROP_INFO dap;
2385 INT_PTR Ret = FALSE;
2386
2387 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
2388 DWL_USER);
2389
2390 if (dap != NULL || uMsg == WM_INITDIALOG)
2391 {
2392 switch (uMsg)
2393 {
2394 case WM_COMMAND:
2395 {
2396 switch (LOWORD(wParam))
2397 {
2398 case IDC_DEVUSAGE:
2399 {
2400 if (HIWORD(wParam) == CBN_SELCHANGE)
2401 {
2402 PropSheet_Changed(GetParent(hwndDlg),
2403 hwndDlg);
2404 dap->DeviceUsageChanged = TRUE;
2405 }
2406 break;
2407 }
2408
2409 case IDC_DEVPROBLEM:
2410 {
2411 if (dap->IsAdmin)
2412 {
2413 /* display the device problem wizard */
2414 ShowDeviceProblemWizard(hwndDlg,
2415 dap->DeviceInfoSet,
2416 &dap->DeviceInfoData,
2417 dap->hMachine);
2418 }
2419 break;
2420 }
2421 }
2422 break;
2423 }
2424
2425 case WM_NOTIFY:
2426 {
2427 NMHDR *hdr = (NMHDR*)lParam;
2428 switch (hdr->code)
2429 {
2430 case PSN_APPLY:
2431 ApplyGeneralSettings(hwndDlg,
2432 dap);
2433 break;
2434 }
2435 break;
2436 }
2437
2438 case WM_INITDIALOG:
2439 {
2440 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2441 if (dap != NULL)
2442 {
2443 HWND hWndParent;
2444
2445 dap->hWndGeneralPage = hwndDlg;
2446
2447 SetWindowLongPtr(hwndDlg,
2448 DWL_USER,
2449 (DWORD_PTR)dap);
2450
2451 /* subclass the parent window to always receive
2452 WM_DEVICECHANGE messages */
2453 hWndParent = GetParent(hwndDlg);
2454 if (hWndParent != NULL)
2455 {
2456 /* subclass the parent window. This is not safe
2457 if the parent window belongs to another thread! */
2458 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
2459 GWLP_WNDPROC,
2460 (LONG_PTR)DlgParentSubWndProc);
2461
2462 if (dap->ParentOldWndProc != NULL &&
2463 SetProp(hWndParent,
2464 L"DevMgrDevChangeSub",
2465 (HANDLE)dap))
2466 {
2467 dap->hWndParent = hWndParent;
2468 }
2469 }
2470
2471 /* do not call UpdateDevInfo directly in here because it modifies
2472 the pages of the property sheet! */
2473 PostMessage(hwndDlg,
2474 PM_INITIALIZE,
2475 0,
2476 0);
2477 }
2478 Ret = TRUE;
2479 break;
2480 }
2481
2482 case WM_DEVICECHANGE:
2483 {
2484 /* FIXME - don't call UpdateDevInfo for all events */
2485 UpdateDevInfo(hwndDlg,
2486 dap,
2487 TRUE);
2488 Ret = TRUE;
2489 break;
2490 }
2491
2492 case PM_INITIALIZE:
2493 {
2494 UpdateDevInfo(hwndDlg,
2495 dap,
2496 FALSE);
2497 dap->PageInitialized = TRUE;
2498 break;
2499 }
2500
2501 case WM_DESTROY:
2502 {
2503 /* restore the old window proc of the subclassed parent window */
2504 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
2505 {
2506 if (SetWindowLongPtr(dap->hWndParent,
2507 GWLP_WNDPROC,
2508 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
2509 {
2510 RemoveProp(dap->hWndParent,
2511 L"DevMgrDevChangeSub");
2512 }
2513 }
2514 break;
2515 }
2516 }
2517 }
2518
2519 return Ret;
2520 }
2521
2522
2523 INT_PTR
2524 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
2525 IN LPCWSTR lpDeviceID OPTIONAL,
2526 IN HDEVINFO DeviceInfoSet,
2527 IN PSP_DEVINFO_DATA DeviceInfoData,
2528 IN HINSTANCE hComCtl32,
2529 IN LPCWSTR lpMachineName,
2530 IN DWORD dwFlags)
2531 {
2532 PROPSHEETHEADER psh = {0};
2533 PROPSHEETPAGE pspGeneral = {0};
2534 PPROPERTYSHEETW pPropertySheetW;
2535 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
2536 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
2537 PDEVADVPROP_INFO DevAdvPropInfo;
2538 HMACHINE hMachine = NULL;
2539 DWORD DevIdSize = 0;
2540 INT_PTR Ret = -1;
2541
2542 /* we don't want to statically link against comctl32, so find the
2543 functions we need dynamically */
2544 pPropertySheetW =
2545 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
2546 "PropertySheetW");
2547 pCreatePropertySheetPageW =
2548 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
2549 "CreatePropertySheetPageW");
2550 pDestroyPropertySheetPage =
2551 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
2552 "DestroyPropertySheetPage");
2553 if (pPropertySheetW == NULL ||
2554 pCreatePropertySheetPageW == NULL ||
2555 pDestroyPropertySheetPage == NULL)
2556 {
2557 return -1;
2558 }
2559
2560 if (lpDeviceID == NULL)
2561 {
2562 /* find out how much size is needed for the device id */
2563 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
2564 DeviceInfoData,
2565 NULL,
2566 0,
2567 &DevIdSize))
2568 {
2569 ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
2570 return -1;
2571 }
2572
2573 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2574 {
2575 return -1;
2576 }
2577 }
2578 else
2579 {
2580 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
2581 }
2582
2583 if (lpMachineName != NULL && lpMachineName[0] != L'\0')
2584 {
2585 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
2586 &hMachine);
2587 if (cr != CR_SUCCESS)
2588 {
2589 return -1;
2590 }
2591 }
2592
2593 /* create the internal structure associated with the "General",
2594 "Driver", ... pages */
2595 DevAdvPropInfo = (PDEVADVPROP_INFO)HeapAlloc(GetProcessHeap(),
2596 HEAP_ZERO_MEMORY,
2597 FIELD_OFFSET(DEVADVPROP_INFO,
2598 szDeviceID) +
2599 (DevIdSize * sizeof(WCHAR)));
2600 if (DevAdvPropInfo == NULL)
2601 {
2602 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2603 goto Cleanup;
2604 }
2605
2606 if (lpDeviceID == NULL)
2607 {
2608 /* read the device instance id */
2609 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
2610 DeviceInfoData,
2611 DevAdvPropInfo->szDeviceID,
2612 DevIdSize,
2613 NULL))
2614 {
2615 goto Cleanup;
2616 }
2617 }
2618 else
2619 {
2620 /* copy the device instance id supplied by the caller */
2621 wcscpy(DevAdvPropInfo->szDeviceID,
2622 lpDeviceID);
2623 }
2624
2625 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
2626 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
2627 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2628 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2629
2630 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
2631 DevAdvPropInfo->hMachine = hMachine;
2632 DevAdvPropInfo->lpMachineName = lpMachineName;
2633 DevAdvPropInfo->szDevName[0] = L'\0';
2634 DevAdvPropInfo->hComCtl32 = hComCtl32;
2635 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
2636 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
2637
2638 DevAdvPropInfo->IsAdmin = TRUE;// IsUserAdmin();
2639 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
2640 DevAdvPropInfo->Extended = ((dwFlags & DPF_EXTENDED) != 0);
2641
2642 psh.dwSize = sizeof(PROPSHEETHEADER);
2643 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2644 psh.hwndParent = hWndParent;
2645 psh.pszCaption = DevAdvPropInfo->szDevName;
2646
2647 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2648 DIGCDP_FLAG_REMOTE_ADVANCED :
2649 DIGCDP_FLAG_ADVANCED;
2650
2651 psh.phpage = (HPROPSHEETPAGE *)HeapAlloc(GetProcessHeap(),
2652 HEAP_ZERO_MEMORY,
2653 1 * sizeof(HPROPSHEETPAGE));
2654 if (psh.phpage == NULL)
2655 {
2656 goto Cleanup;
2657 }
2658
2659 /* add the "General" property sheet */
2660 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2661 pspGeneral.dwFlags = PSP_DEFAULT;
2662 pspGeneral.hInstance = hDllInstance;
2663 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2664 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2665 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2666 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2667 if (psh.phpage[psh.nPages] != NULL)
2668 {
2669 psh.nPages++;
2670 }
2671
2672 DevAdvPropInfo->nDevPropSheets = psh.nPages;
2673
2674 if (psh.nPages != 0)
2675 {
2676 Ret = pPropertySheetW(&psh);
2677
2678 /* NOTE: no need to destroy the property sheets anymore! */
2679 }
2680 else
2681 {
2682 UINT i;
2683
2684 Cleanup:
2685 /* in case of failure the property sheets must be destroyed */
2686 if (psh.phpage != NULL)
2687 {
2688 for (i = 0;
2689 i < psh.nPages;
2690 i++)
2691 {
2692 if (psh.phpage[i] != NULL)
2693 {
2694 pDestroyPropertySheetPage(psh.phpage[i]);
2695 }
2696 }
2697 }
2698 }
2699
2700 if (DevAdvPropInfo != NULL)
2701 {
2702 if (DevAdvPropInfo->FreeDevPropSheets)
2703 {
2704 /* don't free the array if it's the one allocated in
2705 DisplayDeviceAdvancedProperties */
2706 HeapFree(GetProcessHeap(),
2707 0,
2708 DevAdvPropInfo->DevPropSheets);
2709 }
2710
2711 if (DevAdvPropInfo->CloseDevInst)
2712 {
2713 /* close the device info set in case a new one was created */
2714 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2715 }
2716
2717 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2718 {
2719 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2720 }
2721
2722 if (DevAdvPropInfo->hDevIcon != NULL)
2723 {
2724 DestroyIcon(DevAdvPropInfo->hDevIcon);
2725 }
2726
2727 HeapFree(GetProcessHeap(),
2728 0,
2729 DevAdvPropInfo);
2730 }
2731
2732 if (psh.phpage != NULL)
2733 {
2734 HeapFree(GetProcessHeap(),
2735 0,
2736 psh.phpage);
2737 }
2738
2739 if (hMachine != NULL)
2740 {
2741 CM_Disconnect_Machine(hMachine);
2742 }
2743
2744 return Ret;
2745 }