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