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