- hide devices if necessary
[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 HDEVINFO DeviceInfoSet;
40 PSP_DEVINFO_DATA DeviceInfoData;
41 HINSTANCE hComCtl32;
42 HANDLE hMachine;
43 WCHAR szDevName[255];
44 WCHAR szTemp[255];
45 } DEVADVPROP_INFO, *PDEVADVPROP_INFO;
46
47
48 static INT_PTR
49 CALLBACK
50 AdvPropGeneralDlgProc(IN HWND hwndDlg,
51 IN UINT uMsg,
52 IN WPARAM wParam,
53 IN LPARAM lParam)
54 {
55 PDEVADVPROP_INFO dap;
56 INT_PTR Ret = FALSE;
57
58 dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
59 DWL_USER);
60
61 if (dap != NULL || uMsg == WM_INITDIALOG)
62 {
63 switch (uMsg)
64 {
65 case WM_INITDIALOG:
66 {
67 dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
68 if (dap != NULL)
69 {
70 HICON hIcon;
71
72 SetWindowLongPtr(hwndDlg,
73 DWL_USER,
74 (DWORD_PTR)dap);
75
76 /* set the device image */
77 if (SetupDiLoadClassIcon(&dap->DeviceInfoData->ClassGuid,
78 &hIcon,
79 NULL))
80 {
81 SendDlgItemMessage(hwndDlg,
82 IDC_DEVICON,
83 STM_SETICON,
84 (WPARAM)hIcon,
85 0);
86 }
87
88 /* set the device name edit control text */
89 SetDlgItemText(hwndDlg,
90 IDC_DEVNAME,
91 dap->szDevName);
92
93 /* set the device type edit control text */
94 if (GetDeviceTypeString(dap->DeviceInfoData,
95 dap->szTemp,
96 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
97 {
98 SetDlgItemText(hwndDlg,
99 IDC_DEVTYPE,
100 dap->szTemp);
101 }
102
103 /* set the device manufacturer edit control text */
104 if (GetDeviceManufacturerString(dap->DeviceInfoSet,
105 dap->DeviceInfoData,
106 dap->szTemp,
107 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
108 {
109 SetDlgItemText(hwndDlg,
110 IDC_DEVMANUFACTURER,
111 dap->szTemp);
112 }
113
114 /* set the device location edit control text */
115 if (GetDeviceLocationString(dap->DeviceInfoData->DevInst,
116 dap->szTemp,
117 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
118 {
119 SetDlgItemText(hwndDlg,
120 IDC_DEVLOCATION,
121 dap->szTemp);
122 }
123
124 /* set the device status edit control text */
125 if (GetDeviceStatusString(dap->DeviceInfoData->DevInst,
126 dap->hMachine,
127 dap->szTemp,
128 sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
129 {
130 SetDlgItemText(hwndDlg,
131 IDC_DEVSTATUS,
132 dap->szTemp);
133 }
134 }
135 Ret = TRUE;
136 break;
137 }
138
139 case WM_DESTROY:
140 {
141 HICON hDevIcon;
142
143 /* destroy the device icon */
144 hDevIcon = (HICON)SendDlgItemMessage(hwndDlg,
145 IDC_DEVICON,
146 STM_GETICON,
147 0,
148 0);
149 if (hDevIcon != NULL)
150 {
151 DestroyIcon(hDevIcon);
152 }
153 break;
154 }
155 }
156 }
157
158 return Ret;
159 }
160
161
162 INT_PTR
163 DisplayDeviceAdvancedProperties(IN HWND hWndParent,
164 IN HDEVINFO DeviceInfoSet,
165 IN PSP_DEVINFO_DATA DeviceInfoData,
166 IN HINSTANCE hComCtl32,
167 IN LPCWSTR lpMachineName)
168 {
169 PROPSHEETHEADER psh = {0};
170 PROPSHEETPAGE pspGeneral = {0};
171 DWORD nPropSheets = 0;
172 PPROPERTYSHEETW pPropertySheetW;
173 PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
174 PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
175 PDEVADVPROP_INFO DevAdvPropInfo;
176 DWORD PropertySheetType;
177 HANDLE hMachine = NULL;
178 INT_PTR Ret = -1;
179
180 /* we don't want to statically link against comctl32, so find the
181 functions we need dynamically */
182 pPropertySheetW =
183 (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
184 "PropertySheetW");
185 pCreatePropertySheetPageW =
186 (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
187 "CreatePropertySheetPageW");
188 pDestroyPropertySheetPage =
189 (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
190 "DestroyPropertySheetPage");
191 if (pPropertySheetW == NULL ||
192 pCreatePropertySheetPageW == NULL ||
193 pDestroyPropertySheetPage == NULL)
194 {
195 return -1;
196 }
197
198 if (lpMachineName != NULL)
199 {
200 CONFIGRET cr = CM_Connect_Machine(lpMachineName,
201 &hMachine);
202 if (cr != CR_SUCCESS)
203 {
204 return -1;
205 }
206 }
207
208 /* create the internal structure associated with the "General",
209 "Driver", ... pages */
210 DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
211 0,
212 sizeof(DEVADVPROP_INFO));
213 if (DevAdvPropInfo == NULL)
214 {
215 goto Cleanup;
216 }
217
218 DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
219 DevAdvPropInfo->DeviceInfoData = DeviceInfoData;
220 DevAdvPropInfo->hComCtl32 = hComCtl32;
221 DevAdvPropInfo->hMachine = hMachine;
222 DevAdvPropInfo->szDevName[0] = L'\0';
223
224 /* get the device name */
225 if (GetDeviceDescriptionString(DeviceInfoSet,
226 DeviceInfoData,
227 DevAdvPropInfo->szDevName,
228 sizeof(DevAdvPropInfo->szDevName) / sizeof(DevAdvPropInfo->szDevName[0])))
229 {
230 psh.dwSize = sizeof(PROPSHEETHEADER);
231 psh.dwFlags = PSH_PROPTITLE;
232 psh.hwndParent = hWndParent;
233 psh.pszCaption = DevAdvPropInfo->szDevName;
234
235 PropertySheetType = lpMachineName != NULL ?
236 DIGCDP_FLAG_REMOTE_ADVANCED :
237 DIGCDP_FLAG_ADVANCED;
238
239 /* find out how many property sheets we need */
240 if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
241 DeviceInfoData,
242 &psh,
243 0,
244 &nPropSheets,
245 PropertySheetType) &&
246 nPropSheets != 0)
247 {
248 DPRINT1("SetupDiGetClassDevPropertySheets unexpectedly returned TRUE!\n");
249 goto Cleanup;
250 }
251
252 if (nPropSheets != 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
253 {
254 goto Cleanup;
255 }
256
257 psh.phpage = HeapAlloc(GetProcessHeap(),
258 HEAP_ZERO_MEMORY,
259 (nPropSheets + 1) * sizeof(HPROPSHEETPAGE));
260 if (psh.phpage == NULL)
261 {
262 goto Cleanup;
263 }
264
265 /* add the "General" property sheet */
266 pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
267 pspGeneral.dwFlags = PSP_DEFAULT;
268 pspGeneral.hInstance = hDllInstance;
269 pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
270 pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
271 pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
272 psh.phpage[0] = pCreatePropertySheetPageW(&pspGeneral);
273 if (psh.phpage[0] != NULL)
274 {
275 psh.nPages++;
276 }
277
278 if (nPropSheets != 0)
279 {
280 /* create the device property sheets */
281 if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
282 DeviceInfoData,
283 &psh,
284 nPropSheets + psh.nPages,
285 NULL,
286 PropertySheetType))
287 {
288 goto Cleanup;
289 }
290 }
291
292 /* FIXME - add the "Driver" property sheet if necessary */
293
294 if (psh.nPages != 0)
295 {
296 Ret = pPropertySheetW(&psh);
297
298 /* NOTE: no need to destroy the property sheets anymore! */
299 }
300 else
301 {
302 UINT i;
303
304 Cleanup:
305 /* in case of failure the property sheets must be destroyed */
306 for (i = 0;
307 i < psh.nPages;
308 i++)
309 {
310 if (psh.phpage[i] != NULL)
311 {
312 pDestroyPropertySheetPage(psh.phpage[i]);
313 }
314 }
315 }
316
317 HeapFree(GetProcessHeap(),
318 0,
319 psh.phpage);
320 }
321
322 HeapFree(GetProcessHeap(),
323 0,
324 DevAdvPropInfo);
325
326 if (hMachine != NULL)
327 {
328 CM_Disconnect_Machine(hMachine);
329 }
330
331 return Ret;
332 }
333
334
335 /***************************************************************************
336 * NAME EXPORTED
337 * DeviceAdvancedPropertiesW
338 *
339 * DESCRIPTION
340 * Invokes the device properties dialog, this version may add some property pages
341 * for some devices
342 *
343 * ARGUMENTS
344 * hWndParent: Handle to the parent window
345 * lpMachineName: Machine Name, NULL is the local machine
346 * lpDeviceID: Specifies the device whose properties are to be shown
347 *
348 * RETURN VALUE
349 * -1: if errors occured
350 *
351 * REVISIONS
352 *
353 * NOTE
354 *
355 * @implemented
356 */
357 INT_PTR
358 WINAPI
359 DeviceAdvancedPropertiesW(HWND hWndParent,
360 LPCWSTR lpMachineName,
361 LPCWSTR lpDeviceID)
362 {
363 HDEVINFO hDevInfo;
364 SP_DEVINFO_DATA DevInfoData;
365 HINSTANCE hComCtl32;
366 INT_PTR Ret = -1;
367
368 /* dynamically load comctl32 */
369 hComCtl32 = LoadAndInitComctl32();
370 if (hComCtl32 != NULL)
371 {
372 if (lpMachineName != NULL)
373 {
374 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
375 hWndParent,
376 lpMachineName,
377 NULL);
378 }
379 else
380 {
381 hDevInfo = SetupDiCreateDeviceInfoList(NULL,
382 hWndParent);
383 }
384
385 if (hDevInfo != INVALID_HANDLE_VALUE)
386 {
387 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
388 if (SetupDiOpenDeviceInfo(hDevInfo,
389 lpDeviceID,
390 hWndParent,
391 0,
392 &DevInfoData))
393 {
394 Ret = DisplayDeviceAdvancedProperties(hWndParent,
395 hDevInfo,
396 &DevInfoData,
397 hComCtl32,
398 lpMachineName);
399 }
400
401 SetupDiDestroyDeviceInfoList(hDevInfo);
402 }
403
404 FreeLibrary(hComCtl32);
405 }
406
407 return Ret;
408 }
409
410
411 /***************************************************************************
412 * NAME EXPORTED
413 * DeviceAdvancedPropertiesA
414 *
415 * DESCRIPTION
416 * Invokes the device properties dialog, this version may add some property pages
417 * for some devices
418 *
419 * ARGUMENTS
420 * hWndParent: Handle to the parent window
421 * lpMachineName: Machine Name, NULL is the local machine
422 * lpDeviceID: Specifies the device whose properties are to be shown
423 *
424 * RETURN VALUE
425 * -1: if errors occured
426 *
427 * REVISIONS
428 *
429 * NOTE
430 *
431 * @implemented
432 */
433 INT_PTR
434 WINAPI
435 DeviceAdvancedPropertiesA(HWND hWndParent,
436 LPCSTR lpMachineName,
437 LPCSTR lpDeviceID)
438 {
439 LPWSTR lpMachineNameW = NULL;
440 LPWSTR lpDeviceIDW = NULL;
441 INT_PTR Ret = -1;
442
443 if (lpMachineName != NULL)
444 {
445 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
446 CP_ACP)))
447 {
448 goto Cleanup;
449 }
450 }
451 if (lpDeviceID != NULL)
452 {
453 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
454 CP_ACP)))
455 {
456 goto Cleanup;
457 }
458 }
459
460 Ret = DeviceAdvancedPropertiesW(hWndParent,
461 lpMachineNameW,
462 lpDeviceIDW);
463
464 Cleanup:
465 if (lpMachineNameW != NULL)
466 {
467 HeapFree(GetProcessHeap(),
468 0,
469 lpMachineNameW);
470 }
471 if (lpDeviceIDW != NULL)
472 {
473 HeapFree(GetProcessHeap(),
474 0,
475 lpDeviceIDW);
476 }
477
478 return Ret;
479 }