Как программно принудительно использовать универсальный драйвер Microsoft (RNDIS) с помощью setupapi DiInstallDevice, есC#

Место общения программистов C#
Anonymous
Как программно принудительно использовать универсальный драйвер Microsoft (RNDIS) с помощью setupapi DiInstallDevice, ес

Сообщение Anonymous »

Когда я подключаю USB-устройство RNDIS (гаджет Linux) к ПК с Windows, оно отображается как устройство RNDIS без драйвера. Чтобы все заработало, я захожу в диспетчер устройств и вручную выбираю Microsoft Generic Remote RNDIS Driver.
Моей конечной целью было принудительно установить этот универсальный драйвер Microsoft из кода (C#), чтобы пользователи не делали это вручную.
Я пробовал devcon, pnputil и другие способы, но ничего не помогло. Наконец, я реализовал pinvoke для DiInstallDevice Windows SetupAPI.

Код: Выделить всё

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPTStr)] string Enumerator, IntPtr hwndParent, uint Flags);

[DllImport("setupapi.dll", SetLastError = true)]
static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);

[DllImport("setupapi.dll", SetLastError = true)]
static extern bool SetupDiEnumDriverInfo(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, int driverType, int MemberIndex, ref SP_DRVINFO_DATA drvinfo);

[DllImport("newdev.dll", SetLastError = true)]
public static extern bool DiInstallDevice(
IntPtr hwndParent,
IntPtr deviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref SP_DRVINFO_DATA DriverInfoData,
DiFlags Flags,
ref bool NeedReboot);

[DllImport("setupapi.dll", SetLastError = true)]
static extern bool SetupDiBuildDriverInfoList(
IntPtr deviceInfoSet,
ref SP_DEVINFO_DATA deviceInfoData,
int DriverType);

...

public static void ForceRNDISDriver(IntPtr hwndParent)
{
var nullguid = Guid.Empty;
IntPtr deviceInfoSet = SetupDiGetClassDevs(ref nullguid, null, IntPtr.Zero, (uint)(DiGetClassFlags.DIGCF_ALLCLASSES)); //all devices
if (deviceInfoSet.ToInt64() != -1 &&  deviceInfoSet.ToInt64() != 0)
{
uint BUFFER_SIZE = 32000;
byte[] ptrBuf = new byte[BUFFER_SIZE];

SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA();
deviceInfoData.cbSize = (uint)Marshal.SizeOf(deviceInfoData);
SP_DRVINFO_DATA driverInfoData = new SP_DRVINFO_DATA();
driverInfoData.cbSize = Marshal.SizeOf(driverInfoData);
bool Success = true;
uint i = 0;
while (Success)
{
// start the enumeration searching for hardware ID
Success = SetupDiEnumDeviceInfo(deviceInfoSet, i, ref deviceInfoData);
if (Success)
{
if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, (uint)SetupDiGetDeviceRegistryPropertyEnum.SPDRP_HARDWAREID, out uint RegType, ptrBuf, BUFFER_SIZE, out uint RequiredSize))
{
string hwid = Encoding.Unicode.GetString(ptrBuf, 0, (int)RequiredSize - 2);
if (hwid.ToUpper().Contains("HARDWAREIDEXAMPLE"))
{
int SPDIT_NODRIVER = 0x00000000;
int SPDIT_CLASSDRIVER = 0x00000001;
int SPDIT_COMPATDRIVER = 0x00000002;

bool built = SetupDiBuildDriverInfoList(deviceInfoSet, ref deviceInfoData, SPDIT_CLASSDRIVER);
if (built)
{
int di = 0;
while (true)
{
bool enumed = SetupDiEnumDriverInfo(deviceInfoSet, ref deviceInfoData, SPDIT_CLASSDRIVER, di++, ref driverInfoData);
if (enumed)
{
if (driverInfoData.Description.ToUpper().Contains("NDIS"))
{
break;
}
}
else
break;
}
}
break;
}
}
}
i++;
}

bool reboot = true;
bool dii = DiInstallDevice(hwndParent,
deviceInfoSet,
ref deviceInfoData,
ref driverInfoData,
DiFlags.DIIDFLAG_INSTALLNULLDRIVER,
ref reboot);
int le = GetLastError();//87: INVALID_PARAMETER

}
}
Я могу получить как данные deviceInfoData, так и driverInfoData со значимыми данными внутри.
Последний вызов DiInstallDevice всегда завершается последней ошибкой 87: ERROR_INVALID_PARAMETER.
Я что-то упускаю? Есть ли другой способ выбрать универсальный драйвер для неопознанного устройства?

Вернуться в «C#»