f3f69553306b35d6ec632d7e5ddb17f20cb26306
[reactos.git] / 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(DeviceInfoSet,
1409 DeviceInfoData,
1410 dap->ParentDevInst,
1411 dap->szTemp,
1412 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1413 {
1414 SetDlgItemText(hwndDlg,
1415 IDC_DEVLOCATION,
1416 dap->szTemp);
1417 }
1418
1419 /* set the device status edit control text */
1420 if (GetDeviceStatusString(DeviceInfoData->DevInst,
1421 dap->hMachine,
1422 dap->szTemp,
1423 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
1424 {
1425 SetDlgItemText(hwndDlg,
1426 IDC_DEVSTATUS,
1427 dap->szTemp);
1428 }
1429
1430 /* set the device troubleshoot button text and disable it if necessary */
1431 hDevProbBtn = GetDlgItem(hwndDlg,
1432 IDC_DEVPROBLEM);
1433 cr = CM_Get_DevNode_Status_Ex(&Status,
1434 &ProblemNumber,
1435 DeviceInfoData->DevInst,
1436 0,
1437 dap->hMachine);
1438 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
1439 {
1440 switch (ProblemNumber)
1441 {
1442 case CM_PROB_DEVLOADER_FAILED:
1443 {
1444 /* FIXME - only if it's not a root bus devloader,
1445 disable the button otherwise */
1446 TroubleShootStrId = IDS_UPDATEDRV;
1447 break;
1448 }
1449
1450 case CM_PROB_OUT_OF_MEMORY:
1451 case CM_PROB_ENTRY_IS_WRONG_TYPE:
1452 case CM_PROB_LACKED_ARBITRATOR:
1453 case CM_PROB_FAILED_START:
1454 case CM_PROB_LIAR:
1455 case CM_PROB_UNKNOWN_RESOURCE:
1456 {
1457 TroubleShootStrId = IDS_UPDATEDRV;
1458 break;
1459 }
1460
1461 case CM_PROB_BOOT_CONFIG_CONFLICT:
1462 case CM_PROB_NORMAL_CONFLICT:
1463 case CM_PROB_REENUMERATION:
1464 {
1465 /* FIXME - Troubleshoot conflict */
1466 break;
1467 }
1468
1469 case CM_PROB_FAILED_FILTER:
1470 case CM_PROB_REINSTALL:
1471 case CM_PROB_FAILED_INSTALL:
1472 {
1473 TroubleShootStrId = IDS_REINSTALLDRV;
1474 break;
1475 }
1476
1477 case CM_PROB_DEVLOADER_NOT_FOUND:
1478 {
1479 /* FIXME - 4 cases:
1480 1) if it's a missing system devloader:
1481 - disable the button (Reinstall Driver)
1482 2) if it's not a system devloader but still missing:
1483 - Reinstall Driver
1484 3) if it's not a system devloader but the file can be found:
1485 - Update Driver
1486 4) if it's a missing or empty software key
1487 - Update Driver
1488 */
1489 break;
1490 }
1491
1492 case CM_PROB_INVALID_DATA:
1493 case CM_PROB_PARTIAL_LOG_CONF:
1494 case CM_PROB_NO_VALID_LOG_CONF:
1495 case CM_PROB_HARDWARE_DISABLED:
1496 case CM_PROB_CANT_SHARE_IRQ:
1497 case CM_PROB_TRANSLATION_FAILED:
1498 case CM_PROB_SYSTEM_SHUTDOWN:
1499 case CM_PROB_PHANTOM:
1500 bDevActionAvailable = FALSE;
1501 break;
1502
1503 case CM_PROB_NOT_VERIFIED:
1504 case CM_PROB_DEVICE_NOT_THERE:
1505 /* FIXME - search hardware */
1506 break;
1507
1508 case CM_PROB_NEED_RESTART:
1509 case CM_PROB_WILL_BE_REMOVED:
1510 case CM_PROB_MOVED:
1511 case CM_PROB_TOO_EARLY:
1512 case CM_PROB_DISABLED_SERVICE:
1513 TroubleShootStrId = IDS_REBOOT;
1514 break;
1515
1516 case CM_PROB_REGISTRY:
1517 /* FIXME - check registry? */
1518 break;
1519
1520 case CM_PROB_DISABLED:
1521 /* if device was disabled by the user: */
1522 TroubleShootStrId = IDS_ENABLEDEV;
1523 /* FIXME - otherwise disable button because the device was
1524 disabled by the system*/
1525 break;
1526
1527 case CM_PROB_DEVLOADER_NOT_READY:
1528 /* FIXME - if it's a graphics adapter:
1529 - if it's a a secondary adapter and the main adapter
1530 couldn't be found
1531 - disable button
1532 - else
1533 - Properties
1534 - else
1535 - Update driver
1536 */
1537 break;
1538
1539 case CM_PROB_FAILED_ADD:
1540 TroubleShootStrId = IDS_PROPERTIES;
1541 break;
1542 }
1543 }
1544
1545 if (LoadString(hDllInstance,
1546 TroubleShootStrId,
1547 dap->szTemp,
1548 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
1549 {
1550 SetWindowText(hDevProbBtn,
1551 dap->szTemp);
1552 }
1553 EnableWindow(hDevProbBtn,
1554 dap->IsAdmin && bDevActionAvailable);
1555
1556 /* check if the device can be enabled/disabled */
1557 hDevUsage = GetDlgItem(hwndDlg,
1558 IDC_DEVUSAGE);
1559
1560 dap->CanDisable = FALSE;
1561 dap->DeviceStarted = FALSE;
1562
1563 if (CanDisableDevice(DeviceInfoData->DevInst,
1564 dap->hMachine,
1565 &bFlag))
1566 {
1567 dap->CanDisable = bFlag;
1568 }
1569
1570 if (IsDeviceStarted(DeviceInfoData->DevInst,
1571 dap->hMachine,
1572 &bFlag))
1573 {
1574 dap->DeviceStarted = bFlag;
1575 }
1576
1577 /* enable/disable the device usage controls */
1578 EnableWindow(GetDlgItem(hwndDlg,
1579 IDC_DEVUSAGELABEL),
1580 dap->CanDisable && dap->IsAdmin);
1581 EnableWindow(hDevUsage,
1582 dap->CanDisable && dap->IsAdmin);
1583
1584 /* clear the combobox */
1585 SendMessage(hDevUsage,
1586 CB_RESETCONTENT,
1587 0,
1588 0);
1589 if (dap->CanDisable)
1590 {
1591 InitDevUsageActions(hwndDlg,
1592 hDevUsage,
1593 dap);
1594 }
1595
1596 /* find out how many new device property sheets to add.
1597 fake a PROPSHEETHEADER structure, we don't plan to
1598 call PropertySheet again!*/
1599 psh.dwSize = sizeof(PROPSHEETHEADER);
1600 psh.dwFlags = 0;
1601 psh.nPages = 0;
1602
1603 /* get the number of device property sheets for the device */
1604 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
1605 DeviceInfoData,
1606 &psh,
1607 0,
1608 &nDriverPages,
1609 dap->PropertySheetType) &&
1610 nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1611 {
1612 dap->nDevPropSheets += nDriverPages;
1613 }
1614 else
1615 {
1616 nDriverPages = 0;
1617 }
1618
1619 /* include the driver page */
1620 if (dap->HasDriverPage)
1621 dap->nDevPropSheets++;
1622
1623 /* include the details page */
1624 dap->nDevPropSheets++;
1625
1626 /* add the device property sheets */
1627 if (dap->nDevPropSheets != 0)
1628 {
1629 dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
1630 HEAP_ZERO_MEMORY,
1631 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
1632 if (dap->DevPropSheets != NULL)
1633 {
1634 if (nDriverPages != 0)
1635 {
1636 psh.phpage = dap->DevPropSheets;
1637
1638 /* query the device property sheet pages to add */
1639 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
1640 DeviceInfoData,
1641 &psh,
1642 dap->nDevPropSheets,
1643 NULL,
1644 dap->PropertySheetType))
1645 {
1646 /* add the property sheets */
1647 for (iPage = 0;
1648 iPage != nDriverPages;
1649 iPage++)
1650 {
1651 if (PropSheet_AddPage(hPropSheetDlg,
1652 dap->DevPropSheets[iPage]))
1653 {
1654 RecalcPages = TRUE;
1655 }
1656 }
1657
1658 dap->FreeDevPropSheets = TRUE;
1659 }
1660 else
1661 {
1662 /* cleanup, we were unable to get the device property sheets */
1663 iPage = nDriverPages;
1664 dap->nDevPropSheets -= nDriverPages;
1665 nDriverPages = 0;
1666 }
1667 }
1668 else
1669 iPage = 0;
1670
1671 /* add the driver page if necessary */
1672 if (dap->HasDriverPage)
1673 {
1674 PROPSHEETPAGE pspDriver = {0};
1675 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
1676 pspDriver.dwFlags = PSP_DEFAULT;
1677 pspDriver.hInstance = hDllInstance;
1678 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
1679 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
1680 pspDriver.lParam = (LPARAM)dap;
1681 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
1682 if (dap->DevPropSheets[iPage] != NULL)
1683 {
1684 if (PropSheet_AddPage(hPropSheetDlg,
1685 dap->DevPropSheets[iPage]))
1686 {
1687 iPage++;
1688 RecalcPages = TRUE;
1689 }
1690 else
1691 {
1692 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
1693 dap->DevPropSheets[iPage] = NULL;
1694 }
1695 }
1696 }
1697
1698 if (1)
1699 {
1700 PROPSHEETPAGE pspDetails = {0};
1701 pspDetails.dwSize = sizeof(PROPSHEETPAGE);
1702 pspDetails.dwFlags = PSP_DEFAULT;
1703 pspDetails.hInstance = hDllInstance;
1704 pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
1705 pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
1706 pspDetails.lParam = (LPARAM)dap;
1707 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
1708 if (dap->DevPropSheets[iPage] != NULL)
1709 {
1710 if (PropSheet_AddPage(hPropSheetDlg,
1711 dap->DevPropSheets[iPage]))
1712 {
1713 iPage++;
1714 RecalcPages = TRUE;
1715 }
1716 else
1717 {
1718 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
1719 dap->DevPropSheets[iPage] = NULL;
1720 }
1721 }
1722 }
1723
1724 /* FIXME: Add the resources page */
1725
1726 /* FIXME: Add the power page */
1727 }
1728 else
1729 dap->nDevPropSheets = 0;
1730 }
1731
1732 if (RecalcPages)
1733 {
1734 PropSheet_RecalcPageSizes(hPropSheetDlg);
1735 }
1736
1737 /* finally, disable the apply button */
1738 PropSheet_UnChanged(hPropSheetDlg,
1739 hwndDlg);
1740 dap->DeviceUsageChanged = FALSE;
1741 }
1742
1743
1744 static LRESULT
1745 CALLBACK
1746 DlgParentSubWndProc(IN HWND hwnd,
1747 IN UINT uMsg,
1748 IN WPARAM wParam,
1749 IN LPARAM lParam)
1750 {
1751 PDEVADVPROP_INFO dap;
1752
1753 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
1754 L"DevMgrDevChangeSub");
1755 if (dap != NULL)
1756 {
1757 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
1758 {
1759 SendMessage(dap->hWndGeneralPage,
1760 WM_DEVICECHANGE,
1761 wParam,
1762 lParam);
1763 }
1764
1765 /* pass the message the the old window proc */
1766 return CallWindowProc(dap->ParentOldWndProc,
1767 hwnd,
1768 uMsg,
1769 wParam,
1770 lParam);
1771 }
1772 else
1773 {
1774 /* this is not a good idea if the subclassed window was an ansi
1775 window, but we failed finding out the previous window proc
1776 so we can't use CallWindowProc. This should rarely - if ever -
1777 happen. */
1778
1779 return DefWindowProc(hwnd,
1780 uMsg,
1781 wParam,
1782 lParam);
1783 }
1784 }
1785
1786
1787 static INT_PTR
1788 CALLBACK
1789 AdvPropGeneralDlgProc(IN HWND hwndDlg,
1790 IN UINT uMsg,
1791 IN WPARAM wParam,
1792 IN LPARAM lParam)
1793 {
1794 PDEVADVPROP_INFO dap;
1795 INT_PTR Ret = FALSE;
1796
1797 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
1798 DWL_USER);
1799
1800 if (dap != NULL || uMsg == WM_INITDIALOG)
1801 {
1802 switch (uMsg)
1803 {
1804 case WM_COMMAND:
1805 {
1806 switch (LOWORD(wParam))
1807 {
1808 case IDC_DEVUSAGE:
1809 {
1810 if (HIWORD(wParam) == CBN_SELCHANGE)
1811 {
1812 PropSheet_Changed(GetParent(hwndDlg),
1813 hwndDlg);
1814 dap->DeviceUsageChanged = TRUE;
1815 }
1816 break;
1817 }
1818
1819 case IDC_DEVPROBLEM:
1820 {
1821 if (dap->IsAdmin)
1822 {
1823 /* display the device problem wizard */
1824 ShowDeviceProblemWizard(hwndDlg,
1825 dap->DeviceInfoSet,
1826 &dap->DeviceInfoData,
1827 dap->hMachine);
1828 }
1829 break;
1830 }
1831 }
1832 break;
1833 }
1834
1835 case WM_NOTIFY:
1836 {
1837 NMHDR *hdr = (NMHDR*)lParam;
1838 switch (hdr->code)
1839 {
1840 case PSN_APPLY:
1841 ApplyGeneralSettings(hwndDlg,
1842 dap);
1843 break;
1844 }
1845 break;
1846 }
1847
1848 case WM_INITDIALOG:
1849 {
1850 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
1851 if (dap != NULL)
1852 {
1853 HWND hWndParent;
1854
1855 dap->hWndGeneralPage = hwndDlg;
1856
1857 SetWindowLongPtr(hwndDlg,
1858 DWL_USER,
1859 (DWORD_PTR)dap);
1860
1861 /* subclass the parent window to always receive
1862 WM_DEVICECHANGE messages */
1863 hWndParent = GetParent(hwndDlg);
1864 if (hWndParent != NULL)
1865 {
1866 /* subclass the parent window. This is not safe
1867 if the parent window belongs to another thread! */
1868 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
1869 GWLP_WNDPROC,
1870 (LONG_PTR)DlgParentSubWndProc);
1871
1872 if (dap->ParentOldWndProc != NULL &&
1873 SetProp(hWndParent,
1874 L"DevMgrDevChangeSub",
1875 (HANDLE)dap))
1876 {
1877 dap->hWndParent = hWndParent;
1878 }
1879 }
1880
1881 /* do not call UpdateDevInfo directly in here because it modifies
1882 the pages of the property sheet! */
1883 PostMessage(hwndDlg,
1884 PM_INITIALIZE,
1885 0,
1886 0);
1887 }
1888 Ret = TRUE;
1889 break;
1890 }
1891
1892 case WM_DEVICECHANGE:
1893 {
1894 /* FIXME - don't call UpdateDevInfo for all events */
1895 UpdateDevInfo(hwndDlg,
1896 dap,
1897 TRUE);
1898 Ret = TRUE;
1899 break;
1900 }
1901
1902 case PM_INITIALIZE:
1903 {
1904 UpdateDevInfo(hwndDlg,
1905 dap,
1906 FALSE);
1907 dap->PageInitialized = TRUE;
1908 break;
1909 }
1910
1911 case WM_DESTROY:
1912 {
1913 /* restore the old window proc of the subclassed parent window */
1914 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
1915 {
1916 if (SetWindowLongPtr(dap->hWndParent,
1917 GWLP_WNDPROC,
1918 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
1919 {
1920 RemoveProp(dap->hWndParent,
1921 L"DevMgrDevChangeSub");
1922 }
1923 }
1924 break;
1925 }
1926 }
1927 }
1928
1929 return Ret;
1930 }
1931
1932
1933 INT_PTR
1934 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
1935 IN LPCWSTR lpDeviceID OPTIONAL,
1936 IN HDEVINFO DeviceInfoSet,
1937 IN PSP_DEVINFO_DATA DeviceInfoData,
1938 IN HINSTANCE hComCtl32,
1939 IN LPCWSTR lpMachineName,
1940 IN DWORD dwFlags)
1941 {
1942 PROPSHEETHEADER psh = {0};
1943 PROPSHEETPAGE pspGeneral = {0};
1944 PPROPERTYSHEETW pPropertySheetW;
1945 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
1946 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
1947 PDEVADVPROP_INFO DevAdvPropInfo;
1948 HMACHINE hMachine = NULL;
1949 DWORD DevIdSize = 0;
1950 INT_PTR Ret = -1;
1951
1952 /* we don't want to statically link against comctl32, so find the
1953 functions we need dynamically */
1954 pPropertySheetW =
1955 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
1956 "PropertySheetW");
1957 pCreatePropertySheetPageW =
1958 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
1959 "CreatePropertySheetPageW");
1960 pDestroyPropertySheetPage =
1961 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
1962 "DestroyPropertySheetPage");
1963 if (pPropertySheetW == NULL ||
1964 pCreatePropertySheetPageW == NULL ||
1965 pDestroyPropertySheetPage == NULL)
1966 {
1967 return -1;
1968 }
1969
1970 if (lpDeviceID == NULL)
1971 {
1972 /* find out how much size is needed for the device id */
1973 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
1974 DeviceInfoData,
1975 NULL,
1976 0,
1977 &DevIdSize))
1978 {
1979 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1980 return -1;
1981 }
1982
1983 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1984 {
1985 return -1;
1986 }
1987 }
1988 else
1989 {
1990 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
1991 }
1992
1993 if (lpMachineName != NULL && lpMachineName[0] != L'\0')
1994 {
1995 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
1996 &hMachine);
1997 if (cr != CR_SUCCESS)
1998 {
1999 return -1;
2000 }
2001 }
2002
2003 /* create the internal structure associated with the "General",
2004 "Driver", ... pages */
2005 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
2006 HEAP_ZERO_MEMORY,
2007 FIELD_OFFSET(DEVADVPROP_INFO,
2008 szDeviceID) +
2009 (DevIdSize * sizeof(WCHAR)));
2010 if (DevAdvPropInfo == NULL)
2011 {
2012 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2013 goto Cleanup;
2014 }
2015
2016 if (lpDeviceID == NULL)
2017 {
2018 /* read the device instance id */
2019 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
2020 DeviceInfoData,
2021 DevAdvPropInfo->szDeviceID,
2022 DevIdSize,
2023 NULL))
2024 {
2025 goto Cleanup;
2026 }
2027 }
2028 else
2029 {
2030 /* copy the device instance id supplied by the caller */
2031 wcscpy(DevAdvPropInfo->szDeviceID,
2032 lpDeviceID);
2033 }
2034
2035 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
2036 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
2037 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
2038 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2039
2040 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
2041 DevAdvPropInfo->hMachine = hMachine;
2042 DevAdvPropInfo->lpMachineName = lpMachineName;
2043 DevAdvPropInfo->szDevName[0] = L'\0';
2044 DevAdvPropInfo->hComCtl32 = hComCtl32;
2045 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
2046 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
2047
2048 DevAdvPropInfo->IsAdmin = IsUserAdmin();
2049 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
2050
2051 psh.dwSize = sizeof(PROPSHEETHEADER);
2052 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
2053 psh.hwndParent = hWndParent;
2054 psh.pszCaption = DevAdvPropInfo->szDevName;
2055
2056 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
2057 DIGCDP_FLAG_REMOTE_ADVANCED :
2058 DIGCDP_FLAG_ADVANCED;
2059
2060 psh.phpage = HeapAlloc(GetProcessHeap(),
2061 HEAP_ZERO_MEMORY,
2062 1 * sizeof(HPROPSHEETPAGE));
2063 if (psh.phpage == NULL)
2064 {
2065 goto Cleanup;
2066 }
2067
2068 /* add the "General" property sheet */
2069 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
2070 pspGeneral.dwFlags = PSP_DEFAULT;
2071 pspGeneral.hInstance = hDllInstance;
2072 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
2073 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
2074 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
2075 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
2076 if (psh.phpage[psh.nPages] != NULL)
2077 {
2078 psh.nPages++;
2079 }
2080
2081 DevAdvPropInfo->nDevPropSheets = psh.nPages;
2082
2083 if (psh.nPages != 0)
2084 {
2085 Ret = pPropertySheetW(&psh);
2086
2087 /* NOTE: no need to destroy the property sheets anymore! */
2088 }
2089 else
2090 {
2091 UINT i;
2092
2093 Cleanup:
2094 /* in case of failure the property sheets must be destroyed */
2095 if (psh.phpage != NULL)
2096 {
2097 for (i = 0;
2098 i < psh.nPages;
2099 i++)
2100 {
2101 if (psh.phpage[i] != NULL)
2102 {
2103 pDestroyPropertySheetPage(psh.phpage[i]);
2104 }
2105 }
2106 }
2107 }
2108
2109 if (DevAdvPropInfo != NULL)
2110 {
2111 if (DevAdvPropInfo->FreeDevPropSheets)
2112 {
2113 /* don't free the array if it's the one allocated in
2114 DisplayDeviceAdvancedProperties */
2115 HeapFree(GetProcessHeap(),
2116 0,
2117 DevAdvPropInfo->DevPropSheets);
2118 }
2119
2120 if (DevAdvPropInfo->CloseDevInst)
2121 {
2122 /* close the device info set in case a new one was created */
2123 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
2124 }
2125
2126 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
2127 {
2128 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
2129 }
2130
2131 if (DevAdvPropInfo->hDevIcon != NULL)
2132 {
2133 DestroyIcon(DevAdvPropInfo->hDevIcon);
2134 }
2135
2136 HeapFree(GetProcessHeap(),
2137 0,
2138 DevAdvPropInfo);
2139 }
2140
2141 if (psh.phpage != NULL)
2142 {
2143 HeapFree(GetProcessHeap(),
2144 0,
2145 psh.phpage);
2146 }
2147
2148 if (hMachine != NULL)
2149 {
2150 CM_Disconnect_Machine(hMachine);
2151 }
2152
2153 return Ret;
2154 }
2155
2156
2157 static BOOL
2158 GetDeviceAndComputerName(LPWSTR lpString,
2159 WCHAR szDeviceID[],
2160 WCHAR szMachineName[])
2161 {
2162 BOOL ret = FALSE;
2163
2164 szDeviceID[0] = L'\0';
2165 szMachineName[0] = L'\0';
2166
2167 while (*lpString != L'\0')
2168 {
2169 if (*lpString == L'/')
2170 {
2171 lpString++;
2172 if(!_wcsnicmp(lpString, L"DeviceID", 8))
2173 {
2174 lpString += 9;
2175 if (*lpString != L'\0')
2176 {
2177 int i = 0;
2178 while ((*lpString != L' ') &&
2179 (*lpString != L'\0') &&
2180 (i <= MAX_DEVICE_ID_LEN))
2181 {
2182 szDeviceID[i++] = *lpString++;
2183 }
2184 szDeviceID[i] = L'\0';
2185 ret = TRUE;
2186 }
2187 }
2188 else if (!_wcsnicmp(lpString, L"MachineName", 11))
2189 {
2190 lpString += 12;
2191 if (*lpString != L'\0')
2192 {
2193 int i = 0;
2194 while ((*lpString != L' ') &&
2195 (*lpString != L'\0') &&
2196 (i <= MAX_COMPUTERNAME_LENGTH))
2197 {
2198 szMachineName[i++] = *lpString++;
2199 }
2200 szMachineName[i] = L'\0';
2201 }
2202 }
2203 /* knock the pointer back one and let the next
2204 * pointer deal with incrementing, otherwise we
2205 * go past the end of the string */
2206 lpString--;
2207 }
2208 lpString++;
2209 }
2210
2211 return ret;
2212 }
2213
2214
2215 /***************************************************************************
2216 * NAME EXPORTED
2217 * DeviceAdvancedPropertiesW
2218 *
2219 * DESCRIPTION
2220 * Invokes the device properties dialog, this version may add some property pages
2221 * for some devices
2222 *
2223 * ARGUMENTS
2224 * hWndParent: Handle to the parent window
2225 * lpMachineName: Machine Name, NULL is the local machine
2226 * lpDeviceID: Specifies the device whose properties are to be shown
2227 *
2228 * RETURN VALUE
2229 * Always returns -1, a call to GetLastError returns 0 if successful
2230 *
2231 * @implemented
2232 */
2233 INT_PTR
2234 WINAPI
2235 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL,
2236 IN LPCWSTR lpMachineName OPTIONAL,
2237 IN LPCWSTR lpDeviceID)
2238 {
2239 HDEVINFO hDevInfo;
2240 SP_DEVINFO_DATA DevInfoData;
2241 HINSTANCE hComCtl32;
2242 INT_PTR Ret = -1;
2243
2244 if (lpDeviceID == NULL)
2245 {
2246 SetLastError(ERROR_INVALID_PARAMETER);
2247 return FALSE;
2248 }
2249
2250 /* dynamically load comctl32 */
2251 hComCtl32 = LoadAndInitComctl32();
2252 if (hComCtl32 != NULL)
2253 {
2254 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2255 hWndParent,
2256 lpMachineName,
2257 NULL);
2258 if (hDevInfo != INVALID_HANDLE_VALUE)
2259 {
2260 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2261 if (SetupDiOpenDeviceInfo(hDevInfo,
2262 lpDeviceID,
2263 hWndParent,
2264 0,
2265 &DevInfoData))
2266 {
2267 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2268 lpDeviceID,
2269 hDevInfo,
2270 &DevInfoData,
2271 hComCtl32,
2272 lpMachineName,
2273 0);
2274 }
2275
2276 SetupDiDestroyDeviceInfoList(hDevInfo);
2277 }
2278
2279 FreeLibrary(hComCtl32);
2280 }
2281
2282 return Ret;
2283 }
2284
2285
2286 /***************************************************************************
2287 * NAME EXPORTED
2288 * DeviceAdvancedPropertiesA
2289 *
2290 * DESCRIPTION
2291 * Invokes the device properties dialog, this version may add some property pages
2292 * for some devices
2293 *
2294 * ARGUMENTS
2295 * hWndParent: Handle to the parent window
2296 * lpMachineName: Machine Name, NULL is the local machine
2297 * lpDeviceID: Specifies the device whose properties are to be shown
2298 *
2299 * RETURN VALUE
2300 * Always returns -1, a call to GetLastError returns 0 if successful
2301 *
2302 * @implemented
2303 */
2304 INT_PTR
2305 WINAPI
2306 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL,
2307 IN LPCSTR lpMachineName OPTIONAL,
2308 IN LPCSTR lpDeviceID)
2309 {
2310 LPWSTR lpMachineNameW = NULL;
2311 LPWSTR lpDeviceIDW = NULL;
2312 INT_PTR Ret = -1;
2313
2314 if (lpMachineName != NULL)
2315 {
2316 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2317 CP_ACP)))
2318 {
2319 goto Cleanup;
2320 }
2321 }
2322 if (lpDeviceID != NULL)
2323 {
2324 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2325 CP_ACP)))
2326 {
2327 goto Cleanup;
2328 }
2329 }
2330
2331 Ret = DeviceAdvancedPropertiesW(hWndParent,
2332 lpMachineNameW,
2333 lpDeviceIDW);
2334
2335 Cleanup:
2336 if (lpMachineNameW != NULL)
2337 {
2338 HeapFree(GetProcessHeap(),
2339 0,
2340 lpMachineNameW);
2341 }
2342 if (lpDeviceIDW != NULL)
2343 {
2344 HeapFree(GetProcessHeap(),
2345 0,
2346 lpDeviceIDW);
2347 }
2348
2349 return Ret;
2350 }
2351
2352
2353 /***************************************************************************
2354 * NAME EXPORTED
2355 * DevicePropertiesExA
2356 *
2357 * DESCRIPTION
2358 * Invokes the extended device properties dialog
2359 *
2360 * ARGUMENTS
2361 * hWndParent: Handle to the parent window
2362 * lpMachineName: Machine Name, NULL is the local machine
2363 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2364 * bShowDevMgr is nonzero
2365 * dwFlags: This parameter can be a combination of the following flags:
2366 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2367 * the default device status action button
2368 * to be clicked (Troubleshoot, Enable
2369 * Device, etc)
2370 * bShowDevMgr: If non-zero it displays the device manager instead of
2371 * the advanced device property dialog
2372 *
2373 * RETURN VALUE
2374 * 1: if bShowDevMgr is non-zero and no error occured
2375 * -1: a call to GetLastError returns 0 if successful
2376 *
2377 * @implemented
2378 */
2379 INT_PTR
2380 WINAPI
2381 DevicePropertiesExA(IN HWND hWndParent OPTIONAL,
2382 IN LPCSTR lpMachineName OPTIONAL,
2383 IN LPCSTR lpDeviceID OPTIONAL,
2384 IN DWORD dwFlags OPTIONAL,
2385 IN BOOL bShowDevMgr)
2386 {
2387 LPWSTR lpMachineNameW = NULL;
2388 LPWSTR lpDeviceIDW = NULL;
2389 INT_PTR Ret = -1;
2390
2391 if (lpMachineName != NULL)
2392 {
2393 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
2394 CP_ACP)))
2395 {
2396 goto Cleanup;
2397 }
2398 }
2399 if (lpDeviceID != NULL)
2400 {
2401 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
2402 CP_ACP)))
2403 {
2404 goto Cleanup;
2405 }
2406 }
2407
2408 Ret = DevicePropertiesExW(hWndParent,
2409 lpMachineNameW,
2410 lpDeviceIDW,
2411 dwFlags,
2412 bShowDevMgr);
2413
2414 Cleanup:
2415 if (lpMachineNameW != NULL)
2416 {
2417 HeapFree(GetProcessHeap(),
2418 0,
2419 lpMachineNameW);
2420 }
2421 if (lpDeviceIDW != NULL)
2422 {
2423 HeapFree(GetProcessHeap(),
2424 0,
2425 lpDeviceIDW);
2426 }
2427
2428 return Ret;
2429 }
2430
2431
2432 /***************************************************************************
2433 * NAME EXPORTED
2434 * DevicePropertiesExW
2435 *
2436 * DESCRIPTION
2437 * Invokes the extended device properties dialog
2438 *
2439 * ARGUMENTS
2440 * hWndParent: Handle to the parent window
2441 * lpMachineName: Machine Name, NULL is the local machine
2442 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
2443 * bShowDevMgr is nonzero
2444 * dwFlags: This parameter can be a combination of the following flags:
2445 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
2446 * the default device status action button
2447 * to be clicked (Troubleshoot, Enable
2448 * Device, etc)
2449 * bShowDevMgr: If non-zero it displays the device manager instead of
2450 * the advanced device property dialog
2451 *
2452 * RETURN VALUE
2453 * 1: if bShowDevMgr is non-zero and no error occured
2454 * -1: a call to GetLastError returns 0 if successful
2455 *
2456 * @implemented
2457 */
2458 INT_PTR
2459 WINAPI
2460 DevicePropertiesExW(IN HWND hWndParent OPTIONAL,
2461 IN LPCWSTR lpMachineName OPTIONAL,
2462 IN LPCWSTR lpDeviceID OPTIONAL,
2463 IN DWORD dwFlags OPTIONAL,
2464 IN BOOL bShowDevMgr)
2465 {
2466 INT_PTR Ret = -1;
2467
2468 if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
2469 {
2470 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
2471 dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
2472 SetLastError(ERROR_INVALID_FLAGS);
2473 return -1;
2474 }
2475
2476 if (bShowDevMgr)
2477 {
2478 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
2479 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2480 }
2481 else
2482 {
2483 HDEVINFO hDevInfo;
2484 SP_DEVINFO_DATA DevInfoData;
2485 HINSTANCE hComCtl32;
2486
2487 if (lpDeviceID == NULL)
2488 {
2489 SetLastError(ERROR_INVALID_PARAMETER);
2490 return -1;
2491 }
2492
2493 /* dynamically load comctl32 */
2494 hComCtl32 = LoadAndInitComctl32();
2495 if (hComCtl32 != NULL)
2496 {
2497 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
2498 hWndParent,
2499 lpMachineName,
2500 NULL);
2501 if (hDevInfo != INVALID_HANDLE_VALUE)
2502 {
2503 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2504 if (SetupDiOpenDeviceInfo(hDevInfo,
2505 lpDeviceID,
2506 hWndParent,
2507 0,
2508 &DevInfoData))
2509 {
2510 Ret = DisplayDeviceAdvancedProperties(hWndParent,
2511 lpDeviceID,
2512 hDevInfo,
2513 &DevInfoData,
2514 hComCtl32,
2515 lpMachineName,
2516 dwFlags);
2517 }
2518
2519 SetupDiDestroyDeviceInfoList(hDevInfo);
2520 }
2521
2522 FreeLibrary(hComCtl32);
2523 }
2524 }
2525
2526 return Ret;
2527 }
2528
2529
2530 /***************************************************************************
2531 * NAME EXPORTED
2532 * DevicePropertiesA
2533 *
2534 * DESCRIPTION
2535 * Invokes the device properties dialog directly
2536 *
2537 * ARGUMENTS
2538 * hWndParent: Handle to the parent window
2539 * lpMachineName: Machine Name, NULL is the local machine
2540 * lpDeviceID: Specifies the device whose properties are to be shown
2541 * bShowDevMgr: If non-zero it displays the device manager instead of
2542 * the device property dialog
2543 *
2544 * RETURN VALUE
2545 * >=0: if no errors occured
2546 * -1: if errors occured
2547 *
2548 * REVISIONS
2549 *
2550 * @implemented
2551 */
2552 int
2553 WINAPI
2554 DevicePropertiesA(HWND hWndParent,
2555 LPCSTR lpMachineName,
2556 LPCSTR lpDeviceID,
2557 BOOL bShowDevMgr)
2558 {
2559 return DevicePropertiesExA(hWndParent,
2560 lpMachineName,
2561 lpDeviceID,
2562 DPF_EXTENDED,
2563 bShowDevMgr);
2564 }
2565
2566
2567 /***************************************************************************
2568 * NAME EXPORTED
2569 * DevicePropertiesW
2570 *
2571 * DESCRIPTION
2572 * Invokes the device properties dialog directly
2573 *
2574 * ARGUMENTS
2575 * hWndParent: Handle to the parent window
2576 * lpMachineName: Machine Name, NULL is the local machine
2577 * lpDeviceID: Specifies the device whose properties are to be shown
2578 * bShowDevMgr: If non-zero it displays the device manager instead of
2579 * the device property dialog
2580 *
2581 * RETURN VALUE
2582 * >=0: if no errors occured
2583 * -1: if errors occured
2584 *
2585 * REVISIONS
2586 *
2587 * @implemented
2588 */
2589 int
2590 WINAPI
2591 DevicePropertiesW(HWND hWndParent,
2592 LPCWSTR lpMachineName,
2593 LPCWSTR lpDeviceID,
2594 BOOL bShowDevMgr)
2595 {
2596 return DevicePropertiesExW(hWndParent,
2597 lpMachineName,
2598 lpDeviceID,
2599 DPF_EXTENDED,
2600 bShowDevMgr);
2601 }
2602
2603
2604 /***************************************************************************
2605 * NAME EXPORTED
2606 * DeviceProperties_RunDLLA
2607 *
2608 * DESCRIPTION
2609 * Invokes the device properties dialog
2610 *
2611 * ARGUMENTS
2612 * hWndParent: Handle to the parent window
2613 * hInst: Handle to the application instance
2614 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
2615 * also see NOTEs
2616 * nCmdShow: Specifies how the window should be shown
2617 *
2618 * RETURN VALUE
2619 *
2620 * REVISIONS
2621 *
2622 * NOTE
2623 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
2624 * (/MachineName is optional). This function only parses this string and eventually
2625 * calls DeviceProperties().
2626 *
2627 * @implemented
2628 */
2629 VOID
2630 WINAPI
2631 DeviceProperties_RunDLLA(HWND hWndParent,
2632 HINSTANCE hInst,
2633 LPCSTR lpDeviceCmd,
2634 int nCmdShow)
2635 {
2636 LPWSTR lpDeviceCmdW = NULL;
2637
2638 if (lpDeviceCmd != NULL)
2639 {
2640 if ((lpDeviceCmdW = ConvertMultiByteToUnicode(lpDeviceCmd,
2641 CP_ACP)))
2642 {
2643 DeviceProperties_RunDLLW(hWndParent,
2644 hInst,
2645 lpDeviceCmdW,
2646 nCmdShow);
2647 }
2648 }
2649
2650 if (lpDeviceCmdW != NULL)
2651 {
2652 HeapFree(GetProcessHeap(),
2653 0,
2654 lpDeviceCmdW);
2655 }
2656 }
2657
2658
2659 /***************************************************************************
2660 * NAME EXPORTED
2661 * DeviceProperties_RunDLLW
2662 *
2663 * DESCRIPTION
2664 * Invokes the device properties dialog
2665 *
2666 * ARGUMENTS
2667 * hWndParent: Handle to the parent window
2668 * hInst: Handle to the application instance
2669 * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
2670 * also see NOTEs
2671 * nCmdShow: Specifies how the window should be shown
2672 *
2673 * RETURN VALUE
2674 *
2675 * REVISIONS
2676 *
2677 * NOTE
2678 * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
2679 * (/MachineName is optional). This function only parses this string and eventually
2680 * calls DeviceProperties().
2681 *
2682 * @implemented
2683 */
2684 VOID
2685 WINAPI
2686 DeviceProperties_RunDLLW(HWND hWndParent,
2687 HINSTANCE hInst,
2688 LPCWSTR lpDeviceCmd,
2689 int nCmdShow)
2690 {
2691 WCHAR szDeviceID[MAX_DEVICE_ID_LEN+1];
2692 WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
2693 LPWSTR lpString = (LPWSTR)lpDeviceCmd;
2694
2695 if (!GetDeviceAndComputerName(lpString,
2696 szDeviceID,
2697 szMachineName))
2698 {
2699 DPRINT1("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
2700 return;
2701 }
2702
2703 DevicePropertiesW(hWndParent,
2704 szMachineName,
2705 szDeviceID,
2706 FALSE);
2707 }