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