I have an UMDF driver which currently is redistributed through 2 standalone installers, one for x64 and one for x86.
The install driver function is this one, copied from devcon:
bool InstallDriver(const TCHAR* InfPath, const wchar_t* TargetID)
{
#define MAX_CLASS_NAME_LEN 32
GUID ClassGUID = {};
TCHAR ClassName[MAX_CLASS_NAME_LEN] = {};
TCHAR hwIdList[LINE_LEN + 4] = {};
//
// List of hardware ID's must be double zero-terminated
//
ZeroMemory(hwIdList, sizeof(hwIdList));
if (FAILED(StringCchCopy(hwIdList, LINE_LEN, TargetID)))
{
return false;
}
//
// Use the INF File to extract the Class GUID.
//
if (!SetupDiGetINFClass(InfPath, &ClassGUID, ClassName, sizeof(ClassName) / sizeof(ClassName[0]), 0))
{
return false;
}
//
// Create the container for the to-be-created Device Information Element.
//
HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, 0);
if (DeviceInfoSet == INVALID_HANDLE_VALUE)
{
return false;
}
//
// Now create the element.
// Use the Class GUID and Name from the INF file.
//
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiCreateDeviceInfo(DeviceInfoSet,
ClassName,
&ClassGUID,
NULL,
0,
DICD_GENERATE_ID,
&DeviceInfoData))
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return false;
}
//
// Add the HardwareID to the Device's HardwareID property.
//
if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
&DeviceInfoData,
SPDRP_HARDWAREID,
(LPBYTE)hwIdList,
(lstrlen(hwIdList) + 1 + 1) * sizeof(TCHAR)))
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return false;
}
//
// Transform the registry element into an actual devnode
// in the PnP HW tree.
//
if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
DeviceInfoSet,
&DeviceInfoData))
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return false;
}
//
// update the driver for the device we just created
//
if (!UpdateDriverForPlugAndPlayDevices(0, TargetID, InfPath, INSTALLFLAG_FORCE, 0))
{
int y = GetLastError();
if (y == ERROR_IN_WOW64 || y == ERROR_NO_SUCH_DEVINST || y == ERROR_NO_SUCH_DEVINST || y == ERROR_FILE_NOT_FOUND)
{
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return false;
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return true;
}
This works OK, but I want to have a single x86 redistributable which would contain both the x86 and x64 drivers and detect if running in WOW64 and install the x64 driver.
This time the InstallDriver
function fails at this call:
if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
DeviceInfoSet,
&DeviceInfoData))
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return false;
}
Last error 3758096949.
I couldn't find more info on that error, plus I didn't see any tip in SetupDiSetDeviceRegistryProperty to set the registry to the x64 one, like in RegCreateKeyEx's KEY_WOW64_64KEY flag.
Is there a way to avoid the 2 executables?