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