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