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