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