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