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