reactos/dll/win32/devmgr/properties/devprblm.cpp

618 lines
19 KiB
C++

/*
* ReactOS Device Manager Applet
* Copyright (C) 2004 - 2005 ReactOS Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* PROJECT: ReactOS devmgr.dll
* FILE: lib/devmgr/devprblm.c
* PURPOSE: ReactOS Device Manager
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
* 04-04-2004 Created
*/
#include "precomp.h"
#include "properties.h"
#include "resource.h"
BOOL
ShowDeviceProblemWizard(IN HWND hWndParent OPTIONAL,
IN HDEVINFO hDevInfo,
IN PSP_DEVINFO_DATA DevInfoData,
IN HMACHINE hMachine OPTIONAL)
{
WCHAR szDeviceInstanceId[256];
CONFIGRET cr;
ULONG Status, ProblemNumber;
DWORD dwReboot;
BOOL Ret = FALSE;
/* Get the device instance id */
if (!SetupDiGetDeviceInstanceId(hDevInfo,
DevInfoData,
szDeviceInstanceId,
256,
NULL))
return FALSE;
cr = CM_Get_DevNode_Status_Ex(&Status,
&ProblemNumber,
DevInfoData->DevInst,
0,
hMachine);
if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
{
switch (ProblemNumber)
{
case CM_PROB_DEVLOADER_FAILED:
{
/* FIXME - only if it's not a root bus devloader */
/* FIXME - display the update driver wizard */
break;
}
case CM_PROB_OUT_OF_MEMORY:
case CM_PROB_ENTRY_IS_WRONG_TYPE:
case CM_PROB_LACKED_ARBITRATOR:
case CM_PROB_FAILED_START:
case CM_PROB_LIAR:
case CM_PROB_UNKNOWN_RESOURCE:
{
/* FIXME - display the update driver wizard */
InstallDevInst(hWndParent, szDeviceInstanceId, TRUE, &dwReboot);
break;
}
case CM_PROB_BOOT_CONFIG_CONFLICT:
case CM_PROB_NORMAL_CONFLICT:
case CM_PROB_REENUMERATION:
{
/* FIXME - display the conflict wizard */
break;
}
case CM_PROB_FAILED_FILTER:
case CM_PROB_REINSTALL:
case CM_PROB_FAILED_INSTALL:
{
/* FIXME - display the driver (re)installation wizard */
InstallDevInst(hWndParent, szDeviceInstanceId, TRUE, &dwReboot);
break;
}
case CM_PROB_DEVLOADER_NOT_FOUND:
{
/* FIXME - 4 cases:
1) if it's a missing system devloader:
- fail
2) if it's not a system devloader but still missing:
- display the driver reinstallation wizard
3) if it's not a system devloader but the file can be found:
- display the update driver wizard
4) if it's a missing or empty software key
- display the update driver wizard
*/
break;
}
case CM_PROB_INVALID_DATA:
case CM_PROB_PARTIAL_LOG_CONF:
case CM_PROB_NO_VALID_LOG_CONF:
case CM_PROB_HARDWARE_DISABLED:
case CM_PROB_CANT_SHARE_IRQ:
case CM_PROB_TRANSLATION_FAILED:
case CM_PROB_SYSTEM_SHUTDOWN:
case CM_PROB_PHANTOM:
/* FIXME - do nothing */
break;
case CM_PROB_NOT_VERIFIED:
case CM_PROB_DEVICE_NOT_THERE:
/* FIXME - display search hardware wizard */
break;
case CM_PROB_NEED_RESTART:
case CM_PROB_WILL_BE_REMOVED:
case CM_PROB_MOVED:
case CM_PROB_TOO_EARLY:
case CM_PROB_DISABLED_SERVICE:
/* FIXME - reboot computer */
break;
case CM_PROB_REGISTRY:
/* FIXME - check registry */
break;
case CM_PROB_DISABLED:
{
/* FIXME - if device was disabled by user display the "Enable Device" wizard,
otherwise Troubleshoot because the device was disabled by the system */
break;
}
case CM_PROB_DEVLOADER_NOT_READY:
{
/* FIXME - if it's a graphics adapter:
- if it's a a secondary adapter and the main adapter
couldn't be found
- do nothing or default action
- else
- display the Properties
- else
- Update driver
*/
break;
}
case CM_PROB_FAILED_ADD:
{
/* FIXME - display the properties of the sub-device */
break;
}
case CM_PROB_NO_SOFTCONFIG:
case CM_PROB_IRQ_TRANSLATION_FAILED:
case CM_PROB_FAILED_DRIVER_ENTRY:
case CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD:
case CM_PROB_DRIVER_FAILED_LOAD:
case CM_PROB_DRIVER_SERVICE_KEY_INVALID:
case CM_PROB_LEGACY_SERVICE_NO_DEVICES:
case CM_PROB_DUPLICATE_DEVICE:
case CM_PROB_FAILED_POST_START:
case CM_PROB_HALTED:
case CM_PROB_HELD_FOR_EJECT:
case CM_PROB_DRIVER_BLOCKED:
case CM_PROB_REGISTRY_TOO_LARGE:
default:
{
/* FIXME - troubleshoot the device */
break;
}
}
}
return Ret;
}
/***************************************************************************
* NAME EXPORTED
* DeviceProblemWizardA
*
* DESCRIPTION
* Calls the device problem wizard
*
* ARGUMENTS
* hWndParent: Handle to the parent window
* lpMachineName: Machine Name, NULL is the local machine
* lpDeviceID: Specifies the device, also see NOTEs
*
* RETURN VALUE
* TRUE: if no errors occured
* FALSE: if errors occured
*
* @implemented
*/
BOOL
WINAPI
DeviceProblemWizardA(IN HWND hWndParent OPTIONAL,
IN LPCSTR lpMachineName OPTIONAL,
IN LPCSTR lpDeviceID)
{
LPWSTR lpMachineNameW = NULL;
LPWSTR lpDeviceIDW = NULL;
BOOL Ret = FALSE;
if (lpMachineName != NULL)
{
if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
CP_ACP)))
{
goto Cleanup;
}
}
if (lpDeviceID != NULL)
{
if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
CP_ACP)))
{
goto Cleanup;
}
}
Ret = DeviceProblemWizardW(hWndParent,
lpMachineNameW,
lpDeviceIDW);
Cleanup:
if (lpMachineNameW != NULL)
{
HeapFree(GetProcessHeap(),
0,
lpMachineNameW);
}
if (lpDeviceIDW != NULL)
{
HeapFree(GetProcessHeap(),
0,
lpDeviceIDW);
}
return Ret;
}
/***************************************************************************
* NAME EXPORTED
* DeviceProblemWizardW
*
* DESCRIPTION
* Calls the device problem wizard
*
* ARGUMENTS
* hWndParent: Handle to the parent window
* lpMachineName: Machine Name, NULL is the local machine
* lpDeviceID: Specifies the device, also see NOTEs
*
* RETURN VALUE
* TRUE: if no errors occured
* FALSE: if errors occured
*
* @unimplemented
*/
BOOL
WINAPI
DeviceProblemWizardW(IN HWND hWndParent OPTIONAL,
IN LPCWSTR lpMachineName OPTIONAL,
IN LPCWSTR lpDeviceID)
{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DevInfoData;
HINSTANCE hComCtl32;
CONFIGRET cr;
HMACHINE hMachine;
BOOL Ret = FALSE;
if (lpDeviceID == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/* dynamically load comctl32 */
hComCtl32 = LoadAndInitComctl32();
if (hComCtl32 != NULL)
{
hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
hWndParent,
lpMachineName,
NULL);
if (hDevInfo != INVALID_HANDLE_VALUE)
{
cr = CM_Connect_Machine(lpMachineName,
&hMachine);
if (cr == CR_SUCCESS)
{
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiOpenDeviceInfo(hDevInfo,
lpDeviceID,
hWndParent,
0,
&DevInfoData))
{
Ret = ShowDeviceProblemWizard(hWndParent,
hDevInfo,
&DevInfoData,
hMachine);
}
CM_Disconnect_Machine(hMachine);
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
FreeLibrary(hComCtl32);
}
return Ret;
}
static const UINT ProblemStringId[NUM_CM_PROB] =
{
IDS_DEV_NO_PROBLEM,
IDS_DEV_DEVLOADER_FAILED,
IDS_DEV_NOT_CONFIGURED,
IDS_DEV_OUT_OF_MEMORY,
IDS_DEV_ENTRY_IS_WRONG_TYPE,
IDS_DEV_LACKED_ARBITRATOR,
IDS_DEV_BOOT_CONFIG_CONFLICT,
IDS_DEV_FAILED_FILTER,
IDS_DEV_DEVLOADER_NOT_FOUND,
IDS_DEV_INVALID_DATA,
IDS_DEV_FAILED_START,
IDS_DEV_LIAR,
IDS_DEV_NORMAL_CONFLICT,
IDS_DEV_NOT_VERIFIED,
IDS_DEV_NEED_RESTART,
IDS_DEV_REENUMERATION,
IDS_DEV_PARTIAL_LOG_CONF,
IDS_DEV_UNKNOWN_RESOURCE,
IDS_DEV_REINSTALL,
IDS_DEV_REGISTRY,
IDS_UNKNOWN, /* CM_PROB_VXDLDR, not used on NT */
IDS_DEV_WILL_BE_REMOVED,
IDS_DEV_DISABLED,
IDS_DEV_DEVLOADER_NOT_READY,
IDS_DEV_DEVICE_NOT_THERE,
IDS_DEV_MOVED,
IDS_DEV_TOO_EARLY,
IDS_DEV_NO_VALID_LOG_CONF,
IDS_DEV_FAILED_INSTALL,
IDS_DEV_HARDWARE_DISABLED,
IDS_DEV_CANT_SHARE_IRQ,
IDS_DEV_FAILED_ADD,
IDS_DEV_DISABLED_SERVICE,
IDS_DEV_TRANSLATION_FAILED,
IDS_DEV_NO_SOFTCONFIG,
IDS_DEV_BIOS_TABLE,
IDS_DEV_IRQ_TRANSLATION_FAILED,
IDS_DEV_FAILED_DRIVER_ENTRY,
IDS_DEV_DRIVER_FAILED_PRIOR_UNLOAD,
IDS_DEV_DRIVER_FAILED_LOAD,
IDS_DEV_DRIVER_SERVICE_KEY_INVALID,
IDS_DEV_LEGACY_SERVICE_NO_DEVICES,
IDS_DEV_DUPLICATE_DEVICE,
IDS_DEV_FAILED_POST_START,
IDS_DEV_HALTED,
IDS_DEV_PHANTOM,
IDS_DEV_SYSTEM_SHUTDOWN,
IDS_DEV_HELD_FOR_EJECT,
IDS_DEV_DRIVER_BLOCKED,
IDS_DEV_REGISTRY_TOO_LARGE,
IDS_DEV_SETPROPERTIES_FAILED
};
/***************************************************************************
* NAME EXPORTED
* DeviceProblemTextA
*
* DESCRIPTION
* Gets the problem text from a problem number displayed in the properties dialog
*
* ARGUMENTS
* hMachine: Machine handle or NULL for the local machine
* DevInst: Device instance handle
* uProblemId: Specifies the problem ID
* lpString: Pointer to a buffer where the string is to be copied to. If the buffer
* is too small, the return value is the required string length in characters,
* excluding the NULL-termination.
* uMaxString: Size of the buffer in characters
*
* RETURN VALUE
* The return value is the length of the string in characters.
* It returns 0 if an error occured.
*
* @implemented
*/
UINT
WINAPI
DeviceProblemTextA(IN HMACHINE hMachine OPTIONAL,
IN DEVINST dnDevInst,
IN ULONG uProblemId,
OUT LPSTR lpString,
IN UINT uMaxString)
{
LPWSTR lpBuffer = NULL;
UINT Ret = 0;
if (uMaxString != 0)
{
lpBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(),
0,
(uMaxString + 1) * sizeof(WCHAR));
if (lpBuffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
}
Ret = DeviceProblemTextW(hMachine,
dnDevInst,
uProblemId,
lpBuffer,
uMaxString);
if (lpBuffer != NULL)
{
if (Ret)
{
WideCharToMultiByte(CP_ACP,
0,
lpBuffer,
(int)Ret,
lpString,
(int)uMaxString,
NULL,
NULL);
}
HeapFree(GetProcessHeap(),
0,
lpBuffer);
}
return Ret;
}
/***************************************************************************
* NAME EXPORTED
* DeviceProblemTextW
*
* DESCRIPTION
* Gets the problem text from a problem number displayed in the properties dialog
*
* ARGUMENTS
* hMachine: Machine handle or NULL for the local machine
* DevInst: Device instance handle
* uProblemId: Specifies the problem ID
* lpString: Pointer to a buffer where the string is to be copied to. If the buffer
* is too small, the return value is the required string length in characters,
* excluding the NULL-termination.
* uMaxString: Size of the buffer in characters
*
* RETURN VALUE
* The return value is the length of the string in characters.
* It returns 0 if an error occured.
*
* @implemented
*/
UINT
WINAPI
DeviceProblemTextW(IN HMACHINE hMachine OPTIONAL,
IN DEVINST dnDevInst,
IN ULONG uProblemId,
OUT LPWSTR lpString,
IN UINT uMaxString)
{
UINT MessageId = IDS_UNKNOWN;
UINT Ret = 0;
if (uProblemId < sizeof(ProblemStringId) / sizeof(ProblemStringId[0]))
MessageId = ProblemStringId[uProblemId];
if (uProblemId == 0)
{
if (uMaxString != 0)
{
Ret = LoadString(hDllInstance,
MessageId,
lpString,
(int)uMaxString);
}
else
{
Ret = (UINT)LengthOfStrResource(hDllInstance,
MessageId);
}
}
else
{
LPWSTR szProblem;
WCHAR szInfo[] = L"FIXME";
DWORD dwRet;
BOOL AdvFormat = FALSE;
UINT StringIDs[] =
{
MessageId,
IDS_DEVCODE,
};
switch (uProblemId)
{
case CM_PROB_DEVLOADER_FAILED:
{
/* FIXME - if not a root bus devloader then use IDS_DEV_DEVLOADER_FAILED2 */
/* FIXME - get the type string (ie. ISAPNP, PCI or BIOS for root bus devloaders,
or FLOP, ESDI, SCSI, etc for others */
AdvFormat = TRUE;
break;
}
case CM_PROB_DEVLOADER_NOT_FOUND:
{
/* FIXME - 4 cases:
1) if it's a missing system devloader:
- get the system devloader name
2) if it's not a system devloader but still missing:
- get the devloader name (file name?)
3) if it's not a system devloader but the file can be found:
- use IDS_DEV_DEVLOADER_NOT_FOUND2
4) if it's a missing or empty software key
- use IDS_DEV_DEVLOADER_NOT_FOUND3
- AdvFormat = FALSE!
*/
AdvFormat = TRUE;
break;
}
case CM_PROB_INVALID_DATA:
/* FIXME - if the device isn't enumerated by the BIOS/ACPI use IDS_DEV_INVALID_DATA2 */
AdvFormat = FALSE;
break;
case CM_PROB_NORMAL_CONFLICT:
/* FIXME - get resource type (IRQ, DMA, Memory or I/O) */
AdvFormat = TRUE;
break;
case CM_PROB_UNKNOWN_RESOURCE:
/* FIXME - get the .inf file name */
AdvFormat = TRUE;
break;
case CM_PROB_DISABLED:
/* FIXME - if the device was disabled by the system use IDS_DEV_DISABLED2 */
break;
case CM_PROB_FAILED_ADD:
/* FIXME - get the name of the sub-device with the error */
AdvFormat = TRUE;
break;
}
if (AdvFormat)
{
StringIDs[1] = IDS_DEVCODE2;
dwRet = LoadAndFormatStringsCat(hDllInstance,
StringIDs,
sizeof(StringIDs) / sizeof(StringIDs[0]),
&szProblem,
szInfo,
uProblemId);
}
else
{
dwRet = LoadAndFormatStringsCat(hDllInstance,
StringIDs,
sizeof(StringIDs) / sizeof(StringIDs[0]),
&szProblem,
uProblemId);
}
if (dwRet != 0)
{
if (uMaxString != 0 && uMaxString >= dwRet)
{
wcscpy(lpString,
szProblem);
}
LocalFree((HLOCAL)szProblem);
Ret = dwRet;
}
}
return Ret;
}