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