update hu langues file patch from talley.
[reactos.git] / reactos / lib / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 /* $Id: hwpage.c 19599 2005-11-26 02:12:58Z weiden $
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 * UPDATE HISTORY:
26 * 04-04-2004 Created
27 */
28 #include <precomp.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33 typedef INT_PTR (WINAPI *PPROPERTYSHEETW)(LPCPROPSHEETHEADERW);
34 typedef HPROPSHEETPAGE (WINAPI *PCREATEPROPERTYSHEETPAGEW)(LPCPROPSHEETPAGEW);
35 typedef BOOL (WINAPI *PDESTROYPROPERTYSHEETPAGE)(HPROPSHEETPAGE);
36
37 typedef struct _DEVADVPROP_INFO
38 {
39 HWND hWndGeneralPage;
40 HWND hWndParent;
41 WNDPROC ParentOldWndProc;
42 HICON hDevIcon;
43
44 HDEVINFO DeviceInfoSet;
45 SP_DEVINFO_DATA DeviceInfoData;
46 HDEVINFO CurrentDeviceInfoSet;
47 SP_DEVINFO_DATA CurrentDeviceInfoData;
48 DEVINST ParentDevInst;
49 HMACHINE hMachine;
50 LPCWSTR lpMachineName;
51
52 HINSTANCE hComCtl32;
53 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
54 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
55
56 DWORD PropertySheetType;
57 DWORD nDevPropSheets;
58 HPROPSHEETPAGE *DevPropSheets;
59
60 BOOL FreeDevPropSheets : 1;
61 BOOL CanDisable : 1;
62 BOOL DeviceStarted : 1;
63 BOOL DeviceUsageChanged : 1;
64 BOOL CloseDevInst : 1;
65 BOOL IsAdmin : 1;
66 BOOL DoDefaultDevAction : 1;
67 BOOL PageInitialized : 1;
68 BOOL ShowRemotePages : 1;
69 BOOL HasDriverPage : 1;
70 BOOL HasResourcePage : 1;
71 BOOL HasPowerPage : 1;
72
73 WCHAR szDevName[255];
74 WCHAR szTemp[255];
75 WCHAR szDeviceID[1];
76 /* struct may be dynamically expanded here! */
77 } DEVADVPROP_INFO, *PDEVADVPROP_INFO;
78
79 #define PM_INITIALIZE (WM_APP + 0x101)
80
81
82 static VOID
83 UpdateDriverDlg(IN HWND hwndDlg,
84 IN PDEVADVPROP_INFO dap)
85 {
86 HDEVINFO DeviceInfoSet;
87 PSP_DEVINFO_DATA DeviceInfoData;
88
89 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
90 {
91 DeviceInfoSet = dap->CurrentDeviceInfoSet;
92 DeviceInfoData = &dap->CurrentDeviceInfoData;
93 }
94 else
95 {
96 DeviceInfoSet = dap->DeviceInfoSet;
97 DeviceInfoData = &dap->DeviceInfoData;
98 }
99
100 /* set the device image */
101 SendDlgItemMessage(hwndDlg,
102 IDC_DEVICON,
103 STM_SETICON,
104 (WPARAM)dap->hDevIcon,
105 0);
106
107 /* set the device name edit control text */
108 SetDlgItemText(hwndDlg,
109 IDC_DEVNAME,
110 dap->szDevName);
111
112 /* query the driver provider */
113 if (GetDriverProviderString(DeviceInfoSet,
114 DeviceInfoData,
115 dap->szTemp,
116 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
117 {
118 SetDlgItemText(hwndDlg,
119 IDC_DRVPROVIDER,
120 dap->szTemp);
121 }
122
123 /* query the driver date */
124 if (GetDriverDateString(DeviceInfoSet,
125 DeviceInfoData,
126 dap->szTemp,
127 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
128 {
129 SetDlgItemText(hwndDlg,
130 IDC_DRVDATE,
131 dap->szTemp);
132 }
133
134 /* query the driver version */
135 if (GetDriverVersionString(DeviceInfoSet,
136 DeviceInfoData,
137 dap->szTemp,
138 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
139 {
140 SetDlgItemText(hwndDlg,
141 IDC_DRVVERSION,
142 dap->szTemp);
143 }
144 }
145
146
147 static INT_PTR
148 CALLBACK
149 AdvProcDriverDlgProc(IN HWND hwndDlg,
150 IN UINT uMsg,
151 IN WPARAM wParam,
152 IN LPARAM lParam)
153 {
154 PDEVADVPROP_INFO dap;
155 INT_PTR Ret = FALSE;
156
157 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
158 DWL_USER);
159
160 if (dap != NULL || uMsg == WM_INITDIALOG)
161 {
162 switch (uMsg)
163 {
164 case WM_NOTIFY:
165 {
166 NMHDR *hdr = (NMHDR*)lParam;
167 switch (hdr->code)
168 {
169 case PSN_APPLY:
170 break;
171 }
172 break;
173 }
174
175 case WM_INITDIALOG:
176 {
177 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
178 if (dap != NULL)
179 {
180 SetWindowLongPtr(hwndDlg,
181 DWL_USER,
182 (DWORD_PTR)dap);
183
184 UpdateDriverDlg(hwndDlg,
185 dap);
186 }
187 Ret = TRUE;
188 break;
189 }
190 }
191 }
192
193 return Ret;
194 }
195
196
197 static VOID
198 InitDevUsageActions(IN HWND hwndDlg,
199 IN HWND hComboBox,
200 IN PDEVADVPROP_INFO dap)
201 {
202 INT Index;
203 UINT i;
204 UINT Actions[] =
205 {
206 IDS_ENABLEDEVICE,
207 IDS_DISABLEDEVICE,
208 };
209
210 for (i = 0;
211 i != sizeof(Actions) / sizeof(Actions[0]);
212 i++)
213 {
214 /* fill in the device usage combo box */
215 if (LoadString(hDllInstance,
216 Actions[i],
217 dap->szTemp,
218 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
219 {
220 Index = (INT)SendMessage(hComboBox,
221 CB_ADDSTRING,
222 0,
223 (LPARAM)dap->szTemp);
224 if (Index != CB_ERR)
225 {
226 SendMessage(hComboBox,
227 CB_SETITEMDATA,
228 (WPARAM)Index,
229 (LPARAM)Actions[i]);
230
231 switch (Actions[i])
232 {
233 case IDS_ENABLEDEVICE:
234 if (dap->DeviceStarted)
235 {
236 SendMessage(hComboBox,
237 CB_SETCURSEL,
238 (WPARAM)Index,
239 0);
240 }
241 break;
242
243 case IDS_DISABLEDEVICE:
244 if (!dap->DeviceStarted)
245 {
246 SendMessage(hComboBox,
247 CB_SETCURSEL,
248 (WPARAM)Index,
249 0);
250 }
251 break;
252
253 default:
254 break;
255 }
256 }
257 }
258 }
259 }
260
261
262 static UINT
263 GetSelectedUsageAction(IN HWND hComboBox)
264 {
265 INT Index;
266 UINT Ret = 0;
267
268 Index = (INT)SendMessage(hComboBox,
269 CB_GETCURSEL,
270 0,
271 0);
272 if (Index != CB_ERR)
273 {
274 INT iRet = SendMessage(hComboBox,
275 CB_GETITEMDATA,
276 (WPARAM)Index,
277 0);
278 if (iRet != CB_ERR)
279 {
280 Ret = (UINT)iRet;
281 }
282 }
283
284 return Ret;
285 }
286
287
288 static BOOL
289 ApplyGeneralSettings(IN HWND hwndDlg,
290 IN PDEVADVPROP_INFO dap)
291 {
292 BOOL Ret = FALSE;
293
294 if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
295 {
296 UINT SelectedUsageAction;
297 BOOL NeedReboot = FALSE;
298
299 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
300 IDC_DEVUSAGE));
301 switch (SelectedUsageAction)
302 {
303 case IDS_ENABLEDEVICE:
304 if (!dap->DeviceStarted)
305 {
306 Ret = EnableDevice(dap->DeviceInfoSet,
307 &dap->DeviceInfoData,
308 TRUE,
309 0,
310 &NeedReboot);
311 }
312 break;
313
314 case IDS_DISABLEDEVICE:
315 if (dap->DeviceStarted)
316 {
317 Ret = EnableDevice(dap->DeviceInfoSet,
318 &dap->DeviceInfoData,
319 FALSE,
320 0,
321 &NeedReboot);
322 }
323 break;
324
325 default:
326 break;
327 }
328
329 if (Ret)
330 {
331 if (NeedReboot)
332 {
333 /* make PropertySheet() return PSM_REBOOTSYSTEM */
334 PropSheet_RebootSystem(hwndDlg);
335 }
336 }
337 else
338 {
339 /* FIXME - display an error message */
340 DPRINT1("Failed to enable/disable device! LastError: %d\n",
341 GetLastError());
342 }
343 }
344 else
345 Ret = !dap->DeviceUsageChanged;
346
347 /* disable the apply button */
348 PropSheet_UnChanged(GetParent(hwndDlg),
349 hwndDlg);
350 dap->DeviceUsageChanged = FALSE;
351 return Ret;
352 }
353
354
355 static VOID
356 UpdateDevInfo(IN HWND hwndDlg,
357 IN PDEVADVPROP_INFO dap,
358 IN BOOL ReOpen)
359 {
360 HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
361 CONFIGRET cr;
362 ULONG Status, ProblemNumber;
363 SP_DEVINSTALL_PARAMS_W InstallParams;
364 UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
365 BOOL bFlag, bDevActionAvailable = TRUE;
366 BOOL bDrvInstalled = FALSE;
367 DWORD iPage;
368 HDEVINFO DeviceInfoSet = NULL;
369 PSP_DEVINFO_DATA DeviceInfoData = NULL;
370 PROPSHEETHEADER psh;
371 DWORD nDriverPages = 0;
372
373 hPropSheetDlg = GetParent(hwndDlg);
374
375 if (dap->PageInitialized)
376 {
377 /* switch to the General page */
378 PropSheet_SetCurSelByID(hPropSheetDlg,
379 IDD_DEVICEGENERAL);
380
381 /* remove and destroy the existing device property sheet pages */
382 if (dap->DevPropSheets != NULL)
383 {
384 for (iPage = 0;
385 iPage != dap->nDevPropSheets;
386 iPage++)
387 {
388 if (dap->DevPropSheets[iPage] != NULL)
389 {
390 PropSheet_RemovePage(hPropSheetDlg,
391 -1,
392 dap->DevPropSheets[iPage]);
393 }
394 }
395 }
396 }
397
398 iPage = 0;
399
400 if (dap->FreeDevPropSheets)
401 {
402 /* don't free the array if it's the one allocated in
403 DisplayDeviceAdvancedProperties */
404 HeapFree(GetProcessHeap(),
405 0,
406 dap->DevPropSheets);
407
408 dap->FreeDevPropSheets = FALSE;
409 }
410
411 dap->DevPropSheets = NULL;
412 dap->nDevPropSheets = 0;
413
414 if (ReOpen)
415 {
416 /* create a new device info set and re-open the device */
417 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
418 {
419 SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
420 }
421
422 dap->ParentDevInst = 0;
423 dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
424 hwndDlg,
425 dap->lpMachineName,
426 NULL);
427 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
428 {
429 if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
430 dap->szDeviceID,
431 hwndDlg,
432 0,
433 &dap->CurrentDeviceInfoData))
434 {
435 if (dap->CloseDevInst)
436 {
437 SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
438 }
439
440 dap->CloseDevInst = TRUE;
441 dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
442 dap->DeviceInfoData = dap->CurrentDeviceInfoData;
443 dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
444 }
445 else
446 goto GetParentNode;
447 }
448 else
449 {
450 GetParentNode:
451 /* get the parent node from the initial devinst */
452 CM_Get_Parent_Ex(&dap->ParentDevInst,
453 dap->DeviceInfoData.DevInst,
454 0,
455 dap->hMachine);
456 }
457
458 if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
459 {
460 DeviceInfoSet = dap->CurrentDeviceInfoSet;
461 DeviceInfoData = &dap->CurrentDeviceInfoData;
462 }
463 else
464 {
465 DeviceInfoSet = dap->DeviceInfoSet;
466 DeviceInfoData = &dap->DeviceInfoData;
467 }
468 }
469 else
470 {
471 DeviceInfoSet = dap->DeviceInfoSet;
472 DeviceInfoData = &dap->DeviceInfoData;
473 }
474
475 dap->HasDriverPage = FALSE;
476 dap->HasResourcePage = FALSE;
477 dap->HasPowerPage = FALSE;
478 if (IsDriverInstalled(DeviceInfoData->DevInst,
479 dap->hMachine,
480 &bDrvInstalled) &&
481 bDrvInstalled)
482 {
483 if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
484 DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
485 DIF_ADDPROPERTYPAGE_ADVANCED),
486 DeviceInfoSet,
487 DeviceInfoData))
488 {
489 /* get install params */
490 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
491 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
492 DeviceInfoData,
493 &InstallParams))
494 {
495 /* zero the flags */
496 InstallParams.Flags = 0;
497 }
498
499 dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
500 dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
501 dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
502 }
503 }
504
505 /* get the device icon */
506 if (dap->hDevIcon != NULL)
507 {
508 DestroyIcon(dap->hDevIcon);
509 dap->hDevIcon = NULL;
510 }
511 if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
512 &dap->hDevIcon,
513 NULL))
514 {
515 dap->hDevIcon = NULL;
516 }
517
518 /* get the device name */
519 if (GetDeviceDescriptionString(DeviceInfoSet,
520 DeviceInfoData,
521 dap->szDevName,
522 sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
523 {
524 PropSheet_SetTitle(hPropSheetDlg,
525 PSH_PROPTITLE,
526 dap->szDevName);
527 }
528
529 /* set the device image */
530 SendDlgItemMessage(hwndDlg,
531 IDC_DEVICON,
532 STM_SETICON,
533 (WPARAM)dap->hDevIcon,
534 0);
535
536 /* set the device name edit control text */
537 SetDlgItemText(hwndDlg,
538 IDC_DEVNAME,
539 dap->szDevName);
540
541 /* set the device type edit control text */
542 if (GetDeviceTypeString(DeviceInfoData,
543 dap->szTemp,
544 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
545 {
546 SetDlgItemText(hwndDlg,
547 IDC_DEVTYPE,
548 dap->szTemp);
549 }
550
551 /* set the device manufacturer edit control text */
552 if (GetDeviceManufacturerString(DeviceInfoSet,
553 DeviceInfoData,
554 dap->szTemp,
555 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
556 {
557 SetDlgItemText(hwndDlg,
558 IDC_DEVMANUFACTURER,
559 dap->szTemp);
560 }
561
562 /* set the device location edit control text */
563 if (GetDeviceLocationString(DeviceInfoData->DevInst,
564 dap->ParentDevInst,
565 dap->szTemp,
566 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
567 {
568 SetDlgItemText(hwndDlg,
569 IDC_DEVLOCATION,
570 dap->szTemp);
571 }
572
573 /* set the device status edit control text */
574 if (GetDeviceStatusString(DeviceInfoData->DevInst,
575 dap->hMachine,
576 dap->szTemp,
577 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
578 {
579 SetDlgItemText(hwndDlg,
580 IDC_DEVSTATUS,
581 dap->szTemp);
582 }
583
584 /* set the device troubleshoot button text and disable it if necessary */
585 hDevProbBtn = GetDlgItem(hwndDlg,
586 IDC_DEVPROBLEM);
587 cr = CM_Get_DevNode_Status_Ex(&Status,
588 &ProblemNumber,
589 DeviceInfoData->DevInst,
590 0,
591 dap->hMachine);
592 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
593 {
594 switch (ProblemNumber)
595 {
596 case CM_PROB_DEVLOADER_FAILED:
597 {
598 /* FIXME - only if it's not a root bus devloader,
599 disable the button otherwise */
600 TroubleShootStrId = IDS_UPDATEDRV;
601 break;
602 }
603
604 case CM_PROB_OUT_OF_MEMORY:
605 case CM_PROB_ENTRY_IS_WRONG_TYPE:
606 case CM_PROB_LACKED_ARBITRATOR:
607 case CM_PROB_FAILED_START:
608 case CM_PROB_LIAR:
609 case CM_PROB_UNKNOWN_RESOURCE:
610 {
611 TroubleShootStrId = IDS_UPDATEDRV;
612 break;
613 }
614
615 case CM_PROB_BOOT_CONFIG_CONFLICT:
616 case CM_PROB_NORMAL_CONFLICT:
617 case CM_PROB_REENUMERATION:
618 {
619 /* FIXME - Troubleshoot conflict */
620 break;
621 }
622
623 case CM_PROB_FAILED_FILTER:
624 case CM_PROB_REINSTALL:
625 case CM_PROB_FAILED_INSTALL:
626 {
627 TroubleShootStrId = IDS_REINSTALLDRV;
628 break;
629 }
630
631 case CM_PROB_DEVLOADER_NOT_FOUND:
632 {
633 /* FIXME - 4 cases:
634 1) if it's a missing system devloader:
635 - disable the button (Reinstall Driver)
636 2) if it's not a system devloader but still missing:
637 - Reinstall Driver
638 3) if it's not a system devloader but the file can be found:
639 - Update Driver
640 4) if it's a missing or empty software key
641 - Update Driver
642 */
643 break;
644 }
645
646 case CM_PROB_INVALID_DATA:
647 case CM_PROB_PARTIAL_LOG_CONF:
648 case CM_PROB_NO_VALID_LOG_CONF:
649 case CM_PROB_HARDWARE_DISABLED:
650 case CM_PROB_CANT_SHARE_IRQ:
651 case CM_PROB_TRANSLATION_FAILED:
652 case CM_PROB_SYSTEM_SHUTDOWN:
653 case CM_PROB_PHANTOM:
654 bDevActionAvailable = FALSE;
655 break;
656
657 case CM_PROB_NOT_VERIFIED:
658 case CM_PROB_DEVICE_NOT_THERE:
659 /* FIXME - search hardware */
660 break;
661
662 case CM_PROB_NEED_RESTART:
663 case CM_PROB_WILL_BE_REMOVED:
664 case CM_PROB_MOVED:
665 case CM_PROB_TOO_EARLY:
666 case CM_PROB_DISABLED_SERVICE:
667 TroubleShootStrId = IDS_REBOOT;
668 break;
669
670 case CM_PROB_REGISTRY:
671 /* FIXME - check registry? */
672 break;
673
674 case CM_PROB_DISABLED:
675 /* if device was disabled by the user: */
676 TroubleShootStrId = IDS_ENABLEDEV;
677 /* FIXME - otherwise disable button because the device was
678 disabled by the system*/
679 break;
680
681 case CM_PROB_DEVLOADER_NOT_READY:
682 /* FIXME - if it's a graphics adapter:
683 - if it's a a secondary adapter and the main adapter
684 couldn't be found
685 - disable button
686 - else
687 - Properties
688 - else
689 - Update driver
690 */
691 break;
692
693 case CM_PROB_FAILED_ADD:
694 TroubleShootStrId = IDS_PROPERTIES;
695 break;
696 }
697 }
698
699 if (LoadString(hDllInstance,
700 TroubleShootStrId,
701 dap->szTemp,
702 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
703 {
704 SetWindowText(hDevProbBtn,
705 dap->szTemp);
706 }
707 EnableWindow(hDevProbBtn,
708 dap->IsAdmin && bDevActionAvailable);
709
710 /* check if the device can be enabled/disabled */
711 hDevUsage = GetDlgItem(hwndDlg,
712 IDC_DEVUSAGE);
713
714 dap->CanDisable = FALSE;
715 dap->DeviceStarted = FALSE;
716
717 if (CanDisableDevice(DeviceInfoData->DevInst,
718 dap->hMachine,
719 &bFlag))
720 {
721 dap->CanDisable = bFlag;
722 }
723
724 if (IsDeviceStarted(DeviceInfoData->DevInst,
725 dap->hMachine,
726 &bFlag))
727 {
728 dap->DeviceStarted = bFlag;
729 }
730
731 /* enable/disable the device usage controls */
732 EnableWindow(GetDlgItem(hwndDlg,
733 IDC_DEVUSAGELABEL),
734 dap->CanDisable && dap->IsAdmin);
735 EnableWindow(hDevUsage,
736 dap->CanDisable && dap->IsAdmin);
737
738 /* clear the combobox */
739 SendMessage(hDevUsage,
740 CB_RESETCONTENT,
741 0,
742 0);
743 if (dap->CanDisable)
744 {
745 InitDevUsageActions(hwndDlg,
746 hDevUsage,
747 dap);
748 }
749
750 /* find out how many new device property sheets to add.
751 fake a PROPSHEETHEADER structure, we don't plan to
752 call PropertySheet again!*/
753 psh.dwSize = sizeof(PROPSHEETHEADER);
754 psh.dwFlags = 0;
755 psh.nPages = 0;
756
757 /* get the number of device property sheets for the device */
758 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
759 DeviceInfoData,
760 &psh,
761 0,
762 &nDriverPages,
763 dap->PropertySheetType) &&
764 nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
765 {
766 dap->nDevPropSheets += nDriverPages;
767 }
768 else
769 {
770 nDriverPages = 0;
771 }
772
773 /* include the driver page */
774 if (dap->HasDriverPage)
775 dap->nDevPropSheets++;
776
777 /* add the device property sheets */
778 if (dap->nDevPropSheets != 0)
779 {
780 dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
781 HEAP_ZERO_MEMORY,
782 dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
783 if (dap->DevPropSheets != NULL)
784 {
785 if (nDriverPages != 0)
786 {
787 psh.phpage = dap->DevPropSheets;
788
789 /* query the device property sheet pages to add */
790 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
791 DeviceInfoData,
792 &psh,
793 dap->nDevPropSheets,
794 NULL,
795 dap->PropertySheetType))
796 {
797 /* add the property sheets */
798 for (iPage = 0;
799 iPage != nDriverPages;
800 iPage++)
801 {
802 PropSheet_AddPage(hPropSheetDlg,
803 dap->DevPropSheets[iPage]);
804 }
805
806 dap->FreeDevPropSheets = TRUE;
807 }
808 else
809 {
810 /* cleanup, we were unable to get the device property sheets */
811 dap->nDevPropSheets -= nDriverPages;
812 nDriverPages = 0;
813 if (dap->nDevPropSheets == 0)
814 {
815 HeapFree(GetProcessHeap(),
816 0,
817 dap->DevPropSheets);
818 dap->DevPropSheets = NULL;
819 }
820 }
821 }
822
823 /* add the driver page if necessary */
824 if (dap->HasDriverPage)
825 {
826 PROPSHEETPAGE pspDriver = {0};
827 pspDriver.dwSize = sizeof(PROPSHEETPAGE);
828 pspDriver.dwFlags = PSP_DEFAULT;
829 pspDriver.hInstance = hDllInstance;
830 pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
831 pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
832 pspDriver.lParam = (LPARAM)dap;
833 dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
834 if (dap->DevPropSheets[iPage] != NULL)
835 {
836 if (PropSheet_AddPage(hPropSheetDlg,
837 dap->DevPropSheets[iPage]))
838 {
839 iPage++;
840 }
841 else
842 {
843 dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
844 }
845 }
846 }
847 }
848 else
849 dap->nDevPropSheets = 0;
850 }
851
852 /* finally, disable the apply button */
853 PropSheet_UnChanged(hPropSheetDlg,
854 hwndDlg);
855 dap->DeviceUsageChanged = FALSE;
856 }
857
858
859 static LRESULT
860 CALLBACK
861 DlgParentSubWndProc(IN HWND hwnd,
862 IN UINT uMsg,
863 IN WPARAM wParam,
864 IN LPARAM lParam)
865 {
866 PDEVADVPROP_INFO dap;
867
868 dap = (PDEVADVPROP_INFO)GetProp(hwnd,
869 L"DevMgrDevChangeSub");
870 if (dap != NULL)
871 {
872 if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage))
873 {
874 SendMessage(dap->hWndGeneralPage,
875 WM_DEVICECHANGE,
876 wParam,
877 lParam);
878 }
879
880 /* pass the message the the old window proc */
881 return CallWindowProc(dap->ParentOldWndProc,
882 hwnd,
883 uMsg,
884 wParam,
885 lParam);
886 }
887 else
888 {
889 /* this is not a good idea if the subclassed window was an ansi
890 window, but we failed finding out the previous window proc
891 so we can't use CallWindowProc. This should rarely - if ever -
892 happen. */
893
894 return DefWindowProc(hwnd,
895 uMsg,
896 wParam,
897 lParam);
898 }
899 }
900
901
902 static INT_PTR
903 CALLBACK
904 AdvPropGeneralDlgProc(IN HWND hwndDlg,
905 IN UINT uMsg,
906 IN WPARAM wParam,
907 IN LPARAM lParam)
908 {
909 PDEVADVPROP_INFO dap;
910 INT_PTR Ret = FALSE;
911
912 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
913 DWL_USER);
914
915 if (dap != NULL || uMsg == WM_INITDIALOG)
916 {
917 switch (uMsg)
918 {
919 case WM_COMMAND:
920 {
921 switch (LOWORD(wParam))
922 {
923 case IDC_DEVUSAGE:
924 {
925 if (HIWORD(wParam) == CBN_SELCHANGE)
926 {
927 PropSheet_Changed(GetParent(hwndDlg),
928 hwndDlg);
929 dap->DeviceUsageChanged = TRUE;
930 }
931 break;
932 }
933
934 case IDC_DEVPROBLEM:
935 {
936 if (dap->IsAdmin)
937 {
938 /* display the device problem wizard */
939 ShowDeviceProblemWizard(hwndDlg,
940 dap->DeviceInfoSet,
941 &dap->DeviceInfoData,
942 dap->hMachine);
943 }
944 break;
945 }
946 }
947 break;
948 }
949
950 case WM_NOTIFY:
951 {
952 NMHDR *hdr = (NMHDR*)lParam;
953 switch (hdr->code)
954 {
955 case PSN_APPLY:
956 ApplyGeneralSettings(hwndDlg,
957 dap);
958 break;
959 }
960 break;
961 }
962
963 case WM_INITDIALOG:
964 {
965 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
966 if (dap != NULL)
967 {
968 HWND hWndParent;
969
970 dap->hWndGeneralPage = hwndDlg;
971
972 SetWindowLongPtr(hwndDlg,
973 DWL_USER,
974 (DWORD_PTR)dap);
975
976 /* subclass the parent window to always receive
977 WM_DEVICECHANGE messages */
978 hWndParent = GetParent(hwndDlg);
979 if (hWndParent != NULL)
980 {
981 /* subclass the parent window. This is not safe
982 if the parent window belongs to another thread! */
983 dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
984 GWLP_WNDPROC,
985 (LONG_PTR)DlgParentSubWndProc);
986
987 if (dap->ParentOldWndProc != NULL &&
988 SetProp(hWndParent,
989 L"DevMgrDevChangeSub",
990 (HANDLE)dap))
991 {
992 dap->hWndParent = hWndParent;
993 }
994 }
995
996 /* do not call UpdateDevInfo directly in here because it modifies
997 the pages of the property sheet! */
998 PostMessage(hwndDlg,
999 PM_INITIALIZE,
1000 0,
1001 0);
1002 }
1003 Ret = TRUE;
1004 break;
1005 }
1006
1007 case WM_DEVICECHANGE:
1008 {
1009 /* FIXME - don't call UpdateDevInfo for all events */
1010 UpdateDevInfo(hwndDlg,
1011 dap,
1012 TRUE);
1013 Ret = TRUE;
1014 break;
1015 }
1016
1017 case PM_INITIALIZE:
1018 {
1019 UpdateDevInfo(hwndDlg,
1020 dap,
1021 FALSE);
1022 dap->PageInitialized = TRUE;
1023 break;
1024 }
1025
1026 case WM_DESTROY:
1027 {
1028 /* restore the old window proc of the subclassed parent window */
1029 if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
1030 {
1031 if (SetWindowLongPtr(dap->hWndParent,
1032 GWLP_WNDPROC,
1033 (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
1034 {
1035 RemoveProp(dap->hWndParent,
1036 L"DevMgrDevChangeSub");
1037 }
1038 }
1039 break;
1040 }
1041 }
1042 }
1043
1044 return Ret;
1045 }
1046
1047
1048 INT_PTR
1049 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
1050 IN LPCWSTR lpDeviceID OPTIONAL,
1051 IN HDEVINFO DeviceInfoSet,
1052 IN PSP_DEVINFO_DATA DeviceInfoData,
1053 IN HINSTANCE hComCtl32,
1054 IN LPCWSTR lpMachineName,
1055 IN DWORD dwFlags)
1056 {
1057 PROPSHEETHEADER psh = {0};
1058 PROPSHEETPAGE pspGeneral = {0};
1059 PPROPERTYSHEETW pPropertySheetW;
1060 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
1061 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
1062 PDEVADVPROP_INFO DevAdvPropInfo;
1063 HMACHINE hMachine = NULL;
1064 DWORD DevIdSize = 0;
1065 INT_PTR Ret = -1;
1066
1067 /* we don't want to statically link against comctl32, so find the
1068 functions we need dynamically */
1069 pPropertySheetW =
1070 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
1071 "PropertySheetW");
1072 pCreatePropertySheetPageW =
1073 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
1074 "CreatePropertySheetPageW");
1075 pDestroyPropertySheetPage =
1076 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
1077 "DestroyPropertySheetPage");
1078 if (pPropertySheetW == NULL ||
1079 pCreatePropertySheetPageW == NULL ||
1080 pDestroyPropertySheetPage == NULL)
1081 {
1082 return -1;
1083 }
1084
1085 if (lpDeviceID == NULL)
1086 {
1087 /* find out how much size is needed for the device id */
1088 if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
1089 DeviceInfoData,
1090 NULL,
1091 0,
1092 &DevIdSize))
1093 {
1094 DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
1095 return -1;
1096 }
1097
1098 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1099 {
1100 return -1;
1101 }
1102 }
1103 else
1104 {
1105 DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
1106 }
1107
1108 if (lpMachineName != NULL)
1109 {
1110 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
1111 &hMachine);
1112 if (cr != CR_SUCCESS)
1113 {
1114 return -1;
1115 }
1116 }
1117
1118 /* create the internal structure associated with the "General",
1119 "Driver", ... pages */
1120 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
1121 HEAP_ZERO_MEMORY,
1122 FIELD_OFFSET(DEVADVPROP_INFO,
1123 szDeviceID) +
1124 (DevIdSize * sizeof(WCHAR)));
1125 if (DevAdvPropInfo == NULL)
1126 {
1127 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1128 goto Cleanup;
1129 }
1130
1131 if (lpDeviceID == NULL)
1132 {
1133 /* read the device instance id */
1134 if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
1135 DeviceInfoData,
1136 DevAdvPropInfo->szDeviceID,
1137 DevIdSize,
1138 NULL))
1139 {
1140 goto Cleanup;
1141 }
1142 }
1143 else
1144 {
1145 /* copy the device instance id supplied by the caller */
1146 wcscpy(DevAdvPropInfo->szDeviceID,
1147 lpDeviceID);
1148 }
1149
1150 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
1151 DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
1152 DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
1153 DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1154
1155 DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
1156 DevAdvPropInfo->hMachine = hMachine;
1157 DevAdvPropInfo->lpMachineName = lpMachineName;
1158 DevAdvPropInfo->szDevName[0] = L'\0';
1159 DevAdvPropInfo->hComCtl32 = hComCtl32;
1160 DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
1161 DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
1162
1163 DevAdvPropInfo->IsAdmin = IsUserAdmin();
1164 DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
1165
1166 psh.dwSize = sizeof(PROPSHEETHEADER);
1167 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
1168 psh.hwndParent = hWndParent;
1169 psh.pszCaption = DevAdvPropInfo->szDevName;
1170
1171 DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
1172 DIGCDP_FLAG_REMOTE_ADVANCED :
1173 DIGCDP_FLAG_ADVANCED;
1174
1175 psh.phpage = HeapAlloc(GetProcessHeap(),
1176 HEAP_ZERO_MEMORY,
1177 1 * sizeof(HPROPSHEETPAGE));
1178 if (psh.phpage == NULL)
1179 {
1180 goto Cleanup;
1181 }
1182
1183 /* add the "General" property sheet */
1184 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
1185 pspGeneral.dwFlags = PSP_DEFAULT;
1186 pspGeneral.hInstance = hDllInstance;
1187 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
1188 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
1189 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
1190 psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
1191 if (psh.phpage[psh.nPages] != NULL)
1192 {
1193 psh.nPages++;
1194 }
1195
1196 DevAdvPropInfo->nDevPropSheets = psh.nPages;
1197
1198 if (psh.nPages != 0)
1199 {
1200 Ret = pPropertySheetW(&psh);
1201
1202 /* NOTE: no need to destroy the property sheets anymore! */
1203 }
1204 else
1205 {
1206 UINT i;
1207
1208 Cleanup:
1209 /* in case of failure the property sheets must be destroyed */
1210 if (psh.phpage != NULL)
1211 {
1212 for (i = 0;
1213 i < psh.nPages;
1214 i++)
1215 {
1216 if (psh.phpage[i] != NULL)
1217 {
1218 pDestroyPropertySheetPage(psh.phpage[i]);
1219 }
1220 }
1221 }
1222 }
1223
1224 if (DevAdvPropInfo != NULL)
1225 {
1226 if (DevAdvPropInfo->FreeDevPropSheets)
1227 {
1228 /* don't free the array if it's the one allocated in
1229 DisplayDeviceAdvancedProperties */
1230 HeapFree(GetProcessHeap(),
1231 0,
1232 DevAdvPropInfo->DevPropSheets);
1233 }
1234
1235 if (DevAdvPropInfo->CloseDevInst)
1236 {
1237 /* close the device info set in case a new one was created */
1238 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
1239 }
1240
1241 if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
1242 {
1243 SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
1244 }
1245
1246 if (DevAdvPropInfo->hDevIcon != NULL)
1247 {
1248 DestroyIcon(DevAdvPropInfo->hDevIcon);
1249 }
1250
1251 HeapFree(GetProcessHeap(),
1252 0,
1253 DevAdvPropInfo);
1254 }
1255
1256 if (psh.phpage != NULL)
1257 {
1258 HeapFree(GetProcessHeap(),
1259 0,
1260 psh.phpage);
1261 }
1262
1263 if (hMachine != NULL)
1264 {
1265 CM_Disconnect_Machine(hMachine);
1266 }
1267
1268 return Ret;
1269 }
1270
1271
1272 /***************************************************************************
1273 * NAME EXPORTED
1274 * DeviceAdvancedPropertiesW
1275 *
1276 * DESCRIPTION
1277 * Invokes the device properties dialog, this version may add some property pages
1278 * for some devices
1279 *
1280 * ARGUMENTS
1281 * hWndParent: Handle to the parent window
1282 * lpMachineName: Machine Name, NULL is the local machine
1283 * lpDeviceID: Specifies the device whose properties are to be shown
1284 *
1285 * RETURN VALUE
1286 * Always returns -1, a call to GetLastError returns 0 if successful
1287 *
1288 * @implemented
1289 */
1290 INT_PTR
1291 WINAPI
1292 DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL,
1293 IN LPCWSTR lpMachineName OPTIONAL,
1294 IN LPCWSTR lpDeviceID)
1295 {
1296 HDEVINFO hDevInfo;
1297 SP_DEVINFO_DATA DevInfoData;
1298 HINSTANCE hComCtl32;
1299 INT_PTR Ret = -1;
1300
1301 if (lpDeviceID == NULL)
1302 {
1303 SetLastError(ERROR_INVALID_PARAMETER);
1304 return FALSE;
1305 }
1306
1307 /* dynamically load comctl32 */
1308 hComCtl32 = LoadAndInitComctl32();
1309 if (hComCtl32 != NULL)
1310 {
1311 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
1312 hWndParent,
1313 lpMachineName,
1314 NULL);
1315 if (hDevInfo != INVALID_HANDLE_VALUE)
1316 {
1317 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1318 if (SetupDiOpenDeviceInfo(hDevInfo,
1319 lpDeviceID,
1320 hWndParent,
1321 0,
1322 &DevInfoData))
1323 {
1324 Ret = DisplayDeviceAdvancedProperties(hWndParent,
1325 lpDeviceID,
1326 hDevInfo,
1327 &DevInfoData,
1328 hComCtl32,
1329 lpMachineName,
1330 0);
1331 }
1332
1333 SetupDiDestroyDeviceInfoList(hDevInfo);
1334 }
1335
1336 FreeLibrary(hComCtl32);
1337 }
1338
1339 return Ret;
1340 }
1341
1342
1343 /***************************************************************************
1344 * NAME EXPORTED
1345 * DeviceAdvancedPropertiesA
1346 *
1347 * DESCRIPTION
1348 * Invokes the device properties dialog, this version may add some property pages
1349 * for some devices
1350 *
1351 * ARGUMENTS
1352 * hWndParent: Handle to the parent window
1353 * lpMachineName: Machine Name, NULL is the local machine
1354 * lpDeviceID: Specifies the device whose properties are to be shown
1355 *
1356 * RETURN VALUE
1357 * Always returns -1, a call to GetLastError returns 0 if successful
1358 *
1359 * @implemented
1360 */
1361 INT_PTR
1362 WINAPI
1363 DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL,
1364 IN LPCSTR lpMachineName OPTIONAL,
1365 IN LPCSTR lpDeviceID)
1366 {
1367 LPWSTR lpMachineNameW = NULL;
1368 LPWSTR lpDeviceIDW = NULL;
1369 INT_PTR Ret = -1;
1370
1371 if (lpMachineName != NULL)
1372 {
1373 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
1374 CP_ACP)))
1375 {
1376 goto Cleanup;
1377 }
1378 }
1379 if (lpDeviceID != NULL)
1380 {
1381 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
1382 CP_ACP)))
1383 {
1384 goto Cleanup;
1385 }
1386 }
1387
1388 Ret = DeviceAdvancedPropertiesW(hWndParent,
1389 lpMachineNameW,
1390 lpDeviceIDW);
1391
1392 Cleanup:
1393 if (lpMachineNameW != NULL)
1394 {
1395 HeapFree(GetProcessHeap(),
1396 0,
1397 lpMachineNameW);
1398 }
1399 if (lpDeviceIDW != NULL)
1400 {
1401 HeapFree(GetProcessHeap(),
1402 0,
1403 lpDeviceIDW);
1404 }
1405
1406 return Ret;
1407 }
1408
1409
1410 /***************************************************************************
1411 * NAME EXPORTED
1412 * DevicePropertiesExA
1413 *
1414 * DESCRIPTION
1415 * Invokes the extended device properties dialog
1416 *
1417 * ARGUMENTS
1418 * hWndParent: Handle to the parent window
1419 * lpMachineName: Machine Name, NULL is the local machine
1420 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1421 * bShowDevMgr is nonzero
1422 * dwFlags: This parameter can be a combination of the following flags:
1423 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1424 * the default device status action button
1425 * to be clicked (Troubleshoot, Enable
1426 * Device, etc)
1427 * bShowDevMgr: If non-zero it displays the device manager instead of
1428 * the advanced device property dialog
1429 *
1430 * RETURN VALUE
1431 * 1: if bShowDevMgr is non-zero and no error occured
1432 * -1: a call to GetLastError returns 0 if successful
1433 *
1434 * @implemented
1435 */
1436 INT_PTR
1437 WINAPI
1438 DevicePropertiesExA(IN HWND hWndParent OPTIONAL,
1439 IN LPCSTR lpMachineName OPTIONAL,
1440 IN LPCSTR lpDeviceID OPTIONAL,
1441 IN DWORD dwFlags OPTIONAL,
1442 IN BOOL bShowDevMgr)
1443 {
1444 LPWSTR lpMachineNameW = NULL;
1445 LPWSTR lpDeviceIDW = NULL;
1446 INT_PTR Ret = -1;
1447
1448 if (lpMachineName != NULL)
1449 {
1450 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
1451 CP_ACP)))
1452 {
1453 goto Cleanup;
1454 }
1455 }
1456 if (lpDeviceID != NULL)
1457 {
1458 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
1459 CP_ACP)))
1460 {
1461 goto Cleanup;
1462 }
1463 }
1464
1465 Ret = DevicePropertiesExW(hWndParent,
1466 lpMachineNameW,
1467 lpDeviceIDW,
1468 dwFlags,
1469 bShowDevMgr);
1470
1471 Cleanup:
1472 if (lpMachineNameW != NULL)
1473 {
1474 HeapFree(GetProcessHeap(),
1475 0,
1476 lpMachineNameW);
1477 }
1478 if (lpDeviceIDW != NULL)
1479 {
1480 HeapFree(GetProcessHeap(),
1481 0,
1482 lpDeviceIDW);
1483 }
1484
1485 return Ret;
1486 }
1487
1488
1489 /***************************************************************************
1490 * NAME EXPORTED
1491 * DevicePropertiesExW
1492 *
1493 * DESCRIPTION
1494 * Invokes the extended device properties dialog
1495 *
1496 * ARGUMENTS
1497 * hWndParent: Handle to the parent window
1498 * lpMachineName: Machine Name, NULL is the local machine
1499 * lpDeviceID: Specifies the device whose properties are to be shown, optional if
1500 * bShowDevMgr is nonzero
1501 * dwFlags: This parameter can be a combination of the following flags:
1502 * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
1503 * the default device status action button
1504 * to be clicked (Troubleshoot, Enable
1505 * Device, etc)
1506 * bShowDevMgr: If non-zero it displays the device manager instead of
1507 * the advanced device property dialog
1508 *
1509 * RETURN VALUE
1510 * 1: if bShowDevMgr is non-zero and no error occured
1511 * -1: a call to GetLastError returns 0 if successful
1512 *
1513 * @unimplemented
1514 */
1515 INT_PTR
1516 WINAPI
1517 DevicePropertiesExW(IN HWND hWndParent OPTIONAL,
1518 IN LPCWSTR lpMachineName OPTIONAL,
1519 IN LPCWSTR lpDeviceID OPTIONAL,
1520 IN DWORD dwFlags OPTIONAL,
1521 IN BOOL bShowDevMgr)
1522 {
1523 INT_PTR Ret = -1;
1524
1525 if (dwFlags & ~(DPF_UNKNOWN | DPF_DEVICE_STATUS_ACTION))
1526 {
1527 DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
1528 dwFlags & ~(DPF_UNKNOWN | DPF_DEVICE_STATUS_ACTION));
1529 SetLastError(ERROR_INVALID_FLAGS);
1530 return -1;
1531 }
1532
1533 if (bShowDevMgr)
1534 {
1535 DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
1536 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1537 }
1538 else
1539 {
1540 HDEVINFO hDevInfo;
1541 SP_DEVINFO_DATA DevInfoData;
1542 HINSTANCE hComCtl32;
1543
1544 if (lpDeviceID == NULL)
1545 {
1546 SetLastError(ERROR_INVALID_PARAMETER);
1547 return -1;
1548 }
1549
1550 /* dynamically load comctl32 */
1551 hComCtl32 = LoadAndInitComctl32();
1552 if (hComCtl32 != NULL)
1553 {
1554 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
1555 hWndParent,
1556 lpMachineName,
1557 NULL);
1558 if (hDevInfo != INVALID_HANDLE_VALUE)
1559 {
1560 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
1561 if (SetupDiOpenDeviceInfo(hDevInfo,
1562 lpDeviceID,
1563 hWndParent,
1564 0,
1565 &DevInfoData))
1566 {
1567 Ret = DisplayDeviceAdvancedProperties(hWndParent,
1568 lpDeviceID,
1569 hDevInfo,
1570 &DevInfoData,
1571 hComCtl32,
1572 lpMachineName,
1573 dwFlags);
1574 }
1575
1576 SetupDiDestroyDeviceInfoList(hDevInfo);
1577 }
1578
1579 FreeLibrary(hComCtl32);
1580 }
1581 }
1582
1583 return Ret;
1584 }