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