fe8773bb89544e32049c6a40e7905026c5e723ce
[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 static VOID
795 DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
796 IN HWND hwndListView)
797 {
798 HDEVINFO DeviceInfoSet;
799 PSP_DEVINFO_DATA DeviceInfoData;
800
801 DWORD dwType = 0;
802 WCHAR szBuffer[256];
803 DWORD dwSize = 256 * sizeof(WCHAR);
804
805 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
806 {
807 DeviceInfoSet = dap->CurrentDeviceInfoSet;
808 DeviceInfoData = &dap->CurrentDeviceInfoData;
809 }
810 else
811 {
812 DeviceInfoSet = dap->DeviceInfoSet;
813 DeviceInfoData = &dap->DeviceInfoData;
814 }
815
816 CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
817 CM_DRP_ENUMERATOR_NAME,
818 &dwType,
819 &szBuffer,
820 &dwSize,
821 0,
822 dap->hMachine);
823
824 SetListViewText(hwndListView, 0, szBuffer);
825 }
826
827
828
829 static VOID
830 DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
831 IN HWND hwndComboBox,
832 IN HWND hwndListView)
833 {
834 INT Index;
835
836 Index = (INT)SendMessage(hwndComboBox,
837 CB_GETCURSEL,
838 0,
839 0);
840 if (Index == CB_ERR)
841 return;
842
843 (void)ListView_DeleteAllItems(hwndListView);
844
845 switch (Index)
846 {
847 case 0:
848 SetListViewText(hwndListView, 0, dap->szDeviceID);
849 break;
850
851
852 case 1: /* Hardware ID */
853 DisplayDevicePropertyText(dap,
854 hwndListView,
855 SPDRP_HARDWAREID);
856 break;
857
858 case 2: /* Compatible IDs */
859 DisplayDevicePropertyText(dap,
860 hwndListView,
861 SPDRP_COMPATIBLEIDS);
862 break;
863
864 #if 0
865 case 3: /* Matching ID */
866 break;
867 #endif
868
869 case 4: /* Service */
870 DisplayDevicePropertyText(dap,
871 hwndListView,
872 SPDRP_SERVICE);
873 break;
874
875 case 5: /* Enumerator */
876 DisplayDevNodeEnumerator(dap,
877 hwndListView);
878 // DisplayDevicePropertyText(dap,
879 // hwndListView,
880 // SPDRP_ENUMERATOR_NAME);
881 break;
882
883 case 6: /* Capabilities */
884 DisplayDevicePropertyText(dap,
885 hwndListView,
886 SPDRP_CAPABILITIES);
887 break;
888
889 case 7: /* Devnode Flags */
890 DisplayDevNodeFlags(dap,
891 hwndListView);
892 break;
893
894 case 8: /* Config Flags */
895 DisplayDevicePropertyText(dap,
896 hwndListView,
897 SPDRP_CONFIGFLAGS);
898 break;
899
900 #if 0
901 case 9: /* CSConfig Flags */
902 break;
903 #endif
904
905 case 13: /* Upper Filters */
906 DisplayDevicePropertyText(dap,
907 hwndListView,
908 SPDRP_UPPERFILTERS);
909 break;
910
911 case 14: /* Lower Filters */
912 DisplayDevicePropertyText(dap,
913 hwndListView,
914 SPDRP_LOWERFILTERS);
915 break;
916
917 default:
918 SetListViewText(hwndListView, 0, L"<Not implemented yet>");
919 break;
920 }
921 }
922
923
924 static INT_PTR
925 CALLBACK
926 AdvProcDetailsDlgProc(IN HWND hwndDlg,
927 IN UINT uMsg,
928 IN WPARAM wParam,
929 IN LPARAM lParam)
930 {
931 PDEVADVPROP_INFO dap;
932 INT_PTR Ret = FALSE;
933
934 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
935 DWL_USER);
936
937 if (dap != NULL || uMsg == WM_INITDIALOG)
938 {
939 switch (uMsg)
940 {
941 case WM_COMMAND:
942 {
943 switch (LOWORD(wParam))
944 {
945 case IDC_DETAILSPROPNAME:
946 if (HIWORD(wParam) == CBN_SELCHANGE)
947 {
948 DisplayDeviceProperties(dap,
949 GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
950 GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
951 }
952 break;
953 }
954 break;
955 }
956
957 case WM_NOTIFY:
958 {
959 NMHDR *hdr = (NMHDR*)lParam;
960 switch (hdr->code)
961 {
962 case PSN_APPLY:
963 break;
964 }
965 break;
966 }
967
968 case WM_INITDIALOG:
969 {
970 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
971 if (dap != NULL)
972 {
973 SetWindowLongPtr(hwndDlg,
974 DWL_USER,
975 (DWORD_PTR)dap);
976
977 UpdateDetailsDlg(hwndDlg,
978 dap);
979 }
980 Ret = TRUE;
981 break;
982 }
983 }
984 }
985
986 return Ret;
987 }
988
989
990 static VOID
991 InitDevUsageActions(IN HWND hwndDlg,
992 IN HWND hComboBox,
993 IN PDEVADVPROP_INFO dap)
994 {
995 INT Index;
996 UINT i;
997 UINT Actions[] =
998 {
999 IDS_ENABLEDEVICE,
1000 IDS_DISABLEDEVICE,
1001 };
1002
1003 for (i = 0;
1004 i != sizeof(Actions) / sizeof(Actions[0]);
1005 i++)
1006 {
1007 /* fill in the device usage combo box */
1008 if (LoadString(hDllInstance,
1009 Actions[i],
1010 dap->szTemp,
1011 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1012 {
1013 Index = (INT)SendMessage(hComboBox,
1014 CB_ADDSTRING,
1015 0,
1016 (LPARAM)dap->szTemp);
1017 if (Index != CB_ERR)
1018 {
1019 SendMessage(hComboBox,
1020 CB_SETITEMDATA,
1021 (WPARAM)Index,
1022 (LPARAM)Actions[i]);
1023
1024 switch (Actions[i])
1025 {
1026 case IDS_ENABLEDEVICE:
1027 if (dap->DeviceStarted)
1028 {
1029 SendMessage(hComboBox,
1030 CB_SETCURSEL,
1031 (WPARAM)Index,
1032 0);
1033 }
1034 break;
1035
1036 case IDS_DISABLEDEVICE:
1037 if (!dap->DeviceStarted)
1038 {
1039 SendMessage(hComboBox,
1040 CB_SETCURSEL,
1041 (WPARAM)Index,
1042 0);
1043 }
1044 break;
1045
1046 default:
1047 break;
1048 }
1049 }
1050 }
1051 }
1052 }
1053
1054
1055 static UINT
1056 GetSelectedUsageAction(IN HWND hComboBox)
1057 {
1058 INT Index;
1059 UINT Ret = 0;
1060
1061 Index = (INT)SendMessage(hComboBox,
1062 CB_GETCURSEL,
1063 0,
1064 0);
1065 if (Index != CB_ERR)
1066 {
1067 INT iRet = (INT) SendMessage(hComboBox,
1068 CB_GETITEMDATA,
1069 (WPARAM)Index,
1070 0);
1071 if (iRet != CB_ERR)
1072 {
1073 Ret = (UINT)iRet;
1074 }
1075 }
1076
1077 return Ret;
1078 }
1079
1080
1081 static BOOL
1082 ApplyGeneralSettings(IN HWND hwndDlg,
1083 IN PDEVADVPROP_INFO dap)
1084 {
1085 BOOL Ret = FALSE;
1086
1087 if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
1088 {
1089 UINT SelectedUsageAction;
1090 BOOL NeedReboot = FALSE;
1091
1092 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
1093 IDC_DEVUSAGE));
1094 switch (SelectedUsageAction)
1095 {
1096 case IDS_ENABLEDEVICE:
1097 if (!dap->DeviceStarted)
1098 {
1099 Ret = EnableDevice(dap->DeviceInfoSet,
1100 &dap->DeviceInfoData,
1101 TRUE,
1102 0,
1103 &NeedReboot);
1104 }
1105 break;
1106
1107 case IDS_DISABLEDEVICE:
1108 if (dap->DeviceStarted)
1109 {
1110 Ret = EnableDevice(dap->DeviceInfoSet,
1111 &dap->DeviceInfoData,
1112 FALSE,
1113 0,
1114 &NeedReboot);
1115 }
1116 break;
1117
1118 default:
1119 break;
1120 }
1121
1122 if (Ret)
1123 {
1124 if (NeedReboot)
1125 {
1126 /* make PropertySheet() return PSM_REBOOTSYSTEM */
1127 PropSheet_RebootSystem(hwndDlg);
1128 }
1129 }
1130 else
1131 {
1132 /* FIXME - display an error message */
1133 DPRINT1("Failed to enable/disable device! LastError: %d\n",
1134 GetLastError());
1135 }
1136 }
1137 else
1138 Ret = !dap->DeviceUsageChanged;
1139
1140 /* disable the apply button */
1141 PropSheet_UnChanged(GetParent(hwndDlg),
1142 hwndDlg);
1143 dap->DeviceUsageChanged = FALSE;
1144 return Ret;
1145 }
1146
1147
1148 static VOID
1149 UpdateDevInfo(IN HWND hwndDlg,
1150 IN PDEVADVPROP_INFO dap,
1151 IN BOOL ReOpen)
1152 {
1153 HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
1154 CONFIGRET cr;
1155 ULONG Status, ProblemNumber;
1156 SP_DEVINSTALL_PARAMS_W InstallParams;
1157 UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
1158 BOOL bFlag, bDevActionAvailable = TRUE;
1159 BOOL bDrvInstalled = FALSE;
1160 DWORD iPage;
1161 HDEVINFO DeviceInfoSet = NULL;
1162 PSP_DEVINFO_DATA DeviceInfoData = NULL;
1163 PROPSHEETHEADER psh;
1164 DWORD nDriverPages = 0;
1165 BOOL RecalcPages = FALSE;
1166
1167 hPropSheetDlg = GetParent(hwndDlg);
1168
1169 if (dap->PageInitialized)
1170 {
1171 /* switch to the General page */
1172 PropSheet_SetCurSelByID(hPropSheetDlg,
1173 IDD_DEVICEGENERAL);
1174
1175 /* remove and destroy the existing device property sheet pages */
1176 if (dap->DevPropSheets != NULL)
1177 {
1178 for (iPage = 0;
1179 iPage != dap->nDevPropSheets;
1180 iPage++)
1181 {
1182 if (dap->DevPropSheets[iPage] != NULL)
1183 {
1184 PropSheet_RemovePage(hPropSheetDlg,
1185 (WPARAM) -1,
1186 dap->DevPropSheets[iPage]);
1187 RecalcPages = TRUE;
1188 }
1189 }
1190 }
1191 }
1192
1193 iPage = 0;
1194
1195 if (dap->FreeDevPropSheets)
1196 {
1197 /* don't free the array if it's the one allocated in
1198 DisplayDeviceAdvancedProperties */
1199 HeapFree(GetProcessHeap(),
1200 0,
1201 dap->DevPropSheets);
1202
1203 dap->FreeDevPropSheets = FALSE;
1204 }
1205
1206 dap->DevPropSheets = NULL;
1207 dap->nDevPropSheets = 0;
1208
1209 if (ReOpen)
1210 {
1211 /* create a new device info set and re-open the device */
1212 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1213 {
1214 SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
1215 }
1216
1217 dap->ParentDevInst = 0;
1218 dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
1219 hwndDlg,
1220 dap->lpMachineName,
1221 NULL);
1222 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1223 {
1224 if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
1225 dap->szDeviceID,
1226 hwndDlg,
1227 0,
1228 &dap->CurrentDeviceInfoData))
1229 {
1230 if (dap->CloseDevInst)
1231 {
1232 SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
1233 }
1234
1235 dap->CloseDevInst = TRUE;
1236 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
1237 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
1238 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1239 }
1240 else
1241 goto GetParentNode;
1242 }
1243 else
1244 {
1245 GetParentNode:
1246 /* get the parent node from the initial devinst */
1247 CM_Get_Parent_Ex(&dap->ParentDevInst,
1248 dap->DeviceInfoData.DevInst,
1249 0,
1250 dap->hMachine);
1251 }
1252
1253 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1254 {
1255 DeviceInfoSet = dap->CurrentDeviceInfoSet;
1256 DeviceInfoData = &dap->CurrentDeviceInfoData;
1257 }
1258 else
1259 {
1260 DeviceInfoSet = dap->DeviceInfoSet;
1261 DeviceInfoData = &dap->DeviceInfoData;
1262 }
1263 }
1264 else
1265 {
1266 DeviceInfoSet = dap->DeviceInfoSet;
1267 DeviceInfoData = &dap->DeviceInfoData;
1268 }
1269
1270 dap->HasDriverPage = FALSE;
1271 dap->HasResourcePage = FALSE;
1272 dap->HasPowerPage = FALSE;
1273 if (IsDriverInstalled(DeviceInfoData->DevInst,
1274 dap->hMachine,
1275 &bDrvInstalled) &&
1276 bDrvInstalled)
1277 {
1278 if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
1279 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
1280 DIF_ADDPROPERTYPAGE_ADVANCED),
1281 DeviceInfoSet,
1282 DeviceInfoData))
1283 {
1284 /* get install params */
1285 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1286 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
1287 DeviceInfoData,
1288 &InstallParams))
1289 {
1290 /* zero the flags */
1291 InstallParams.Flags = 0;
1292 }
1293
1294 dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
1295 dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
1296 dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
1297 }
1298 }
1299
1300 /* get the device icon */
1301 if (dap->hDevIcon != NULL)
1302 {
1303 DestroyIcon(dap->hDevIcon);
1304 dap->hDevIcon = NULL;
1305 }
1306 if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
1307 &dap->hDevIcon,
1308 NULL))
1309 {
1310 dap->hDevIcon = NULL;
1311 }
1312
1313 /* get the device name */
1314 if (GetDeviceDescriptionString(DeviceInfoSet,
1315 DeviceInfoData,
1316 dap->szDevName,
1317 sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
1318 {
1319 PropSheet_SetTitle(hPropSheetDlg,
1320 PSH_PROPTITLE,
1321 dap->szDevName);
1322 }
1323
1324 /* set the device image */
1325 SendDlgItemMessage(hwndDlg,
1326 IDC_DEVICON,
1327 STM_SETICON,
1328 (WPARAM)dap->hDevIcon,
1329 0);
1330
1331 /* set the device name edit control text */
1332 SetDlgItemText(hwndDlg,
1333 IDC_DEVNAME,
1334 dap->szDevName);
1335
1336 /* set the device type edit control text */
1337 if (GetDeviceTypeString(DeviceInfoData,
1338 dap->szTemp,
1339 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1340 {
1341 SetDlgItemText(hwndDlg,
1342 IDC_DEVTYPE,
1343 dap->szTemp);
1344 }
1345
1346 /* set the device manufacturer edit control text */
1347 if (GetDeviceManufacturerString(DeviceInfoSet,
1348 DeviceInfoData,
1349 dap->szTemp,
1350 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1351 {
1352 SetDlgItemText(hwndDlg,
1353 IDC_DEVMANUFACTURER,
1354 dap->szTemp);
1355 }
1356
1357 /* set the device location edit control text */
1358 if (GetDeviceLocationString(DeviceInfoData->DevInst,
1359 dap->ParentDevInst,
1360 dap->szTemp,
1361 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1362 {
1363 SetDlgItemText(hwndDlg,
1364 IDC_DEVLOCATION,
1365 dap->szTemp);
1366 }
1367
1368 /* set the device status edit control text */
1369 if (GetDeviceStatusString(DeviceInfoData->DevInst,
1370 dap->hMachine,
1371 dap->szTemp,
1372 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1373 {
1374 SetDlgItemText(hwndDlg,
1375 IDC_DEVSTATUS,
1376 dap->szTemp);
1377 }
1378
1379 /* set the device troubleshoot button text and disable it if necessary */
1380 hDevProbBtn = GetDlgItem(hwndDlg,
1381 IDC_DEVPROBLEM);
1382 cr = CM_Get_DevNode_Status_Ex(&Status,
1383 &ProblemNumber,
1384 DeviceInfoData->DevInst,
1385 0,
1386 dap->hMachine);
1387 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
1388 {
1389 switch (ProblemNumber)
1390 {
1391 case CM_PROB_DEVLOADER_FAILED:
1392 {
1393 /* FIXME - only if it's not a root bus devloader,
1394 disable the button otherwise */
1395 TroubleShootStrId = IDS_UPDATEDRV;
1396 break;
1397 }
1398
1399 case CM_PROB_OUT_OF_MEMORY:
1400 case CM_PROB_ENTRY_IS_WRONG_TYPE:
1401 case CM_PROB_LACKED_ARBITRATOR:
1402 case CM_PROB_FAILED_START:
1403 case CM_PROB_LIAR:
1404 case CM_PROB_UNKNOWN_RESOURCE:
1405 {
1406 TroubleShootStrId = IDS_UPDATEDRV;
1407 break;
1408 }
1409
1410 case CM_PROB_BOOT_CONFIG_CONFLICT:
1411 case CM_PROB_NORMAL_CONFLICT:
1412 case CM_PROB_REENUMERATION:
1413 {
1414 /* FIXME - Troubleshoot conflict */
1415 break;
1416 }
1417
1418 case CM_PROB_FAILED_FILTER:
1419 case CM_PROB_REINSTALL:
1420 case CM_PROB_FAILED_INSTALL:
1421 {
1422 TroubleShootStrId = IDS_REINSTALLDRV;
1423 break;
1424 }
1425
1426 case CM_PROB_DEVLOADER_NOT_FOUND:
1427 {
1428 /* FIXME - 4 cases:
1429 1) if it's a missing system devloader:
1430 - disable the button (Reinstall Driver)
1431 2) if it's not a system devloader but still missing:
1432 - Reinstall Driver
1433 3) if it's not a system devloader but the file can be found:
1434 - Update Driver
1435 4) if it's a missing or empty software key
1436 - Update Driver
1437 */
1438 break;
1439 }
1440
1441 case CM_PROB_INVALID_DATA:
1442 case CM_PROB_PARTIAL_LOG_CONF:
1443 case CM_PROB_NO_VALID_LOG_CONF:
1444 case CM_PROB_HARDWARE_DISABLED:
1445 case CM_PROB_CANT_SHARE_IRQ:
1446 case CM_PROB_TRANSLATION_FAILED:
1447 case CM_PROB_SYSTEM_SHUTDOWN:
1448 case CM_PROB_PHANTOM:
1449 bDevActionAvailable = FALSE;
1450 break;
1451
1452 case CM_PROB_NOT_VERIFIED:
1453 case CM_PROB_DEVICE_NOT_THERE:
1454 /* FIXME - search hardware */
1455 break;
1456
1457 case CM_PROB_NEED_RESTART:
1458 case CM_PROB_WILL_BE_REMOVED:
1459 case CM_PROB_MOVED:
1460 case CM_PROB_TOO_EARLY:
1461 case CM_PROB_DISABLED_SERVICE:
1462 TroubleShootStrId = IDS_REBOOT;
1463 break;
1464
1465 case CM_PROB_REGISTRY:
1466 /* FIXME - check registry? */
1467 break;
1468
1469 case CM_PROB_DISABLED:
1470 /* if device was disabled by the user: */
1471 TroubleShootStrId = IDS_ENABLEDEV;
1472 /* FIXME - otherwise disable button because the device was
1473 disabled by the system*/
1474 break;
1475
1476 case CM_PROB_DEVLOADER_NOT_READY:
1477 /* FIXME - if it's a graphics adapter:
1478 - if it's a a secondary adapter and the main adapter
1479 couldn't be found
1480 - disable button
1481 - else
1482 - Properties
1483 - else
1484 - Update driver
1485 */
1486 break;
1487
1488 case CM_PROB_FAILED_ADD:
1489 TroubleShootStrId = IDS_PROPERTIES;
1490 break;
1491 }
1492 }
1493
1494 if (LoadString(hDllInstance,
1495 TroubleShootStrId,
1496 dap->szTemp,
1497 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
1498 {
1499 SetWindowText(hDevProbBtn,
1500 dap->szTemp);
1501 }
1502 EnableWindow(hDevProbBtn,
1503 dap->IsAdmin && bDevActionAvailable);
1504
1505 /* check if the device can be enabled/disabled */
1506 hDevUsage = GetDlgItem(hwndDlg,
1507 IDC_DEVUSAGE);
1508
1509 dap->CanDisable = FALSE;
1510 dap->DeviceStarted = FALSE;
1511
1512 if (CanDisableDevice(DeviceInfoData->DevInst,
1513 dap->hMachine,
1514 &bFlag))
1515 {
1516 dap->CanDisable = bFlag;
1517 }
1518
1519 if (IsDeviceStarted(DeviceInfoData->DevInst,
1520 dap->hMachine,
1521 &bFlag))
1522 {
1523 dap->DeviceStarted = bFlag;
1524 }
1525
1526 /* enable/disable the device usage controls */
1527 EnableWindow(GetDlgItem(hwndDlg,
1528 IDC_DEVUSAGELABEL),
1529 dap->CanDisable && dap->IsAdmin);
1530 EnableWindow(hDevUsage,
1531 dap->CanDisable && dap->IsAdmin);
1532
1533 /* clear the combobox */
1534 SendMessage(hDevUsage,
1535 CB_RESETCONTENT,
1536 0,
1537 0);
1538 if (dap->CanDisable)
1539 {
1540 InitDevUsageActions(hwndDlg,
1541 hDevUsage,
1542 dap);
1543 }
1544
1545 /* find out how many new device property sheets to add.
1546 fake a PROPSHEETHEADER structure, we don't plan to
1547 call PropertySheet again!*/
1548 psh.dwSize = sizeof(PROPSHEETHEADER);
1549 psh.dwFlags = 0;
1550 psh.nPages = 0;
1551
1552 /* get the number of device property sheets for the device */
1553 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
1554 DeviceInfoData,
1555 &psh,
1556 0,
1557 &nDriverPages,
1558 dap->PropertySheetType) &&
1559 nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1560 {
1561 dap->nDevPropSheets += nDriverPages;
1562 }
1563 else
1564 {
1565 nDriverPages = 0;
1566 }
1567
1568 /* include the driver page */
1569 if (dap->HasDriverPage)
1570 dap->nDevPropSheets++;
1571
1572 /* include the details page */
1573 dap->nDevPropSheets++;
1574
1575 /* add the device property sheets */
1576 if (dap->nDevPropSheets != 0)
1577 {
1578 dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
1579 HEAP_ZERO_MEMORY,
1580 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
1581 if (dap->DevPropSheets != NULL)
1582 {
1583 if (nDriverPages != 0)
1584 {
1585 psh.phpage = dap->DevPropSheets;
1586
1587 /* query the device property sheet pages to add */
1588 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
1589 DeviceInfoData,
1590 &psh,
1591 dap->nDevPropSheets,
1592 NULL,
1593 dap->PropertySheetType))
1594 {
1595 /* add the property sheets */
1596 for (iPage = 0;
1597 iPage != nDriverPages;
1598 iPage++)
1599 {
1600 if (PropSheet_AddPage(hPropSheetDlg,
1601 dap->DevPropSheets[iPage]))
1602 {
1603 RecalcPages = TRUE;
1604 }
1605 }
1606
1607 dap->FreeDevPropSheets = TRUE;
1608 }
1609 else
1610 {
1611 /* cleanup, we were unable to get the device property sheets */
1612 iPage = nDriverPages;
1613 dap->nDevPropSheets -= nDriverPages;
1614 nDriverPages = 0;
1615 }
1616 }
1617 else
1618 iPage = 0;
1619
1620 /* add the driver page if necessary */
1621 if (dap->HasDriverPage)
1622 {
1623 PROPSHEETPAGE pspDriver = {0};
1624 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
1625 pspDriver.dwFlags = PSP_DEFAULT;
1626 pspDriver.hInstance = hDllInstance;
1627 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
1628 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
1629 pspDriver.lParam = (LPARAM)dap;
1630 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
1631 if (dap->DevPropSheets[iPage] != NULL)
1632 {
1633 if (PropSheet_AddPage(hPropSheetDlg,
1634 dap->DevPropSheets[iPage]))
1635 {
1636 iPage++;
1637 RecalcPages = TRUE;
1638 }
1639 else
1640 {
1641 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
1642 dap->DevPropSheets[iPage] = NULL;
1643 }
1644 }
1645 }
1646
1647 if (1)
1648 {
1649 PROPSHEETPAGE pspDetails = {0};
1650 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
1651 pspDetails.dwFlags = PSP_DEFAULT;
1652 pspDetails.hInstance = hDllInstance;
1653 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
1654 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
1655 pspDetails.lParam = (LPARAM)dap;
1656 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
1657 if (dap->DevPropSheets[iPage] != NULL)
1658 {
1659 if (PropSheet_AddPage(hPropSheetDlg,
1660 dap->DevPropSheets[iPage]))
1661 {
1662 iPage++;
1663 RecalcPages = TRUE;
1664 }
1665 else
1666 {
1667 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
1668 dap->DevPropSheets[iPage] = NULL;
1669 }
1670 }
1671 }
1672
1673 /* FIXME: Add the resources page */
1674
1675 /* FIXME: Add the power page */
1676 }
1677 else
1678 dap->nDevPropSheets = 0;
1679 }
1680
1681 if (RecalcPages)
1682 {
1683 PropSheet_RecalcPageSizes(hPropSheetDlg);
1684 }
1685
1686 /* finally, disable the apply button */
1687 PropSheet_UnChanged(hPropSheetDlg,
1688 hwndDlg);
1689 dap->DeviceUsageChanged = FALSE;
1690 }
1691
1692
1693 static LRESULT
1694 CALLBACK
1695 DlgParentSubWndProc(IN HWND hwnd,
1696 IN UINT uMsg,
1697 IN WPARAM wParam,
1698 IN LPARAM lParam)
1699 {
1700 PDEVADVPROP_INFO dap;
1701
1702 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
1703 L"DevMgrDevChangeSub");
1704 if (dap != NULL)
1705 {
1706 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
1707 {
1708 SendMessage(dap->hWndGeneralPage,
1709 WM_DEVICECHANGE,
1710 wParam,
1711 lParam);
1712 }
1713
1714 /* pass the message the the old window proc */
1715 return CallWindowProc(dap->ParentOldWndProc,
1716 hwnd,
1717 uMsg,
1718 wParam,
1719 lParam);
1720 }
1721 else
1722 {
1723 /* this is not a good idea if the subclassed window was an ansi
1724 window, but we failed finding out the previous window proc
1725 so we can't use CallWindowProc. This should rarely - if ever -
1726 happen. */
1727
1728 return DefWindowProc(hwnd,
1729 uMsg,
1730 wParam,
1731 lParam);
1732 }
1733 }
1734
1735
1736 static INT_PTR
1737 CALLBACK
1738 AdvPropGeneralDlgProc(IN HWND hwndDlg,
1739 IN UINT uMsg,
1740 IN WPARAM wParam,
1741 IN LPARAM lParam)
1742 {
1743 PDEVADVPROP_INFO dap;
1744 INT_PTR Ret = FALSE;
1745
1746 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1747 DWL_USER);
1748
1749 if (dap != NULL || uMsg == WM_INITDIALOG)
1750 {
1751 switch (uMsg)
1752 {
1753 case WM_COMMAND:
1754 {
1755 switch (LOWORD(wParam))
1756 {
1757 case IDC_DEVUSAGE:
1758 {
1759 if (HIWORD(wParam) == CBN_SELCHANGE)
1760 {
1761 PropSheet_Changed(GetParent(hwndDlg),
1762 hwndDlg);
1763 dap->DeviceUsageChanged = TRUE;
1764 }
1765 break;
1766 }
1767
1768 case IDC_DEVPROBLEM:
1769 {
1770 if (dap->IsAdmin)
1771 {
1772 /* display the device problem wizard */
1773 ShowDeviceProblemWizard(hwndDlg,
1774 dap->DeviceInfoSet,
1775 &dap->DeviceInfoData,
1776 dap->hMachine);
1777 }
1778 break;
1779 }
1780 }
1781 break;
1782 }
1783
1784 case WM_NOTIFY:
1785 {
1786 NMHDR *hdr = (NMHDR*)lParam;
1787 switch (hdr->code)
1788 {
1789 case PSN_APPLY:
1790 ApplyGeneralSettings(hwndDlg,
1791 dap);
1792 break;
1793 }
1794 break;
1795 }
1796
1797 case WM_INITDIALOG:
1798 {
1799 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1800 if (dap != NULL)
1801 {
1802 HWND hWndParent;
1803
1804 dap->hWndGeneralPage = hwndDlg;
1805
1806 SetWindowLongPtr(hwndDlg,
1807 DWL_USER,
1808 (DWORD_PTR)dap);
1809
1810 /* subclass the parent window to always receive
1811 WM_DEVICECHANGE messages */
1812 hWndParent = GetParent(hwndDlg);
1813 if (hWndParent != NULL)
1814 {
1815 /* subclass the parent window. This is not safe
1816 if the parent window belongs to another thread! */
1817 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
1818 GWLP_WNDPROC,
1819 (LONG_PTR)DlgParentSubWndProc);
1820
1821 if (dap->ParentOldWndProc != NULL &&
1822 SetProp(hWndParent,
1823 L"DevMgrDevChangeSub",
1824 (HANDLE)dap))
1825 {
1826 dap->hWndParent = hWndParent;
1827 }
1828 }
1829
1830 /* do not call UpdateDevInfo directly in here because it modifies
1831 the pages of the property sheet! */
1832 PostMessage(hwndDlg,
1833 PM_INITIALIZE,
1834 0,
1835 0);
1836 }
1837 Ret = TRUE;
1838 break;
1839 }
1840
1841 case WM_DEVICECHANGE:
1842 {
1843 /* FIXME - don't call UpdateDevInfo for all events */
1844 UpdateDevInfo(hwndDlg,
1845 dap,
1846 TRUE);
1847 Ret = TRUE;
1848 break;
1849 }
1850
1851 case PM_INITIALIZE:
1852 {
1853 UpdateDevInfo(hwndDlg,
1854 dap,
1855 FALSE);
1856 dap->PageInitialized = TRUE;
1857 break;
1858 }
1859
1860 case WM_DESTROY:
1861 {
1862 /* restore the old window proc of the subclassed parent window */
1863 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
1864 {
1865 if (SetWindowLongPtr(dap->hWndParent,
1866 GWLP_WNDPROC,
1867 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
1868 {
1869 RemoveProp(dap->hWndParent,
1870 L"DevMgrDevChangeSub");
1871 }
1872 }
1873 break;
1874 }
1875 }
1876 }
1877
1878 return Ret;
1879 }
1880
1881
1882 INT_PTR
1883 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
1884 IN LPCWSTR lpDeviceID OPTIONAL,
1885 IN HDEVINFO DeviceInfoSet,
1886 IN PSP_DEVINFO_DATA DeviceInfoData,
1887 IN HINSTANCE hComCtl32,
1888 IN LPCWSTR lpMachineName,
1889 IN DWORD dwFlags)
1890 {
1891 PROPSHEETHEADER psh = {0};
1892 PROPSHEETPAGE pspGeneral = {0};
1893 PPROPERTYSHEETW pPropertySheetW;
1894 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
1895 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
1896 PDEVADVPROP_INFO DevAdvPropInfo;
1897 HMACHINE hMachine = NULL;
1898 DWORD DevIdSize = 0;
1899 INT_PTR Ret = -1;
1900
1901 /* we don't want to statically link against comctl32, so find the
1902 functions we need dynamically */
1903 pPropertySheetW =
1904 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
1905 "PropertySheetW");
1906 pCreatePropertySheetPageW =
1907 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
1908 "CreatePropertySheetPageW");
1909 pDestroyPropertySheetPage =
1910 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
1911 "DestroyPropertySheetPage");
1912 if (pPropertySheetW == NULL ||
1913 pCreatePropertySheetPageW == NULL ||
1914 pDestroyPropertySheetPage == NULL)
1915 {
1916 return -1;
1917 }
1918
1919 if (lpDeviceID == NULL)
1920 {
1921 /* find out how much size is needed for the device id */
1922 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
1923 DeviceInfoData,
1924 NULL,
1925 0,
1926 &DevIdSize))
1927 {
1928 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1929 return -1;
1930 }
1931
1932 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1933 {
1934 return -1;
1935 }
1936 }
1937 else
1938 {
1939 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
1940 }
1941
1942 if (lpMachineName != NULL && lpMachineName[0] != L'\0')
1943 {
1944 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
1945 &hMachine);
1946 if (cr != CR_SUCCESS)
1947 {
1948 return -1;
1949 }
1950 }
1951
1952 /* create the internal structure associated with the "General",
1953 "Driver", ... pages */
1954 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
1955 HEAP_ZERO_MEMORY,
1956 FIELD_OFFSET(DEVADVPROP_INFO,
1957 szDeviceID) +
1958 (DevIdSize * sizeof(WCHAR)));
1959 if (DevAdvPropInfo == NULL)
1960 {
1961 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1962 goto Cleanup;
1963 }
1964
1965 if (lpDeviceID == NULL)
1966 {
1967 /* read the device instance id */
1968 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
1969 DeviceInfoData,
1970 DevAdvPropInfo->szDeviceID,
1971 DevIdSize,
1972 NULL))
1973 {
1974 goto Cleanup;
1975 }
1976 }
1977 else
1978 {
1979 /* copy the device instance id supplied by the caller */
1980 wcscpy(DevAdvPropInfo->szDeviceID,
1981 lpDeviceID);
1982 }
1983
1984 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
1985 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
1986 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1987 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1988
1989 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
1990 DevAdvPropInfo->hMachine = hMachine;
1991 DevAdvPropInfo->lpMachineName = lpMachineName;
1992 DevAdvPropInfo->szDevName[0] = L'\0';
1993 DevAdvPropInfo->hComCtl32 = hComCtl32;
1994 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
1995 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
1996
1997 DevAdvPropInfo->IsAdmin = IsUserAdmin();
1998 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
1999
2000 psh.dwSize = sizeof(PROPSHEETHEADER);
2001 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2002 psh.hwndParent = hWndParent;
2003 psh.pszCaption = DevAdvPropInfo->szDevName;
2004
2005 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2006 DIGCDP_FLAG_REMOTE_ADVANCED :
2007 DIGCDP_FLAG_ADVANCED;
2008
2009 psh.phpage = HeapAlloc(GetProcessHeap(),
2010 HEAP_ZERO_MEMORY,
2011 1 * sizeof(HPROPSHEETPAGE));
2012 if (psh.phpage == NULL)
2013 {
2014 goto Cleanup;
2015 }
2016
2017 /* add the "General" property sheet */
2018 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2019 pspGeneral.dwFlags = PSP_DEFAULT;
2020 pspGeneral.hInstance = hDllInstance;
2021 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2022 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2023 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2024 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2025 if (psh.phpage[psh.nPages] != NULL)
2026 {
2027 psh.nPages++;
2028 }
2029
2030 DevAdvPropInfo->nDevPropSheets = psh.nPages;
2031
2032 if (psh.nPages != 0)
2033 {
2034 Ret = pPropertySheetW(&psh);
2035
2036 /* NOTE: no need to destroy the property sheets anymore! */
2037 }
2038 else
2039 {
2040 UINT i;
2041
2042 Cleanup:
2043 /* in case of failure the property sheets must be destroyed */
2044 if (psh.phpage != NULL)
2045 {
2046 for (i = 0;
2047 i < psh.nPages;
2048 i++)
2049 {
2050 if (psh.phpage[i] != NULL)
2051 {
2052 pDestroyPropertySheetPage(psh.phpage[i]);
2053 }
2054 }
2055 }
2056 }
2057
2058 if (DevAdvPropInfo != NULL)
2059 {
2060 if (DevAdvPropInfo->FreeDevPropSheets)
2061 {
2062 /* don't free the array if it's the one allocated in
2063 DisplayDeviceAdvancedProperties */
2064 HeapFree(GetProcessHeap(),
2065 0,
2066 DevAdvPropInfo->DevPropSheets);
2067 }
2068
2069 if (DevAdvPropInfo->CloseDevInst)
2070 {
2071 /* close the device info set in case a new one was created */
2072 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2073 }
2074
2075 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2076 {
2077 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2078 }
2079
2080 if (DevAdvPropInfo->hDevIcon != NULL)
2081 {
2082 DestroyIcon(DevAdvPropInfo->hDevIcon);
2083 }
2084
2085 HeapFree(GetProcessHeap(),
2086 0,
2087 DevAdvPropInfo);
2088 }
2089
2090 if (psh.phpage != NULL)
2091 {
2092 HeapFree(GetProcessHeap(),
2093 0,
2094 psh.phpage);
2095 }
2096
2097 if (hMachine != NULL)
2098 {
2099 CM_Disconnect_Machine(hMachine);
2100 }
2101
2102 return Ret;
2103 }
2104
2105
2106 static BOOL
2107 GetDeviceAndComputerName(LPWSTR lpString,
2108 WCHAR szDeviceID[],
2109 WCHAR szMachineName[])
2110 {
2111 BOOL ret = FALSE;
2112
2113 szDeviceID[0] = L'\0';
2114 szMachineName[0] = L'\0';
2115
2116 while (*lpString != L'\0')
2117 {
2118 if (*lpString == L'/')
2119 {
2120 lpString++;
2121 if(!_wcsnicmp(lpString, L"DeviceID", 8))
2122 {
2123 lpString += 9;
2124 if (*lpString != L'\0')
2125 {
2126 int i = 0;
2127 while ((*lpString != L' ') &&
2128 (*lpString != L'\0') &&
2129 (i <= MAX_DEVICE_ID_LEN))
2130 {
2131 szDeviceID[i++] = *lpString++;
2132 }
2133 szDeviceID[i] = L'\0';
2134 ret = TRUE;
2135 }
2136 }
2137 else if (!_wcsnicmp(lpString, L"MachineName", 11))
2138 {
2139 lpString += 12;
2140 if (*lpString != L'\0')
2141 {
2142 int i = 0;
2143 while ((*lpString != L' ') &&
2144 (*lpString != L'\0') &&
2145 (i <= MAX_COMPUTERNAME_LENGTH))
2146 {
2147 szMachineName[i++] = *lpString++;
2148 }
2149 szMachineName[i] = L'\0';
2150 }
2151 }
2152 /* knock the pointer back one and let the next
2153 * pointer deal with incrementing, otherwise we
2154 * go past the end of the string */
2155 lpString--;
2156 }
2157 lpString++;
2158 }
2159
2160 return ret;
2161 }
2162
2163
2164 /***************************************************************************
2165 * NAME EXPORTED
2166 * DeviceAdvancedPropertiesW
2167 *
2168 * DESCRIPTION
2169 * Invokes the device properties dialog, this version may add some property pages
2170 * for some devices
2171 *
2172 * ARGUMENTS
2173 * hWndParent: Handle to the parent window
2174 * lpMachineName: Machine Name, NULL is the local machine
2175 * lpDeviceID: Specifies the device whose properties are to be shown
2176 *
2177 * RETURN VALUE
2178 * Always returns -1, a call to GetLastError returns 0 if successful
2179 *
2180 * @implemented
2181 */
2182 INT_PTR
2183 WINAPI
2184 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL,
2185 IN LPCWSTR lpMachineName OPTIONAL,
2186 IN LPCWSTR lpDeviceID)
2187 {
2188 HDEVINFO hDevInfo;
2189 SP_DEVINFO_DATA DevInfoData;
2190 HINSTANCE hComCtl32;
2191 INT_PTR Ret = -1;
2192
2193 if (lpDeviceID == NULL)
2194 {
2195 SetLastError(ERROR_INVALID_PARAMETER);
2196 return FALSE;
2197 }
2198
2199 /* dynamically load comctl32 */
2200 hComCtl32 = LoadAndInitComctl32();
2201 if (hComCtl32 != NULL)
2202 {
2203 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2204 hWndParent,
2205 lpMachineName,
2206 NULL);
2207 if (hDevInfo != INVALID_HANDLE_VALUE)
2208 {
2209 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2210 if (SetupDiOpenDeviceInfo(hDevInfo,
2211 lpDeviceID,
2212 hWndParent,
2213 0,
2214 &DevInfoData))
2215 {
2216 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2217 lpDeviceID,
2218 hDevInfo,
2219 &DevInfoData,
2220 hComCtl32,
2221 lpMachineName,
2222 0);
2223 }
2224
2225 SetupDiDestroyDeviceInfoList(hDevInfo);
2226 }
2227
2228 FreeLibrary(hComCtl32);
2229 }
2230
2231 return Ret;
2232 }
2233
2234
2235 /***************************************************************************
2236 * NAME EXPORTED
2237 * DeviceAdvancedPropertiesA
2238 *
2239 * DESCRIPTION
2240 * Invokes the device properties dialog, this version may add some property pages
2241 * for some devices
2242 *
2243 * ARGUMENTS
2244 * hWndParent: Handle to the parent window
2245 * lpMachineName: Machine Name, NULL is the local machine
2246 * lpDeviceID: Specifies the device whose properties are to be shown
2247 *
2248 * RETURN VALUE
2249 * Always returns -1, a call to GetLastError returns 0 if successful
2250 *
2251 * @implemented
2252 */
2253 INT_PTR
2254 WINAPI
2255 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL,
2256 IN LPCSTR lpMachineName OPTIONAL,
2257 IN LPCSTR lpDeviceID)
2258 {
2259 LPWSTR lpMachineNameW = NULL;
2260 LPWSTR lpDeviceIDW = NULL;
2261 INT_PTR Ret = -1;
2262
2263 if (lpMachineName != NULL)
2264 {
2265 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2266 CP_ACP)))
2267 {
2268 goto Cleanup;
2269 }
2270 }
2271 if (lpDeviceID != NULL)
2272 {
2273 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2274 CP_ACP)))
2275 {
2276 goto Cleanup;
2277 }
2278 }
2279
2280 Ret = DeviceAdvancedPropertiesW(hWndParent,
2281 lpMachineNameW,
2282 lpDeviceIDW);
2283
2284 Cleanup:
2285 if (lpMachineNameW != NULL)
2286 {
2287 HeapFree(GetProcessHeap(),
2288 0,
2289 lpMachineNameW);
2290 }
2291 if (lpDeviceIDW != NULL)
2292 {
2293 HeapFree(GetProcessHeap(),
2294 0,
2295 lpDeviceIDW);
2296 }
2297
2298 return Ret;
2299 }
2300
2301
2302 /***************************************************************************
2303 * NAME EXPORTED
2304 * DevicePropertiesExA
2305 *
2306 * DESCRIPTION
2307 * Invokes the extended device properties dialog
2308 *
2309 * ARGUMENTS
2310 * hWndParent: Handle to the parent window
2311 * lpMachineName: Machine Name, NULL is the local machine
2312 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2313 * bShowDevMgr is nonzero
2314 * dwFlags: This parameter can be a combination of the following flags:
2315 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2316 * the default device status action button
2317 * to be clicked (Troubleshoot, Enable
2318 * Device, etc)
2319 * bShowDevMgr: If non-zero it displays the device manager instead of
2320 * the advanced device property dialog
2321 *
2322 * RETURN VALUE
2323 * 1: if bShowDevMgr is non-zero and no error occured
2324 * -1: a call to GetLastError returns 0 if successful
2325 *
2326 * @implemented
2327 */
2328 INT_PTR
2329 WINAPI
2330 DevicePropertiesExA(IN HWND hWndParent OPTIONAL,
2331 IN LPCSTR lpMachineName OPTIONAL,
2332 IN LPCSTR lpDeviceID OPTIONAL,
2333 IN DWORD dwFlags OPTIONAL,
2334 IN BOOL bShowDevMgr)
2335 {
2336 LPWSTR lpMachineNameW = NULL;
2337 LPWSTR lpDeviceIDW = NULL;
2338 INT_PTR Ret = -1;
2339
2340 if (lpMachineName != NULL)
2341 {
2342 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2343 CP_ACP)))
2344 {
2345 goto Cleanup;
2346 }
2347 }
2348 if (lpDeviceID != NULL)
2349 {
2350 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2351 CP_ACP)))
2352 {
2353 goto Cleanup;
2354 }
2355 }
2356
2357 Ret = DevicePropertiesExW(hWndParent,
2358 lpMachineNameW,
2359 lpDeviceIDW,
2360 dwFlags,
2361 bShowDevMgr);
2362
2363 Cleanup:
2364 if (lpMachineNameW != NULL)
2365 {
2366 HeapFree(GetProcessHeap(),
2367 0,
2368 lpMachineNameW);
2369 }
2370 if (lpDeviceIDW != NULL)
2371 {
2372 HeapFree(GetProcessHeap(),
2373 0,
2374 lpDeviceIDW);
2375 }
2376
2377 return Ret;
2378 }
2379
2380
2381 /***************************************************************************
2382 * NAME EXPORTED
2383 * DevicePropertiesExW
2384 *
2385 * DESCRIPTION
2386 * Invokes the extended device properties dialog
2387 *
2388 * ARGUMENTS
2389 * hWndParent: Handle to the parent window
2390 * lpMachineName: Machine Name, NULL is the local machine
2391 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2392 * bShowDevMgr is nonzero
2393 * dwFlags: This parameter can be a combination of the following flags:
2394 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2395 * the default device status action button
2396 * to be clicked (Troubleshoot, Enable
2397 * Device, etc)
2398 * bShowDevMgr: If non-zero it displays the device manager instead of
2399 * the advanced device property dialog
2400 *
2401 * RETURN VALUE
2402 * 1: if bShowDevMgr is non-zero and no error occured
2403 * -1: a call to GetLastError returns 0 if successful
2404 *
2405 * @implemented
2406 */
2407 INT_PTR
2408 WINAPI
2409 DevicePropertiesExW(IN HWND hWndParent OPTIONAL,
2410 IN LPCWSTR lpMachineName OPTIONAL,
2411 IN LPCWSTR lpDeviceID OPTIONAL,
2412 IN DWORD dwFlags OPTIONAL,
2413 IN BOOL bShowDevMgr)
2414 {
2415 INT_PTR Ret = -1;
2416
2417 if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
2418 {
2419 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
2420 dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
2421 SetLastError(ERROR_INVALID_FLAGS);
2422 return -1;
2423 }
2424
2425 if (bShowDevMgr)
2426 {
2427 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
2428 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2429 }
2430 else
2431 {
2432 HDEVINFO hDevInfo;
2433 SP_DEVINFO_DATA DevInfoData;
2434 HINSTANCE hComCtl32;
2435
2436 if (lpDeviceID == NULL)
2437 {
2438 SetLastError(ERROR_INVALID_PARAMETER);
2439 return -1;
2440 }
2441
2442 /* dynamically load comctl32 */
2443 hComCtl32 = LoadAndInitComctl32();
2444 if (hComCtl32 != NULL)
2445 {
2446 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2447 hWndParent,
2448 lpMachineName,
2449 NULL);
2450 if (hDevInfo != INVALID_HANDLE_VALUE)
2451 {
2452 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2453 if (SetupDiOpenDeviceInfo(hDevInfo,
2454 lpDeviceID,
2455 hWndParent,
2456 0,
2457 &DevInfoData))
2458 {
2459 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2460 lpDeviceID,
2461 hDevInfo,
2462 &DevInfoData,
2463 hComCtl32,
2464 lpMachineName,
2465 dwFlags);
2466 }
2467
2468 SetupDiDestroyDeviceInfoList(hDevInfo);
2469 }
2470
2471 FreeLibrary(hComCtl32);
2472 }
2473 }
2474
2475 return Ret;
2476 }
2477
2478
2479 /***************************************************************************
2480 * NAME EXPORTED
2481 * DevicePropertiesA
2482 *
2483 * DESCRIPTION
2484 * Invokes the device properties dialog directly
2485 *
2486 * ARGUMENTS
2487 * hWndParent: Handle to the parent window
2488 * lpMachineName: Machine Name, NULL is the local machine
2489 * lpDeviceID: Specifies the device whose properties are to be shown
2490 * bShowDevMgr: If non-zero it displays the device manager instead of
2491 * the device property dialog
2492 *
2493 * RETURN VALUE
2494 * >=0: if no errors occured
2495 * -1: if errors occured
2496 *
2497 * REVISIONS
2498 *
2499 * @implemented
2500 */
2501 int
2502 WINAPI
2503 DevicePropertiesA(HWND hWndParent,
2504 LPCSTR lpMachineName,
2505 LPCSTR lpDeviceID,
2506 BOOL bShowDevMgr)
2507 {
2508 return DevicePropertiesExA(hWndParent,
2509 lpMachineName,
2510 lpDeviceID,
2511 DPF_EXTENDED,
2512 bShowDevMgr);
2513 }
2514
2515
2516 /***************************************************************************
2517 * NAME EXPORTED
2518 * DevicePropertiesW
2519 *
2520 * DESCRIPTION
2521 * Invokes the device properties dialog directly
2522 *
2523 * ARGUMENTS
2524 * hWndParent: Handle to the parent window
2525 * lpMachineName: Machine Name, NULL is the local machine
2526 * lpDeviceID: Specifies the device whose properties are to be shown
2527 * bShowDevMgr: If non-zero it displays the device manager instead of
2528 * the device property dialog
2529 *
2530 * RETURN VALUE
2531 * >=0: if no errors occured
2532 * -1: if errors occured
2533 *
2534 * REVISIONS
2535 *
2536 * @implemented
2537 */
2538 int
2539 WINAPI
2540 DevicePropertiesW(HWND hWndParent,
2541 LPCWSTR lpMachineName,
2542 LPCWSTR lpDeviceID,
2543 BOOL bShowDevMgr)
2544 {
2545 return DevicePropertiesExW(hWndParent,
2546 lpMachineName,
2547 lpDeviceID,
2548 DPF_EXTENDED,
2549 bShowDevMgr);
2550 }
2551
2552
2553 /***************************************************************************
2554 * NAME EXPORTED
2555 * DeviceProperties_RunDLLA
2556 *
2557 * DESCRIPTION
2558 * Invokes the device properties dialog
2559 *
2560 * ARGUMENTS
2561 * hWndParent: Handle to the parent window
2562 * hInst: Handle to the application instance
2563 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
2564 * also see NOTEs
2565 * nCmdShow: Specifies how the window should be shown
2566 *
2567 * RETURN VALUE
2568 *
2569 * REVISIONS
2570 *
2571 * NOTE
2572 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
2573 * (/MachineName is optional). This function only parses this string and eventually
2574 * calls DeviceProperties().
2575 *
2576 * @implemented
2577 */
2578 VOID
2579 WINAPI
2580 DeviceProperties_RunDLLA(HWND hWndParent,
2581 HINSTANCE hInst,
2582 LPCSTR lpDeviceCmd,
2583 int nCmdShow)
2584 {
2585 LPWSTR lpDeviceCmdW = NULL;
2586
2587 if (lpDeviceCmd != NULL)
2588 {
2589 if ((lpDeviceCmdW = ConvertMultiByteToUnicode(lpDeviceCmd,
2590 CP_ACP)))
2591 {
2592 DeviceProperties_RunDLLW(hWndParent,
2593 hInst,
2594 lpDeviceCmdW,
2595 nCmdShow);
2596 }
2597 }
2598
2599 if (lpDeviceCmdW != NULL)
2600 {
2601 HeapFree(GetProcessHeap(),
2602 0,
2603 lpDeviceCmdW);
2604 }
2605 }
2606
2607
2608 /***************************************************************************
2609 * NAME EXPORTED
2610 * DeviceProperties_RunDLLW
2611 *
2612 * DESCRIPTION
2613 * Invokes the device properties dialog
2614 *
2615 * ARGUMENTS
2616 * hWndParent: Handle to the parent window
2617 * hInst: Handle to the application instance
2618 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
2619 * also see NOTEs
2620 * nCmdShow: Specifies how the window should be shown
2621 *
2622 * RETURN VALUE
2623 *
2624 * REVISIONS
2625 *
2626 * NOTE
2627 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
2628 * (/MachineName is optional). This function only parses this string and eventually
2629 * calls DeviceProperties().
2630 *
2631 * @implemented
2632 */
2633 VOID
2634 WINAPI
2635 DeviceProperties_RunDLLW(HWND hWndParent,
2636 HINSTANCE hInst,
2637 LPCWSTR lpDeviceCmd,
2638 int nCmdShow)
2639 {
2640 WCHAR szDeviceID[MAX_DEVICE_ID_LEN+1];
2641 WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
2642 LPWSTR lpString = (LPWSTR)lpDeviceCmd;
2643
2644 if (!GetDeviceAndComputerName(lpString,
2645 szDeviceID,
2646 szMachineName))
2647 {
2648 DPRINT1("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
2649 return;
2650 }
2651
2652 DevicePropertiesW(hWndParent,
2653 szMachineName,
2654 szDeviceID,
2655 FALSE);
2656 }