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