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