@ebroker

C# передать параметр в Win32Api функцию?

Нужно вызвать функцию Win32Api DeviceIoControl с парметром IOCTL_DISK_SET_DISK_ATTRIBUTES и передать структуру SET_DISK_ATTRIBUTES такая команда должна установить диск только для чтения.

Как я это пытаюсь сделать:
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
    IntPtr hDevice,
    uint dwIoControlCode,
    IntPtr lpInBuffer,
    uint nInBufferSize,
    IntPtr lpOutBuffer,
    uint nOutBufferSize,
    out uint lpBytesReturned,
    IntPtr lpOverlapped
);

const ulong DISK_ATTRIBUTE_READ_ONLY = 0x0000000000000002;
struct SET_DISK_ATTRIBUTES
{
    public uint Version;
    public bool Persist;
    public byte[] Reserved1;
    public ulong Attributes;
    public ulong AttributesMask;
    public uint[] Reserved2;
};       


private bool SetReadonly(IntPtr handle)
{
    var sda = new SET_DISK_ATTRIBUTES();
    sda.Reserved1 = new byte[3];
    sda.Reserved2 = new uint[4];

    sda.AttributesMask = DISK_ATTRIBUTE_READ_ONLY;
    sda.Attributes = DISK_ATTRIBUTE_READ_ONLY;

    int nPtrQryBytes = Marshal.SizeOf(sda);
    IntPtr ptrQuery = Marshal.AllocHGlobal(nPtrQryBytes);

    uint byteReturned;
    var res = DeviceIoControl(handle, IOCTL_DISK_SET_DISK_ATTRIBUTES, ptrQuery, (uint)nPtrQryBytes, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);

    var ex = new Win32Exception(Marshal.GetLastWin32Error());
    MessageBox.Show(ex.Message);

    return res;
}


Получаю ошибку "Invalid parameter"
Подскажите как правильно передать структуру в параметр Win32Api функции.
  • Вопрос задан
  • 75 просмотров
Пригласить эксперта
Ответы на вопрос 2
@none7
Во первых эти массивы должны размещаться в самой структуре, а не управляемые ссылки на них. Странно уже то, что маршалинг исключение не выплюнул. Должно быть как то так:
struct SET_DISK_ATTRIBUTES
{
    public uint Version;
    public bool Persist;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] Reserved1;
    public ulong Attributes;
    public ulong AttributesMask;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public uint[] Reserved2;
};

Во вторых Вы забыли скопировать структуру в память и передаете функции DeviceIoControl не инициализированный мусор. Так же можно добавить перегруженный метод DeviceIoControl принимающий ref SET_DISK_ATTRIBUTES вместо IntPtr и не возится с динамической памятью. Пока структура является локальной переменной синхронного метода, GC её никуда не утащит.
Ответ написан
petermzg
@petermzg
Самый лучший программист
Открываете Total Commander или подобный файл менеджер
переходите в каталог c:\Program Files\dotnet\
Делаете поиск по всем dll файлам и в поиске по содержимому: DeviceIoControl

Далее используете приложение .Net Reflector (есть 15 дней триала ;) )
Подгружаете найденные dll (File/Open Assembly..)
В строке поиска DeviceIoControl и "Search member" тип поиска.
Он находит все.
В дереве выбираете найденый метод и в контекстом меню Analyze
В открывшемся окне Analyze выбипаете "Used by" и далее "Go to member".

Остается только найденные примеры преобразовать под собственные нужды.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы
от 40 000 до 70 000 руб.
SLC7 Екатеринбург
от 50 000 до 90 000 руб.
19 янв. 2019, в 09:50
650 руб./за проект
19 янв. 2019, в 07:41
10000 руб./за проект
19 янв. 2019, в 06:34
2500 руб./за проект