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