Sync trunk.
[reactos.git] / 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 LPBYTE lpBuffer;
724 LPWSTR lpStr;
725 INT len;
726 INT index;
727
728 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
729 {
730 DeviceInfoSet = dap->CurrentDeviceInfoSet;
731 DeviceInfoData = &dap->CurrentDeviceInfoData;
732 }
733 else
734 {
735 DeviceInfoSet = dap->DeviceInfoSet;
736 DeviceInfoData = &dap->DeviceInfoData;
737 }
738
739 dwSize = 0;
740 SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
741 DeviceInfoData,
742 dwProperty,
743 &dwType,
744 NULL,
745 0,
746 &dwSize);
747 if (dwSize == 0)
748 {
749 if (GetLastError() != ERROR_FILE_NOT_FOUND)
750 {
751 swprintf(dap->szTemp, L"Error: Getting the size failed! (Error: %ld)", GetLastError());
752 SetListViewText(hwndListView, 0, dap->szTemp);
753 }
754 return;
755 }
756
757 lpBuffer = HeapAlloc(GetProcessHeap(),
758 HEAP_ZERO_MEMORY,
759 dwSize);
760 if (lpBuffer == NULL)
761 {
762 SetListViewText(hwndListView, 0, L"Error: Allocating the buffer failed!");
763 return;
764 }
765
766 if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
767 DeviceInfoData,
768 dwProperty,
769 &dwType,
770 lpBuffer,
771 dwSize,
772 &dwSize))
773 {
774 if (dwType == REG_SZ)
775 {
776 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
777 }
778 else if (dwType == REG_MULTI_SZ)
779 {
780 lpStr = (LPWSTR)lpBuffer;
781 index = 0;
782 while (*lpStr != 0)
783 {
784 len = wcslen(lpStr) + 1;
785
786 SetListViewText(hwndListView, index, lpStr);
787
788 lpStr += len;
789 index++;
790 }
791 }
792 else if (dwType == REG_DWORD)
793 {
794 switch (dwProperty)
795 {
796 case SPDRP_CAPABILITIES:
797 index = 0;
798 if (*lpBuffer & CM_DEVCAP_LOCKSUPPORTED)
799 SetListViewText(hwndListView, index++, L"CM_DEVCAP_LOCKSUPPORTED");
800 if (*lpBuffer & CM_DEVCAP_EJECTSUPPORTED)
801 SetListViewText(hwndListView, index++, L"CM_DEVCAP_EJECTSUPPORTED");
802 if (*lpBuffer & CM_DEVCAP_REMOVABLE)
803 SetListViewText(hwndListView, index++, L"CM_DEVCAP_REMOVABLE");
804 if (*lpBuffer & CM_DEVCAP_DOCKDEVICE)
805 SetListViewText(hwndListView, index++, L"CM_DEVCAP_DOCKDEVICE");
806 if (*lpBuffer & CM_DEVCAP_UNIQUEID)
807 SetListViewText(hwndListView, index++, L"CM_DEVCAP_UNIQUEID");
808 if (*lpBuffer & CM_DEVCAP_SILENTINSTALL)
809 SetListViewText(hwndListView, index++, L"CM_DEVCAP_SILENTINSTALL");
810 if (*lpBuffer & CM_DEVCAP_RAWDEVICEOK)
811 SetListViewText(hwndListView, index++, L"CM_DEVCAP_RAWDEVICEOK");
812 if (*lpBuffer & CM_DEVCAP_SURPRISEREMOVALOK)
813 SetListViewText(hwndListView, index++, L"CM_DEVCAP_SURPRISEREMOVALOK");
814 if (*lpBuffer & CM_DEVCAP_HARDWAREDISABLED)
815 SetListViewText(hwndListView, index++, L"CM_DEVCAP_HARDWAREDISABLED");
816 if (*lpBuffer & CM_DEVCAP_NONDYNAMIC)
817 SetListViewText(hwndListView, index++, L"CM_DEVCAP_NONDYNAMIC");
818 break;
819
820 case SPDRP_CONFIGFLAGS:
821 index = 0;
822 if (*lpBuffer & CONFIGFLAG_DISABLED)
823 SetListViewText(hwndListView, index++, L"CONFIGFLAG_DISABLED");
824 if (*lpBuffer & CONFIGFLAG_REMOVED)
825 SetListViewText(hwndListView, index++, L"CONFIGFLAG_REMOVED");
826 if (*lpBuffer & CONFIGFLAG_MANUAL_INSTALL)
827 SetListViewText(hwndListView, index++, L"CONFIGFLAG_MANUAL_INSTALL");
828 if (*lpBuffer & CONFIGFLAG_IGNORE_BOOT_LC)
829 SetListViewText(hwndListView, index++, L"CONFIGFLAG_IGNORE_BOOT_LC");
830 if (*lpBuffer & CONFIGFLAG_NET_BOOT)
831 SetListViewText(hwndListView, index++, L"CONFIGFLAG_NET_BOOT");
832 if (*lpBuffer & CONFIGFLAG_REINSTALL)
833 SetListViewText(hwndListView, index++, L"CONFIGFLAG_REINSTALL");
834 if (*lpBuffer & CONFIGFLAG_FAILEDINSTALL)
835 SetListViewText(hwndListView, index++, L"CONFIGFLAG_FAILEDINSTALL");
836 if (*lpBuffer & CONFIGFLAG_CANTSTOPACHILD)
837 SetListViewText(hwndListView, index++, L"CONFIGFLAG_CANTSTOPACHILD");
838 if (*lpBuffer & CONFIGFLAG_OKREMOVEROM)
839 SetListViewText(hwndListView, index++, L"CONFIGFLAG_OKREMOVEROM");
840 if (*lpBuffer & CONFIGFLAG_NOREMOVEEXIT)
841 SetListViewText(hwndListView, index++, L"CONFIGFLAG_NOREMOVEEXIT");
842 break;
843
844 default:
845 swprintf(dap->szTemp, L"0x%08x", *lpBuffer);
846 SetListViewText(hwndListView, 0, dap->szTemp);
847 break;
848 }
849 }
850 else
851 {
852 SetListViewText(hwndListView, 0, L"Error: Unsupported value type!");
853
854 }
855 }
856 else
857 {
858 SetListViewText(hwndListView, 0, L"Error: Retrieving the value failed!");
859 }
860
861 HeapFree(GetProcessHeap(),
862 0,
863 lpBuffer);
864 }
865
866 static VOID
867 DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,
868 IN HWND hwndListView)
869 {
870 DWORD dwStatus = 0;
871 DWORD dwProblem = 0;
872 INT index;
873
874 CM_Get_DevNode_Status_Ex(&dwStatus,
875 &dwProblem,
876 dap->DeviceInfoData.DevInst,
877 0,
878 dap->hMachine);
879
880 index = 0;
881 if (dwStatus & DN_ROOT_ENUMERATED)
882 SetListViewText(hwndListView, index++, L"DN_ROOT_ENUMERATED");
883 if (dwStatus & DN_DRIVER_LOADED)
884 SetListViewText(hwndListView, index++, L"DN_DRIVER_LOADED");
885 if (dwStatus & DN_ENUM_LOADED)
886 SetListViewText(hwndListView, index++, L"DN_ENUM_LOADED");
887 if (dwStatus & DN_STARTED)
888 SetListViewText(hwndListView, index++, L"DN_STARTED");
889 if (dwStatus & DN_MANUAL)
890 SetListViewText(hwndListView, index++, L"DN_MANUAL");
891 if (dwStatus & DN_NEED_TO_ENUM)
892 SetListViewText(hwndListView, index++, L"DN_NEED_TO_ENUM");
893 if (dwStatus & DN_DRIVER_BLOCKED)
894 SetListViewText(hwndListView, index++, L"DN_DRIVER_BLOCKED");
895 if (dwStatus & DN_HARDWARE_ENUM)
896 SetListViewText(hwndListView, index++, L"DN_HARDWARE_ENUM");
897 if (dwStatus & DN_NEED_RESTART)
898 SetListViewText(hwndListView, index++, L"DN_NEED_RESTART");
899 if (dwStatus & DN_CHILD_WITH_INVALID_ID)
900 SetListViewText(hwndListView, index++, L"DN_CHILD_WITH_INVALID_ID");
901 if (dwStatus & DN_HAS_PROBLEM)
902 SetListViewText(hwndListView, index++, L"DN_HAS_PROBLEM");
903 if (dwStatus & DN_FILTERED)
904 SetListViewText(hwndListView, index++, L"DN_FILTERED");
905 if (dwStatus & DN_LEGACY_DRIVER)
906 SetListViewText(hwndListView, index++, L"DN_LEGACY_DRIVER");
907 if (dwStatus & DN_DISABLEABLE)
908 SetListViewText(hwndListView, index++, L"DN_DISABLEABLE");
909 if (dwStatus & DN_REMOVABLE)
910 SetListViewText(hwndListView, index++, L"DN_REMOVABLE");
911 if (dwStatus & DN_PRIVATE_PROBLEM)
912 SetListViewText(hwndListView, index++, L"DN_PRIVATE_PROBLEM");
913 if (dwStatus & DN_MF_PARENT)
914 SetListViewText(hwndListView, index++, L"DN_MF_PARENT");
915 if (dwStatus & DN_MF_CHILD)
916 SetListViewText(hwndListView, index++, L"DN_MF_CHILD");
917 if (dwStatus & DN_WILL_BE_REMOVED)
918 SetListViewText(hwndListView, index++, L"DN_WILL_BE_REMOVED");
919
920 if (dwStatus & DN_NOT_FIRST_TIMEE)
921 SetListViewText(hwndListView, index++, L"DN_NOT_FIRST_TIMEE");
922 if (dwStatus & DN_STOP_FREE_RES)
923 SetListViewText(hwndListView, index++, L"DN_STOP_FREE_RES");
924 if (dwStatus & DN_REBAL_CANDIDATE)
925 SetListViewText(hwndListView, index++, L"DN_REBAL_CANDIDATE");
926 if (dwStatus & DN_BAD_PARTIAL)
927 SetListViewText(hwndListView, index++, L"DN_BAD_PARTIAL");
928 if (dwStatus & DN_NT_ENUMERATOR)
929 SetListViewText(hwndListView, index++, L"DN_NT_ENUMERATOR");
930 if (dwStatus & DN_NT_DRIVER)
931 SetListViewText(hwndListView, index++, L"DN_NT_DRIVER");
932
933 if (dwStatus & DN_NEEDS_LOCKING)
934 SetListViewText(hwndListView, index++, L"DN_NEEDS_LOCKING");
935 if (dwStatus & DN_ARM_WAKEUP)
936 SetListViewText(hwndListView, index++, L"DN_ARM_WAKEUP");
937 if (dwStatus & DN_APM_ENUMERATOR)
938 SetListViewText(hwndListView, index++, L"DN_APM_ENUMERATOR");
939 if (dwStatus & DN_APM_DRIVER)
940 SetListViewText(hwndListView, index++, L"DN_APM_DRIVER");
941 if (dwStatus & DN_SILENT_INSTALL)
942 SetListViewText(hwndListView, index++, L"DN_SILENT_INSTALL");
943 if (dwStatus & DN_NO_SHOW_IN_DM)
944 SetListViewText(hwndListView, index++, L"DN_NO_SHOW_IN_DM");
945 if (dwStatus & DN_BOOT_LOG_PROB)
946 SetListViewText(hwndListView, index++, L"DN_BOOT_LOG_PROB");
947
948 // swprintf(dap->szTemp, L"0x%08x", dwStatus);
949 // SetListViewText(hwndListView, 0, dap->szTemp);
950 }
951
952
953 static VOID
954 DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
955 IN HWND hwndListView)
956 {
957 HDEVINFO DeviceInfoSet;
958 PSP_DEVINFO_DATA DeviceInfoData;
959
960 DWORD dwType = 0;
961 WCHAR szBuffer[256];
962 DWORD dwSize = 256 * sizeof(WCHAR);
963
964 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
965 {
966 DeviceInfoSet = dap->CurrentDeviceInfoSet;
967 DeviceInfoData = &dap->CurrentDeviceInfoData;
968 }
969 else
970 {
971 DeviceInfoSet = dap->DeviceInfoSet;
972 DeviceInfoData = &dap->DeviceInfoData;
973 }
974
975 CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
976 CM_DRP_ENUMERATOR_NAME,
977 &dwType,
978 &szBuffer,
979 &dwSize,
980 0,
981 dap->hMachine);
982
983 SetListViewText(hwndListView, 0, szBuffer);
984 }
985
986
987 static VOID
988 DisplayCsFlags(IN PDEVADVPROP_INFO dap,
989 IN HWND hwndListView)
990 {
991 DWORD dwValue = 0;
992 INT index;
993
994 CM_Get_HW_Prof_Flags_Ex(dap->szDevName,
995 0, /* current hardware profile */
996 &dwValue,
997 0,
998 dap->hMachine);
999
1000 index = 0;
1001 if (dwValue & CSCONFIGFLAG_DISABLED)
1002 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DISABLED");
1003
1004 if (dwValue & CSCONFIGFLAG_DO_NOT_CREATE)
1005 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_CREATE");
1006
1007 if (dwValue & CSCONFIGFLAG_DO_NOT_START)
1008 SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_START");
1009 }
1010
1011
1012 static VOID
1013 DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
1014 IN HWND hwndListView)
1015 {
1016 HDEVINFO DeviceInfoSet;
1017 PSP_DEVINFO_DATA DeviceInfoData;
1018 WCHAR szBuffer[256];
1019 HKEY hKey;
1020 DWORD dwSize;
1021 DWORD dwType;
1022
1023 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1024 {
1025 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1026 DeviceInfoData = &dap->CurrentDeviceInfoData;
1027 }
1028 else
1029 {
1030 DeviceInfoSet = dap->DeviceInfoSet;
1031 DeviceInfoData = &dap->DeviceInfoData;
1032 }
1033
1034 hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1035 DeviceInfoData,
1036 DICS_FLAG_GLOBAL,
1037 0,
1038 DIREG_DRV,
1039 KEY_QUERY_VALUE);
1040 if (hKey != INVALID_HANDLE_VALUE)
1041 {
1042 dwSize = 256 * sizeof(WCHAR);
1043 if (RegQueryValueEx(hKey,
1044 L"MatchingDeviceId",
1045 NULL,
1046 &dwType,
1047 (LPBYTE)szBuffer,
1048 &dwSize) == ERROR_SUCCESS)
1049 {
1050 SetListViewText(hwndListView, 0, szBuffer);
1051 }
1052
1053 RegCloseKey(hKey);
1054 }
1055 }
1056
1057
1058 static VOID
1059 DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
1060 IN HWND hwndListView)
1061 {
1062 HDEVINFO DeviceInfoSet;
1063 PSP_DEVINFO_DATA DeviceInfoData;
1064 HKEY hKey;
1065 DWORD dwSize;
1066 DWORD dwType;
1067 LPBYTE lpBuffer;
1068 LPWSTR lpStr;
1069 INT index;
1070 INT len;
1071
1072 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1073 {
1074 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1075 DeviceInfoData = &dap->CurrentDeviceInfoData;
1076 }
1077 else
1078 {
1079 DeviceInfoSet = dap->DeviceInfoSet;
1080 DeviceInfoData = &dap->DeviceInfoData;
1081 }
1082
1083 hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
1084 DeviceInfoData,
1085 DICS_FLAG_GLOBAL,
1086 0,
1087 DIREG_DRV,
1088 KEY_QUERY_VALUE);
1089 if (hKey != INVALID_HANDLE_VALUE)
1090 {
1091 dwSize = 0;
1092 if (RegQueryValueEx(hKey,
1093 L"CoInstallers32",
1094 NULL,
1095 &dwType,
1096 NULL,
1097 &dwSize) == ERROR_SUCCESS &&
1098 dwSize > 0)
1099 {
1100
1101 lpBuffer = HeapAlloc(GetProcessHeap(),
1102 HEAP_ZERO_MEMORY,
1103 dwSize);
1104
1105 RegQueryValueEx(hKey,
1106 L"CoInstallers32",
1107 NULL,
1108 &dwType,
1109 lpBuffer,
1110 &dwSize);
1111
1112 lpStr = (LPWSTR)lpBuffer;
1113 index = 0;
1114 while (*lpStr != 0)
1115 {
1116 len = wcslen(lpStr) + 1;
1117
1118 SetListViewText(hwndListView, index, lpStr);
1119
1120 lpStr += len;
1121 index++;
1122 }
1123
1124 HeapFree(GetProcessHeap(),
1125 0,
1126 lpBuffer);
1127 }
1128
1129 RegCloseKey(hKey);
1130 }
1131 }
1132
1133
1134 static VOID
1135 DisplayClassProperties(IN PDEVADVPROP_INFO dap,
1136 IN HWND hwndListView,
1137 IN LPWSTR lpProperty)
1138 {
1139 HDEVINFO DeviceInfoSet;
1140 PSP_DEVINFO_DATA DeviceInfoData;
1141 WCHAR szClassGuid[45];
1142 DWORD dwSize;
1143 DWORD dwType;
1144 HKEY hKey;
1145 GUID ClassGuid;
1146 LPBYTE lpBuffer;
1147 LPWSTR lpStr;
1148 INT index = 0;
1149 INT len;
1150
1151 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1152 {
1153 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1154 DeviceInfoData = &dap->CurrentDeviceInfoData;
1155 }
1156 else
1157 {
1158 DeviceInfoSet = dap->DeviceInfoSet;
1159 DeviceInfoData = &dap->DeviceInfoData;
1160 }
1161
1162 dwSize = 45 * sizeof(WCHAR);
1163 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
1164 DeviceInfoData,
1165 SPDRP_CLASSGUID,
1166 &dwType,
1167 (LPBYTE)szClassGuid,
1168 dwSize,
1169 &dwSize))
1170 return;
1171
1172 pSetupGuidFromString(szClassGuid,
1173 &ClassGuid);
1174
1175 hKey = SetupDiOpenClassRegKey(&ClassGuid,
1176 KEY_QUERY_VALUE);
1177 if (hKey != INVALID_HANDLE_VALUE)
1178 {
1179 dwSize = 0;
1180 if (RegQueryValueEx(hKey,
1181 lpProperty,
1182 NULL,
1183 &dwType,
1184 NULL,
1185 &dwSize) == ERROR_SUCCESS &&
1186 dwSize > 0)
1187 {
1188 lpBuffer = HeapAlloc(GetProcessHeap(),
1189 HEAP_ZERO_MEMORY,
1190 dwSize);
1191
1192 RegQueryValueEx(hKey,
1193 lpProperty,
1194 NULL,
1195 &dwType,
1196 lpBuffer,
1197 &dwSize);
1198
1199 if (dwType == REG_SZ)
1200 {
1201 SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
1202 }
1203 else if (dwType == REG_MULTI_SZ)
1204 {
1205 lpStr = (LPWSTR)lpBuffer;
1206 index = 0;
1207 while (*lpStr != 0)
1208 {
1209 len = wcslen(lpStr) + 1;
1210
1211 SetListViewText(hwndListView, index, lpStr);
1212
1213 lpStr += len;
1214 index++;
1215 }
1216 }
1217
1218 HeapFree(GetProcessHeap(),
1219 0,
1220 lpBuffer);
1221 }
1222
1223 RegCloseKey(hKey);
1224 }
1225 }
1226
1227
1228 static VOID
1229 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
1230 IN HWND hwndComboBox,
1231 IN HWND hwndListView)
1232 {
1233 INT Index;
1234
1235 Index = (INT)SendMessage(hwndComboBox,
1236 CB_GETCURSEL,
1237 0,
1238 0);
1239 if (Index == CB_ERR)
1240 return;
1241
1242 (void)ListView_DeleteAllItems(hwndListView);
1243
1244 switch (Index)
1245 {
1246 case 0:
1247 SetListViewText(hwndListView, 0, dap->szDeviceID);
1248 break;
1249
1250 case 1: /* Hardware ID */
1251 DisplayDevicePropertyText(dap,
1252 hwndListView,
1253 SPDRP_HARDWAREID);
1254 break;
1255
1256 case 2: /* Compatible IDs */
1257 DisplayDevicePropertyText(dap,
1258 hwndListView,
1259 SPDRP_COMPATIBLEIDS);
1260 break;
1261
1262 case 3: /* Matching ID */
1263 DisplayMatchingDeviceId(dap,
1264 hwndListView);
1265 break;
1266
1267 case 4: /* Service */
1268 DisplayDevicePropertyText(dap,
1269 hwndListView,
1270 SPDRP_SERVICE);
1271 break;
1272
1273 case 5: /* Enumerator */
1274 DisplayDevNodeEnumerator(dap,
1275 hwndListView);
1276 break;
1277
1278 case 6: /* Capabilities */
1279 DisplayDevicePropertyText(dap,
1280 hwndListView,
1281 SPDRP_CAPABILITIES);
1282 break;
1283
1284 case 7: /* Devnode Flags */
1285 DisplayDevNodeFlags(dap,
1286 hwndListView);
1287 break;
1288
1289 case 8: /* Config Flags */
1290 DisplayDevicePropertyText(dap,
1291 hwndListView,
1292 SPDRP_CONFIGFLAGS);
1293 break;
1294
1295 case 9: /* CSConfig Flags */
1296 DisplayCsFlags(dap,
1297 hwndListView);
1298 break;
1299
1300 #if 0
1301 case 10: /* Ejection relation */
1302 break;
1303
1304 case 11: /* Removal relations */
1305 break;
1306
1307 case 12: /* Bus relation */
1308 break;
1309 #endif
1310
1311 case 13: /* Device Upper Filters */
1312 DisplayDevicePropertyText(dap,
1313 hwndListView,
1314 SPDRP_UPPERFILTERS);
1315 break;
1316
1317 case 14: /* Device Lower Filters */
1318 DisplayDevicePropertyText(dap,
1319 hwndListView,
1320 SPDRP_LOWERFILTERS);
1321 break;
1322
1323 case 15: /* Class Upper Filters */
1324 DisplayClassProperties(dap,
1325 hwndListView,
1326 L"UpperFilters");
1327 break;
1328
1329 case 16: /* Class Lower Filters */
1330 DisplayClassProperties(dap,
1331 hwndListView,
1332 L"LowerFilters");
1333 break;
1334
1335 case 17: /* Class Installer */
1336 DisplayClassProperties(dap,
1337 hwndListView,
1338 L"Installer32");
1339 break;
1340
1341 #if 0
1342 case 18: /* Class Coinstaller */
1343 break;
1344 #endif
1345
1346 case 19: /* Device Coinstaller */
1347 DisplayDeviceCoinstallers(dap,
1348 hwndListView);
1349 break;
1350
1351 #if 0
1352 case 20: /* Firmware Revision */
1353 break;
1354
1355 case 21: /* Current Power State */
1356 break;
1357
1358 case 20: /* Power Capabilities */
1359 break;
1360
1361 case 21: /* Power State Mappings */
1362 break;
1363 #endif
1364
1365 default:
1366 SetListViewText(hwndListView, 0, L"<Not implemented yet>");
1367 break;
1368 }
1369 }
1370
1371
1372 static INT_PTR
1373 CALLBACK
1374 AdvProcDetailsDlgProc(IN HWND hwndDlg,
1375 IN UINT uMsg,
1376 IN WPARAM wParam,
1377 IN LPARAM lParam)
1378 {
1379 PDEVADVPROP_INFO dap;
1380 INT_PTR Ret = FALSE;
1381
1382 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1383 DWL_USER);
1384
1385 if (dap != NULL || uMsg == WM_INITDIALOG)
1386 {
1387 switch (uMsg)
1388 {
1389 case WM_COMMAND:
1390 {
1391 switch (LOWORD(wParam))
1392 {
1393 case IDC_DETAILSPROPNAME:
1394 if (HIWORD(wParam) == CBN_SELCHANGE)
1395 {
1396 DisplayDeviceProperties(dap,
1397 GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
1398 GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
1399 }
1400 break;
1401 }
1402 break;
1403 }
1404
1405 case WM_NOTIFY:
1406 {
1407 NMHDR *hdr = (NMHDR*)lParam;
1408 switch (hdr->code)
1409 {
1410 case PSN_APPLY:
1411 break;
1412 }
1413 break;
1414 }
1415
1416 case WM_INITDIALOG:
1417 {
1418 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1419 if (dap != NULL)
1420 {
1421 SetWindowLongPtr(hwndDlg,
1422 DWL_USER,
1423 (DWORD_PTR)dap);
1424
1425 UpdateDetailsDlg(hwndDlg,
1426 dap);
1427 }
1428 Ret = TRUE;
1429 break;
1430 }
1431 }
1432 }
1433
1434 return Ret;
1435 }
1436
1437
1438 static VOID
1439 InitDevUsageActions(IN HWND hwndDlg,
1440 IN HWND hComboBox,
1441 IN PDEVADVPROP_INFO dap)
1442 {
1443 INT Index;
1444 UINT i;
1445 UINT Actions[] =
1446 {
1447 IDS_ENABLEDEVICE,
1448 IDS_DISABLEDEVICE,
1449 };
1450
1451 for (i = 0;
1452 i != sizeof(Actions) / sizeof(Actions[0]);
1453 i++)
1454 {
1455 /* fill in the device usage combo box */
1456 if (LoadString(hDllInstance,
1457 Actions[i],
1458 dap->szTemp,
1459 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1460 {
1461 Index = (INT)SendMessage(hComboBox,
1462 CB_ADDSTRING,
1463 0,
1464 (LPARAM)dap->szTemp);
1465 if (Index != CB_ERR)
1466 {
1467 SendMessage(hComboBox,
1468 CB_SETITEMDATA,
1469 (WPARAM)Index,
1470 (LPARAM)Actions[i]);
1471
1472 switch (Actions[i])
1473 {
1474 case IDS_ENABLEDEVICE:
1475 if (dap->DeviceStarted)
1476 {
1477 SendMessage(hComboBox,
1478 CB_SETCURSEL,
1479 (WPARAM)Index,
1480 0);
1481 }
1482 break;
1483
1484 case IDS_DISABLEDEVICE:
1485 if (!dap->DeviceStarted)
1486 {
1487 SendMessage(hComboBox,
1488 CB_SETCURSEL,
1489 (WPARAM)Index,
1490 0);
1491 }
1492 break;
1493
1494 default:
1495 break;
1496 }
1497 }
1498 }
1499 }
1500 }
1501
1502
1503 static UINT
1504 GetSelectedUsageAction(IN HWND hComboBox)
1505 {
1506 INT Index;
1507 UINT Ret = 0;
1508
1509 Index = (INT)SendMessage(hComboBox,
1510 CB_GETCURSEL,
1511 0,
1512 0);
1513 if (Index != CB_ERR)
1514 {
1515 INT iRet = (INT) SendMessage(hComboBox,
1516 CB_GETITEMDATA,
1517 (WPARAM)Index,
1518 0);
1519 if (iRet != CB_ERR)
1520 {
1521 Ret = (UINT)iRet;
1522 }
1523 }
1524
1525 return Ret;
1526 }
1527
1528
1529 static BOOL
1530 ApplyGeneralSettings(IN HWND hwndDlg,
1531 IN PDEVADVPROP_INFO dap)
1532 {
1533 BOOL Ret = FALSE;
1534
1535 if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
1536 {
1537 UINT SelectedUsageAction;
1538 BOOL NeedReboot = FALSE;
1539
1540 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
1541 IDC_DEVUSAGE));
1542 switch (SelectedUsageAction)
1543 {
1544 case IDS_ENABLEDEVICE:
1545 if (!dap->DeviceStarted)
1546 {
1547 Ret = EnableDevice(dap->DeviceInfoSet,
1548 &dap->DeviceInfoData,
1549 TRUE,
1550 0,
1551 &NeedReboot);
1552 }
1553 break;
1554
1555 case IDS_DISABLEDEVICE:
1556 if (dap->DeviceStarted)
1557 {
1558 Ret = EnableDevice(dap->DeviceInfoSet,
1559 &dap->DeviceInfoData,
1560 FALSE,
1561 0,
1562 &NeedReboot);
1563 }
1564 break;
1565
1566 default:
1567 break;
1568 }
1569
1570 if (Ret)
1571 {
1572 if (NeedReboot)
1573 {
1574 /* make PropertySheet() return PSM_REBOOTSYSTEM */
1575 PropSheet_RebootSystem(hwndDlg);
1576 }
1577 }
1578 else
1579 {
1580 /* FIXME - display an error message */
1581 DPRINT1("Failed to enable/disable device! LastError: %d\n",
1582 GetLastError());
1583 }
1584 }
1585 else
1586 Ret = !dap->DeviceUsageChanged;
1587
1588 /* disable the apply button */
1589 PropSheet_UnChanged(GetParent(hwndDlg),
1590 hwndDlg);
1591 dap->DeviceUsageChanged = FALSE;
1592 return Ret;
1593 }
1594
1595
1596 static VOID
1597 UpdateDevInfo(IN HWND hwndDlg,
1598 IN PDEVADVPROP_INFO dap,
1599 IN BOOL ReOpen)
1600 {
1601 HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
1602 CONFIGRET cr;
1603 ULONG Status, ProblemNumber;
1604 SP_DEVINSTALL_PARAMS_W InstallParams;
1605 UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
1606 BOOL bFlag, bDevActionAvailable = TRUE;
1607 BOOL bDrvInstalled = FALSE;
1608 DWORD iPage;
1609 HDEVINFO DeviceInfoSet = NULL;
1610 PSP_DEVINFO_DATA DeviceInfoData = NULL;
1611 PROPSHEETHEADER psh;
1612 DWORD nDriverPages = 0;
1613 BOOL RecalcPages = FALSE;
1614
1615 hPropSheetDlg = GetParent(hwndDlg);
1616
1617 if (dap->PageInitialized)
1618 {
1619 /* switch to the General page */
1620 PropSheet_SetCurSelByID(hPropSheetDlg,
1621 IDD_DEVICEGENERAL);
1622
1623 /* remove and destroy the existing device property sheet pages */
1624 if (dap->DevPropSheets != NULL)
1625 {
1626 for (iPage = 0;
1627 iPage != dap->nDevPropSheets;
1628 iPage++)
1629 {
1630 if (dap->DevPropSheets[iPage] != NULL)
1631 {
1632 PropSheet_RemovePage(hPropSheetDlg,
1633 (WPARAM) -1,
1634 dap->DevPropSheets[iPage]);
1635 RecalcPages = TRUE;
1636 }
1637 }
1638 }
1639 }
1640
1641 iPage = 0;
1642
1643 if (dap->FreeDevPropSheets)
1644 {
1645 /* don't free the array if it's the one allocated in
1646 DisplayDeviceAdvancedProperties */
1647 HeapFree(GetProcessHeap(),
1648 0,
1649 dap->DevPropSheets);
1650
1651 dap->FreeDevPropSheets = FALSE;
1652 }
1653
1654 dap->DevPropSheets = NULL;
1655 dap->nDevPropSheets = 0;
1656
1657 if (ReOpen)
1658 {
1659 /* create a new device info set and re-open the device */
1660 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1661 {
1662 SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
1663 }
1664
1665 dap->ParentDevInst = 0;
1666 dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
1667 hwndDlg,
1668 dap->lpMachineName,
1669 NULL);
1670 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1671 {
1672 if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
1673 dap->szDeviceID,
1674 hwndDlg,
1675 0,
1676 &dap->CurrentDeviceInfoData))
1677 {
1678 if (dap->CloseDevInst)
1679 {
1680 SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
1681 }
1682
1683 dap->CloseDevInst = TRUE;
1684 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
1685 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
1686 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1687 }
1688 else
1689 goto GetParentNode;
1690 }
1691 else
1692 {
1693 GetParentNode:
1694 /* get the parent node from the initial devinst */
1695 CM_Get_Parent_Ex(&dap->ParentDevInst,
1696 dap->DeviceInfoData.DevInst,
1697 0,
1698 dap->hMachine);
1699 }
1700
1701 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1702 {
1703 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1704 DeviceInfoData = &dap->CurrentDeviceInfoData;
1705 }
1706 else
1707 {
1708 DeviceInfoSet = dap->DeviceInfoSet;
1709 DeviceInfoData = &dap->DeviceInfoData;
1710 }
1711 }
1712 else
1713 {
1714 DeviceInfoSet = dap->DeviceInfoSet;
1715 DeviceInfoData = &dap->DeviceInfoData;
1716 }
1717
1718 dap->HasDriverPage = FALSE;
1719 dap->HasResourcePage = FALSE;
1720 dap->HasPowerPage = FALSE;
1721 if (IsDriverInstalled(DeviceInfoData->DevInst,
1722 dap->hMachine,
1723 &bDrvInstalled) &&
1724 bDrvInstalled)
1725 {
1726 if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
1727 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
1728 DIF_ADDPROPERTYPAGE_ADVANCED),
1729 DeviceInfoSet,
1730 DeviceInfoData))
1731 {
1732 /* get install params */
1733 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1734 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
1735 DeviceInfoData,
1736 &InstallParams))
1737 {
1738 /* zero the flags */
1739 InstallParams.Flags = 0;
1740 }
1741
1742 dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
1743 dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
1744 dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
1745 }
1746 }
1747
1748 /* get the device icon */
1749 if (dap->hDevIcon != NULL)
1750 {
1751 DestroyIcon(dap->hDevIcon);
1752 dap->hDevIcon = NULL;
1753 }
1754 if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
1755 &dap->hDevIcon,
1756 NULL))
1757 {
1758 dap->hDevIcon = NULL;
1759 }
1760
1761 /* get the device name */
1762 if (GetDeviceDescriptionString(DeviceInfoSet,
1763 DeviceInfoData,
1764 dap->szDevName,
1765 sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
1766 {
1767 PropSheet_SetTitle(hPropSheetDlg,
1768 PSH_PROPTITLE,
1769 dap->szDevName);
1770 }
1771
1772 /* set the device image */
1773 SendDlgItemMessage(hwndDlg,
1774 IDC_DEVICON,
1775 STM_SETICON,
1776 (WPARAM)dap->hDevIcon,
1777 0);
1778
1779 /* set the device name edit control text */
1780 SetDlgItemText(hwndDlg,
1781 IDC_DEVNAME,
1782 dap->szDevName);
1783
1784 /* set the device type edit control text */
1785 if (GetDeviceTypeString(DeviceInfoData,
1786 dap->szTemp,
1787 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1788 {
1789 SetDlgItemText(hwndDlg,
1790 IDC_DEVTYPE,
1791 dap->szTemp);
1792 }
1793
1794 /* set the device manufacturer edit control text */
1795 if (GetDeviceManufacturerString(DeviceInfoSet,
1796 DeviceInfoData,
1797 dap->szTemp,
1798 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1799 {
1800 SetDlgItemText(hwndDlg,
1801 IDC_DEVMANUFACTURER,
1802 dap->szTemp);
1803 }
1804
1805 /* set the device location edit control text */
1806 if (GetDeviceLocationString(DeviceInfoSet,
1807 DeviceInfoData,
1808 dap->ParentDevInst,
1809 dap->szTemp,
1810 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1811 {
1812 SetDlgItemText(hwndDlg,
1813 IDC_DEVLOCATION,
1814 dap->szTemp);
1815 }
1816
1817 /* set the device status edit control text */
1818 if (GetDeviceStatusString(DeviceInfoData->DevInst,
1819 dap->hMachine,
1820 dap->szTemp,
1821 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1822 {
1823 SetDlgItemText(hwndDlg,
1824 IDC_DEVSTATUS,
1825 dap->szTemp);
1826 }
1827
1828 /* set the device troubleshoot button text and disable it if necessary */
1829 hDevProbBtn = GetDlgItem(hwndDlg,
1830 IDC_DEVPROBLEM);
1831 cr = CM_Get_DevNode_Status_Ex(&Status,
1832 &ProblemNumber,
1833 DeviceInfoData->DevInst,
1834 0,
1835 dap->hMachine);
1836 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
1837 {
1838 switch (ProblemNumber)
1839 {
1840 case CM_PROB_DEVLOADER_FAILED:
1841 {
1842 /* FIXME - only if it's not a root bus devloader,
1843 disable the button otherwise */
1844 TroubleShootStrId = IDS_UPDATEDRV;
1845 break;
1846 }
1847
1848 case CM_PROB_OUT_OF_MEMORY:
1849 case CM_PROB_ENTRY_IS_WRONG_TYPE:
1850 case CM_PROB_LACKED_ARBITRATOR:
1851 case CM_PROB_FAILED_START:
1852 case CM_PROB_LIAR:
1853 case CM_PROB_UNKNOWN_RESOURCE:
1854 {
1855 TroubleShootStrId = IDS_UPDATEDRV;
1856 break;
1857 }
1858
1859 case CM_PROB_BOOT_CONFIG_CONFLICT:
1860 case CM_PROB_NORMAL_CONFLICT:
1861 case CM_PROB_REENUMERATION:
1862 {
1863 /* FIXME - Troubleshoot conflict */
1864 break;
1865 }
1866
1867 case CM_PROB_FAILED_FILTER:
1868 case CM_PROB_REINSTALL:
1869 case CM_PROB_FAILED_INSTALL:
1870 {
1871 TroubleShootStrId = IDS_REINSTALLDRV;
1872 break;
1873 }
1874
1875 case CM_PROB_DEVLOADER_NOT_FOUND:
1876 {
1877 /* FIXME - 4 cases:
1878 1) if it's a missing system devloader:
1879 - disable the button (Reinstall Driver)
1880 2) if it's not a system devloader but still missing:
1881 - Reinstall Driver
1882 3) if it's not a system devloader but the file can be found:
1883 - Update Driver
1884 4) if it's a missing or empty software key
1885 - Update Driver
1886 */
1887 break;
1888 }
1889
1890 case CM_PROB_INVALID_DATA:
1891 case CM_PROB_PARTIAL_LOG_CONF:
1892 case CM_PROB_NO_VALID_LOG_CONF:
1893 case CM_PROB_HARDWARE_DISABLED:
1894 case CM_PROB_CANT_SHARE_IRQ:
1895 case CM_PROB_TRANSLATION_FAILED:
1896 case CM_PROB_SYSTEM_SHUTDOWN:
1897 case CM_PROB_PHANTOM:
1898 bDevActionAvailable = FALSE;
1899 break;
1900
1901 case CM_PROB_NOT_VERIFIED:
1902 case CM_PROB_DEVICE_NOT_THERE:
1903 /* FIXME - search hardware */
1904 break;
1905
1906 case CM_PROB_NEED_RESTART:
1907 case CM_PROB_WILL_BE_REMOVED:
1908 case CM_PROB_MOVED:
1909 case CM_PROB_TOO_EARLY:
1910 case CM_PROB_DISABLED_SERVICE:
1911 TroubleShootStrId = IDS_REBOOT;
1912 break;
1913
1914 case CM_PROB_REGISTRY:
1915 /* FIXME - check registry? */
1916 break;
1917
1918 case CM_PROB_DISABLED:
1919 /* if device was disabled by the user: */
1920 TroubleShootStrId = IDS_ENABLEDEV;
1921 /* FIXME - otherwise disable button because the device was
1922 disabled by the system*/
1923 break;
1924
1925 case CM_PROB_DEVLOADER_NOT_READY:
1926 /* FIXME - if it's a graphics adapter:
1927 - if it's a a secondary adapter and the main adapter
1928 couldn't be found
1929 - disable button
1930 - else
1931 - Properties
1932 - else
1933 - Update driver
1934 */
1935 break;
1936
1937 case CM_PROB_FAILED_ADD:
1938 TroubleShootStrId = IDS_PROPERTIES;
1939 break;
1940 }
1941 }
1942
1943 if (LoadString(hDllInstance,
1944 TroubleShootStrId,
1945 dap->szTemp,
1946 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
1947 {
1948 SetWindowText(hDevProbBtn,
1949 dap->szTemp);
1950 }
1951 EnableWindow(hDevProbBtn,
1952 dap->IsAdmin && bDevActionAvailable);
1953
1954 /* check if the device can be enabled/disabled */
1955 hDevUsage = GetDlgItem(hwndDlg,
1956 IDC_DEVUSAGE);
1957
1958 dap->CanDisable = FALSE;
1959 dap->DeviceStarted = FALSE;
1960
1961 if (CanDisableDevice(DeviceInfoData->DevInst,
1962 dap->hMachine,
1963 &bFlag))
1964 {
1965 dap->CanDisable = bFlag;
1966 }
1967
1968 if (IsDeviceStarted(DeviceInfoData->DevInst,
1969 dap->hMachine,
1970 &bFlag))
1971 {
1972 dap->DeviceStarted = bFlag;
1973 }
1974
1975 /* enable/disable the device usage controls */
1976 EnableWindow(GetDlgItem(hwndDlg,
1977 IDC_DEVUSAGELABEL),
1978 dap->CanDisable && dap->IsAdmin);
1979 EnableWindow(hDevUsage,
1980 dap->CanDisable && dap->IsAdmin);
1981
1982 /* clear the combobox */
1983 SendMessage(hDevUsage,
1984 CB_RESETCONTENT,
1985 0,
1986 0);
1987 if (dap->CanDisable)
1988 {
1989 InitDevUsageActions(hwndDlg,
1990 hDevUsage,
1991 dap);
1992 }
1993
1994 /* find out how many new device property sheets to add.
1995 fake a PROPSHEETHEADER structure, we don't plan to
1996 call PropertySheet again!*/
1997 psh.dwSize = sizeof(PROPSHEETHEADER);
1998 psh.dwFlags = 0;
1999 psh.nPages = 0;
2000
2001 /* get the number of device property sheets for the device */
2002 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2003 DeviceInfoData,
2004 &psh,
2005 0,
2006 &nDriverPages,
2007 dap->PropertySheetType) &&
2008 nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2009 {
2010 dap->nDevPropSheets += nDriverPages;
2011 }
2012 else
2013 {
2014 nDriverPages = 0;
2015 }
2016
2017 /* include the driver page */
2018 if (dap->HasDriverPage)
2019 dap->nDevPropSheets++;
2020
2021 /* include the details page */
2022 dap->nDevPropSheets++;
2023
2024 /* add the device property sheets */
2025 if (dap->nDevPropSheets != 0)
2026 {
2027 dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
2028 HEAP_ZERO_MEMORY,
2029 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
2030 if (dap->DevPropSheets != NULL)
2031 {
2032 if (nDriverPages != 0)
2033 {
2034 psh.phpage = dap->DevPropSheets;
2035
2036 /* query the device property sheet pages to add */
2037 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
2038 DeviceInfoData,
2039 &psh,
2040 dap->nDevPropSheets,
2041 NULL,
2042 dap->PropertySheetType))
2043 {
2044 /* add the property sheets */
2045 for (iPage = 0;
2046 iPage != nDriverPages;
2047 iPage++)
2048 {
2049 if (PropSheet_AddPage(hPropSheetDlg,
2050 dap->DevPropSheets[iPage]))
2051 {
2052 RecalcPages = TRUE;
2053 }
2054 }
2055
2056 dap->FreeDevPropSheets = TRUE;
2057 }
2058 else
2059 {
2060 /* cleanup, we were unable to get the device property sheets */
2061 iPage = nDriverPages;
2062 dap->nDevPropSheets -= nDriverPages;
2063 nDriverPages = 0;
2064 }
2065 }
2066 else
2067 iPage = 0;
2068
2069 /* add the driver page if necessary */
2070 if (dap->HasDriverPage)
2071 {
2072 PROPSHEETPAGE pspDriver = {0};
2073 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
2074 pspDriver.dwFlags = PSP_DEFAULT;
2075 pspDriver.hInstance = hDllInstance;
2076 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
2077 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
2078 pspDriver.lParam = (LPARAM)dap;
2079 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
2080 if (dap->DevPropSheets[iPage] != NULL)
2081 {
2082 if (PropSheet_AddPage(hPropSheetDlg,
2083 dap->DevPropSheets[iPage]))
2084 {
2085 iPage++;
2086 RecalcPages = TRUE;
2087 }
2088 else
2089 {
2090 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2091 dap->DevPropSheets[iPage] = NULL;
2092 }
2093 }
2094 }
2095
2096 if (1)
2097 {
2098 PROPSHEETPAGE pspDetails = {0};
2099 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
2100 pspDetails.dwFlags = PSP_DEFAULT;
2101 pspDetails.hInstance = hDllInstance;
2102 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
2103 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
2104 pspDetails.lParam = (LPARAM)dap;
2105 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
2106 if (dap->DevPropSheets[iPage] != NULL)
2107 {
2108 if (PropSheet_AddPage(hPropSheetDlg,
2109 dap->DevPropSheets[iPage]))
2110 {
2111 iPage++;
2112 RecalcPages = TRUE;
2113 }
2114 else
2115 {
2116 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
2117 dap->DevPropSheets[iPage] = NULL;
2118 }
2119 }
2120 }
2121
2122 /* FIXME: Add the resources page */
2123
2124 /* FIXME: Add the power page */
2125 }
2126 else
2127 dap->nDevPropSheets = 0;
2128 }
2129
2130 if (RecalcPages)
2131 {
2132 PropSheet_RecalcPageSizes(hPropSheetDlg);
2133 }
2134
2135 /* finally, disable the apply button */
2136 PropSheet_UnChanged(hPropSheetDlg,
2137 hwndDlg);
2138 dap->DeviceUsageChanged = FALSE;
2139 }
2140
2141
2142 static LRESULT
2143 CALLBACK
2144 DlgParentSubWndProc(IN HWND hwnd,
2145 IN UINT uMsg,
2146 IN WPARAM wParam,
2147 IN LPARAM lParam)
2148 {
2149 PDEVADVPROP_INFO dap;
2150
2151 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
2152 L"DevMgrDevChangeSub");
2153 if (dap != NULL)
2154 {
2155 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
2156 {
2157 SendMessage(dap->hWndGeneralPage,
2158 WM_DEVICECHANGE,
2159 wParam,
2160 lParam);
2161 }
2162
2163 /* pass the message the the old window proc */
2164 return CallWindowProc(dap->ParentOldWndProc,
2165 hwnd,
2166 uMsg,
2167 wParam,
2168 lParam);
2169 }
2170 else
2171 {
2172 /* this is not a good idea if the subclassed window was an ansi
2173 window, but we failed finding out the previous window proc
2174 so we can't use CallWindowProc. This should rarely - if ever -
2175 happen. */
2176
2177 return DefWindowProc(hwnd,
2178 uMsg,
2179 wParam,
2180 lParam);
2181 }
2182 }
2183
2184
2185 static INT_PTR
2186 CALLBACK
2187 AdvPropGeneralDlgProc(IN HWND hwndDlg,
2188 IN UINT uMsg,
2189 IN WPARAM wParam,
2190 IN LPARAM lParam)
2191 {
2192 PDEVADVPROP_INFO dap;
2193 INT_PTR Ret = FALSE;
2194
2195 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
2196 DWL_USER);
2197
2198 if (dap != NULL || uMsg == WM_INITDIALOG)
2199 {
2200 switch (uMsg)
2201 {
2202 case WM_COMMAND:
2203 {
2204 switch (LOWORD(wParam))
2205 {
2206 case IDC_DEVUSAGE:
2207 {
2208 if (HIWORD(wParam) == CBN_SELCHANGE)
2209 {
2210 PropSheet_Changed(GetParent(hwndDlg),
2211 hwndDlg);
2212 dap->DeviceUsageChanged = TRUE;
2213 }
2214 break;
2215 }
2216
2217 case IDC_DEVPROBLEM:
2218 {
2219 if (dap->IsAdmin)
2220 {
2221 /* display the device problem wizard */
2222 ShowDeviceProblemWizard(hwndDlg,
2223 dap->DeviceInfoSet,
2224 &dap->DeviceInfoData,
2225 dap->hMachine);
2226 }
2227 break;
2228 }
2229 }
2230 break;
2231 }
2232
2233 case WM_NOTIFY:
2234 {
2235 NMHDR *hdr = (NMHDR*)lParam;
2236 switch (hdr->code)
2237 {
2238 case PSN_APPLY:
2239 ApplyGeneralSettings(hwndDlg,
2240 dap);
2241 break;
2242 }
2243 break;
2244 }
2245
2246 case WM_INITDIALOG:
2247 {
2248 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
2249 if (dap != NULL)
2250 {
2251 HWND hWndParent;
2252
2253 dap->hWndGeneralPage = hwndDlg;
2254
2255 SetWindowLongPtr(hwndDlg,
2256 DWL_USER,
2257 (DWORD_PTR)dap);
2258
2259 /* subclass the parent window to always receive
2260 WM_DEVICECHANGE messages */
2261 hWndParent = GetParent(hwndDlg);
2262 if (hWndParent != NULL)
2263 {
2264 /* subclass the parent window. This is not safe
2265 if the parent window belongs to another thread! */
2266 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
2267 GWLP_WNDPROC,
2268 (LONG_PTR)DlgParentSubWndProc);
2269
2270 if (dap->ParentOldWndProc != NULL &&
2271 SetProp(hWndParent,
2272 L"DevMgrDevChangeSub",
2273 (HANDLE)dap))
2274 {
2275 dap->hWndParent = hWndParent;
2276 }
2277 }
2278
2279 /* do not call UpdateDevInfo directly in here because it modifies
2280 the pages of the property sheet! */
2281 PostMessage(hwndDlg,
2282 PM_INITIALIZE,
2283 0,
2284 0);
2285 }
2286 Ret = TRUE;
2287 break;
2288 }
2289
2290 case WM_DEVICECHANGE:
2291 {
2292 /* FIXME - don't call UpdateDevInfo for all events */
2293 UpdateDevInfo(hwndDlg,
2294 dap,
2295 TRUE);
2296 Ret = TRUE;
2297 break;
2298 }
2299
2300 case PM_INITIALIZE:
2301 {
2302 UpdateDevInfo(hwndDlg,
2303 dap,
2304 FALSE);
2305 dap->PageInitialized = TRUE;
2306 break;
2307 }
2308
2309 case WM_DESTROY:
2310 {
2311 /* restore the old window proc of the subclassed parent window */
2312 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
2313 {
2314 if (SetWindowLongPtr(dap->hWndParent,
2315 GWLP_WNDPROC,
2316 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
2317 {
2318 RemoveProp(dap->hWndParent,
2319 L"DevMgrDevChangeSub");
2320 }
2321 }
2322 break;
2323 }
2324 }
2325 }
2326
2327 return Ret;
2328 }
2329
2330
2331 INT_PTR
2332 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
2333 IN LPCWSTR lpDeviceID OPTIONAL,
2334 IN HDEVINFO DeviceInfoSet,
2335 IN PSP_DEVINFO_DATA DeviceInfoData,
2336 IN HINSTANCE hComCtl32,
2337 IN LPCWSTR lpMachineName,
2338 IN DWORD dwFlags)
2339 {
2340 PROPSHEETHEADER psh = {0};
2341 PROPSHEETPAGE pspGeneral = {0};
2342 PPROPERTYSHEETW pPropertySheetW;
2343 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
2344 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
2345 PDEVADVPROP_INFO DevAdvPropInfo;
2346 HMACHINE hMachine = NULL;
2347 DWORD DevIdSize = 0;
2348 INT_PTR Ret = -1;
2349
2350 /* we don't want to statically link against comctl32, so find the
2351 functions we need dynamically */
2352 pPropertySheetW =
2353 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
2354 "PropertySheetW");
2355 pCreatePropertySheetPageW =
2356 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
2357 "CreatePropertySheetPageW");
2358 pDestroyPropertySheetPage =
2359 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
2360 "DestroyPropertySheetPage");
2361 if (pPropertySheetW == NULL ||
2362 pCreatePropertySheetPageW == NULL ||
2363 pDestroyPropertySheetPage == NULL)
2364 {
2365 return -1;
2366 }
2367
2368 if (lpDeviceID == NULL)
2369 {
2370 /* find out how much size is needed for the device id */
2371 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
2372 DeviceInfoData,
2373 NULL,
2374 0,
2375 &DevIdSize))
2376 {
2377 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
2378 return -1;
2379 }
2380
2381 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2382 {
2383 return -1;
2384 }
2385 }
2386 else
2387 {
2388 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
2389 }
2390
2391 if (lpMachineName != NULL && lpMachineName[0] != L'\0')
2392 {
2393 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
2394 &hMachine);
2395 if (cr != CR_SUCCESS)
2396 {
2397 return -1;
2398 }
2399 }
2400
2401 /* create the internal structure associated with the "General",
2402 "Driver", ... pages */
2403 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
2404 HEAP_ZERO_MEMORY,
2405 FIELD_OFFSET(DEVADVPROP_INFO,
2406 szDeviceID) +
2407 (DevIdSize * sizeof(WCHAR)));
2408 if (DevAdvPropInfo == NULL)
2409 {
2410 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2411 goto Cleanup;
2412 }
2413
2414 if (lpDeviceID == NULL)
2415 {
2416 /* read the device instance id */
2417 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
2418 DeviceInfoData,
2419 DevAdvPropInfo->szDeviceID,
2420 DevIdSize,
2421 NULL))
2422 {
2423 goto Cleanup;
2424 }
2425 }
2426 else
2427 {
2428 /* copy the device instance id supplied by the caller */
2429 wcscpy(DevAdvPropInfo->szDeviceID,
2430 lpDeviceID);
2431 }
2432
2433 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
2434 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
2435 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2436 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2437
2438 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
2439 DevAdvPropInfo->hMachine = hMachine;
2440 DevAdvPropInfo->lpMachineName = lpMachineName;
2441 DevAdvPropInfo->szDevName[0] = L'\0';
2442 DevAdvPropInfo->hComCtl32 = hComCtl32;
2443 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
2444 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
2445
2446 DevAdvPropInfo->IsAdmin = IsUserAdmin();
2447 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
2448
2449 psh.dwSize = sizeof(PROPSHEETHEADER);
2450 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2451 psh.hwndParent = hWndParent;
2452 psh.pszCaption = DevAdvPropInfo->szDevName;
2453
2454 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2455 DIGCDP_FLAG_REMOTE_ADVANCED :
2456 DIGCDP_FLAG_ADVANCED;
2457
2458 psh.phpage = HeapAlloc(GetProcessHeap(),
2459 HEAP_ZERO_MEMORY,
2460 1 * sizeof(HPROPSHEETPAGE));
2461 if (psh.phpage == NULL)
2462 {
2463 goto Cleanup;
2464 }
2465
2466 /* add the "General" property sheet */
2467 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2468 pspGeneral.dwFlags = PSP_DEFAULT;
2469 pspGeneral.hInstance = hDllInstance;
2470 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2471 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2472 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2473 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2474 if (psh.phpage[psh.nPages] != NULL)
2475 {
2476 psh.nPages++;
2477 }
2478
2479 DevAdvPropInfo->nDevPropSheets = psh.nPages;
2480
2481 if (psh.nPages != 0)
2482 {
2483 Ret = pPropertySheetW(&psh);
2484
2485 /* NOTE: no need to destroy the property sheets anymore! */
2486 }
2487 else
2488 {
2489 UINT i;
2490
2491 Cleanup:
2492 /* in case of failure the property sheets must be destroyed */
2493 if (psh.phpage != NULL)
2494 {
2495 for (i = 0;
2496 i < psh.nPages;
2497 i++)
2498 {
2499 if (psh.phpage[i] != NULL)
2500 {
2501 pDestroyPropertySheetPage(psh.phpage[i]);
2502 }
2503 }
2504 }
2505 }
2506
2507 if (DevAdvPropInfo != NULL)
2508 {
2509 if (DevAdvPropInfo->FreeDevPropSheets)
2510 {
2511 /* don't free the array if it's the one allocated in
2512 DisplayDeviceAdvancedProperties */
2513 HeapFree(GetProcessHeap(),
2514 0,
2515 DevAdvPropInfo->DevPropSheets);
2516 }
2517
2518 if (DevAdvPropInfo->CloseDevInst)
2519 {
2520 /* close the device info set in case a new one was created */
2521 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2522 }
2523
2524 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2525 {
2526 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2527 }
2528
2529 if (DevAdvPropInfo->hDevIcon != NULL)
2530 {
2531 DestroyIcon(DevAdvPropInfo->hDevIcon);
2532 }
2533
2534 HeapFree(GetProcessHeap(),
2535 0,
2536 DevAdvPropInfo);
2537 }
2538
2539 if (psh.phpage != NULL)
2540 {
2541 HeapFree(GetProcessHeap(),
2542 0,
2543 psh.phpage);
2544 }
2545
2546 if (hMachine != NULL)
2547 {
2548 CM_Disconnect_Machine(hMachine);
2549 }
2550
2551 return Ret;
2552 }
2553
2554
2555 static BOOL
2556 GetDeviceAndComputerName(LPWSTR lpString,
2557 WCHAR szDeviceID[],
2558 WCHAR szMachineName[])
2559 {
2560 BOOL ret = FALSE;
2561
2562 szDeviceID[0] = L'\0';
2563 szMachineName[0] = L'\0';
2564
2565 while (*lpString != L'\0')
2566 {
2567 if (*lpString == L'/')
2568 {
2569 lpString++;
2570 if(!_wcsnicmp(lpString, L"DeviceID", 8))
2571 {
2572 lpString += 9;
2573 if (*lpString != L'\0')
2574 {
2575 int i = 0;
2576 while ((*lpString != L' ') &&
2577 (*lpString != L'\0') &&
2578 (i <= MAX_DEVICE_ID_LEN))
2579 {
2580 szDeviceID[i++] = *lpString++;
2581 }
2582 szDeviceID[i] = L'\0';
2583 ret = TRUE;
2584 }
2585 }
2586 else if (!_wcsnicmp(lpString, L"MachineName", 11))
2587 {
2588 lpString += 12;
2589 if (*lpString != L'\0')
2590 {
2591 int i = 0;
2592 while ((*lpString != L' ') &&
2593 (*lpString != L'\0') &&
2594 (i <= MAX_COMPUTERNAME_LENGTH))
2595 {
2596 szMachineName[i++] = *lpString++;
2597 }
2598 szMachineName[i] = L'\0';
2599 }
2600 }
2601 /* knock the pointer back one and let the next
2602 * pointer deal with incrementing, otherwise we
2603 * go past the end of the string */
2604 lpString--;
2605 }
2606 lpString++;
2607 }
2608
2609 return ret;
2610 }
2611
2612
2613 /***************************************************************************
2614 * NAME EXPORTED
2615 * DeviceAdvancedPropertiesW
2616 *
2617 * DESCRIPTION
2618 * Invokes the device properties dialog, this version may add some property pages
2619 * for some devices
2620 *
2621 * ARGUMENTS
2622 * hWndParent: Handle to the parent window
2623 * lpMachineName: Machine Name, NULL is the local machine
2624 * lpDeviceID: Specifies the device whose properties are to be shown
2625 *
2626 * RETURN VALUE
2627 * Always returns -1, a call to GetLastError returns 0 if successful
2628 *
2629 * @implemented
2630 */
2631 INT_PTR
2632 WINAPI
2633 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL,
2634 IN LPCWSTR lpMachineName OPTIONAL,
2635 IN LPCWSTR lpDeviceID)
2636 {
2637 HDEVINFO hDevInfo;
2638 SP_DEVINFO_DATA DevInfoData;
2639 HINSTANCE hComCtl32;
2640 INT_PTR Ret = -1;
2641
2642 if (lpDeviceID == NULL)
2643 {
2644 SetLastError(ERROR_INVALID_PARAMETER);
2645 return FALSE;
2646 }
2647
2648 /* dynamically load comctl32 */
2649 hComCtl32 = LoadAndInitComctl32();
2650 if (hComCtl32 != NULL)
2651 {
2652 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2653 hWndParent,
2654 lpMachineName,
2655 NULL);
2656 if (hDevInfo != INVALID_HANDLE_VALUE)
2657 {
2658 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2659 if (SetupDiOpenDeviceInfo(hDevInfo,
2660 lpDeviceID,
2661 hWndParent,
2662 0,
2663 &DevInfoData))
2664 {
2665 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2666 lpDeviceID,
2667 hDevInfo,
2668 &DevInfoData,
2669 hComCtl32,
2670 lpMachineName,
2671 0);
2672 }
2673
2674 SetupDiDestroyDeviceInfoList(hDevInfo);
2675 }
2676
2677 FreeLibrary(hComCtl32);
2678 }
2679
2680 return Ret;
2681 }
2682
2683
2684 /***************************************************************************
2685 * NAME EXPORTED
2686 * DeviceAdvancedPropertiesA
2687 *
2688 * DESCRIPTION
2689 * Invokes the device properties dialog, this version may add some property pages
2690 * for some devices
2691 *
2692 * ARGUMENTS
2693 * hWndParent: Handle to the parent window
2694 * lpMachineName: Machine Name, NULL is the local machine
2695 * lpDeviceID: Specifies the device whose properties are to be shown
2696 *
2697 * RETURN VALUE
2698 * Always returns -1, a call to GetLastError returns 0 if successful
2699 *
2700 * @implemented
2701 */
2702 INT_PTR
2703 WINAPI
2704 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL,
2705 IN LPCSTR lpMachineName OPTIONAL,
2706 IN LPCSTR lpDeviceID)
2707 {
2708 LPWSTR lpMachineNameW = NULL;
2709 LPWSTR lpDeviceIDW = NULL;
2710 INT_PTR Ret = -1;
2711
2712 if (lpMachineName != NULL)
2713 {
2714 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2715 CP_ACP)))
2716 {
2717 goto Cleanup;
2718 }
2719 }
2720 if (lpDeviceID != NULL)
2721 {
2722 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2723 CP_ACP)))
2724 {
2725 goto Cleanup;
2726 }
2727 }
2728
2729 Ret = DeviceAdvancedPropertiesW(hWndParent,
2730 lpMachineNameW,
2731 lpDeviceIDW);
2732
2733 Cleanup:
2734 if (lpMachineNameW != NULL)
2735 {
2736 HeapFree(GetProcessHeap(),
2737 0,
2738 lpMachineNameW);
2739 }
2740 if (lpDeviceIDW != NULL)
2741 {
2742 HeapFree(GetProcessHeap(),
2743 0,
2744 lpDeviceIDW);
2745 }
2746
2747 return Ret;
2748 }
2749
2750
2751 /***************************************************************************
2752 * NAME EXPORTED
2753 * DevicePropertiesExA
2754 *
2755 * DESCRIPTION
2756 * Invokes the extended device properties dialog
2757 *
2758 * ARGUMENTS
2759 * hWndParent: Handle to the parent window
2760 * lpMachineName: Machine Name, NULL is the local machine
2761 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2762 * bShowDevMgr is nonzero
2763 * dwFlags: This parameter can be a combination of the following flags:
2764 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2765 * the default device status action button
2766 * to be clicked (Troubleshoot, Enable
2767 * Device, etc)
2768 * bShowDevMgr: If non-zero it displays the device manager instead of
2769 * the advanced device property dialog
2770 *
2771 * RETURN VALUE
2772 * 1: if bShowDevMgr is non-zero and no error occured
2773 * -1: a call to GetLastError returns 0 if successful
2774 *
2775 * @implemented
2776 */
2777 INT_PTR
2778 WINAPI
2779 DevicePropertiesExA(IN HWND hWndParent OPTIONAL,
2780 IN LPCSTR lpMachineName OPTIONAL,
2781 IN LPCSTR lpDeviceID OPTIONAL,
2782 IN DWORD dwFlags OPTIONAL,
2783 IN BOOL bShowDevMgr)
2784 {
2785 LPWSTR lpMachineNameW = NULL;
2786 LPWSTR lpDeviceIDW = NULL;
2787 INT_PTR Ret = -1;
2788
2789 if (lpMachineName != NULL)
2790 {
2791 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2792 CP_ACP)))
2793 {
2794 goto Cleanup;
2795 }
2796 }
2797 if (lpDeviceID != NULL)
2798 {
2799 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2800 CP_ACP)))
2801 {
2802 goto Cleanup;
2803 }
2804 }
2805
2806 Ret = DevicePropertiesExW(hWndParent,
2807 lpMachineNameW,
2808 lpDeviceIDW,
2809 dwFlags,
2810 bShowDevMgr);
2811
2812 Cleanup:
2813 if (lpMachineNameW != NULL)
2814 {
2815 HeapFree(GetProcessHeap(),
2816 0,
2817 lpMachineNameW);
2818 }
2819 if (lpDeviceIDW != NULL)
2820 {
2821 HeapFree(GetProcessHeap(),
2822 0,
2823 lpDeviceIDW);
2824 }
2825
2826 return Ret;
2827 }
2828
2829
2830 /***************************************************************************
2831 * NAME EXPORTED
2832 * DevicePropertiesExW
2833 *
2834 * DESCRIPTION
2835 * Invokes the extended device properties dialog
2836 *
2837 * ARGUMENTS
2838 * hWndParent: Handle to the parent window
2839 * lpMachineName: Machine Name, NULL is the local machine
2840 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2841 * bShowDevMgr is nonzero
2842 * dwFlags: This parameter can be a combination of the following flags:
2843 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2844 * the default device status action button
2845 * to be clicked (Troubleshoot, Enable
2846 * Device, etc)
2847 * bShowDevMgr: If non-zero it displays the device manager instead of
2848 * the advanced device property dialog
2849 *
2850 * RETURN VALUE
2851 * 1: if bShowDevMgr is non-zero and no error occured
2852 * -1: a call to GetLastError returns 0 if successful
2853 *
2854 * @implemented
2855 */
2856 INT_PTR
2857 WINAPI
2858 DevicePropertiesExW(IN HWND hWndParent OPTIONAL,
2859 IN LPCWSTR lpMachineName OPTIONAL,
2860 IN LPCWSTR lpDeviceID OPTIONAL,
2861 IN DWORD dwFlags OPTIONAL,
2862 IN BOOL bShowDevMgr)
2863 {
2864 INT_PTR Ret = -1;
2865
2866 if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
2867 {
2868 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
2869 dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
2870 SetLastError(ERROR_INVALID_FLAGS);
2871 return -1;
2872 }
2873
2874 if (bShowDevMgr)
2875 {
2876 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
2877 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2878 }
2879 else
2880 {
2881 HDEVINFO hDevInfo;
2882 SP_DEVINFO_DATA DevInfoData;
2883 HINSTANCE hComCtl32;
2884
2885 if (lpDeviceID == NULL)
2886 {
2887 SetLastError(ERROR_INVALID_PARAMETER);
2888 return -1;
2889 }
2890
2891 /* dynamically load comctl32 */
2892 hComCtl32 = LoadAndInitComctl32();
2893 if (hComCtl32 != NULL)
2894 {
2895 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2896 hWndParent,
2897 lpMachineName,
2898 NULL);
2899 if (hDevInfo != INVALID_HANDLE_VALUE)
2900 {
2901 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2902 if (SetupDiOpenDeviceInfo(hDevInfo,
2903 lpDeviceID,
2904 hWndParent,
2905 0,
2906 &DevInfoData))
2907 {
2908 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2909 lpDeviceID,
2910 hDevInfo,
2911 &DevInfoData,
2912 hComCtl32,
2913 lpMachineName,
2914 dwFlags);
2915 }
2916
2917 SetupDiDestroyDeviceInfoList(hDevInfo);
2918 }
2919
2920 FreeLibrary(hComCtl32);
2921 }
2922 }
2923
2924 return Ret;
2925 }
2926
2927
2928 /***************************************************************************
2929 * NAME EXPORTED
2930 * DevicePropertiesA
2931 *
2932 * DESCRIPTION
2933 * Invokes the device properties dialog directly
2934 *
2935 * ARGUMENTS
2936 * hWndParent: Handle to the parent window
2937 * lpMachineName: Machine Name, NULL is the local machine
2938 * lpDeviceID: Specifies the device whose properties are to be shown
2939 * bShowDevMgr: If non-zero it displays the device manager instead of
2940 * the device property dialog
2941 *
2942 * RETURN VALUE
2943 * >=0: if no errors occured
2944 * -1: if errors occured
2945 *
2946 * REVISIONS
2947 *
2948 * @implemented
2949 */
2950 int
2951 WINAPI
2952 DevicePropertiesA(HWND hWndParent,
2953 LPCSTR lpMachineName,
2954 LPCSTR lpDeviceID,
2955 BOOL bShowDevMgr)
2956 {
2957 return DevicePropertiesExA(hWndParent,
2958 lpMachineName,
2959 lpDeviceID,
2960 DPF_EXTENDED,
2961 bShowDevMgr);
2962 }
2963
2964
2965 /***************************************************************************
2966 * NAME EXPORTED
2967 * DevicePropertiesW
2968 *
2969 * DESCRIPTION
2970 * Invokes the device properties dialog directly
2971 *
2972 * ARGUMENTS
2973 * hWndParent: Handle to the parent window
2974 * lpMachineName: Machine Name, NULL is the local machine
2975 * lpDeviceID: Specifies the device whose properties are to be shown
2976 * bShowDevMgr: If non-zero it displays the device manager instead of
2977 * the device property dialog
2978 *
2979 * RETURN VALUE
2980 * >=0: if no errors occured
2981 * -1: if errors occured
2982 *
2983 * REVISIONS
2984 *
2985 * @implemented
2986 */
2987 int
2988 WINAPI
2989 DevicePropertiesW(HWND hWndParent,
2990 LPCWSTR lpMachineName,
2991 LPCWSTR lpDeviceID,
2992 BOOL bShowDevMgr)
2993 {
2994 return DevicePropertiesExW(hWndParent,
2995 lpMachineName,
2996 lpDeviceID,
2997 DPF_EXTENDED,
2998 bShowDevMgr);
2999 }
3000
3001
3002 /***************************************************************************
3003 * NAME EXPORTED
3004 * DeviceProperties_RunDLLA
3005 *
3006 * DESCRIPTION
3007 * Invokes the device properties dialog
3008 *
3009 * ARGUMENTS
3010 * hWndParent: Handle to the parent window
3011 * hInst: Handle to the application instance
3012 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
3013 * also see NOTEs
3014 * nCmdShow: Specifies how the window should be shown
3015 *
3016 * RETURN VALUE
3017 *
3018 * REVISIONS
3019 *
3020 * NOTE
3021 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
3022 * (/MachineName is optional). This function only parses this string and eventually
3023 * calls DeviceProperties().
3024 *
3025 * @implemented
3026 */
3027 VOID
3028 WINAPI
3029 DeviceProperties_RunDLLA(HWND hWndParent,
3030 HINSTANCE hInst,
3031 LPCSTR lpDeviceCmd,
3032 int nCmdShow)
3033 {
3034 LPWSTR lpDeviceCmdW = NULL;
3035
3036 if (lpDeviceCmd != NULL)
3037 {
3038 if ((lpDeviceCmdW = ConvertMultiByteToUnicode(lpDeviceCmd,
3039 CP_ACP)))
3040 {
3041 DeviceProperties_RunDLLW(hWndParent,
3042 hInst,
3043 lpDeviceCmdW,
3044 nCmdShow);
3045 }
3046 }
3047
3048 if (lpDeviceCmdW != NULL)
3049 {
3050 HeapFree(GetProcessHeap(),
3051 0,
3052 lpDeviceCmdW);
3053 }
3054 }
3055
3056
3057 /***************************************************************************
3058 * NAME EXPORTED
3059 * DeviceProperties_RunDLLW
3060 *
3061 * DESCRIPTION
3062 * Invokes the device properties dialog
3063 *
3064 * ARGUMENTS
3065 * hWndParent: Handle to the parent window
3066 * hInst: Handle to the application instance
3067 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
3068 * also see NOTEs
3069 * nCmdShow: Specifies how the window should be shown
3070 *
3071 * RETURN VALUE
3072 *
3073 * REVISIONS
3074 *
3075 * NOTE
3076 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
3077 * (/MachineName is optional). This function only parses this string and eventually
3078 * calls DeviceProperties().
3079 *
3080 * @implemented
3081 */
3082 VOID
3083 WINAPI
3084 DeviceProperties_RunDLLW(HWND hWndParent,
3085 HINSTANCE hInst,
3086 LPCWSTR lpDeviceCmd,
3087 int nCmdShow)
3088 {
3089 WCHAR szDeviceID[MAX_DEVICE_ID_LEN+1];
3090 WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
3091 LPWSTR lpString = (LPWSTR)lpDeviceCmd;
3092
3093 if (!GetDeviceAndComputerName(lpString,
3094 szDeviceID,
3095 szMachineName))
3096 {
3097 DPRINT1("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
3098 return;
3099 }
3100
3101 DevicePropertiesW(hWndParent,
3102 szMachineName,
3103 szDeviceID,
3104 FALSE);
3105 }