b20170030091c92907f4ee6db02f15c50211c99f
[reactos.git] / reactos / dll / win32 / devmgr / properties / devprblm.cpp
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
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
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
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
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
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 case CM_PROB_FAILED_ADD:
578 /* FIXME - get the name of the sub-device with the error */
579 AdvFormat = TRUE;
580 break;
581 }
582
583 if (AdvFormat)
584 {
585 StringIDs[1] = IDS_DEVCODE2;
586 dwRet = LoadAndFormatStringsCat(hDllInstance,
587 StringIDs,
588 sizeof(StringIDs) / sizeof(StringIDs[0]),
589 &szProblem,
590 szInfo,
591 uProblemId);
592 }
593 else
594 {
595 dwRet = LoadAndFormatStringsCat(hDllInstance,
596 StringIDs,
597 sizeof(StringIDs) / sizeof(StringIDs[0]),
598 &szProblem,
599 uProblemId);
600 }
601
602 if (dwRet != 0)
603 {
604 if (uMaxString != 0 && uMaxString >= dwRet)
605 {
606 wcscpy(lpString,
607 szProblem);
608 }
609
610 LocalFree((HLOCAL)szProblem);
611
612 Ret = dwRet;
613 }
614 }
615
616 return Ret;
617 }