PInvoke с SetupDiGetDriverInfoDetail - PullRequest
       3

PInvoke с SetupDiGetDriverInfoDetail

2 голосов
/ 25 февраля 2011

Я пытаюсь вызвать SetupDiGetDriverInfoDetail из приложения C #. Вызов не удался, и ошибка win32, которую я получаю, равна 0x6F8 («Предоставленный пользовательский буфер недопустим для запрошенной операции.»). До этого момента мне удавалось успешно вызывать другие функции setupdi, поэтому я думаю, что проблема в том, как я маршалю либо функцию, либо структуру SP_DRVINFO_DETAIL_DATA.

Я не уверен, но думаю, что проблема может быть в элементе HardwareID структуры SP_DRVINFO_DETAIL_DATA. Я попытался указать HardwareID как разные типы (например, байтовый массив и выделить буфер перед установкой размера и вызовом функции), но всегда одна и та же ошибка. Если у кого-либо есть опыт работы с этим звонком или есть какие-либо указатели, я был бы признателен за помощь.

Ниже приведено определение структуры, импорт функций и фрагмент кода. В этой версии я использую буфер HardwareID фиксированного размера. Я также попытался указать размер буфера, равный 1, ожидая ошибку «слишком маленький буфер», но всегда получаю ошибку «неверный буфер».

    [DllImport("setupapi.dll", SetLastError = true)]
    internal static extern Int32 SetupDiGetDriverInfoDetail(
        IntPtr DeviceInfoSet,
        SP_DEVINFO_DATA DeviceInfoData,
        SP_DRVINFO_DATA DriverInfoData,
        ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData,
        Int32 DriverInfoDetailDataSize,
        ref Int32 RequiredSize);


    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct SP_DRVINFO_DETAIL_DATA
    {
        public Int32 cbSize;
        public System.Runtime.InteropServices.ComTypes.FILETIME InfDate;
        public Int32 CompatIDsOffset;
        public Int32 CompatIDsLength;
        public IntPtr Reserved;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String SectionName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String InfFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String DrvDescription;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String HardwareID;
    };

SetupApiWrapper.SP_DRVINFO_DETAIL_DATA DriverInfoDetailData = new SetupApiWrapper.SP_DRVINFO_DETAIL_DATA();
DriverInfoDetailData.cbSize = Marshal.SizeOf(DriverInfoDetailData);

result = SetupApiWrapper.SetupDiGetDriverInfoDetail(
                            DevInfo,
                            DeviceInfoData,
                            DriverInfoData,
                            ref DriverInfoDetailData,
                            DriverInfoDetailData.cbSize,
                            ref reqSize);

Ответы [ 2 ]

1 голос
/ 25 февраля 2011

Объявление функции неверно, 2-й и 3-й аргументы передаются ref . Объясняет "неверный буфер", API хочет указатель. Осторожно с пакетом, это только 1 на 32-битных операционных системах. Установите целевую платформу на x86, чтобы быть уверенным. Вы должны сначала измерить необходимый размер конструкции. Сложно сделать, сделать HardwareID красивым и большим, не будь скромным и брось в него 16 КБ.

1 голос
/ 25 февраля 2011

oХотя я согласен, что код ошибки кажется неожиданным, я думаю, проблема в том, что cbSize должен быть установлен в sizeof (SP_DRVINFO_DETAIL_DATA) (это правильный размер C, а не Marshal.SizeOf в вашей структуре p / invoke.)

Быстрый тест с программой на две строки C дает:

ANSI 797
UNICODE 1570

Для двух правильных значений sizeof (вам нужно выяснить, какое из них вам нужно ...)

Для сравнения Marshal.SizeOf(typeof(SP_DRVINFO_DETAIL_DATA)) для вашей структуры дает 1048 как длину.

Я думаю, вам нужно выстроить это в очередь, прежде чем идти дальше.

Я подозреваю, что, возможно, ошибка слишком маленького буфера возвращается, если DriverInfoDetailDataSize слишком мала, но ошибка неверного буфера возвращается, если cbSize неверен.

В справке по SetupDiGetDriverInfoDetail также явным образом указано, что cbSize и DriverInfoDetailDataSize не должны быть одинаковыми значениями (поскольку ANYSIZE_ARRAY определяется как 1 как заполнитель), поэтому не следует ожидать, что Marshal.SizeOf будет работать правильно намеренно негабаритная структура.

Дополнительная коррекция:

Ваш член InfFilename также имеет неправильную длину - структура, которая точно соответствует структуре из SETUPAPI.H:

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Unicode)]
    internal struct SP_DRVINFO_DETAIL_DATA
    {
        public Int32 cbSize;
        public System.Runtime.InteropServices.ComTypes.FILETIME InfDate;
        public Int32 CompatIDsOffset;
        public Int32 CompatIDsLength;
        public IntPtr Reserved;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String SectionName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public String InfFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String DrvDescription;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
        public String HardwareID;
    };

Это дает правильную длину как в версиях ANSI, так и в UNICODE. Однако вы не хотите использовать это как есть, потому что вам нужен HardwareID, чтобы быть длиннее, поэтому вам придется отрегулировать длину и затем использовать Marshal.SizeOf, давая неправильное значение для прямого подключения к cbSize.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...