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