[PSAPI_WINETEST]
[reactos.git] / reactos / dll / win32 / devmgr / devprblm.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 /*
20 * PROJECT: ReactOS devmgr.dll
21 * FILE: lib/devmgr/devprblm.c
22 * PURPOSE: ReactOS Device Manager
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
24 * UPDATE HISTORY:
25 * 04-04-2004 Created
26 */
27
28 #include "precomp.h"
29
30
31 BOOL
32 ShowDeviceProblemWizard(IN HWND hWndParent OPTIONAL,
33 IN HDEVINFO hDevInfo,
34 IN PSP_DEVINFO_DATA DevInfoData,
35 IN HMACHINE hMachine OPTIONAL)
36 {
37 CONFIGRET cr;
38 ULONG Status, ProblemNumber;
39 BOOL Ret = FALSE;
40
41 cr = CM_Get_DevNode_Status_Ex(&Status,
42 &ProblemNumber,
43 DevInfoData->DevInst,
44 0,
45 hMachine);
46 if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
47 {
48 switch (ProblemNumber)
49 {
50 case CM_PROB_DEVLOADER_FAILED:
51 {
52 /* FIXME - only if it's not a root bus devloader */
53 /* FIXME - display the update driver wizard */
54 break;
55 }
56
57 case CM_PROB_OUT_OF_MEMORY:
58 case CM_PROB_ENTRY_IS_WRONG_TYPE:
59 case CM_PROB_LACKED_ARBITRATOR:
60 case CM_PROB_FAILED_START:
61 case CM_PROB_LIAR:
62 case CM_PROB_UNKNOWN_RESOURCE:
63 {
64 /* FIXME - display the update driver wizard */
65 break;
66 }
67
68 case CM_PROB_BOOT_CONFIG_CONFLICT:
69 case CM_PROB_NORMAL_CONFLICT:
70 case CM_PROB_REENUMERATION:
71 {
72 /* FIXME - display the conflict wizard */
73 break;
74 }
75
76 case CM_PROB_FAILED_FILTER:
77 case CM_PROB_REINSTALL:
78 case CM_PROB_FAILED_INSTALL:
79 {
80 /* FIXME - display the driver (re)installation wizard */
81 break;
82 }
83
84 case CM_PROB_DEVLOADER_NOT_FOUND:
85 {
86 /* FIXME - 4 cases:
87 1) if it's a missing system devloader:
88 - fail
89 2) if it's not a system devloader but still missing:
90 - display the driver reinstallation wizard
91 3) if it's not a system devloader but the file can be found:
92 - display the update driver wizard
93 4) if it's a missing or empty software key
94 - display the update driver wizard
95 */
96 break;
97 }
98
99 case CM_PROB_INVALID_DATA:
100 case CM_PROB_PARTIAL_LOG_CONF:
101 case CM_PROB_NO_VALID_LOG_CONF:
102 case CM_PROB_HARDWARE_DISABLED:
103 case CM_PROB_CANT_SHARE_IRQ:
104 case CM_PROB_TRANSLATION_FAILED:
105 case CM_PROB_SYSTEM_SHUTDOWN:
106 case CM_PROB_PHANTOM:
107 /* FIXME - do nothing */
108 break;
109
110 case CM_PROB_NOT_VERIFIED:
111 case CM_PROB_DEVICE_NOT_THERE:
112 /* FIXME - display search hardware wizard */
113 break;
114
115 case CM_PROB_NEED_RESTART:
116 case CM_PROB_WILL_BE_REMOVED:
117 case CM_PROB_MOVED:
118 case CM_PROB_TOO_EARLY:
119 case CM_PROB_DISABLED_SERVICE:
120 /* FIXME - reboot computer */
121 break;
122
123 case CM_PROB_REGISTRY:
124 /* FIXME - check registry */
125 break;
126
127 case CM_PROB_DISABLED:
128 {
129 /* FIXME - if device was disabled by user display the "Enable Device" wizard,
130 otherwise Troubleshoot because the device was disabled by the system */
131 break;
132 }
133
134 case CM_PROB_DEVLOADER_NOT_READY:
135 {
136 /* FIXME - if it's a graphics adapter:
137 - if it's a a secondary adapter and the main adapter
138 couldn't be found
139 - do nothing or default action
140 - else
141 - display the Properties
142 - else
143 - Update driver
144 */
145 break;
146 }
147
148 case CM_PROB_FAILED_ADD:
149 {
150 /* FIXME - display the properties of the sub-device */
151 break;
152 }
153
154 case CM_PROB_NO_SOFTCONFIG:
155 case CM_PROB_IRQ_TRANSLATION_FAILED:
156 case CM_PROB_FAILED_DRIVER_ENTRY:
157 case CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD:
158 case CM_PROB_DRIVER_FAILED_LOAD:
159 case CM_PROB_DRIVER_SERVICE_KEY_INVALID:
160 case CM_PROB_LEGACY_SERVICE_NO_DEVICES:
161 case CM_PROB_DUPLICATE_DEVICE:
162 case CM_PROB_FAILED_POST_START:
163 case CM_PROB_HALTED:
164 case CM_PROB_HELD_FOR_EJECT:
165 case CM_PROB_DRIVER_BLOCKED:
166 case CM_PROB_REGISTRY_TOO_LARGE:
167 default:
168 {
169 /* FIXME - troubleshoot the device */
170 break;
171 }
172 }
173 }
174
175 return Ret;
176 }
177
178
179 /***************************************************************************
180 * NAME EXPORTED
181 * DeviceProblemWizardA
182 *
183 * DESCRIPTION
184 * Calls the device problem wizard
185 *
186 * ARGUMENTS
187 * hWndParent: Handle to the parent window
188 * lpMachineName: Machine Name, NULL is the local machine
189 * lpDeviceID: Specifies the device, also see NOTEs
190 *
191 * RETURN VALUE
192 * TRUE: if no errors occured
193 * FALSE: if errors occured
194 *
195 * @implemented
196 */
197 BOOL
198 WINAPI
199 DeviceProblemWizardA(IN HWND hWndParent OPTIONAL,
200 IN LPCSTR lpMachineName OPTIONAL,
201 IN LPCSTR lpDeviceID)
202 {
203 LPWSTR lpMachineNameW = NULL;
204 LPWSTR lpDeviceIDW = NULL;
205 BOOL Ret = FALSE;
206
207 if (lpMachineName != NULL)
208 {
209 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
210 CP_ACP)))
211 {
212 goto Cleanup;
213 }
214 }
215 if (lpDeviceID != NULL)
216 {
217 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
218 CP_ACP)))
219 {
220 goto Cleanup;
221 }
222 }
223
224 Ret = DeviceProblemWizardW(hWndParent,
225 lpMachineNameW,
226 lpDeviceIDW);
227
228 Cleanup:
229 if (lpMachineNameW != NULL)
230 {
231 HeapFree(GetProcessHeap(),
232 0,
233 lpMachineNameW);
234 }
235 if (lpDeviceIDW != NULL)
236 {
237 HeapFree(GetProcessHeap(),
238 0,
239 lpDeviceIDW);
240 }
241
242 return Ret;
243 }
244
245
246 /***************************************************************************
247 * NAME EXPORTED
248 * DeviceProblemWizardW
249 *
250 * DESCRIPTION
251 * Calls the device problem wizard
252 *
253 * ARGUMENTS
254 * hWndParent: Handle to the parent window
255 * lpMachineName: Machine Name, NULL is the local machine
256 * lpDeviceID: Specifies the device, also see NOTEs
257 *
258 * RETURN VALUE
259 * TRUE: if no errors occured
260 * FALSE: if errors occured
261 *
262 * @unimplemented
263 */
264 BOOL
265 WINAPI
266 DeviceProblemWizardW(IN HWND hWndParent OPTIONAL,
267 IN LPCWSTR lpMachineName OPTIONAL,
268 IN LPCWSTR lpDeviceID)
269 {
270 HDEVINFO hDevInfo;
271 SP_DEVINFO_DATA DevInfoData;
272 HINSTANCE hComCtl32;
273 CONFIGRET cr;
274 HMACHINE hMachine;
275 BOOL Ret = FALSE;
276
277 if (lpDeviceID == NULL)
278 {
279 SetLastError(ERROR_INVALID_PARAMETER);
280 return FALSE;
281 }
282
283 /* dynamically load comctl32 */
284 hComCtl32 = LoadAndInitComctl32();
285 if (hComCtl32 != NULL)
286 {
287 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
288 hWndParent,
289 lpMachineName,
290 NULL);
291 if (hDevInfo != INVALID_HANDLE_VALUE)
292 {
293 cr = CM_Connect_Machine(lpMachineName,
294 &hMachine);
295 if (cr == CR_SUCCESS)
296 {
297 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
298 if (SetupDiOpenDeviceInfo(hDevInfo,
299 lpDeviceID,
300 hWndParent,
301 0,
302 &DevInfoData))
303 {
304 Ret = ShowDeviceProblemWizard(hWndParent,
305 hDevInfo,
306 &DevInfoData,
307 hMachine);
308 }
309
310 CM_Disconnect_Machine(hMachine);
311 }
312
313 SetupDiDestroyDeviceInfoList(hDevInfo);
314 }
315
316 FreeLibrary(hComCtl32);
317 }
318
319 return Ret;
320 }
321
322
323 static const UINT ProblemStringId[NUM_CM_PROB] =
324 {
325 IDS_DEV_NO_PROBLEM,
326 IDS_DEV_DEVLOADER_FAILED,
327 IDS_DEV_NOT_CONFIGURED,
328 IDS_DEV_OUT_OF_MEMORY,
329 IDS_DEV_ENTRY_IS_WRONG_TYPE,
330 IDS_DEV_LACKED_ARBITRATOR,
331 IDS_DEV_BOOT_CONFIG_CONFLICT,
332 IDS_DEV_FAILED_FILTER,
333 IDS_DEV_DEVLOADER_NOT_FOUND,
334 IDS_DEV_INVALID_DATA,
335 IDS_DEV_FAILED_START,
336 IDS_DEV_LIAR,
337 IDS_DEV_NORMAL_CONFLICT,
338 IDS_DEV_NOT_VERIFIED,
339 IDS_DEV_NEED_RESTART,
340 IDS_DEV_REENUMERATION,
341 IDS_DEV_PARTIAL_LOG_CONF,
342 IDS_DEV_UNKNOWN_RESOURCE,
343 IDS_DEV_REINSTALL,
344 IDS_DEV_REGISTRY,
345 IDS_UNKNOWN, /* CM_PROB_VXDLDR, not used on NT */
346 IDS_DEV_WILL_BE_REMOVED,
347 IDS_DEV_DISABLED,
348 IDS_DEV_DEVLOADER_NOT_READY,
349 IDS_DEV_DEVICE_NOT_THERE,
350 IDS_DEV_MOVED,
351 IDS_DEV_TOO_EARLY,
352 IDS_DEV_NO_VALID_LOG_CONF,
353 IDS_DEV_FAILED_INSTALL,
354 IDS_DEV_HARDWARE_DISABLED,
355 IDS_DEV_CANT_SHARE_IRQ,
356 IDS_DEV_FAILED_ADD,
357 IDS_DEV_DISABLED_SERVICE,
358 IDS_DEV_TRANSLATION_FAILED,
359 IDS_DEV_NO_SOFTCONFIG,
360 IDS_DEV_BIOS_TABLE,
361 IDS_DEV_IRQ_TRANSLATION_FAILED,
362 IDS_DEV_FAILED_DRIVER_ENTRY,
363 IDS_DEV_DRIVER_FAILED_PRIOR_UNLOAD,
364 IDS_DEV_DRIVER_FAILED_LOAD,
365 IDS_DEV_DRIVER_SERVICE_KEY_INVALID,
366 IDS_DEV_LEGACY_SERVICE_NO_DEVICES,
367 IDS_DEV_DUPLICATE_DEVICE,
368 IDS_DEV_FAILED_POST_START,
369 IDS_DEV_HALTED,
370 IDS_DEV_PHANTOM,
371 IDS_DEV_SYSTEM_SHUTDOWN,
372 IDS_DEV_HELD_FOR_EJECT,
373 IDS_DEV_DRIVER_BLOCKED,
374 IDS_DEV_REGISTRY_TOO_LARGE,
375 IDS_DEV_SETPROPERTIES_FAILED
376 };
377
378
379 /***************************************************************************
380 * NAME EXPORTED
381 * DeviceProblemTextA
382 *
383 * DESCRIPTION
384 * Gets the problem text from a problem number displayed in the properties dialog
385 *
386 * ARGUMENTS
387 * hMachine: Machine handle or NULL for the local machine
388 * DevInst: Device instance handle
389 * uProblemId: Specifies the problem ID
390 * lpString: Pointer to a buffer where the string is to be copied to. If the buffer
391 * is too small, the return value is the required string length in characters,
392 * excluding the NULL-termination.
393 * uMaxString: Size of the buffer in characters
394 *
395 * RETURN VALUE
396 * The return value is the length of the string in characters.
397 * It returns 0 if an error occured.
398 *
399 * @implemented
400 */
401 UINT
402 WINAPI
403 DeviceProblemTextA(IN HMACHINE hMachine OPTIONAL,
404 IN DEVINST dnDevInst,
405 IN ULONG uProblemId,
406 OUT LPSTR lpString,
407 IN UINT uMaxString)
408 {
409 LPWSTR lpBuffer = NULL;
410 UINT Ret = 0;
411
412 if (uMaxString != 0)
413 {
414 lpBuffer = HeapAlloc(GetProcessHeap(),
415 0,
416 (uMaxString + 1) * sizeof(WCHAR));
417 if (lpBuffer == NULL)
418 {
419 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
420 return 0;
421 }
422 }
423
424 Ret = DeviceProblemTextW(hMachine,
425 dnDevInst,
426 uProblemId,
427 lpBuffer,
428 uMaxString);
429
430 if (lpBuffer != NULL)
431 {
432 if (Ret)
433 {
434 WideCharToMultiByte(CP_ACP,
435 0,
436 lpBuffer,
437 (int)Ret,
438 lpString,
439 (int)uMaxString,
440 NULL,
441 NULL);
442 }
443
444 HeapFree(GetProcessHeap(),
445 0,
446 lpBuffer);
447 }
448
449 return Ret;
450 }
451
452
453 /***************************************************************************
454 * NAME EXPORTED
455 * DeviceProblemTextW
456 *
457 * DESCRIPTION
458 * Gets the problem text from a problem number displayed in the properties dialog
459 *
460 * ARGUMENTS
461 * hMachine: Machine handle or NULL for the local machine
462 * DevInst: Device instance handle
463 * uProblemId: Specifies the problem ID
464 * lpString: Pointer to a buffer where the string is to be copied to. If the buffer
465 * is too small, the return value is the required string length in characters,
466 * excluding the NULL-termination.
467 * uMaxString: Size of the buffer in characters
468 *
469 * RETURN VALUE
470 * The return value is the length of the string in characters.
471 * It returns 0 if an error occured.
472 *
473 * @implemented
474 */
475 UINT
476 WINAPI
477 DeviceProblemTextW(IN HMACHINE hMachine OPTIONAL,
478 IN DEVINST dnDevInst,
479 IN ULONG uProblemId,
480 OUT LPWSTR lpString,
481 IN UINT uMaxString)
482 {
483 UINT MessageId = IDS_UNKNOWN;
484 UINT Ret = 0;
485
486 if (uProblemId < sizeof(ProblemStringId) / sizeof(ProblemStringId[0]))
487 MessageId = ProblemStringId[uProblemId];
488
489 if (uProblemId == 0)
490 {
491 if (uMaxString != 0)
492 {
493 Ret = LoadString(hDllInstance,
494 MessageId,
495 lpString,
496 (int)uMaxString);
497 }
498 else
499 {
500 Ret = (UINT)LengthOfStrResource(hDllInstance,
501 MessageId);
502 }
503 }
504 else
505 {
506 LPWSTR szProblem, szInfo = L"FIXME";
507 DWORD dwRet;
508 BOOL AdvFormat = FALSE;
509 UINT StringIDs[] =
510 {
511 MessageId,
512 IDS_DEVCODE,
513 };
514
515 switch (uProblemId)
516 {
517 case CM_PROB_DEVLOADER_FAILED:
518 {
519 /* FIXME - if not a root bus devloader then use IDS_DEV_DEVLOADER_FAILED2 */
520 /* FIXME - get the type string (ie. ISAPNP, PCI or BIOS for root bus devloaders,
521 or FLOP, ESDI, SCSI, etc for others */
522 AdvFormat = TRUE;
523 break;
524 }
525
526 case CM_PROB_DEVLOADER_NOT_FOUND:
527 {
528 /* FIXME - 4 cases:
529 1) if it's a missing system devloader:
530 - get the system devloader name
531 2) if it's not a system devloader but still missing:
532 - get the devloader name (file name?)
533 3) if it's not a system devloader but the file can be found:
534 - use IDS_DEV_DEVLOADER_NOT_FOUND2
535 4) if it's a missing or empty software key
536 - use IDS_DEV_DEVLOADER_NOT_FOUND3
537 - AdvFormat = FALSE!
538 */
539 AdvFormat = TRUE;
540 break;
541 }
542
543 case CM_PROB_INVALID_DATA:
544 /* FIXME - if the device isn't enumerated by the BIOS/ACPI use IDS_DEV_INVALID_DATA2 */
545 AdvFormat = FALSE;
546 break;
547
548 case CM_PROB_NORMAL_CONFLICT:
549 /* FIXME - get resource type (IRQ, DMA, Memory or I/O) */
550 AdvFormat = TRUE;
551 break;
552
553 case CM_PROB_UNKNOWN_RESOURCE:
554 /* FIXME - get the .inf file name */
555 AdvFormat = TRUE;
556 break;
557
558 case CM_PROB_DISABLED:
559 /* FIXME - if the device was disabled by the system use IDS_DEV_DISABLED2 */
560 break;
561
562 case CM_PROB_FAILED_ADD:
563 /* FIXME - get the name of the sub-device with the error */
564 AdvFormat = TRUE;
565 break;
566 }
567
568 if (AdvFormat)
569 {
570 StringIDs[1] = IDS_DEVCODE2;
571 dwRet = LoadAndFormatStringsCat(hDllInstance,
572 StringIDs,
573 sizeof(StringIDs) / sizeof(StringIDs[0]),
574 &szProblem,
575 szInfo,
576 uProblemId);
577 LocalFree((HLOCAL)szInfo);
578 }
579 else
580 {
581 dwRet = LoadAndFormatStringsCat(hDllInstance,
582 StringIDs,
583 sizeof(StringIDs) / sizeof(StringIDs[0]),
584 &szProblem,
585 uProblemId);
586 }
587
588 if (dwRet != 0)
589 {
590 if (uMaxString != 0 && uMaxString >= dwRet)
591 {
592 wcscpy(lpString,
593 szProblem);
594 }
595
596 LocalFree((HLOCAL)szProblem);
597
598 Ret = dwRet;
599 }
600 }
601
602 return Ret;
603 }