- display whether the device is enabled or disabled
[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 enum
38 {
39 DEA_DISABLE = 0,
40 DEA_ENABLE,
41 DEA_UNKNOWN
42 } DEVENABLEACTION;
43
44 typedef struct _DEVADVPROP_INFO
45 {
46 HDEVINFO DeviceInfoSet;
47 PSP_DEVINFO_DATA DeviceInfoData;
48 HINSTANCE hComCtl32;
49 HANDLE hMachine;
50 BOOL CanDisable;
51 BOOL DeviceEnabled;
52 WCHAR szDevName[255];
53 WCHAR szTemp[255];
54 } DEVADVPROP_INFO, *PDEVADVPROP_INFO;
55
56
57 static VOID
58 InitDevUsageActions(IN HWND hwndDlg,
59 IN HWND hComboBox,
60 IN PDEVADVPROP_INFO dap)
61 {
62 INT Index;
63 UINT i;
64 struct
65 {
66 UINT szId;
67 DEVENABLEACTION Action;
68 } Actions[] =
69 {
70 {IDS_ENABLEDEVICE, DEA_ENABLE},
71 {IDS_DISABLEDEVICE, DEA_DISABLE},
72 };
73
74 for (i = 0;
75 i != sizeof(Actions) / sizeof(Actions[0]);
76 i++)
77 {
78 /* fill in the device usage combo box */
79 if (LoadString(hDllInstance,
80 Actions[i].szId,
81 dap->szTemp,
82 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
83 {
84 Index = (INT)SendMessage(hComboBox,
85 CB_ADDSTRING,
86 0,
87 (LPARAM)dap->szTemp);
88 if (Index != CB_ERR)
89 {
90 SendMessage(hComboBox,
91 CB_SETITEMDATA,
92 (WPARAM)Index,
93 (LPARAM)Actions[i].Action);
94
95 switch (Actions[i].Action)
96 {
97 case DEA_ENABLE:
98 if (dap->DeviceEnabled)
99 {
100 SendMessage(hComboBox,
101 CB_SETCURSEL,
102 (WPARAM)Index,
103 0);
104 }
105 break;
106
107 case DEA_DISABLE:
108 if (!dap->DeviceEnabled)
109 {
110 SendMessage(hComboBox,
111 CB_SETCURSEL,
112 (WPARAM)Index,
113 0);
114 }
115 break;
116
117 default:
118 break;
119 }
120 }
121 }
122 }
123 }
124
125
126 static DEVENABLEACTION
127 GetSelectedUsageAction(IN HWND hComboBox)
128 {
129 INT Index;
130 DEVENABLEACTION Ret = DEA_UNKNOWN;
131
132 Index = (INT)SendMessage(hComboBox,
133 CB_GETCURSEL,
134 0,
135 0);
136 if (Index != CB_ERR)
137 {
138 INT iRet = SendMessage(hComboBox,
139 CB_GETITEMDATA,
140 (WPARAM)Index,
141 0);
142 if (iRet != CB_ERR && iRet < (INT)DEA_UNKNOWN)
143 {
144 Ret = (DEVENABLEACTION)iRet;
145 }
146 }
147
148 return Ret;
149 }
150
151
152 static VOID
153 ApplyGeneralSettings(IN HWND hwndDlg,
154 IN PDEVADVPROP_INFO dap)
155 {
156 DEVENABLEACTION SelectedUsageAction;
157
158 SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
159 IDC_DEVUSAGE));
160 if (SelectedUsageAction != DEA_UNKNOWN)
161 {
162 switch (SelectedUsageAction)
163 {
164 case DEA_ENABLE:
165 if (!dap->DeviceEnabled)
166 {
167 /* FIXME - enable device */
168 }
169 break;
170
171 case DEA_DISABLE:
172 if (dap->DeviceEnabled)
173 {
174 /* FIXME - disable device */
175 }
176 break;
177
178 default:
179 break;
180 }
181
182 /* disable the apply button */
183 PropSheet_UnChanged(GetParent(hwndDlg),
184 hwndDlg);
185 }
186 }
187
188
189 static VOID
190 UpdateDevInfo(IN HWND hwndDlg,
191 IN PDEVADVPROP_INFO dap)
192 {
193 HICON hIcon;
194 HWND hDevUsage;
195
196 /* get the device name */
197 if (GetDeviceDescriptionString(dap->DeviceInfoSet,
198 dap->DeviceInfoData,
199 dap->szDevName,
200 sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
201 {
202 PropSheet_SetTitle(GetParent(hwndDlg),
203 PSH_PROPTITLE,
204 dap->szDevName);
205 }
206
207 /* set the device image */
208 if (SetupDiLoadClassIcon(&dap->DeviceInfoData->ClassGuid,
209 &hIcon,
210 NULL))
211 {
212 HICON hOldIcon = (HICON)SendDlgItemMessage(hwndDlg,
213 IDC_DEVICON,
214 STM_SETICON,
215 (WPARAM)hIcon,
216 0);
217 if (hOldIcon != NULL)
218 {
219 DestroyIcon(hOldIcon);
220 }
221 }
222
223 /* set the device name edit control text */
224 SetDlgItemText(hwndDlg,
225 IDC_DEVNAME,
226 dap->szDevName);
227
228 /* set the device type edit control text */
229 if (GetDeviceTypeString(dap->DeviceInfoData,
230 dap->szTemp,
231 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
232 {
233 SetDlgItemText(hwndDlg,
234 IDC_DEVTYPE,
235 dap->szTemp);
236 }
237
238 /* set the device manufacturer edit control text */
239 if (GetDeviceManufacturerString(dap->DeviceInfoSet,
240 dap->DeviceInfoData,
241 dap->szTemp,
242 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
243 {
244 SetDlgItemText(hwndDlg,
245 IDC_DEVMANUFACTURER,
246 dap->szTemp);
247 }
248
249 /* set the device location edit control text */
250 if (GetDeviceLocationString(dap->DeviceInfoData->DevInst,
251 dap->szTemp,
252 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
253 {
254 SetDlgItemText(hwndDlg,
255 IDC_DEVLOCATION,
256 dap->szTemp);
257 }
258
259 /* set the device status edit control text */
260 if (GetDeviceStatusString(dap->DeviceInfoData->DevInst,
261 dap->hMachine,
262 dap->szTemp,
263 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
264 {
265 SetDlgItemText(hwndDlg,
266 IDC_DEVSTATUS,
267 dap->szTemp);
268 }
269
270 /* check if the device can be enabled/disabled */
271 hDevUsage = GetDlgItem(hwndDlg,
272 IDC_DEVUSAGE);
273
274 if (!CanDisableDevice(dap->DeviceInfoData->DevInst,
275 dap->hMachine,
276 &dap->CanDisable))
277 {
278 dap->CanDisable = FALSE;
279 }
280
281 if (!IsDeviceEnabled(dap->DeviceInfoData->DevInst,
282 dap->hMachine,
283 &dap->DeviceEnabled))
284 {
285 dap->DeviceEnabled = FALSE;
286 }
287
288 /* enable/disable the device usage controls */
289 EnableWindow(GetDlgItem(hwndDlg,
290 IDC_DEVUSAGELABEL),
291 dap->CanDisable);
292 EnableWindow(hDevUsage,
293 dap->CanDisable);
294
295 /* clear the combobox */
296 SendMessage(hDevUsage,
297 CB_RESETCONTENT,
298 0,
299 0);
300 if (dap->CanDisable)
301 {
302 InitDevUsageActions(hwndDlg,
303 hDevUsage,
304 dap);
305 }
306
307 /* finally, disable the apply button */
308 PropSheet_UnChanged(GetParent(hwndDlg),
309 hwndDlg);
310 }
311
312
313 static INT_PTR
314 CALLBACK
315 AdvPropGeneralDlgProc(IN HWND hwndDlg,
316 IN UINT uMsg,
317 IN WPARAM wParam,
318 IN LPARAM lParam)
319 {
320 PDEVADVPROP_INFO dap;
321 INT_PTR Ret = FALSE;
322
323 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
324 DWL_USER);
325
326 if (dap != NULL || uMsg == WM_INITDIALOG)
327 {
328 switch (uMsg)
329 {
330 case WM_COMMAND:
331 {
332 switch (LOWORD(wParam))
333 {
334 case IDC_DEVUSAGE:
335 {
336 if (HIWORD(wParam) == CBN_SELCHANGE)
337 {
338 PropSheet_Changed(GetParent(hwndDlg),
339 hwndDlg);
340 }
341 break;
342 }
343 }
344 break;
345 }
346
347 case WM_NOTIFY:
348 {
349 NMHDR *hdr = (NMHDR*)lParam;
350 switch (hdr->code)
351 {
352 case PSN_APPLY:
353 ApplyGeneralSettings(hwndDlg,
354 dap);
355 break;
356 }
357 break;
358 }
359
360 case WM_INITDIALOG:
361 {
362 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
363 if (dap != NULL)
364 {
365 SetWindowLongPtr(hwndDlg,
366 DWL_USER,
367 (DWORD_PTR)dap);
368
369 UpdateDevInfo(hwndDlg,
370 dap);
371 }
372 Ret = TRUE;
373 break;
374 }
375
376 case WM_DEVICECHANGE:
377 {
378 /* FIXME - don't call UpdateDevInfo in all events */
379 UpdateDevInfo(hwndDlg,
380 dap);
381 break;
382 }
383
384 case WM_DESTROY:
385 {
386 HICON hDevIcon;
387
388 /* destroy the device icon */
389 hDevIcon = (HICON)SendDlgItemMessage(hwndDlg,
390 IDC_DEVICON,
391 STM_GETICON,
392 0,
393 0);
394 if (hDevIcon != NULL)
395 {
396 DestroyIcon(hDevIcon);
397 }
398 break;
399 }
400 }
401 }
402
403 return Ret;
404 }
405
406
407 INT_PTR
408 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
409 IN HDEVINFO DeviceInfoSet,
410 IN PSP_DEVINFO_DATA DeviceInfoData,
411 IN HINSTANCE hComCtl32,
412 IN LPCWSTR lpMachineName)
413 {
414 PROPSHEETHEADER psh = {0};
415 PROPSHEETPAGE pspGeneral = {0};
416 DWORD nPropSheets = 0;
417 PPROPERTYSHEETW pPropertySheetW;
418 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
419 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
420 PDEVADVPROP_INFO DevAdvPropInfo;
421 DWORD PropertySheetType;
422 HANDLE hMachine = NULL;
423 INT_PTR Ret = -1;
424
425 /* we don't want to statically link against comctl32, so find the
426 functions we need dynamically */
427 pPropertySheetW =
428 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
429 "PropertySheetW");
430 pCreatePropertySheetPageW =
431 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
432 "CreatePropertySheetPageW");
433 pDestroyPropertySheetPage =
434 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
435 "DestroyPropertySheetPage");
436 if (pPropertySheetW == NULL ||
437 pCreatePropertySheetPageW == NULL ||
438 pDestroyPropertySheetPage == NULL)
439 {
440 return -1;
441 }
442
443 if (lpMachineName != NULL)
444 {
445 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
446 &hMachine);
447 if (cr != CR_SUCCESS)
448 {
449 return -1;
450 }
451 }
452
453 /* create the internal structure associated with the "General",
454 "Driver", ... pages */
455 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
456 0,
457 sizeof(DEVADVPROP_INFO));
458 if (DevAdvPropInfo == NULL)
459 {
460 goto Cleanup;
461 }
462
463 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
464 DevAdvPropInfo->DeviceInfoData = DeviceInfoData;
465 DevAdvPropInfo->hComCtl32 = hComCtl32;
466 DevAdvPropInfo->hMachine = hMachine;
467 DevAdvPropInfo->szDevName[0] = L'\0';
468
469 psh.dwSize = sizeof(PROPSHEETHEADER);
470 psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
471 psh.hwndParent = hWndParent;
472 psh.pszCaption = DevAdvPropInfo->szDevName;
473
474 PropertySheetType = lpMachineName != NULL ?
475 DIGCDP_FLAG_REMOTE_ADVANCED :
476 DIGCDP_FLAG_ADVANCED;
477
478 /* find out how many property sheets we need */
479 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
480 DeviceInfoData,
481 &psh,
482 0,
483 &nPropSheets,
484 PropertySheetType) &&
485 nPropSheets != 0)
486 {
487 DPRINT1("SetupDiGetClassDevPropertySheets unexpectedly returned TRUE!\n");
488 goto Cleanup;
489 }
490
491 if (nPropSheets != 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
492 {
493 goto Cleanup;
494 }
495
496 psh.phpage = HeapAlloc(GetProcessHeap(),
497 HEAP_ZERO_MEMORY,
498 (nPropSheets + 1) * sizeof(HPROPSHEETPAGE));
499 if (psh.phpage == NULL)
500 {
501 goto Cleanup;
502 }
503
504 /* add the "General" property sheet */
505 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
506 pspGeneral.dwFlags = PSP_DEFAULT;
507 pspGeneral.hInstance = hDllInstance;
508 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
509 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
510 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
511 psh.phpage[0] = pCreatePropertySheetPageW(&pspGeneral);
512 if (psh.phpage[0] != NULL)
513 {
514 psh.nPages++;
515 }
516
517 if (nPropSheets != 0)
518 {
519 /* create the device property sheets */
520 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
521 DeviceInfoData,
522 &psh,
523 nPropSheets + psh.nPages,
524 NULL,
525 PropertySheetType))
526 {
527 goto Cleanup;
528 }
529 }
530
531 /* FIXME - add the "Driver" property sheet if necessary */
532
533 if (psh.nPages != 0)
534 {
535 Ret = pPropertySheetW(&psh);
536
537 /* NOTE: no need to destroy the property sheets anymore! */
538 }
539 else
540 {
541 UINT i;
542
543 Cleanup:
544 /* in case of failure the property sheets must be destroyed */
545 for (i = 0;
546 i < psh.nPages;
547 i++)
548 {
549 if (psh.phpage[i] != NULL)
550 {
551 pDestroyPropertySheetPage(psh.phpage[i]);
552 }
553 }
554 }
555
556 HeapFree(GetProcessHeap(),
557 0,
558 psh.phpage);
559
560 HeapFree(GetProcessHeap(),
561 0,
562 DevAdvPropInfo);
563
564 if (hMachine != NULL)
565 {
566 CM_Disconnect_Machine(hMachine);
567 }
568
569 return Ret;
570 }
571
572
573 /***************************************************************************
574 * NAME EXPORTED
575 * DeviceAdvancedPropertiesW
576 *
577 * DESCRIPTION
578 * Invokes the device properties dialog, this version may add some property pages
579 * for some devices
580 *
581 * ARGUMENTS
582 * hWndParent: Handle to the parent window
583 * lpMachineName: Machine Name, NULL is the local machine
584 * lpDeviceID: Specifies the device whose properties are to be shown
585 *
586 * RETURN VALUE
587 * -1: if errors occured
588 *
589 * REVISIONS
590 *
591 * NOTE
592 *
593 * @implemented
594 */
595 INT_PTR
596 WINAPI
597 DeviceAdvancedPropertiesW(HWND hWndParent,
598 LPCWSTR lpMachineName,
599 LPCWSTR lpDeviceID)
600 {
601 HDEVINFO hDevInfo;
602 SP_DEVINFO_DATA DevInfoData;
603 HINSTANCE hComCtl32;
604 INT_PTR Ret = -1;
605
606 /* dynamically load comctl32 */
607 hComCtl32 = LoadAndInitComctl32();
608 if (hComCtl32 != NULL)
609 {
610 if (lpMachineName != NULL)
611 {
612 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
613 hWndParent,
614 lpMachineName,
615 NULL);
616 }
617 else
618 {
619 hDevInfo = SetupDiCreateDeviceInfoList(NULL,
620 hWndParent);
621 }
622
623 if (hDevInfo != INVALID_HANDLE_VALUE)
624 {
625 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
626 if (SetupDiOpenDeviceInfo(hDevInfo,
627 lpDeviceID,
628 hWndParent,
629 0,
630 &DevInfoData))
631 {
632 Ret = DisplayDeviceAdvancedProperties(hWndParent,
633 hDevInfo,
634 &DevInfoData,
635 hComCtl32,
636 lpMachineName);
637 }
638
639 SetupDiDestroyDeviceInfoList(hDevInfo);
640 }
641
642 FreeLibrary(hComCtl32);
643 }
644
645 return Ret;
646 }
647
648
649 /***************************************************************************
650 * NAME EXPORTED
651 * DeviceAdvancedPropertiesA
652 *
653 * DESCRIPTION
654 * Invokes the device properties dialog, this version may add some property pages
655 * for some devices
656 *
657 * ARGUMENTS
658 * hWndParent: Handle to the parent window
659 * lpMachineName: Machine Name, NULL is the local machine
660 * lpDeviceID: Specifies the device whose properties are to be shown
661 *
662 * RETURN VALUE
663 * -1: if errors occured
664 *
665 * REVISIONS
666 *
667 * NOTE
668 *
669 * @implemented
670 */
671 INT_PTR
672 WINAPI
673 DeviceAdvancedPropertiesA(HWND hWndParent,
674 LPCSTR lpMachineName,
675 LPCSTR lpDeviceID)
676 {
677 LPWSTR lpMachineNameW = NULL;
678 LPWSTR lpDeviceIDW = NULL;
679 INT_PTR Ret = -1;
680
681 if (lpMachineName != NULL)
682 {
683 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
684 CP_ACP)))
685 {
686 goto Cleanup;
687 }
688 }
689 if (lpDeviceID != NULL)
690 {
691 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
692 CP_ACP)))
693 {
694 goto Cleanup;
695 }
696 }
697
698 Ret = DeviceAdvancedPropertiesW(hWndParent,
699 lpMachineNameW,
700 lpDeviceIDW);
701
702 Cleanup:
703 if (lpMachineNameW != NULL)
704 {
705 HeapFree(GetProcessHeap(),
706 0,
707 lpMachineNameW);
708 }
709 if (lpDeviceIDW != NULL)
710 {
711 HeapFree(GetProcessHeap(),
712 0,
713 lpDeviceIDW);
714 }
715
716 return Ret;
717 }