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