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