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