[DEVMGR]
[reactos.git] / reactos / dll / win32 / devmgr / advprop.c
1 /*
2 * ReactOS Device Manager Applet
3 * Copyright (C) 2004 - 2005 ReactOS Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 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
32 #include <winver.h>
33
34
35 static UINT WINAPI
36 EnumDeviceDriverFilesCallback(IN PVOID Context,
37 IN UINT Notification,
38 IN UINT_PTR Param1,
39 IN UINT_PTR Param2)
40 {
41 LVITEM li;
42 PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext = (PENUMDRIVERFILES_CONTEXT)Context;
43
44 li.mask = LVIF_TEXT | LVIF_STATE;
45 li.iItem = EnumDriverFilesContext->nCount++;
46 li.iSubItem = 0;
47 li.state = (li.iItem == 0 ? LVIS_SELECTED : 0);
48 li.stateMask = LVIS_SELECTED;
49 li.pszText = (LPWSTR)Param1;
50 (void)ListView_InsertItem(EnumDriverFilesContext->hDriversListView,
51 &li);
52 return NO_ERROR;
53 }
54
55
56 static VOID
57 UpdateDriverDetailsDlg(IN HWND hwndDlg,
58 IN HWND hDriversListView,
59 IN PDEVADVPROP_INFO dap)
60 {
61 HDEVINFO DeviceInfoSet;
62 PSP_DEVINFO_DATA DeviceInfoData;
63 SP_DRVINFO_DATA DriverInfoData;
64 ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext;
65
66 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
67 {
68 DeviceInfoSet = dap->CurrentDeviceInfoSet;
69 DeviceInfoData = &dap->CurrentDeviceInfoData;
70 }
71 else
72 {
73 DeviceInfoSet = dap->DeviceInfoSet;
74 DeviceInfoData = &dap->DeviceInfoData;
75 }
76
77 /* set the device image */
78 SendDlgItemMessage(hwndDlg,
79 IDC_DEVICON,
80 STM_SETICON,
81 (WPARAM)dap->hDevIcon,
82 0);
83
84 /* set the device name edit control text */
85 SetDlgItemText(hwndDlg,
86 IDC_DEVNAME,
87 dap->szDevName);
88
89 /* fill the driver files list view */
90 EnumDriverFilesContext.hDriversListView = hDriversListView;
91 EnumDriverFilesContext.nCount = 0;
92
93 (void)ListView_DeleteAllItems(EnumDriverFilesContext.hDriversListView);
94 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
95 if (FindCurrentDriver(DeviceInfoSet,
96 DeviceInfoData,
97 &DriverInfoData) &&
98 SetupDiSetSelectedDriver(DeviceInfoSet,
99 DeviceInfoData,
100 &DriverInfoData))
101 {
102 HSPFILEQ queueHandle;
103
104 queueHandle = SetupOpenFileQueue();
105 if (queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE)
106 {
107 SP_DEVINSTALL_PARAMS DeviceInstallParams = {0};
108 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
109 if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
110 DeviceInfoData,
111 &DeviceInstallParams))
112 {
113 DeviceInstallParams.FileQueue = queueHandle;
114 DeviceInstallParams.Flags |= DI_NOVCP;
115
116 if (SetupDiSetDeviceInstallParams(DeviceInfoSet,
117 DeviceInfoData,
118 &DeviceInstallParams) &&
119 SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
120 DeviceInfoSet,
121 DeviceInfoData))
122 {
123 DWORD scanResult;
124 RECT rcClient;
125 LVCOLUMN lvc;
126
127 /* enumerate the driver files */
128 SetupScanFileQueue(queueHandle,
129 SPQ_SCAN_USE_CALLBACK,
130 NULL,
131 EnumDeviceDriverFilesCallback,
132 &EnumDriverFilesContext,
133 &scanResult);
134
135 /* update the list view column width */
136 GetClientRect(hDriversListView,
137 &rcClient);
138 lvc.mask = LVCF_WIDTH;
139 lvc.cx = rcClient.right;
140 (void)ListView_SetColumn(hDriversListView,
141 0,
142 &lvc);
143
144 /* highlight the first item from list */
145 if (ListView_GetSelectedCount(hDriversListView) != 0)
146 {
147 ListView_SetItemState(hDriversListView,
148 0,
149 LVIS_FOCUSED | LVIS_SELECTED,
150 LVIS_FOCUSED | LVIS_SELECTED);
151 }
152 }
153 }
154
155 SetupCloseFileQueue(queueHandle);
156 }
157 }
158 }
159
160
161 static VOID
162 UpdateDriverVersionInfoDetails(IN HWND hwndDlg,
163 IN LPCWSTR lpszDriverPath)
164 {
165 DWORD dwHandle;
166 DWORD dwVerInfoSize;
167 LPVOID lpData = NULL;
168 LPVOID lpInfo;
169 UINT uInfoLen;
170 DWORD dwLangId;
171 WCHAR szLangInfo[255];
172 WCHAR szLangPath[MAX_PATH];
173 LPWSTR lpCompanyName = NULL;
174 LPWSTR lpFileVersion = NULL;
175 LPWSTR lpLegalCopyright = NULL;
176 LPWSTR lpDigitalSigner = NULL;
177 UINT uBufLen;
178 WCHAR szNotAvailable[255];
179
180 /* extract version info from selected file */
181 dwVerInfoSize = GetFileVersionInfoSize(lpszDriverPath,
182 &dwHandle);
183 if (!dwVerInfoSize)
184 goto done;
185
186 lpData = HeapAlloc(GetProcessHeap(),
187 HEAP_ZERO_MEMORY,
188 dwVerInfoSize);
189 if (!lpData)
190 goto done;
191
192 if (!GetFileVersionInfo(lpszDriverPath,
193 dwHandle,
194 dwVerInfoSize,
195 lpData))
196 goto done;
197
198 if (!VerQueryValue(lpData,
199 L"\\VarFileInfo\\Translation",
200 &lpInfo,
201 &uInfoLen))
202 goto done;
203
204 dwLangId = *(LPDWORD)lpInfo;
205 swprintf(szLangInfo, L"\\StringFileInfo\\%04x%04x\\",
206 LOWORD(dwLangId), HIWORD(dwLangId));
207
208 /* read CompanyName */
209 wcscpy(szLangPath, szLangInfo);
210 wcscat(szLangPath, L"CompanyName");
211
212 VerQueryValue(lpData,
213 szLangPath,
214 (void **)&lpCompanyName,
215 (PUINT)&uBufLen);
216
217 /* read FileVersion */
218 wcscpy(szLangPath, szLangInfo);
219 wcscat(szLangPath, L"FileVersion");
220
221 VerQueryValue(lpData,
222 szLangPath,
223 (void **)&lpFileVersion,
224 (PUINT)&uBufLen);
225
226 /* read LegalTrademarks */
227 wcscpy(szLangPath, szLangInfo);
228 wcscat(szLangPath, L"LegalCopyright");
229
230 VerQueryValue(lpData,
231 szLangPath,
232 (void **)&lpLegalCopyright,
233 (PUINT)&uBufLen);
234
235 /* TODO: read digital signer info */
236
237 done:
238 if (!LoadString(hDllInstance,
239 IDS_NOTAVAILABLE,
240 szNotAvailable,
241 sizeof(szNotAvailable) / sizeof(WCHAR)))
242 {
243 wcscpy(szNotAvailable, L"n/a");
244 }
245
246 /* update labels */
247 if (!lpCompanyName)
248 lpCompanyName = szNotAvailable;
249 SetDlgItemText(hwndDlg,
250 IDC_FILEPROVIDER,
251 lpCompanyName);
252
253 if (!lpFileVersion)
254 lpFileVersion = szNotAvailable;
255 SetDlgItemText(hwndDlg,
256 IDC_FILEVERSION,
257 lpFileVersion);
258
259 if (!lpLegalCopyright)
260 lpLegalCopyright = szNotAvailable;
261 SetDlgItemText(hwndDlg,
262 IDC_FILECOPYRIGHT,
263 lpLegalCopyright);
264
265 if (!lpDigitalSigner)
266 lpDigitalSigner = szNotAvailable;
267 SetDlgItemText(hwndDlg,
268 IDC_DIGITALSIGNER,
269 lpDigitalSigner);
270
271 /* release version info */
272 if (lpData)
273 HeapFree(GetProcessHeap(),
274 0,
275 lpData);
276 }
277
278
279 static INT_PTR
280 CALLBACK
281 DriverDetailsDlgProc(IN HWND hwndDlg,
282 IN UINT uMsg,
283 IN WPARAM wParam,
284 IN LPARAM lParam)
285 {
286 PDEVADVPROP_INFO dap;
287 INT_PTR Ret = FALSE;
288
289 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
290 DWL_USER);
291
292 if (dap != NULL || uMsg == WM_INITDIALOG)
293 {
294 switch (uMsg)
295 {
296 case WM_COMMAND:
297 {
298 switch (LOWORD(wParam))
299 {
300 case IDOK:
301 case IDCANCEL:
302 {
303 EndDialog(hwndDlg,
304 IDOK);
305 break;
306 }
307 }
308 break;
309 }
310
311 case WM_CLOSE:
312 {
313 EndDialog(hwndDlg,
314 IDCANCEL);
315 break;
316 }
317
318 case WM_INITDIALOG:
319 {
320 LV_COLUMN lvc;
321 HWND hDriversListView;
322 WCHAR szBuffer[260];
323
324 dap = (PDEVADVPROP_INFO)lParam;
325 if (dap != NULL)
326 {
327 SetWindowLongPtr(hwndDlg,
328 DWL_USER,
329 (DWORD_PTR)dap);
330
331 hDriversListView = GetDlgItem(hwndDlg,
332 IDC_DRIVERFILES);
333
334 /* add a column to the list view control */
335 lvc.mask = LVCF_FMT | LVCF_WIDTH;
336 lvc.fmt = LVCFMT_LEFT;
337 lvc.cx = 0;
338 (void)ListView_InsertColumn(hDriversListView,
339 0,
340 &lvc);
341
342 UpdateDriverDetailsDlg(hwndDlg,
343 hDriversListView,
344 dap);
345
346 if (ListView_GetItemCount(hDriversListView) == 0)
347 {
348 if(LoadStringW(hDllInstance, IDS_NODRIVERS, szBuffer, _countof(szBuffer)))
349 MessageBoxW(hwndDlg, szBuffer, dap->szDevName, MB_OK);
350 EndDialog(hwndDlg, IDCANCEL);
351 }
352 }
353
354 Ret = TRUE;
355 break;
356 }
357
358 case WM_NOTIFY:
359 {
360 LPNMHDR pnmhdr = (LPNMHDR)lParam;
361
362 switch (pnmhdr->code)
363 {
364 case LVN_ITEMCHANGED:
365 {
366 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
367 HWND hDriversListView = GetDlgItem(hwndDlg,
368 IDC_DRIVERFILES);
369
370 if (ListView_GetSelectedCount(hDriversListView) == 0)
371 {
372 /* nothing is selected - empty the labels */
373 SetDlgItemText(hwndDlg,
374 IDC_FILEPROVIDER,
375 NULL);
376 SetDlgItemText(hwndDlg,
377 IDC_FILEVERSION,
378 NULL);
379 SetDlgItemText(hwndDlg,
380 IDC_FILECOPYRIGHT,
381 NULL);
382 SetDlgItemText(hwndDlg,
383 IDC_DIGITALSIGNER,
384 NULL);
385 }
386 else if (pnmv->uNewState != 0)
387 {
388 /* extract version info and update the labels */
389 WCHAR szDriverPath[MAX_PATH];
390
391 ListView_GetItemText(hDriversListView,
392 pnmv->iItem,
393 pnmv->iSubItem,
394 szDriverPath,
395 MAX_PATH);
396
397 UpdateDriverVersionInfoDetails(hwndDlg,
398 szDriverPath);
399 }
400 }
401 }
402 break;
403 }
404 }
405 }
406
407 return Ret;
408 }
409
410
411 static
412 VOID
413 UpdateDriver(
414 IN HWND hwndDlg,
415 IN PDEVADVPROP_INFO dap)
416 {
417 TOKEN_PRIVILEGES Privileges;
418 HANDLE hToken;
419 DWORD dwReboot;
420 BOOL NeedReboot = FALSE;
421
422 // Better use InstallDevInst:
423 // BOOL
424 // WINAPI
425 // InstallDevInst(
426 // HWND hWnd,
427 // LPWSTR wszDeviceId,
428 // BOOL bUpdate,
429 // DWORD *dwReboot);
430 // See: http://comp.os.ms-windows.programmer.win32.narkive.com/J8FTd4KK/signature-of-undocumented-installdevinstex
431
432 if (!InstallDevInst(hwndDlg, dap->szDeviceID, TRUE, &dwReboot))
433 return;
434
435 if (NeedReboot == FALSE)
436 return;
437
438 //FIXME: load text from resource file
439 if (MessageBoxW(hwndDlg, L"Reboot now?", L"Reboot required", MB_YESNO | MB_ICONQUESTION) != IDYES)
440 return;
441
442 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
443 {
444 ERR("OpenProcessToken failed\n");
445 return;
446 }
447
448 /* Get the LUID for the Shutdown privilege */
449 if (!LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &Privileges.Privileges[0].Luid))
450 {
451 ERR("LookupPrivilegeValue failed\n");
452 CloseHandle(hToken);
453 return;
454 }
455
456 /* Assign the Shutdown privilege to our process */
457 Privileges.PrivilegeCount = 1;
458 Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
459
460 if (!AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL))
461 {
462 ERR("AdjustTokenPrivileges failed\n");
463 CloseHandle(hToken);
464 return;
465 }
466
467 /* Finally shut down the system */
468 if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
469 {
470 ERR("ExitWindowsEx failed\n");
471 CloseHandle(hToken);
472 }
473 }
474
475
476 static VOID
477 UpdateDriverDlg(IN HWND hwndDlg,
478 IN PDEVADVPROP_INFO dap)
479 {
480 HDEVINFO DeviceInfoSet;
481 PSP_DEVINFO_DATA DeviceInfoData;
482
483 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
484 {
485 DeviceInfoSet = dap->CurrentDeviceInfoSet;
486 DeviceInfoData = &dap->CurrentDeviceInfoData;
487 }
488 else
489 {
490 DeviceInfoSet = dap->DeviceInfoSet;
491 DeviceInfoData = &dap->DeviceInfoData;
492 }
493
494 /* set the device image */
495 SendDlgItemMessage(hwndDlg,
496 IDC_DEVICON,
497 STM_SETICON,
498 (WPARAM)dap->hDevIcon,
499 0);
500
501 /* set the device name edit control text */
502 SetDlgItemText(hwndDlg,
503 IDC_DEVNAME,
504 dap->szDevName);
505
506 /* query the driver provider */
507 if (GetDriverProviderString(DeviceInfoSet,
508 DeviceInfoData,
509 dap->szTemp,
510 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
511 {
512 SetDlgItemText(hwndDlg,
513 IDC_DRVPROVIDER,
514 dap->szTemp);
515 }
516
517 /* query the driver date */
518 if (GetDriverDateString(DeviceInfoSet,
519 DeviceInfoData,
520 dap->szTemp,
521 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
522 {
523 SetDlgItemText(hwndDlg,
524 IDC_DRVDATE,
525 dap->szTemp);
526 }
527
528 /* query the driver version */
529 if (GetDriverVersionString(DeviceInfoSet,
530 DeviceInfoData,
531 dap->szTemp,
532 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
533 {
534 SetDlgItemText(hwndDlg,
535 IDC_DRVVERSION,
536 dap->szTemp);
537 }
538 }
539
540
541 static INT_PTR
542 CALLBACK
543 AdvProcDriverDlgProc(IN HWND hwndDlg,
544 IN UINT uMsg,
545 IN WPARAM wParam,
546 IN LPARAM lParam)
547 {
548 PDEVADVPROP_INFO dap;
549 INT_PTR Ret = FALSE;
550
551 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
552 DWL_USER);
553
554 if (dap != NULL || uMsg == WM_INITDIALOG)
555 {
556 switch (uMsg)
557 {
558 case WM_COMMAND:
559 {
560 switch (LOWORD(wParam))
561 {
562 case IDC_DRIVERDETAILS:
563 DialogBoxParam(hDllInstance,
564 MAKEINTRESOURCE(IDD_DRIVERDETAILS),
565 hwndDlg,
566 DriverDetailsDlgProc,
567 (ULONG_PTR)dap);
568 break;
569
570 case IDC_UPDATEDRIVER:
571 UpdateDriver(hwndDlg, dap);
572 break;
573 }
574 break;
575 }
576
577 case WM_NOTIFY:
578 {
579 NMHDR *hdr = (NMHDR*)lParam;
580 switch (hdr->code)
581 {
582 case PSN_APPLY:
583 break;
584 }
585 break;
586 }
587
588 case WM_INITDIALOG:
589 {
590 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
591 if (dap != NULL)
592 {
593 SetWindowLongPtr(hwndDlg,
594 DWL_USER,
595 (DWORD_PTR)dap);
596
597 UpdateDriverDlg(hwndDlg,
598 dap);
599 }
600 Ret = TRUE;
601 break;
602 }
603 }
604 }
605
606 return Ret;
607 }
608
609
610 static VOID
611 SetListViewText(HWND hwnd,
612 INT iItem,
613 LPWSTR lpText)
614 {
615 LVITEM li;
616
617 li.mask = LVIF_TEXT | LVIF_STATE;
618 li.iItem = iItem;
619 li.iSubItem = 0;
620 li.state = 0; //(li.iItem == 0 ? LVIS_SELECTED : 0);
621 li.stateMask = LVIS_SELECTED;
622 li.pszText = lpText;
623 (void)ListView_InsertItem(hwnd,
624 &li);
625 }
626
627
628 static VOID
629 UpdateDetailsDlg(IN HWND hwndDlg,
630 IN PDEVADVPROP_INFO dap)
631 {
632 HWND hwndComboBox;
633 HWND hwndListView;
634 LV_COLUMN lvc;
635 RECT rcClient;
636
637 UINT i;
638 UINT Properties[] =
639 {
640 IDS_PROP_DEVICEID,
641 IDS_PROP_HARDWAREIDS,
642 IDS_PROP_COMPATIBLEIDS,
643 IDS_PROP_MATCHINGDEVICEID,
644 IDS_PROP_SERVICE,
645 IDS_PROP_ENUMERATOR,
646 IDS_PROP_CAPABILITIES,
647 IDS_PROP_DEVNODEFLAGS,
648 IDS_PROP_CONFIGFLAGS,
649 IDS_PROP_CSCONFIGFLAGS,
650 IDS_PROP_EJECTIONRELATIONS,
651 IDS_PROP_REMOVALRELATIONS,
652 IDS_PROP_BUSRELATIONS,
653 IDS_PROP_DEVUPPERFILTERS,
654 IDS_PROP_DEVLOWERFILTERS,
655 IDS_PROP_CLASSUPPERFILTERS,
656 IDS_PROP_CLASSLOWERFILTERS,
657 IDS_PROP_CLASSINSTALLER,
658 IDS_PROP_CLASSCOINSTALLER,
659 IDS_PROP_DEVICECOINSTALLER,
660 IDS_PROP_FIRMWAREREVISION,
661 IDS_PROP_CURRENTPOWERSTATE,
662 IDS_PROP_POWERCAPABILITIES,
663 IDS_PROP_POWERSTATEMAPPINGS
664 };
665
666
667 /* set the device image */
668 SendDlgItemMessage(hwndDlg,
669 IDC_DEVICON,
670 STM_SETICON,
671 (WPARAM)dap->hDevIcon,
672 0);
673
674 /* set the device name edit control text */
675 SetDlgItemText(hwndDlg,
676 IDC_DEVNAME,
677 dap->szDevName);
678
679
680 hwndComboBox = GetDlgItem(hwndDlg,
681 IDC_DETAILSPROPNAME);
682
683 hwndListView = GetDlgItem(hwndDlg,
684 IDC_DETAILSPROPVALUE);
685
686 for (i = 0; i != sizeof(Properties) / sizeof(Properties[0]); i++)
687 {
688 /* fill in the device usage combo box */
689 if (LoadString(hDllInstance,
690 Properties[i],
691 dap->szTemp,
692 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
693 {
694 SendMessage(hwndComboBox,
695 CB_ADDSTRING,
696 0,
697 (LPARAM)dap->szTemp);
698 }
699 }
700
701
702 GetClientRect(hwndListView,
703 &rcClient);
704
705 /* add a column to the list view control */
706 lvc.mask = LVCF_FMT | LVCF_WIDTH;
707 lvc.fmt = LVCFMT_LEFT;
708 lvc.cx = rcClient.right;
709 (void)ListView_InsertColumn(hwndListView,
710 0,
711 &lvc);
712
713 SendMessage(hwndComboBox,
714 CB_SETCURSEL,
715 0,
716 0);
717
718 SetListViewText(hwndListView, 0, dap->szDeviceID);
719
720 SetFocus(hwndComboBox);
721 }
722
723
724 static VOID
725 DisplayDevicePropertyText(IN PDEVADVPROP_INFO dap,
726 IN HWND hwndListView,
727 IN DWORD dwProperty)
728 {
729 HDEVINFO DeviceInfoSet;
730 PSP_DEVINFO_DATA DeviceInfoData;
731 DWORD dwType;
732 DWORD dwSize;
733 DWORD dwValue;
734 LPBYTE lpBuffer;
735 LPWSTR lpStr;
736 INT len;
737 INT index;
738
739 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
740 {
741 DeviceInfoSet = dap->CurrentDeviceInfoSet;
742 DeviceInfoData = &dap->CurrentDeviceInfoData;
743 }
744 else
745 {
746 DeviceInfoSet = dap->DeviceInfoSet;
747 DeviceInfoData = &dap->DeviceInfoData;
748 }
749
750 dwSize = 0;
751 SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
752 DeviceInfoData,
753 dwProperty,
754 &dwType,
755 NULL,
756 0,
757 &dwSize);
758 if (dwSize == 0)
759 {
760 if (GetLastError() != ERROR_FILE_NOT_FOUND)
761 {
762 swprintf(dap->szTemp, L"Error: Getting the size failed! (Error: %ld)", GetLastError());
763 SetListViewText(hwndListView, 0, dap->szTemp);
764 }
765 return;
766 }
767
768 if (dwType == REG_SZ)
769 dwSize += sizeof(WCHAR);
770
771 lpBuffer = HeapAlloc(GetProcessHeap(),
772 HEAP_ZERO_MEMORY,
773 dwSize);
774 if (lpBuffer == NULL)
775 {
776 SetListViewText(hwndListView, 0, L"Error: Allocating the buffer failed!");
777 return;
778 }
779
780 if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
781 DeviceInfoData,
782 dwProperty,
783 &dwType,
784 lpBuffer,
785 dwSize,
786 &dwSize))
787 {
788 if (dwType == REG_SZ)
789 {
790 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
791 }
792 else if (dwType == REG_MULTI_SZ)
793 {
794 lpStr = (LPWSTR)lpBuffer;
795 index = 0;
796 while (*lpStr != 0)
797 {
798 len = wcslen(lpStr) + 1;
799
800 SetListViewText(hwndListView, index, lpStr);
801
802 lpStr += len;
803 index++;
804 }
805 }
806 else if (dwType == REG_DWORD)
807 {
808 dwValue = *(DWORD *) lpBuffer;
809
810 switch (dwProperty)
811 {
812 case SPDRP_CAPABILITIES:
813 index = 0;
814 if (dwValue & CM_DEVCAP_LOCKSUPPORTED)
815 SetListViewText(hwndListView, index++, L"CM_DEVCAP_LOCKSUPPORTED");
816 if (dwValue & CM_DEVCAP_EJECTSUPPORTED)
817 SetListViewText(hwndListView, index++, L"CM_DEVCAP_EJECTSUPPORTED");
818 if (dwValue & CM_DEVCAP_REMOVABLE)
819 SetListViewText(hwndListView, index++, L"CM_DEVCAP_REMOVABLE");
820 if (dwValue & CM_DEVCAP_DOCKDEVICE)
821 SetListViewText(hwndListView, index++, L"CM_DEVCAP_DOCKDEVICE");
822 if (dwValue & CM_DEVCAP_UNIQUEID)
823 SetListViewText(hwndListView, index++, L"CM_DEVCAP_UNIQUEID");
824 if (dwValue & CM_DEVCAP_SILENTINSTALL)
825 SetListViewText(hwndListView, index++, L"CM_DEVCAP_SILENTINSTALL");
826 if (dwValue & CM_DEVCAP_RAWDEVICEOK)
827 SetListViewText(hwndListView, index++, L"CM_DEVCAP_RAWDEVICEOK");
828 if (dwValue & CM_DEVCAP_SURPRISEREMOVALOK)
829 SetListViewText(hwndListView, index++, L"CM_DEVCAP_SURPRISEREMOVALOK");
830 if (dwValue & CM_DEVCAP_HARDWAREDISABLED)
831 SetListViewText(hwndListView, index++, L"CM_DEVCAP_HARDWAREDISABLED");
832 if (dwValue & CM_DEVCAP_NONDYNAMIC)
833 SetListViewText(hwndListView, index++, L"CM_DEVCAP_NONDYNAMIC");
834 break;
835
836 case SPDRP_CONFIGFLAGS:
837 index = 0;
838 if (dwValue & CONFIGFLAG_DISABLED)
839 SetListViewText(hwndListView, index++, L"CONFIGFLAG_DISABLED");
840 if (dwValue & CONFIGFLAG_REMOVED)
841 SetListViewText(hwndListView, index++, L"CONFIGFLAG_REMOVED");
842 if (dwValue & CONFIGFLAG_MANUAL_INSTALL)
843 SetListViewText(hwndListView, index++, L"CONFIGFLAG_MANUAL_INSTALL");
844 if (dwValue & CONFIGFLAG_IGNORE_BOOT_LC)
845 SetListViewText(hwndListView, index++, L"CONFIGFLAG_IGNORE_BOOT_LC");
846 if (dwValue & CONFIGFLAG_NET_BOOT)
847 SetListViewText(hwndListView, index++, L"CONFIGFLAG_NET_BOOT");
848 if (dwValue & CONFIGFLAG_REINSTALL)
849 SetListViewText(hwndListView, index++, L"CONFIGFLAG_REINSTALL");
850 if (dwValue & CONFIGFLAG_FAILEDINSTALL)
851 SetListViewText(hwndListView, index++, L"CONFIGFLAG_FAILEDINSTALL");
852 if (dwValue & CONFIGFLAG_CANTSTOPACHILD)
853 SetListViewText(hwndListView, index++, L"CONFIGFLAG_CANTSTOPACHILD");
854 if (dwValue & CONFIGFLAG_OKREMOVEROM)
855 SetListViewText(hwndListView, index++, L"CONFIGFLAG_OKREMOVEROM");
856 if (dwValue & CONFIGFLAG_NOREMOVEEXIT)
857 SetListViewText(hwndListView, index++, L"CONFIGFLAG_NOREMOVEEXIT");
858 break;
859
860 default:
861 swprintf(dap->szTemp, L"0x%08lx", dwValue);
862 SetListViewText(hwndListView, 0, dap->szTemp);
863 break;
864 }
865 }
866 else
867 {
868 SetListViewText(hwndListView, 0, L"Error: Unsupported value type!");
869
870 }
871 }
872 else
873 {
874 SetListViewText(hwndListView, 0, L"Error: Retrieving the value failed!");
875 }
876
877 HeapFree(GetProcessHeap(),
878 0,
879 lpBuffer);
880 }
881
882 static VOID
883 DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,
884 IN HWND hwndListView)
885 {
886 DWORD dwStatus = 0;
887 DWORD dwProblem = 0;
888 INT index;
889
890 CM_Get_DevNode_Status_Ex(&dwStatus,
891 &dwProblem,
892 dap->DeviceInfoData.DevInst,
893 0,
894 dap->hMachine);
895
896 index = 0;
897 if (dwStatus & DN_ROOT_ENUMERATED)
898 SetListViewText(hwndListView, index++, L"DN_ROOT_ENUMERATED");
899 if (dwStatus & DN_DRIVER_LOADED)
900 SetListViewText(hwndListView, index++, L"DN_DRIVER_LOADED");
901 if (dwStatus & DN_ENUM_LOADED)
902 SetListViewText(hwndListView, index++, L"DN_ENUM_LOADED");
903 if (dwStatus & DN_STARTED)
904 SetListViewText(hwndListView, index++, L"DN_STARTED");
905 if (dwStatus & DN_MANUAL)
906 SetListViewText(hwndListView, index++, L"DN_MANUAL");
907 if (dwStatus & DN_NEED_TO_ENUM)
908 SetListViewText(hwndListView, index++, L"DN_NEED_TO_ENUM");
909 if (dwStatus & DN_DRIVER_BLOCKED)
910 SetListViewText(hwndListView, index++, L"DN_DRIVER_BLOCKED");
911 if (dwStatus & DN_HARDWARE_ENUM)
912 SetListViewText(hwndListView, index++, L"DN_HARDWARE_ENUM");
913 if (dwStatus & DN_NEED_RESTART)
914 SetListViewText(hwndListView, index++, L"DN_NEED_RESTART");
915 if (dwStatus & DN_CHILD_WITH_INVALID_ID)
916 SetListViewText(hwndListView, index++, L"DN_CHILD_WITH_INVALID_ID");
917 if (dwStatus & DN_HAS_PROBLEM)
918 SetListViewText(hwndListView, index++, L"DN_HAS_PROBLEM");
919 if (dwStatus & DN_FILTERED)
920 SetListViewText(hwndListView, index++, L"DN_FILTERED");
921 if (dwStatus & DN_LEGACY_DRIVER)
922 SetListViewText(hwndListView, index++, L"DN_LEGACY_DRIVER");
923 if (dwStatus & DN_DISABLEABLE)
924 SetListViewText(hwndListView, index++, L"DN_DISABLEABLE");
925 if (dwStatus & DN_REMOVABLE)
926 SetListViewText(hwndListView, index++, L"DN_REMOVABLE");
927 if (dwStatus & DN_PRIVATE_PROBLEM)
928 SetListViewText(hwndListView, index++, L"DN_PRIVATE_PROBLEM");
929 if (dwStatus & DN_MF_PARENT)
930 SetListViewText(hwndListView, index++, L"DN_MF_PARENT");
931 if (dwStatus & DN_MF_CHILD)
932 SetListViewText(hwndListView, index++, L"DN_MF_CHILD");
933 if (dwStatus & DN_WILL_BE_REMOVED)
934 SetListViewText(hwndListView, index++, L"DN_WILL_BE_REMOVED");
935
936 if (dwStatus & DN_NOT_FIRST_TIMEE)
937 SetListViewText(hwndListView, index++, L"DN_NOT_FIRST_TIMEE");
938 if (dwStatus & DN_STOP_FREE_RES)
939 SetListViewText(hwndListView, index++, L"DN_STOP_FREE_RES");
940 if (dwStatus & DN_REBAL_CANDIDATE)
941 SetListViewText(hwndListView, index++, L"DN_REBAL_CANDIDATE");
942 if (dwStatus & DN_BAD_PARTIAL)
943 SetListViewText(hwndListView, index++, L"DN_BAD_PARTIAL");
944 if (dwStatus & DN_NT_ENUMERATOR)
945 SetListViewText(hwndListView, index++, L"DN_NT_ENUMERATOR");
946 if (dwStatus & DN_NT_DRIVER)
947 SetListViewText(hwndListView, index++, L"DN_NT_DRIVER");
948
949 if (dwStatus & DN_NEEDS_LOCKING)
950 SetListViewText(hwndListView, index++, L"DN_NEEDS_LOCKING");
951 if (dwStatus & DN_ARM_WAKEUP)
952 SetListViewText(hwndListView, index++, L"DN_ARM_WAKEUP");
953 if (dwStatus & DN_APM_ENUMERATOR)
954 SetListViewText(hwndListView, index++, L"DN_APM_ENUMERATOR");
955 if (dwStatus & DN_APM_DRIVER)
956 SetListViewText(hwndListView, index++, L"DN_APM_DRIVER");
957 if (dwStatus & DN_SILENT_INSTALL)
958 SetListViewText(hwndListView, index++, L"DN_SILENT_INSTALL");
959 if (dwStatus & DN_NO_SHOW_IN_DM)
960 SetListViewText(hwndListView, index++, L"DN_NO_SHOW_IN_DM");
961 if (dwStatus & DN_BOOT_LOG_PROB)
962 SetListViewText(hwndListView, index++, L"DN_BOOT_LOG_PROB");
963
964 // swprintf(dap->szTemp, L"0x%08x", dwStatus);
965 // SetListViewText(hwndListView, 0, dap->szTemp);
966 }
967
968
969 static VOID
970 DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
971 IN HWND hwndListView)
972 {
973 PSP_DEVINFO_DATA DeviceInfoData;
974
975 DWORD dwType = 0;
976 WCHAR szBuffer[256];
977 DWORD dwSize = 256 * sizeof(WCHAR);
978
979 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
980 {
981 DeviceInfoData = &dap->CurrentDeviceInfoData;
982 }
983 else
984 {
985 DeviceInfoData = &dap->DeviceInfoData;
986 }
987
988 CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
989 CM_DRP_ENUMERATOR_NAME,
990 &dwType,
991 &szBuffer,
992 &dwSize,
993 0,
994 dap->hMachine);
995
996 SetListViewText(hwndListView, 0, szBuffer);
997 }
998
999
1000 static VOID
1001 DisplayCsFlags(IN PDEVADVPROP_INFO dap,
1002 IN HWND hwndListView)
1003 {
1004 DWORD dwValue = 0;
1005 INT index;
1006
1007 CM_Get_HW_Prof_Flags_Ex(dap->szDevName,
1008 0, /* current hardware profile */
1009 &dwValue,
1010 0,
1011 dap->hMachine);
1012
1013 index = 0;
1014 if (dwValue & CSCONFIGFLAG_DISABLED)
1015 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DISABLED");
1016
1017 if (dwValue & CSCONFIGFLAG_DO_NOT_CREATE)
1018 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_CREATE");
1019
1020 if (dwValue & CSCONFIGFLAG_DO_NOT_START)
1021 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_START");
1022 }
1023
1024
1025 static VOID
1026 DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
1027 IN HWND hwndListView)
1028 {
1029 HDEVINFO DeviceInfoSet;
1030 PSP_DEVINFO_DATA DeviceInfoData;
1031 WCHAR szBuffer[256];
1032 HKEY hKey;
1033 DWORD dwSize;
1034 DWORD dwType;
1035
1036 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1037 {
1038 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1039 DeviceInfoData = &dap->CurrentDeviceInfoData;
1040 }
1041 else
1042 {
1043 DeviceInfoSet = dap->DeviceInfoSet;
1044 DeviceInfoData = &dap->DeviceInfoData;
1045 }
1046
1047 hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1048 DeviceInfoData,
1049 DICS_FLAG_GLOBAL,
1050 0,
1051 DIREG_DRV,
1052 KEY_QUERY_VALUE);
1053 if (hKey != INVALID_HANDLE_VALUE)
1054 {
1055 dwSize = 256 * sizeof(WCHAR);
1056 if (RegQueryValueEx(hKey,
1057 L"MatchingDeviceId",
1058 NULL,
1059 &dwType,
1060 (LPBYTE)szBuffer,
1061 &dwSize) == ERROR_SUCCESS)
1062 {
1063 SetListViewText(hwndListView, 0, szBuffer);
1064 }
1065
1066 RegCloseKey(hKey);
1067 }
1068 }
1069
1070
1071 static VOID
1072 DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,
1073 IN HWND hwndListView)
1074 {
1075 HDEVINFO DeviceInfoSet;
1076 PSP_DEVINFO_DATA DeviceInfoData;
1077 WCHAR szClassGuid[45];
1078 HKEY hKey = INVALID_HANDLE_VALUE;
1079 DWORD dwSize;
1080 DWORD dwType;
1081 LPBYTE lpBuffer = NULL;
1082 LPWSTR lpStr;
1083 INT index;
1084 INT len;
1085 LONG lError;
1086
1087 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1088 {
1089 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1090 DeviceInfoData = &dap->CurrentDeviceInfoData;
1091 }
1092 else
1093 {
1094 DeviceInfoSet = dap->DeviceInfoSet;
1095 DeviceInfoData = &dap->DeviceInfoData;
1096 }
1097
1098 dwSize = 45 * sizeof(WCHAR);
1099 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1100 DeviceInfoData,
1101 SPDRP_CLASSGUID,
1102 &dwType,
1103 (LPBYTE)szClassGuid,
1104 dwSize,
1105 &dwSize))
1106 return;
1107
1108 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1109 L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
1110 0,
1111 GENERIC_READ,
1112 &hKey);
1113 if (lError != ERROR_SUCCESS)
1114 return;
1115
1116 dwSize = 0;
1117 lError = RegQueryValueEx(hKey,
1118 szClassGuid,
1119 NULL,
1120 &dwType,
1121 NULL,
1122 &dwSize);
1123 if (lError != ERROR_SUCCESS)
1124 goto done;
1125
1126 if (dwSize == 0)
1127 goto done;
1128
1129 lpBuffer = HeapAlloc(GetProcessHeap(),
1130 HEAP_ZERO_MEMORY,
1131 dwSize);
1132
1133 RegQueryValueEx(hKey,
1134 szClassGuid,
1135 NULL,
1136 &dwType,
1137 lpBuffer,
1138 &dwSize);
1139
1140 lpStr = (LPWSTR)lpBuffer;
1141 index = 0;
1142 while (*lpStr != 0)
1143 {
1144 len = wcslen(lpStr) + 1;
1145
1146 SetListViewText(hwndListView, index, lpStr);
1147
1148 lpStr += len;
1149 index++;
1150 }
1151
1152 done:
1153 if (lpBuffer != NULL)
1154 HeapFree(GetProcessHeap(), 0, lpBuffer);
1155
1156 if (hKey != INVALID_HANDLE_VALUE)
1157 RegCloseKey(hKey);
1158 }
1159
1160
1161 static VOID
1162 DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
1163 IN HWND hwndListView)
1164 {
1165 HDEVINFO DeviceInfoSet;
1166 PSP_DEVINFO_DATA DeviceInfoData;
1167 HKEY hKey;
1168 DWORD dwSize;
1169 DWORD dwType;
1170 LPBYTE lpBuffer;
1171 LPWSTR lpStr;
1172 INT index;
1173 INT len;
1174
1175 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1176 {
1177 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1178 DeviceInfoData = &dap->CurrentDeviceInfoData;
1179 }
1180 else
1181 {
1182 DeviceInfoSet = dap->DeviceInfoSet;
1183 DeviceInfoData = &dap->DeviceInfoData;
1184 }
1185
1186 hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1187 DeviceInfoData,
1188 DICS_FLAG_GLOBAL,
1189 0,
1190 DIREG_DRV,
1191 KEY_QUERY_VALUE);
1192 if (hKey != INVALID_HANDLE_VALUE)
1193 {
1194 dwSize = 0;
1195 if (RegQueryValueEx(hKey,
1196 L"CoInstallers32",
1197 NULL,
1198 &dwType,
1199 NULL,
1200 &dwSize) == ERROR_SUCCESS &&
1201 dwSize > 0)
1202 {
1203
1204 lpBuffer = HeapAlloc(GetProcessHeap(),
1205 HEAP_ZERO_MEMORY,
1206 dwSize);
1207
1208 RegQueryValueEx(hKey,
1209 L"CoInstallers32",
1210 NULL,
1211 &dwType,
1212 lpBuffer,
1213 &dwSize);
1214
1215 lpStr = (LPWSTR)lpBuffer;
1216 index = 0;
1217 while (*lpStr != 0)
1218 {
1219 len = wcslen(lpStr) + 1;
1220
1221 SetListViewText(hwndListView, index, lpStr);
1222
1223 lpStr += len;
1224 index++;
1225 }
1226
1227 HeapFree(GetProcessHeap(),
1228 0,
1229 lpBuffer);
1230 }
1231
1232 RegCloseKey(hKey);
1233 }
1234 }
1235
1236
1237 static VOID
1238 DisplayClassProperties(IN PDEVADVPROP_INFO dap,
1239 IN HWND hwndListView,
1240 IN LPWSTR lpProperty)
1241 {
1242 HDEVINFO DeviceInfoSet;
1243 PSP_DEVINFO_DATA DeviceInfoData;
1244 WCHAR szClassGuid[45];
1245 DWORD dwSize;
1246 DWORD dwType;
1247 HKEY hKey;
1248 GUID ClassGuid;
1249 LPBYTE lpBuffer;
1250 LPWSTR lpStr;
1251 INT index = 0;
1252 INT len;
1253
1254 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1255 {
1256 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1257 DeviceInfoData = &dap->CurrentDeviceInfoData;
1258 }
1259 else
1260 {
1261 DeviceInfoSet = dap->DeviceInfoSet;
1262 DeviceInfoData = &dap->DeviceInfoData;
1263 }
1264
1265 dwSize = 45 * sizeof(WCHAR);
1266 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1267 DeviceInfoData,
1268 SPDRP_CLASSGUID,
1269 &dwType,
1270 (LPBYTE)szClassGuid,
1271 dwSize,
1272 &dwSize))
1273 return;
1274
1275 pSetupGuidFromString(szClassGuid,
1276 &ClassGuid);
1277
1278 hKey = SetupDiOpenClassRegKey(&ClassGuid,
1279 KEY_QUERY_VALUE);
1280 if (hKey != INVALID_HANDLE_VALUE)
1281 {
1282 dwSize = 0;
1283 if (RegQueryValueEx(hKey,
1284 lpProperty,
1285 NULL,
1286 &dwType,
1287 NULL,
1288 &dwSize) == ERROR_SUCCESS &&
1289 dwSize > 0)
1290 {
1291 lpBuffer = HeapAlloc(GetProcessHeap(),
1292 HEAP_ZERO_MEMORY,
1293 dwSize);
1294
1295 RegQueryValueEx(hKey,
1296 lpProperty,
1297 NULL,
1298 &dwType,
1299 lpBuffer,
1300 &dwSize);
1301
1302 if (dwType == REG_SZ)
1303 {
1304 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
1305 }
1306 else if (dwType == REG_MULTI_SZ)
1307 {
1308 lpStr = (LPWSTR)lpBuffer;
1309 index = 0;
1310 while (*lpStr != 0)
1311 {
1312 len = wcslen(lpStr) + 1;
1313
1314 SetListViewText(hwndListView, index, lpStr);
1315
1316 lpStr += len;
1317 index++;
1318 }
1319 }
1320
1321 HeapFree(GetProcessHeap(),
1322 0,
1323 lpBuffer);
1324 }
1325
1326 RegCloseKey(hKey);
1327 }
1328 }
1329
1330
1331 static VOID
1332 DisplayDeviceRelations(
1333 IN PDEVADVPROP_INFO dap,
1334 IN HWND hwndListView,
1335 IN ULONG ulFlags)
1336 {
1337 ULONG ulLength = 0;
1338 LPWSTR pszBuffer = NULL, pszStr;
1339 INT index = 0, len;
1340
1341 CONFIGRET ret;
1342
1343 ret = CM_Get_Device_ID_List_Size_ExW(&ulLength,
1344 dap->szDeviceID,
1345 ulFlags,
1346 NULL);
1347 if (ret != CR_SUCCESS)
1348 return;
1349
1350 pszBuffer = HeapAlloc(GetProcessHeap(),
1351 HEAP_ZERO_MEMORY,
1352 ulLength);
1353 if (pszBuffer == NULL)
1354 return;
1355
1356 ret = CM_Get_Device_ID_List_ExW(dap->szDeviceID,
1357 pszBuffer,
1358 ulLength,
1359 ulFlags,
1360 NULL);
1361 if (ret != CR_SUCCESS)
1362 {
1363 HeapFree(GetProcessHeap(), 0, pszBuffer);
1364 return;
1365 }
1366
1367 pszStr = pszBuffer;
1368 index = 0;
1369 while (*pszStr != 0)
1370 {
1371 len = wcslen(pszStr) + 1;
1372
1373 SetListViewText(hwndListView, index, pszStr);
1374
1375 pszStr += len;
1376 index++;
1377 }
1378
1379 HeapFree(GetProcessHeap(), 0, pszBuffer);
1380 }
1381
1382
1383 static VOID
1384 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
1385 IN HWND hwndComboBox,
1386 IN HWND hwndListView)
1387 {
1388 INT Index;
1389
1390 Index = (INT)SendMessage(hwndComboBox,
1391 CB_GETCURSEL,
1392 0,
1393 0);
1394 if (Index == CB_ERR)
1395 return;
1396
1397 (void)ListView_DeleteAllItems(hwndListView);
1398
1399 switch (Index)
1400 {
1401 case 0:
1402 SetListViewText(hwndListView, 0, dap->szDeviceID);
1403 break;
1404
1405 case 1: /* Hardware ID */
1406 DisplayDevicePropertyText(dap,
1407 hwndListView,
1408 SPDRP_HARDWAREID);
1409 break;
1410
1411 case 2: /* Compatible IDs */
1412 DisplayDevicePropertyText(dap,
1413 hwndListView,
1414 SPDRP_COMPATIBLEIDS);
1415 break;
1416
1417 case 3: /* Matching ID */
1418 DisplayMatchingDeviceId(dap,
1419 hwndListView);
1420 break;
1421
1422 case 4: /* Service */
1423 DisplayDevicePropertyText(dap,
1424 hwndListView,
1425 SPDRP_SERVICE);
1426 break;
1427
1428 case 5: /* Enumerator */
1429 DisplayDevNodeEnumerator(dap,
1430 hwndListView);
1431 break;
1432
1433 case 6: /* Capabilities */
1434 DisplayDevicePropertyText(dap,
1435 hwndListView,
1436 SPDRP_CAPABILITIES);
1437 break;
1438
1439 case 7: /* Devnode Flags */
1440 DisplayDevNodeFlags(dap,
1441 hwndListView);
1442 break;
1443
1444 case 8: /* Config Flags */
1445 DisplayDevicePropertyText(dap,
1446 hwndListView,
1447 SPDRP_CONFIGFLAGS);
1448 break;
1449
1450 case 9: /* CSConfig Flags */
1451 DisplayCsFlags(dap,
1452 hwndListView);
1453 break;
1454
1455 case 10: /* Ejection relation */
1456 DisplayDeviceRelations(dap,
1457 hwndListView,
1458 CM_GETIDLIST_FILTER_EJECTRELATIONS);
1459 break;
1460
1461 case 11: /* Removal relations */
1462 DisplayDeviceRelations(dap,
1463 hwndListView,
1464 CM_GETIDLIST_FILTER_REMOVALRELATIONS);
1465 break;
1466
1467 case 12: /* Bus relation */
1468 DisplayDeviceRelations(dap,
1469 hwndListView,
1470 CM_GETIDLIST_FILTER_BUSRELATIONS);
1471 break;
1472
1473 case 13: /* Device Upper Filters */
1474 DisplayDevicePropertyText(dap,
1475 hwndListView,
1476 SPDRP_UPPERFILTERS);
1477 break;
1478
1479 case 14: /* Device Lower Filters */
1480 DisplayDevicePropertyText(dap,
1481 hwndListView,
1482 SPDRP_LOWERFILTERS);
1483 break;
1484
1485 case 15: /* Class Upper Filters */
1486 DisplayClassProperties(dap,
1487 hwndListView,
1488 L"UpperFilters");
1489 break;
1490
1491 case 16: /* Class Lower Filters */
1492 DisplayClassProperties(dap,
1493 hwndListView,
1494 L"LowerFilters");
1495 break;
1496
1497 case 17: /* Class Installer */
1498 DisplayClassProperties(dap,
1499 hwndListView,
1500 L"Installer32");
1501 break;
1502
1503 case 18: /* Class Coinstaller */
1504 DisplayClassCoinstallers(dap,
1505 hwndListView);
1506 break;
1507
1508 case 19: /* Device Coinstaller */
1509 DisplayDeviceCoinstallers(dap,
1510 hwndListView);
1511 break;
1512
1513 #if 0
1514 case 20: /* Firmware Revision */
1515 break;
1516
1517 case 21: /* Current Power State */
1518 break;
1519
1520 case 20: /* Power Capabilities */
1521 break;
1522
1523 case 21: /* Power State Mappings */
1524 break;
1525 #endif
1526
1527 default:
1528 SetListViewText(hwndListView, 0, L"<Not implemented yet>");
1529 break;
1530 }
1531 }
1532
1533
1534 static INT_PTR
1535 CALLBACK
1536 AdvProcDetailsDlgProc(IN HWND hwndDlg,
1537 IN UINT uMsg,
1538 IN WPARAM wParam,
1539 IN LPARAM lParam)
1540 {
1541 PDEVADVPROP_INFO dap;
1542 INT_PTR Ret = FALSE;
1543
1544 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1545 DWL_USER);
1546
1547 if (dap != NULL || uMsg == WM_INITDIALOG)
1548 {
1549 switch (uMsg)
1550 {
1551 case WM_COMMAND:
1552 {
1553 switch (LOWORD(wParam))
1554 {
1555 case IDC_DETAILSPROPNAME:
1556 if (HIWORD(wParam) == CBN_SELCHANGE)
1557 {
1558 DisplayDeviceProperties(dap,
1559 GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
1560 GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
1561 }
1562 break;
1563 }
1564 break;
1565 }
1566
1567 case WM_NOTIFY:
1568 {
1569 NMHDR *hdr = (NMHDR*)lParam;
1570 switch (hdr->code)
1571 {
1572 case PSN_APPLY:
1573 break;
1574 }
1575 break;
1576 }
1577
1578 case WM_INITDIALOG:
1579 {
1580 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1581 if (dap != NULL)
1582 {
1583 SetWindowLongPtr(hwndDlg,
1584 DWL_USER,
1585 (DWORD_PTR)dap);
1586
1587 UpdateDetailsDlg(hwndDlg,
1588 dap);
1589 }
1590 Ret = TRUE;
1591 break;
1592 }
1593 }
1594 }
1595
1596 return Ret;
1597 }
1598
1599
1600 static VOID
1601 InitDevUsageActions(IN HWND hwndDlg,
1602 IN HWND hComboBox,
1603 IN PDEVADVPROP_INFO dap)
1604 {
1605 INT Index;
1606 UINT i;
1607 UINT Actions[] =
1608 {
1609 IDS_ENABLEDEVICE,
1610 IDS_DISABLEDEVICE,
1611 };
1612
1613 for (i = 0;
1614 i != sizeof(Actions) / sizeof(Actions[0]);
1615 i++)
1616 {
1617 /* fill in the device usage combo box */
1618 if (LoadString(hDllInstance,
1619 Actions[i],
1620 dap->szTemp,
1621 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1622 {
1623 Index = (INT)SendMessage(hComboBox,
1624 CB_ADDSTRING,
1625 0,
1626 (LPARAM)dap->szTemp);
1627 if (Index != CB_ERR)
1628 {
1629 SendMessage(hComboBox,
1630 CB_SETITEMDATA,
1631 (WPARAM)Index,
1632 (LPARAM)Actions[i]);
1633
1634 switch (Actions[i])
1635 {
1636 case IDS_ENABLEDEVICE:
1637 if (dap->DeviceStarted)
1638 {
1639 SendMessage(hComboBox,
1640 CB_SETCURSEL,
1641 (WPARAM)Index,
1642 0);
1643 }
1644 break;
1645
1646 case IDS_DISABLEDEVICE:
1647 if (!dap->DeviceStarted)
1648 {
1649 SendMessage(hComboBox,
1650 CB_SETCURSEL,
1651 (WPARAM)Index,
1652 0);
1653 }
1654 break;
1655
1656 default:
1657 break;
1658 }
1659 }
1660 }
1661 }
1662 }
1663
1664
1665 static UINT
1666 GetSelectedUsageAction(IN HWND hComboBox)
1667 {
1668 INT Index;
1669 UINT Ret = 0;
1670
1671 Index = (INT)SendMessage(hComboBox,
1672 CB_GETCURSEL,
1673 0,
1674 0);
1675 if (Index != CB_ERR)
1676 {
1677 INT iRet = (INT) SendMessage(hComboBox,
1678 CB_GETITEMDATA,
1679 (WPARAM)Index,
1680 0);
1681 if (iRet != CB_ERR)
1682 {
1683 Ret = (UINT)iRet;
1684 }
1685 }
1686
1687 return Ret;
1688 }
1689
1690
1691 static BOOL
1692 ApplyGeneralSettings(IN HWND hwndDlg,
1693 IN PDEVADVPROP_INFO dap)
1694 {
1695 BOOL Ret = FALSE;
1696
1697 if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
1698 {
1699 UINT SelectedUsageAction;
1700 BOOL NeedReboot = FALSE;
1701
1702 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
1703 IDC_DEVUSAGE));
1704 switch (SelectedUsageAction)
1705 {
1706 case IDS_ENABLEDEVICE:
1707 if (!dap->DeviceStarted)
1708 {
1709 Ret = EnableDevice(dap->DeviceInfoSet,
1710 &dap->DeviceInfoData,
1711 TRUE,
1712 0,
1713 &NeedReboot);
1714 }
1715 break;
1716
1717 case IDS_DISABLEDEVICE:
1718 if (dap->DeviceStarted)
1719 {
1720 Ret = EnableDevice(dap->DeviceInfoSet,
1721 &dap->DeviceInfoData,
1722 FALSE,
1723 0,
1724 &NeedReboot);
1725 }
1726 break;
1727
1728 default:
1729 break;
1730 }
1731
1732 if (Ret)
1733 {
1734 if (NeedReboot)
1735 {
1736 /* make PropertySheet() return PSM_REBOOTSYSTEM */
1737 PropSheet_RebootSystem(hwndDlg);
1738 }
1739 }
1740 else
1741 {
1742 /* FIXME - display an error message */
1743 FIXME("Failed to enable/disable device! LastError: %d\n",
1744 GetLastError());
1745 }
1746 }
1747 else
1748 Ret = !dap->DeviceUsageChanged;
1749
1750 /* disable the apply button */
1751 PropSheet_UnChanged(GetParent(hwndDlg),
1752 hwndDlg);
1753 dap->DeviceUsageChanged = FALSE;
1754 return Ret;
1755 }
1756
1757
1758 static VOID
1759 UpdateDevInfo(IN HWND hwndDlg,
1760 IN PDEVADVPROP_INFO dap,
1761 IN BOOL ReOpen)
1762 {
1763 HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
1764 CONFIGRET cr;
1765 ULONG Status, ProblemNumber;
1766 SP_DEVINSTALL_PARAMS_W InstallParams;
1767 UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
1768 BOOL bFlag, bDevActionAvailable = TRUE;
1769 BOOL bDrvInstalled = FALSE;
1770 DWORD iPage;
1771 HDEVINFO DeviceInfoSet = NULL;
1772 PSP_DEVINFO_DATA DeviceInfoData = NULL;
1773 PROPSHEETHEADER psh;
1774 DWORD nDriverPages = 0;
1775 BOOL RecalcPages = FALSE;
1776
1777 TRACE("UpdateDevInfo()\n");
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 TRACE("Count %d additional pages!\n", nDriverPages);
2175 dap->nDevPropSheets += nDriverPages;
2176 }
2177 else
2178 {
2179 nDriverPages = 0;
2180 }
2181
2182 /* include the driver page */
2183 if (dap->HasDriverPage)
2184 dap->nDevPropSheets++;
2185
2186 /* include the details page */
2187 if (dap->Extended)
2188 dap->nDevPropSheets++;
2189
2190 if (dap->HasResourcePage)
2191 dap->nDevPropSheets++;
2192
2193 /* add the device property sheets */
2194 if (dap->nDevPropSheets != 0)
2195 {
2196 TRACE("Show %d pages!\n", dap->nDevPropSheets);
2197 dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
2198 HEAP_ZERO_MEMORY,
2199 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
2200 if (dap->DevPropSheets != NULL)
2201 {
2202 if (nDriverPages != 0)
2203 {
2204 psh.phpage = dap->DevPropSheets;
2205
2206 /* query the device property sheet pages to add */
2207 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2208 DeviceInfoData,
2209 &psh,
2210 dap->nDevPropSheets,
2211 NULL,
2212 dap->PropertySheetType))
2213 {
2214 /* add the property sheets */
2215 for (iPage = 0;
2216 iPage < nDriverPages;
2217 iPage++)
2218 {
2219 TRACE("Add page %d\n", iPage);
2220 TRACE("Sheet %p\n", dap->DevPropSheets[iPage]);
2221
2222 if (PropSheet_AddPage(hPropSheetDlg,
2223 dap->DevPropSheets[iPage]))
2224 {
2225 RecalcPages = TRUE;
2226 }
2227 else
2228 {
2229 TRACE("PropSheet_AddPage() failed\n");
2230 }
2231 }
2232
2233 dap->FreeDevPropSheets = TRUE;
2234 }
2235 else
2236 {
2237 TRACE("SetupDiGetClassDevPropertySheets() failed\n");
2238 /* cleanup, we were unable to get the device property sheets */
2239 iPage = nDriverPages;
2240 dap->nDevPropSheets -= nDriverPages;
2241 nDriverPages = 0;
2242 }
2243 }
2244 else
2245 iPage = 0;
2246
2247 /* add the driver page if necessary */
2248 if (dap->HasDriverPage)
2249 {
2250 PROPSHEETPAGE pspDriver = {0};
2251 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2252 pspDriver.dwFlags = PSP_DEFAULT;
2253 pspDriver.hInstance = hDllInstance;
2254 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
2255 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
2256 pspDriver.lParam = (LPARAM)dap;
2257 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2258 if (dap->DevPropSheets[iPage] != NULL)
2259 {
2260 if (PropSheet_AddPage(hPropSheetDlg,
2261 dap->DevPropSheets[iPage]))
2262 {
2263 iPage++;
2264 RecalcPages = TRUE;
2265 }
2266 else
2267 {
2268 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2269 dap->DevPropSheets[iPage] = NULL;
2270 }
2271 }
2272 }
2273
2274 if (dap->Extended)
2275 {
2276 /* Add the details page */
2277 PROPSHEETPAGE pspDetails = {0};
2278 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
2279 pspDetails.dwFlags = PSP_DEFAULT;
2280 pspDetails.hInstance = hDllInstance;
2281 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
2282 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
2283 pspDetails.lParam = (LPARAM)dap;
2284 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
2285 if (dap->DevPropSheets[iPage] != NULL)
2286 {
2287 if (PropSheet_AddPage(hPropSheetDlg,
2288 dap->DevPropSheets[iPage]))
2289 {
2290 iPage++;
2291 RecalcPages = TRUE;
2292 }
2293 else
2294 {
2295 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2296 dap->DevPropSheets[iPage] = NULL;
2297 }
2298 }
2299 }
2300
2301 if (dap->HasResourcePage)
2302 {
2303 PROPSHEETPAGE pspDriver = {0};
2304 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2305 pspDriver.dwFlags = PSP_DEFAULT;
2306 pspDriver.hInstance = hDllInstance;
2307 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
2308 pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
2309 pspDriver.lParam = (LPARAM)dap;
2310 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2311 if (dap->DevPropSheets[iPage] != NULL)
2312 {
2313 if (PropSheet_AddPage(hPropSheetDlg,
2314 dap->DevPropSheets[iPage]))
2315 {
2316 iPage++;
2317 RecalcPages = TRUE;
2318 }
2319 else
2320 {
2321 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2322 dap->DevPropSheets[iPage] = NULL;
2323 }
2324 }
2325 }
2326 /* FIXME: Add the power page */
2327 }
2328 else
2329 dap->nDevPropSheets = 0;
2330 }
2331
2332 if (RecalcPages)
2333 {
2334 PropSheet_RecalcPageSizes(hPropSheetDlg);
2335 }
2336
2337 /* finally, disable the apply button */
2338 PropSheet_UnChanged(hPropSheetDlg,
2339 hwndDlg);
2340 dap->DeviceUsageChanged = FALSE;
2341 }
2342
2343
2344 static LRESULT
2345 CALLBACK
2346 DlgParentSubWndProc(IN HWND hwnd,
2347 IN UINT uMsg,
2348 IN WPARAM wParam,
2349 IN LPARAM lParam)
2350 {
2351 PDEVADVPROP_INFO dap;
2352
2353 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
2354 L"DevMgrDevChangeSub");
2355 if (dap != NULL)
2356 {
2357 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
2358 {
2359 SendMessage(dap->hWndGeneralPage,
2360 WM_DEVICECHANGE,
2361 wParam,
2362 lParam);
2363 }
2364
2365 /* pass the message the the old window proc */
2366 return CallWindowProc(dap->ParentOldWndProc,
2367 hwnd,
2368 uMsg,
2369 wParam,
2370 lParam);
2371 }
2372 else
2373 {
2374 /* this is not a good idea if the subclassed window was an ansi
2375 window, but we failed finding out the previous window proc
2376 so we can't use CallWindowProc. This should rarely - if ever -
2377 happen. */
2378
2379 return DefWindowProc(hwnd,
2380 uMsg,
2381 wParam,
2382 lParam);
2383 }
2384 }
2385
2386
2387 static INT_PTR
2388 CALLBACK
2389 AdvPropGeneralDlgProc(IN HWND hwndDlg,
2390 IN UINT uMsg,
2391 IN WPARAM wParam,
2392 IN LPARAM lParam)
2393 {
2394 PDEVADVPROP_INFO dap;
2395 INT_PTR Ret = FALSE;
2396
2397 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
2398 DWL_USER);
2399
2400 if (dap != NULL || uMsg == WM_INITDIALOG)
2401 {
2402 switch (uMsg)
2403 {
2404 case WM_COMMAND:
2405 {
2406 switch (LOWORD(wParam))
2407 {
2408 case IDC_DEVUSAGE:
2409 {
2410 if (HIWORD(wParam) == CBN_SELCHANGE)
2411 {
2412 PropSheet_Changed(GetParent(hwndDlg),
2413 hwndDlg);
2414 dap->DeviceUsageChanged = TRUE;
2415 }
2416 break;
2417 }
2418
2419 case IDC_DEVPROBLEM:
2420 {
2421 if (dap->IsAdmin)
2422 {
2423 /* display the device problem wizard */
2424 ShowDeviceProblemWizard(hwndDlg,
2425 dap->DeviceInfoSet,
2426 &dap->DeviceInfoData,
2427 dap->hMachine);
2428 }
2429 break;
2430 }
2431 }
2432 break;
2433 }
2434
2435 case WM_NOTIFY:
2436 {
2437 NMHDR *hdr = (NMHDR*)lParam;
2438 switch (hdr->code)
2439 {
2440 case PSN_APPLY:
2441 ApplyGeneralSettings(hwndDlg,
2442 dap);
2443 break;
2444 }
2445 break;
2446 }
2447
2448 case WM_INITDIALOG:
2449 {
2450 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2451 if (dap != NULL)
2452 {
2453 HWND hWndParent;
2454
2455 dap->hWndGeneralPage = hwndDlg;
2456
2457 SetWindowLongPtr(hwndDlg,
2458 DWL_USER,
2459 (DWORD_PTR)dap);
2460
2461 /* subclass the parent window to always receive
2462 WM_DEVICECHANGE messages */
2463 hWndParent = GetParent(hwndDlg);
2464 if (hWndParent != NULL)
2465 {
2466 /* subclass the parent window. This is not safe
2467 if the parent window belongs to another thread! */
2468 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
2469 GWLP_WNDPROC,
2470 (LONG_PTR)DlgParentSubWndProc);
2471
2472 if (dap->ParentOldWndProc != NULL &&
2473 SetProp(hWndParent,
2474 L"DevMgrDevChangeSub",
2475 (HANDLE)dap))
2476 {
2477 dap->hWndParent = hWndParent;
2478 }
2479 }
2480
2481 /* do not call UpdateDevInfo directly in here because it modifies
2482 the pages of the property sheet! */
2483 PostMessage(hwndDlg,
2484 PM_INITIALIZE,
2485 0,
2486 0);
2487 }
2488 Ret = TRUE;
2489 break;
2490 }
2491
2492 case WM_DEVICECHANGE:
2493 {
2494 /* FIXME - don't call UpdateDevInfo for all events */
2495 UpdateDevInfo(hwndDlg,
2496 dap,
2497 TRUE);
2498 Ret = TRUE;
2499 break;
2500 }
2501
2502 case PM_INITIALIZE:
2503 {
2504 UpdateDevInfo(hwndDlg,
2505 dap,
2506 FALSE);
2507 dap->PageInitialized = TRUE;
2508 break;
2509 }
2510
2511 case WM_DESTROY:
2512 {
2513 /* restore the old window proc of the subclassed parent window */
2514 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
2515 {
2516 if (SetWindowLongPtr(dap->hWndParent,
2517 GWLP_WNDPROC,
2518 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
2519 {
2520 RemoveProp(dap->hWndParent,
2521 L"DevMgrDevChangeSub");
2522 }
2523 }
2524 break;
2525 }
2526 }
2527 }
2528
2529 return Ret;
2530 }
2531
2532
2533 INT_PTR
2534 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
2535 IN LPCWSTR lpDeviceID OPTIONAL,
2536 IN HDEVINFO DeviceInfoSet,
2537 IN PSP_DEVINFO_DATA DeviceInfoData,
2538 IN HINSTANCE hComCtl32,
2539 IN LPCWSTR lpMachineName,
2540 IN DWORD dwFlags)
2541 {
2542 PROPSHEETHEADER psh = {0};
2543 PROPSHEETPAGE pspGeneral = {0};
2544 PPROPERTYSHEETW pPropertySheetW;
2545 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
2546 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
2547 PDEVADVPROP_INFO DevAdvPropInfo;
2548 HMACHINE hMachine = NULL;
2549 DWORD DevIdSize = 0;
2550 INT_PTR Ret = -1;
2551
2552 /* we don't want to statically link against comctl32, so find the
2553 functions we need dynamically */
2554 pPropertySheetW =
2555 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
2556 "PropertySheetW");
2557 pCreatePropertySheetPageW =
2558 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
2559 "CreatePropertySheetPageW");
2560 pDestroyPropertySheetPage =
2561 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
2562 "DestroyPropertySheetPage");
2563 if (pPropertySheetW == NULL ||
2564 pCreatePropertySheetPageW == NULL ||
2565 pDestroyPropertySheetPage == NULL)
2566 {
2567 return -1;
2568 }
2569
2570 if (lpDeviceID == NULL)
2571 {
2572 /* find out how much size is needed for the device id */
2573 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
2574 DeviceInfoData,
2575 NULL,
2576 0,
2577 &DevIdSize))
2578 {
2579 ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
2580 return -1;
2581 }
2582
2583 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2584 {
2585 return -1;
2586 }
2587 }
2588 else
2589 {
2590 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
2591 }
2592
2593 if (lpMachineName != NULL && lpMachineName[0] != L'\0')
2594 {
2595 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
2596 &hMachine);
2597 if (cr != CR_SUCCESS)
2598 {
2599 return -1;
2600 }
2601 }
2602
2603 /* create the internal structure associated with the "General",
2604 "Driver", ... pages */
2605 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
2606 HEAP_ZERO_MEMORY,
2607 FIELD_OFFSET(DEVADVPROP_INFO,
2608 szDeviceID) +
2609 (DevIdSize * sizeof(WCHAR)));
2610 if (DevAdvPropInfo == NULL)
2611 {
2612 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2613 goto Cleanup;
2614 }
2615
2616 if (lpDeviceID == NULL)
2617 {
2618 /* read the device instance id */
2619 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
2620 DeviceInfoData,
2621 DevAdvPropInfo->szDeviceID,
2622 DevIdSize,
2623 NULL))
2624 {
2625 goto Cleanup;
2626 }
2627 }
2628 else
2629 {
2630 /* copy the device instance id supplied by the caller */
2631 wcscpy(DevAdvPropInfo->szDeviceID,
2632 lpDeviceID);
2633 }
2634
2635 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
2636 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
2637 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2638 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2639
2640 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
2641 DevAdvPropInfo->hMachine = hMachine;
2642 DevAdvPropInfo->lpMachineName = lpMachineName;
2643 DevAdvPropInfo->szDevName[0] = L'\0';
2644 DevAdvPropInfo->hComCtl32 = hComCtl32;
2645 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
2646 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
2647
2648 DevAdvPropInfo->IsAdmin = IsUserAdmin();
2649 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
2650 DevAdvPropInfo->Extended = ((dwFlags & DPF_EXTENDED) != 0);
2651
2652 psh.dwSize = sizeof(PROPSHEETHEADER);
2653 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2654 psh.hwndParent = hWndParent;
2655 psh.pszCaption = DevAdvPropInfo->szDevName;
2656
2657 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2658 DIGCDP_FLAG_REMOTE_ADVANCED :
2659 DIGCDP_FLAG_ADVANCED;
2660
2661 psh.phpage = HeapAlloc(GetProcessHeap(),
2662 HEAP_ZERO_MEMORY,
2663 1 * sizeof(HPROPSHEETPAGE));
2664 if (psh.phpage == NULL)
2665 {
2666 goto Cleanup;
2667 }
2668
2669 /* add the "General" property sheet */
2670 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2671 pspGeneral.dwFlags = PSP_DEFAULT;
2672 pspGeneral.hInstance = hDllInstance;
2673 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2674 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2675 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2676 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2677 if (psh.phpage[psh.nPages] != NULL)
2678 {
2679 psh.nPages++;
2680 }
2681
2682 DevAdvPropInfo->nDevPropSheets = psh.nPages;
2683
2684 if (psh.nPages != 0)
2685 {
2686 Ret = pPropertySheetW(&psh);
2687
2688 /* NOTE: no need to destroy the property sheets anymore! */
2689 }
2690 else
2691 {
2692 UINT i;
2693
2694 Cleanup:
2695 /* in case of failure the property sheets must be destroyed */
2696 if (psh.phpage != NULL)
2697 {
2698 for (i = 0;
2699 i < psh.nPages;
2700 i++)
2701 {
2702 if (psh.phpage[i] != NULL)
2703 {
2704 pDestroyPropertySheetPage(psh.phpage[i]);
2705 }
2706 }
2707 }
2708 }
2709
2710 if (DevAdvPropInfo != NULL)
2711 {
2712 if (DevAdvPropInfo->FreeDevPropSheets)
2713 {
2714 /* don't free the array if it's the one allocated in
2715 DisplayDeviceAdvancedProperties */
2716 HeapFree(GetProcessHeap(),
2717 0,
2718 DevAdvPropInfo->DevPropSheets);
2719 }
2720
2721 if (DevAdvPropInfo->CloseDevInst)
2722 {
2723 /* close the device info set in case a new one was created */
2724 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2725 }
2726
2727 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2728 {
2729 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2730 }
2731
2732 if (DevAdvPropInfo->hDevIcon != NULL)
2733 {
2734 DestroyIcon(DevAdvPropInfo->hDevIcon);
2735 }
2736
2737 HeapFree(GetProcessHeap(),
2738 0,
2739 DevAdvPropInfo);
2740 }
2741
2742 if (psh.phpage != NULL)
2743 {
2744 HeapFree(GetProcessHeap(),
2745 0,
2746 psh.phpage);
2747 }
2748
2749 if (hMachine != NULL)
2750 {
2751 CM_Disconnect_Machine(hMachine);
2752 }
2753
2754 return Ret;
2755 }
2756
2757
2758 static BOOL
2759 GetDeviceAndComputerName(LPWSTR lpString,
2760 WCHAR szDeviceID[],
2761 WCHAR szMachineName[])
2762 {
2763 BOOL ret = FALSE;
2764
2765 szDeviceID[0] = L'\0';
2766 szMachineName[0] = L'\0';
2767
2768 while (*lpString != L'\0')
2769 {
2770 if (*lpString == L'/')
2771 {
2772 lpString++;
2773 if(!_wcsnicmp(lpString, L"DeviceID", 8))
2774 {
2775 lpString += 9;
2776 if (*lpString != L'\0')
2777 {
2778 int i = 0;
2779 while ((*lpString != L' ') &&
2780 (*lpString != L'\0') &&
2781 (i <= MAX_DEVICE_ID_LEN))
2782 {
2783 szDeviceID[i++] = *lpString++;
2784 }
2785 szDeviceID[i] = L'\0';
2786 ret = TRUE;
2787 }
2788 }
2789 else if (!_wcsnicmp(lpString, L"MachineName", 11))
2790 {
2791 lpString += 12;
2792 if (*lpString != L'\0')
2793 {
2794 int i = 0;
2795 while ((*lpString != L' ') &&
2796 (*lpString != L'\0') &&
2797 (i <= MAX_COMPUTERNAME_LENGTH))
2798 {
2799 szMachineName[i++] = *lpString++;
2800 }
2801 szMachineName[i] = L'\0';
2802 }
2803 }
2804 /* knock the pointer back one and let the next
2805 * pointer deal with incrementing, otherwise we
2806 * go past the end of the string */
2807 lpString--;
2808 }
2809 lpString++;
2810 }
2811
2812 return ret;
2813 }
2814
2815
2816 /***************************************************************************
2817 * NAME EXPORTED
2818 * DeviceAdvancedPropertiesW
2819 *
2820 * DESCRIPTION
2821 * Invokes the device properties dialog, this version may add some property pages
2822 * for some devices
2823 *
2824 * ARGUMENTS
2825 * hWndParent: Handle to the parent window
2826 * lpMachineName: Machine Name, NULL is the local machine
2827 * lpDeviceID: Specifies the device whose properties are to be shown
2828 *
2829 * RETURN VALUE
2830 * Always returns -1, a call to GetLastError returns 0 if successful
2831 *
2832 * @implemented
2833 */
2834 INT_PTR
2835 WINAPI
2836 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL,
2837 IN LPCWSTR lpMachineName OPTIONAL,
2838 IN LPCWSTR lpDeviceID)
2839 {
2840 HDEVINFO hDevInfo;
2841 SP_DEVINFO_DATA DevInfoData;
2842 HINSTANCE hComCtl32;
2843 INT_PTR Ret = -1;
2844
2845 if (lpDeviceID == NULL)
2846 {
2847 SetLastError(ERROR_INVALID_PARAMETER);
2848 return FALSE;
2849 }
2850
2851 /* dynamically load comctl32 */
2852 hComCtl32 = LoadAndInitComctl32();
2853 if (hComCtl32 != NULL)
2854 {
2855 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2856 hWndParent,
2857 lpMachineName,
2858 NULL);
2859 if (hDevInfo != INVALID_HANDLE_VALUE)
2860 {
2861 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2862 if (SetupDiOpenDeviceInfo(hDevInfo,
2863 lpDeviceID,
2864 hWndParent,
2865 0,
2866 &DevInfoData))
2867 {
2868 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2869 lpDeviceID,
2870 hDevInfo,
2871 &DevInfoData,
2872 hComCtl32,
2873 lpMachineName,
2874 0);
2875 }
2876
2877 SetupDiDestroyDeviceInfoList(hDevInfo);
2878 }
2879
2880 FreeLibrary(hComCtl32);
2881 }
2882
2883 return Ret;
2884 }
2885
2886
2887 /***************************************************************************
2888 * NAME EXPORTED
2889 * DeviceAdvancedPropertiesA
2890 *
2891 * DESCRIPTION
2892 * Invokes the device properties dialog, this version may add some property pages
2893 * for some devices
2894 *
2895 * ARGUMENTS
2896 * hWndParent: Handle to the parent window
2897 * lpMachineName: Machine Name, NULL is the local machine
2898 * lpDeviceID: Specifies the device whose properties are to be shown
2899 *
2900 * RETURN VALUE
2901 * Always returns -1, a call to GetLastError returns 0 if successful
2902 *
2903 * @implemented
2904 */
2905 INT_PTR
2906 WINAPI
2907 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL,
2908 IN LPCSTR lpMachineName OPTIONAL,
2909 IN LPCSTR lpDeviceID)
2910 {
2911 LPWSTR lpMachineNameW = NULL;
2912 LPWSTR lpDeviceIDW = NULL;
2913 INT_PTR Ret = -1;
2914
2915 if (lpMachineName != NULL)
2916 {
2917 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2918 CP_ACP)))
2919 {
2920 goto Cleanup;
2921 }
2922 }
2923 if (lpDeviceID != NULL)
2924 {
2925 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2926 CP_ACP)))
2927 {
2928 goto Cleanup;
2929 }
2930 }
2931
2932 Ret = DeviceAdvancedPropertiesW(hWndParent,
2933 lpMachineNameW,
2934 lpDeviceIDW);
2935
2936 Cleanup:
2937 if (lpMachineNameW != NULL)
2938 {
2939 HeapFree(GetProcessHeap(),
2940 0,
2941 lpMachineNameW);
2942 }
2943 if (lpDeviceIDW != NULL)
2944 {
2945 HeapFree(GetProcessHeap(),
2946 0,
2947 lpDeviceIDW);
2948 }
2949
2950 return Ret;
2951 }
2952
2953
2954 /***************************************************************************
2955 * NAME EXPORTED
2956 * DevicePropertiesExA
2957 *
2958 * DESCRIPTION
2959 * Invokes the extended device properties dialog
2960 *
2961 * ARGUMENTS
2962 * hWndParent: Handle to the parent window
2963 * lpMachineName: Machine Name, NULL is the local machine
2964 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2965 * bShowDevMgr is nonzero
2966 * dwFlags: This parameter can be a combination of the following flags:
2967 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2968 * the default device status action button
2969 * to be clicked (Troubleshoot, Enable
2970 * Device, etc)
2971 * bShowDevMgr: If non-zero it displays the device manager instead of
2972 * the advanced device property dialog
2973 *
2974 * RETURN VALUE
2975 * 1: if bShowDevMgr is non-zero and no error occured
2976 * -1: a call to GetLastError returns 0 if successful
2977 *
2978 * @implemented
2979 */
2980 INT_PTR
2981 WINAPI
2982 DevicePropertiesExA(IN HWND hWndParent OPTIONAL,
2983 IN LPCSTR lpMachineName OPTIONAL,
2984 IN LPCSTR lpDeviceID OPTIONAL,
2985 IN DWORD dwFlags OPTIONAL,
2986 IN BOOL bShowDevMgr)
2987 {
2988 LPWSTR lpMachineNameW = NULL;
2989 LPWSTR lpDeviceIDW = NULL;
2990 INT_PTR Ret = -1;
2991
2992 if (lpMachineName != NULL)
2993 {
2994 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2995 CP_ACP)))
2996 {
2997 goto Cleanup;
2998 }
2999 }
3000 if (lpDeviceID != NULL)
3001 {
3002 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
3003 CP_ACP)))
3004 {
3005 goto Cleanup;
3006 }
3007 }
3008
3009 Ret = DevicePropertiesExW(hWndParent,
3010 lpMachineNameW,
3011 lpDeviceIDW,
3012 dwFlags,
3013 bShowDevMgr);
3014
3015 Cleanup:
3016 if (lpMachineNameW != NULL)
3017 {
3018 HeapFree(GetProcessHeap(),
3019 0,
3020 lpMachineNameW);
3021 }
3022 if (lpDeviceIDW != NULL)
3023 {
3024 HeapFree(GetProcessHeap(),
3025 0,
3026 lpDeviceIDW);
3027 }
3028
3029 return Ret;
3030 }
3031
3032
3033 /***************************************************************************
3034 * NAME EXPORTED
3035 * DevicePropertiesExW
3036 *
3037 * DESCRIPTION
3038 * Invokes the extended device properties dialog
3039 *
3040 * ARGUMENTS
3041 * hWndParent: Handle to the parent window
3042 * lpMachineName: Machine Name, NULL is the local machine
3043 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
3044 * bShowDevMgr is nonzero
3045 * dwFlags: This parameter can be a combination of the following flags:
3046 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
3047 * the default device status action button
3048 * to be clicked (Troubleshoot, Enable
3049 * Device, etc)
3050 * bShowDevMgr: If non-zero it displays the device manager instead of
3051 * the advanced device property dialog
3052 *
3053 * RETURN VALUE
3054 * 1: if bShowDevMgr is non-zero and no error occured
3055 * -1: a call to GetLastError returns 0 if successful
3056 *
3057 * @implemented
3058 */
3059 INT_PTR
3060 WINAPI
3061 DevicePropertiesExW(IN HWND hWndParent OPTIONAL,
3062 IN LPCWSTR lpMachineName OPTIONAL,
3063 IN LPCWSTR lpDeviceID OPTIONAL,
3064 IN DWORD dwFlags OPTIONAL,
3065 IN BOOL bShowDevMgr)
3066 {
3067 INT_PTR Ret = -1;
3068
3069 if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
3070 {
3071 FIXME("DevPropertiesExW: Invalid flags: 0x%x\n",
3072 dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
3073 SetLastError(ERROR_INVALID_FLAGS);
3074 return -1;
3075 }
3076
3077 if (bShowDevMgr)
3078 {
3079 FIXME("DevPropertiesExW doesn't support bShowDevMgr!\n");
3080 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3081 }
3082 else
3083 {
3084 HDEVINFO hDevInfo;
3085 SP_DEVINFO_DATA DevInfoData;
3086 HINSTANCE hComCtl32;
3087
3088 if (lpDeviceID == NULL)
3089 {
3090 SetLastError(ERROR_INVALID_PARAMETER);
3091 return -1;
3092 }
3093
3094 /* dynamically load comctl32 */
3095 hComCtl32 = LoadAndInitComctl32();
3096 if (hComCtl32 != NULL)
3097 {
3098 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
3099 hWndParent,
3100 lpMachineName,
3101 NULL);
3102 if (hDevInfo != INVALID_HANDLE_VALUE)
3103 {
3104 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
3105 if (SetupDiOpenDeviceInfo(hDevInfo,
3106 lpDeviceID,
3107 hWndParent,
3108 0,
3109 &DevInfoData))
3110 {
3111 Ret = DisplayDeviceAdvancedProperties(hWndParent,
3112 lpDeviceID,
3113 hDevInfo,
3114 &DevInfoData,
3115 hComCtl32,
3116 lpMachineName,
3117 dwFlags);
3118 }
3119
3120 SetupDiDestroyDeviceInfoList(hDevInfo);
3121 }
3122
3123 FreeLibrary(hComCtl32);
3124 }
3125 }
3126
3127 return Ret;
3128 }
3129
3130
3131 /***************************************************************************
3132 * NAME EXPORTED
3133 * DevicePropertiesA
3134 *
3135 * DESCRIPTION
3136 * Invokes the device properties dialog directly
3137 *
3138 * ARGUMENTS
3139 * hWndParent: Handle to the parent window
3140 * lpMachineName: Machine Name, NULL is the local machine
3141 * lpDeviceID: Specifies the device whose properties are to be shown
3142 * bShowDevMgr: If non-zero it displays the device manager instead of
3143 * the device property dialog
3144 *
3145 * RETURN VALUE
3146 * >=0: if no errors occured
3147 * -1: if errors occured
3148 *
3149 * REVISIONS
3150 *
3151 * @implemented
3152 */
3153 int
3154 WINAPI
3155 DevicePropertiesA(HWND hWndParent,
3156 LPCSTR lpMachineName,
3157 LPCSTR lpDeviceID,
3158 BOOL bShowDevMgr)
3159 {
3160 return DevicePropertiesExA(hWndParent,
3161 lpMachineName,
3162 lpDeviceID,
3163 DPF_EXTENDED,
3164 bShowDevMgr);
3165 }
3166
3167
3168 /***************************************************************************
3169 * NAME EXPORTED
3170 * DevicePropertiesW
3171 *
3172 * DESCRIPTION
3173 * Invokes the device properties dialog directly
3174 *
3175 * ARGUMENTS
3176 * hWndParent: Handle to the parent window
3177 * lpMachineName: Machine Name, NULL is the local machine
3178 * lpDeviceID: Specifies the device whose properties are to be shown
3179 * bShowDevMgr: If non-zero it displays the device manager instead of
3180 * the device property dialog
3181 *
3182 * RETURN VALUE
3183 * >=0: if no errors occured
3184 * -1: if errors occured
3185 *
3186 * REVISIONS
3187 *
3188 * @implemented
3189 */
3190 int
3191 WINAPI
3192 DevicePropertiesW(HWND hWndParent,
3193 LPCWSTR lpMachineName,
3194 LPCWSTR lpDeviceID,
3195 BOOL bShowDevMgr)
3196 {
3197 return DevicePropertiesExW(hWndParent,
3198 lpMachineName,
3199 lpDeviceID,
3200 DPF_EXTENDED,
3201 bShowDevMgr);
3202 }
3203
3204
3205 /***************************************************************************
3206 * NAME EXPORTED
3207 * DeviceProperties_RunDLLA
3208 *
3209 * DESCRIPTION
3210 * Invokes the device properties dialog
3211 *
3212 * ARGUMENTS
3213 * hWndParent: Handle to the parent window
3214 * hInst: Handle to the application instance
3215 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
3216 * also see NOTEs
3217 * nCmdShow: Specifies how the window should be shown
3218 *
3219 * RETURN VALUE
3220 *
3221 * REVISIONS
3222 *
3223 * NOTE
3224 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
3225 * (/MachineName is optional). This function only parses this string and eventually
3226 * calls DeviceProperties().
3227 *
3228 * @implemented
3229 */
3230 VOID
3231 WINAPI
3232 DeviceProperties_RunDLLA(HWND hWndParent,
3233 HINSTANCE hInst,
3234 LPCSTR lpDeviceCmd,
3235 int nCmdShow)
3236 {
3237 LPWSTR lpDeviceCmdW = NULL;
3238
3239 if (lpDeviceCmd != NULL)
3240 {
3241 if ((lpDeviceCmdW = ConvertMultiByteToUnicode(lpDeviceCmd,
3242 CP_ACP)))
3243 {
3244 DeviceProperties_RunDLLW(hWndParent,
3245 hInst,
3246 lpDeviceCmdW,
3247 nCmdShow);
3248 }
3249 }
3250
3251 if (lpDeviceCmdW != NULL)
3252 {
3253 HeapFree(GetProcessHeap(),
3254 0,
3255 lpDeviceCmdW);
3256 }
3257 }
3258
3259
3260 /***************************************************************************
3261 * NAME EXPORTED
3262 * DeviceProperties_RunDLLW
3263 *
3264 * DESCRIPTION
3265 * Invokes the device properties dialog
3266 *
3267 * ARGUMENTS
3268 * hWndParent: Handle to the parent window
3269 * hInst: Handle to the application instance
3270 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
3271 * also see NOTEs
3272 * nCmdShow: Specifies how the window should be shown
3273 *
3274 * RETURN VALUE
3275 *
3276 * REVISIONS
3277 *
3278 * NOTE
3279 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
3280 * (/MachineName is optional). This function only parses this string and eventually
3281 * calls DeviceProperties().
3282 *
3283 * @implemented
3284 */
3285 VOID
3286 WINAPI
3287 DeviceProperties_RunDLLW(HWND hWndParent,
3288 HINSTANCE hInst,
3289 LPCWSTR lpDeviceCmd,
3290 int nCmdShow)
3291 {
3292 WCHAR szDeviceID[MAX_DEVICE_ID_LEN+1];
3293 WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
3294 LPWSTR lpString = (LPWSTR)lpDeviceCmd;
3295
3296 if (!GetDeviceAndComputerName(lpString,
3297 szDeviceID,
3298 szMachineName))
3299 {
3300 ERR("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
3301 return;
3302 }
3303
3304 DevicePropertiesW(hWndParent,
3305 szMachineName,
3306 szDeviceID,
3307 FALSE);
3308 }