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