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