reactos/dll/win32/devmgr/misc.c
2013-06-16 22:01:41 +00:00

1150 lines
32 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/misc.c
* PURPOSE: ReactOS Device Manager
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
* 2005/11/24 Created
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
HINSTANCE hDllInstance = NULL;
INT
LengthOfStrResource(IN HINSTANCE hInst,
IN UINT uID)
{
HRSRC hrSrc;
HGLOBAL hRes;
LPWSTR lpName, lpStr;
if (hInst == NULL)
{
return -1;
}
/* There are always blocks of 16 strings */
lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1);
/* Find the string table block */
if ((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) &&
(hRes = LoadResource(hInst, hrSrc)) &&
(lpStr = LockResource(hRes)))
{
UINT x;
/* Find the string we're looking for */
uID &= 0xF; /* position in the block, same as % 16 */
for (x = 0; x < uID; x++)
{
lpStr += (*lpStr) + 1;
}
/* Found the string */
return (int)(*lpStr);
}
return -1;
}
static INT
AllocAndLoadString(OUT LPWSTR *lpTarget,
IN HINSTANCE hInst,
IN UINT uID)
{
INT ln;
ln = LengthOfStrResource(hInst,
uID);
if (ln++ > 0)
{
(*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED,
ln * sizeof(WCHAR));
if ((*lpTarget) != NULL)
{
INT Ret;
if (!(Ret = LoadStringW(hInst, uID, *lpTarget, ln)))
{
LocalFree((HLOCAL)(*lpTarget));
}
return Ret;
}
}
return 0;
}
static INT
AllocAndLoadStringsCat(OUT LPWSTR *lpTarget,
IN HINSTANCE hInst,
IN UINT *uID,
IN UINT nIDs)
{
INT ln = 0;
UINT i;
for (i = 0;
i != nIDs;
i++)
{
ln += LengthOfStrResource(hInst,
uID[i]);
}
if (ln != 0)
{
(*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED,
(ln + 1) * sizeof(WCHAR));
if ((*lpTarget) != NULL)
{
LPWSTR s = *lpTarget;
INT Ret = 0;
for (i = 0;
i != nIDs;
i++)
{
if (!(Ret = LoadStringW(hInst, uID[i], s, ln)))
{
LocalFree((HLOCAL)(*lpTarget));
return 0;
}
s += Ret;
}
return s - *lpTarget;
}
}
return 0;
}
DWORD
LoadAndFormatString(IN HINSTANCE hInstance,
IN UINT uID,
OUT LPWSTR *lpTarget,
...)
{
DWORD Ret = 0;
LPWSTR lpFormat;
va_list lArgs;
if (AllocAndLoadString(&lpFormat,
hInstance,
uID) != 0)
{
va_start(lArgs, lpTarget);
/* let's use FormatMessage to format it because it has the ability to allocate
memory automatically */
Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
lpFormat,
0,
0,
(LPWSTR)lpTarget,
0,
&lArgs);
va_end(lArgs);
LocalFree((HLOCAL)lpFormat);
}
return Ret;
}
DWORD
LoadAndFormatStringsCat(IN HINSTANCE hInstance,
IN UINT *uID,
IN UINT nIDs,
OUT LPWSTR *lpTarget,
...)
{
DWORD Ret = 0;
LPWSTR lpFormat;
va_list lArgs;
if (AllocAndLoadStringsCat(&lpFormat,
hInstance,
uID,
nIDs) != 0)
{
va_start(lArgs, lpTarget);
/* let's use FormatMessage to format it because it has the ability to allocate
memory automatically */
Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
lpFormat,
0,
0,
(LPWSTR)lpTarget,
0,
&lArgs);
va_end(lArgs);
LocalFree((HLOCAL)lpFormat);
}
return Ret;
}
LPARAM
ListViewGetSelectedItemData(IN HWND hwnd)
{
int Index;
Index = ListView_GetNextItem(hwnd,
-1,
LVNI_SELECTED);
if (Index != -1)
{
LVITEM li;
li.mask = LVIF_PARAM;
li.iItem = Index;
li.iSubItem = 0;
if (ListView_GetItem(hwnd,
&li))
{
return li.lParam;
}
}
return 0;
}
LPWSTR
ConvertMultiByteToUnicode(IN LPCSTR lpMultiByteStr,
IN UINT uCodePage)
{
LPWSTR lpUnicodeStr;
INT nLength;
nLength = MultiByteToWideChar(uCodePage,
0,
lpMultiByteStr,
-1,
NULL,
0);
if (nLength == 0)
return NULL;
lpUnicodeStr = HeapAlloc(GetProcessHeap(),
0,
nLength * sizeof(WCHAR));
if (lpUnicodeStr == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
if (!MultiByteToWideChar(uCodePage,
0,
lpMultiByteStr,
nLength,
lpUnicodeStr,
nLength))
{
HeapFree(GetProcessHeap(),
0,
lpUnicodeStr);
return NULL;
}
return lpUnicodeStr;
}
BOOL
GetDeviceManufacturerString(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
DWORD RegDataType;
BOOL Ret = FALSE;
if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_MFG,
&RegDataType,
(PBYTE)szBuffer,
BufferSize * sizeof(WCHAR),
NULL) ||
RegDataType != REG_SZ)
{
szBuffer[0] = L'\0';
if (LoadString(hDllInstance,
IDS_UNKNOWN,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
}
else
{
/* FIXME - check string for NULL termination! */
Ret = TRUE;
}
return Ret;
}
BOOL
GetDeviceLocationString(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN DEVINST dnParentDevInst OPTIONAL,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
DWORD RegDataType;
ULONG DataSize;
CONFIGRET cRet;
LPWSTR szFormatted;
HKEY hKey;
DWORD dwSize, dwType;
BOOL Ret = FALSE;
DataSize = BufferSize * sizeof(WCHAR);
szBuffer[0] = L'\0';
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
{
/* query the LocationInformationOverride value */
dwSize = BufferSize;
if (RegQueryValueEx(hKey,
L"LocationInformationOverride",
NULL,
&dwType,
(LPBYTE)szBuffer,
&dwSize) == ERROR_SUCCESS &&
dwType == REG_SZ &&
szBuffer[0] != L'\0')
{
Ret = TRUE;
}
else
{
szBuffer[0] = L'\0';
}
RegCloseKey(hKey);
}
if (!Ret)
{
if (dnParentDevInst != 0)
{
/* query the parent node name */
if (CM_Get_DevNode_Registry_Property(dnParentDevInst,
CM_DRP_DEVICEDESC,
&RegDataType,
szBuffer,
&DataSize,
0) == CR_SUCCESS &&
RegDataType == REG_SZ &&
LoadAndFormatString(hDllInstance,
IDS_DEVONPARENT,
&szFormatted,
szBuffer) != 0)
{
wcsncpy(szBuffer,
szFormatted,
BufferSize - 1);
szBuffer[BufferSize - 1] = L'\0';
LocalFree((HLOCAL)szFormatted);
Ret = TRUE;
}
}
else if (DeviceInfoData->DevInst != 0)
{
cRet = CM_Get_DevNode_Registry_Property(DeviceInfoData->DevInst,
CM_DRP_LOCATION_INFORMATION,
&RegDataType,
szBuffer,
&DataSize,
0);
if (cRet == CR_SUCCESS && RegDataType == REG_SZ)
{
/* FIXME - check string for NULL termination! */
Ret = TRUE;
}
if (Ret && szBuffer[0] >= L'0' && szBuffer[0] <= L'9')
{
/* convert the string to an integer value and create a
formatted string */
ULONG ulLocation = (ULONG)wcstoul(szBuffer,
NULL,
10);
if (LoadAndFormatString(hDllInstance,
IDS_LOCATIONSTR,
&szFormatted,
ulLocation,
szBuffer) != 0)
{
wcsncpy(szBuffer,
szFormatted,
BufferSize - 1);
szBuffer[BufferSize - 1] = L'\0';
LocalFree((HLOCAL)szFormatted);
}
else
Ret = FALSE;
}
}
}
if (!Ret &&
LoadString(hDllInstance,
IDS_UNKNOWN,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
return Ret;
}
BOOL
GetDeviceStatusString(IN DEVINST DevInst,
IN HMACHINE hMachine,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
CONFIGRET cr;
ULONG Status, ProblemNumber;
UINT MessageId = IDS_UNKNOWN;
BOOL Ret = FALSE;
szBuffer[0] = L'\0';
cr = CM_Get_DevNode_Status_Ex(&Status,
&ProblemNumber,
DevInst,
0,
hMachine);
if (cr == CR_SUCCESS)
{
if (Status & DN_HAS_PROBLEM)
{
UINT uRet;
uRet = DeviceProblemText(hMachine,
DevInst,
ProblemNumber,
szBuffer,
(BufferSize != 0 ? BufferSize : BufferSize - 1));
Ret = (uRet != 0 && uRet < BufferSize);
}
else
{
if (!(Status & (DN_DRIVER_LOADED | DN_STARTED)))
{
MessageId = IDS_NODRIVERLOADED;
}
else
{
MessageId = IDS_DEV_NO_PROBLEM;
}
goto GeneralMessage;
}
}
else
{
GeneralMessage:
if (LoadString(hDllInstance,
MessageId,
szBuffer,
(int)BufferSize))
{
Ret = TRUE;
}
}
return Ret;
}
BOOL
GetDriverProviderString(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
HKEY hKey;
DWORD dwSize, dwType;
BOOL Ret = FALSE;
szBuffer[0] = L'\0';
/* get driver provider, date and version */
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
{
/* query the driver provider */
dwSize = BufferSize;
if (RegQueryValueEx(hKey,
REGSTR_VAL_PROVIDER_NAME,
NULL,
&dwType,
(LPBYTE)szBuffer,
&dwSize) == ERROR_SUCCESS &&
dwType == REG_SZ &&
szBuffer[0] != L'\0')
{
Ret = TRUE;
}
else
{
szBuffer[0] = L'\0';
}
RegCloseKey(hKey);
}
if (szBuffer[0] == L'\0')
{
/* unable to query the information */
if (LoadString(hDllInstance,
IDS_UNKNOWN,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
}
return Ret;
}
BOOL
GetDriverVersionString(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
HKEY hKey;
DWORD dwSize, dwType;
BOOL Ret = FALSE;
szBuffer[0] = L'\0';
/* get driver provider, date and version */
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
{
/* query the driver provider */
dwSize = BufferSize;
if (RegQueryValueEx(hKey,
L"DriverVersion",
NULL,
&dwType,
(LPBYTE)szBuffer,
&dwSize) == ERROR_SUCCESS &&
dwType == REG_SZ &&
szBuffer[0] != L'\0')
{
Ret = TRUE;
}
else
{
szBuffer[0] = L'\0';
}
RegCloseKey(hKey);
}
if (szBuffer[0] == L'\0')
{
/* unable to query the information */
if (LoadString(hDllInstance,
IDS_NOTAVAILABLE,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
}
return Ret;
}
BOOL
GetDriverDateString(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
HKEY hKey;
FILETIME DriverDate;
SYSTEMTIME SystemTime, LocalTime;
DWORD dwSize, dwType;
BOOL Ret = FALSE;
szBuffer[0] = L'\0';
/* get driver provider, date and version */
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE);
if (hKey != INVALID_HANDLE_VALUE)
{
/* query the driver provider */
dwSize = sizeof(FILETIME);
if (RegQueryValueEx(hKey,
L"DriverDateData",
NULL,
&dwType,
(LPBYTE)&DriverDate,
&dwSize) == ERROR_SUCCESS &&
dwType == REG_BINARY &&
dwSize == sizeof(FILETIME) &&
FileTimeToSystemTime(&DriverDate,
&SystemTime) &&
SystemTimeToTzSpecificLocalTime(NULL,
&SystemTime,
&LocalTime) &&
GetDateFormat(LOCALE_USER_DEFAULT,
DATE_SHORTDATE,
&LocalTime,
NULL,
szBuffer,
BufferSize) != 0)
{
Ret = TRUE;
}
RegCloseKey(hKey);
}
if (!Ret)
{
/* unable to query the information */
if (LoadString(hDllInstance,
IDS_NOTAVAILABLE,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
}
return Ret;
}
BOOL
IsDeviceHidden(IN DEVINST DevInst,
IN HMACHINE hMachine,
OUT BOOL *IsHidden)
{
CONFIGRET cr;
ULONG Status, ProblemNumber;
BOOL Ret = FALSE;
cr = CM_Get_DevNode_Status_Ex(&Status,
&ProblemNumber,
DevInst,
0,
hMachine);
if (cr == CR_SUCCESS)
{
*IsHidden = ((Status & DN_NO_SHOW_IN_DM) != 0);
Ret = TRUE;
}
return Ret;
}
BOOL
CanDisableDevice(IN DEVINST DevInst,
IN HMACHINE hMachine,
OUT BOOL *CanDisable)
{
CONFIGRET cr;
ULONG Status, ProblemNumber;
BOOL Ret = FALSE;
cr = CM_Get_DevNode_Status_Ex(&Status,
&ProblemNumber,
DevInst,
0,
hMachine);
if (cr == CR_SUCCESS)
{
*CanDisable = ((Status & DN_DISABLEABLE) != 0);
Ret = TRUE;
}
return Ret;
}
BOOL
IsDeviceStarted(IN DEVINST DevInst,
IN HMACHINE hMachine,
OUT BOOL *IsStarted)
{
CONFIGRET cr;
ULONG Status, ProblemNumber;
BOOL Ret = FALSE;
cr = CM_Get_DevNode_Status_Ex(&Status,
&ProblemNumber,
DevInst,
0,
hMachine);
if (cr == CR_SUCCESS)
{
*IsStarted = ((Status & DN_STARTED) != 0);
Ret = TRUE;
}
return Ret;
}
BOOL
IsDriverInstalled(IN DEVINST DevInst,
IN HMACHINE hMachine,
OUT BOOL *Installed)
{
CONFIGRET cr;
ULONG Status, ProblemNumber;
BOOL Ret = FALSE;
cr = CM_Get_DevNode_Status_Ex(&Status,
&ProblemNumber,
DevInst,
0,
hMachine);
if (cr == CR_SUCCESS)
{
*Installed = ((Status & DN_HAS_PROBLEM) != 0 ||
(Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
Ret = TRUE;
}
return Ret;
}
BOOL
EnableDevice(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DevInfoData OPTIONAL,
IN BOOL bEnable,
IN DWORD HardwareProfile OPTIONAL,
OUT BOOL *bNeedReboot OPTIONAL)
{
SP_PROPCHANGE_PARAMS pcp;
SP_DEVINSTALL_PARAMS dp;
DWORD LastErr;
BOOL Ret = FALSE;
pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
pcp.HwProfile = HardwareProfile;
if (bEnable)
{
/* try to enable the device on the global profile */
pcp.StateChange = DICS_ENABLE;
pcp.Scope = DICS_FLAG_GLOBAL;
/* ignore errors */
LastErr = GetLastError();
if (SetupDiSetClassInstallParams(DeviceInfoSet,
DevInfoData,
&pcp.ClassInstallHeader,
sizeof(SP_PROPCHANGE_PARAMS)))
{
SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
DeviceInfoSet,
DevInfoData);
}
SetLastError(LastErr);
}
/* try config-specific */
pcp.StateChange = (bEnable ? DICS_ENABLE : DICS_DISABLE);
pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
if (SetupDiSetClassInstallParams(DeviceInfoSet,
DevInfoData,
&pcp.ClassInstallHeader,
sizeof(SP_PROPCHANGE_PARAMS)) &&
SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
DeviceInfoSet,
DevInfoData))
{
dp.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
DevInfoData,
&dp))
{
if (bNeedReboot != NULL)
{
*bNeedReboot = ((dp.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0);
}
Ret = TRUE;
}
}
return Ret;
}
BOOL
GetDeviceTypeString(IN PSP_DEVINFO_DATA DeviceInfoData,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
BOOL Ret = FALSE;
if (!SetupDiGetClassDescription(&DeviceInfoData->ClassGuid,
szBuffer,
BufferSize,
NULL))
{
szBuffer[0] = L'\0';
if (LoadString(hDllInstance,
IDS_UNKNOWN,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
}
else
{
/* FIXME - check string for NULL termination! */
Ret = TRUE;
}
return Ret;
}
BOOL
GetDeviceDescriptionString(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT LPWSTR szBuffer,
IN DWORD BufferSize)
{
DWORD RegDataType;
BOOL Ret = FALSE;
if ((SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_FRIENDLYNAME,
&RegDataType,
(PBYTE)szBuffer,
BufferSize * sizeof(WCHAR),
NULL) ||
SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_DEVICEDESC,
&RegDataType,
(PBYTE)szBuffer,
BufferSize * sizeof(WCHAR),
NULL)) &&
RegDataType == REG_SZ)
{
/* FIXME - check string for NULL termination! */
Ret = TRUE;
}
else
{
szBuffer[0] = L'\0';
if (LoadString(hDllInstance,
IDS_UNKNOWNDEVICE,
szBuffer,
BufferSize))
{
Ret = TRUE;
}
}
return Ret;
}
BOOL
FindCurrentDriver(IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
OUT PSP_DRVINFO_DATA DriverInfoData)
{
HKEY hKey = INVALID_HANDLE_VALUE;
SP_DEVINSTALL_PARAMS InstallParams = {0};
SP_DRVINFO_DETAIL_DATA DriverInfoDetailData = {0};
WCHAR InfPath[MAX_PATH];
WCHAR InfSection[LINE_LEN];
DWORD dwType, dwLength;
DWORD i = 0;
LONG rc;
BOOL Ret = FALSE;
/* Steps to find the right driver:
* 1) Get the device install parameters
* 2) Open the driver registry key
* 3) Read the .inf file name
* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name
* 5) Build class driver list
* 6) Read inf section and inf section extension from registry
* 7) Enumerate drivers
* 8) Find the one who is in the same section as current driver?
*/
/* 1) Get the install params */
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&InstallParams))
{
DPRINT1("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
#ifdef DI_FLAGSEX_INSTALLEDDRIVER
InstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
if (SetupDiSetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&InstallParams))
{
if (SetupDiBuildDriverInfoList(DeviceInfoSet,
DeviceInfoData,
SPDIT_CLASSDRIVER) &&
SetupDiEnumDriverInfo(DeviceInfoSet,
DeviceInfoData,
SPDIT_CLASSDRIVER,
0,
DriverInfoData))
{
Ret = TRUE;
}
goto Cleanup;
}
InstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
#endif
/* 2) Open the driver registry key */
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE);
if (hKey == INVALID_HANDLE_VALUE)
{
DPRINT1("SetupDiOpenDevRegKey() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
/* 3) Read the .inf file name */
dwLength = (sizeof(InfPath) / sizeof(InfPath[0])) - 1;
rc = RegQueryValueEx(hKey,
REGSTR_VAL_INFPATH,
0,
&dwType,
(LPBYTE)InfPath,
&dwLength);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
DPRINT1("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
else if (dwType != REG_SZ)
{
SetLastError(ERROR_GEN_FAILURE);
DPRINT1("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ, dwType);
goto Cleanup;
}
InfPath[(dwLength / sizeof(WCHAR)) - 1] = L'\0';
/* 4) Update install params, by setting DI_ENUMSINGLEINF and .inf file name */
InstallParams.Flags |= DI_ENUMSINGLEINF;
InstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
wcscpy(InstallParams.DriverPath, InfPath);
if (!SetupDiSetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&InstallParams))
{
DPRINT1("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
/* 5) Build class driver list */
if (!SetupDiBuildDriverInfoList(DeviceInfoSet,
DeviceInfoData,
SPDIT_CLASSDRIVER))
{
DPRINT1("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
/* 6) Read inf section and from registry */
dwLength = (sizeof(InfSection) / sizeof(InfSection[0])) - 1;
rc = RegQueryValueEx(hKey,
REGSTR_VAL_INFSECTION,
0,
&dwType,
(LPBYTE)InfSection,
&dwLength);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
DPRINT1("RegQueryValueEx() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
else if (dwType != REG_SZ)
{
SetLastError(ERROR_GEN_FAILURE);
DPRINT1("Expected registry type REG_SZ (%lu), got %lu\n", REG_SZ, dwType);
goto Cleanup;
}
InfPath[(dwLength / sizeof(WCHAR)) - 1] = L'\0';
/* 7) Enumerate drivers */
DriverInfoData->cbSize = sizeof(SP_DRVINFO_DATA);
DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
while (SetupDiEnumDriverInfo(DeviceInfoSet,
DeviceInfoData,
SPDIT_CLASSDRIVER,
i,
DriverInfoData))
{
/* 8) Find the one who is in the same section as current driver */
if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
DeviceInfoData,
DriverInfoData,
&DriverInfoDetailData,
DriverInfoDetailData.cbSize,
NULL) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
DPRINT1("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
if (!wcsicmp(DriverInfoDetailData.SectionName,
InfSection) != 0)
{
/* We have found the right driver */
Ret = TRUE;
goto Cleanup;
}
i++;
}
if (GetLastError() != ERROR_NO_MORE_ITEMS)
{
DPRINT1("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
goto Cleanup;
}
SetLastError(ERROR_NO_DRIVER_SELECTED);
Cleanup:
if (hKey != INVALID_HANDLE_VALUE)
RegCloseKey(hKey);
return Ret;
}
HINSTANCE
LoadAndInitComctl32(VOID)
{
typedef VOID (WINAPI *PINITCOMMONCONTROLS)(VOID);
PINITCOMMONCONTROLS pInitCommonControls;
HINSTANCE hComCtl32;
hComCtl32 = LoadLibrary(L"comctl32.dll");
if (hComCtl32 != NULL)
{
/* initialize the common controls */
pInitCommonControls = (PINITCOMMONCONTROLS)GetProcAddress(hComCtl32,
"InitCommonControls");
if (pInitCommonControls == NULL)
{
FreeLibrary(hComCtl32);
return NULL;
}
pInitCommonControls();
}
return hComCtl32;
}
BOOL
WINAPI
DllMain(IN HINSTANCE hinstDLL,
IN DWORD dwReason,
IN LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
hDllInstance = hinstDLL;
break;
}
return TRUE;
}