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