P / вызов функции NtQueryVolumeInformationFile возвращает ошибку 0xC0000003 - PullRequest
0 голосов
/ 04 ноября 2019

Код импорта C #:

[DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
public static extern long NtQueryVolumeInformationFile(IntPtr FileHandle, out IO_STATUS_BLOCK IoStatusBlock, IntPtr FsInformation, uint Length, FSINFOCLASS FsInformationClass);

Перечисление FSINFOCLASS:

public enum FSINFOCLASS
{
    FileFsVolumeInformation,
    FileFsLabelInformation,
    FileFsSizeInformation,
    FileFsDeviceInformation,
    FileFsAttributeInformation,
    FileFsControlInformation,
    FileFsFullSizeInformation,
    FileFsObjectIdInformation,
    FileFsDriverPathInformation,
    FileFsVolumeFlagsInformation,
    FileFsSectorSizeInformation,
    FileFsDataCopyInformation,
    FileFsMetadataSizeInformation,
    FileFsFullSizeInformationEx,
    FileFsMaximumInformation
}

Как это называется:

var handlePtr = Win32.CreateFile(@"\\.\c:", Win32.GENERIC_READ, Win32.FILE_SHARE_READ | Win32.FILE_SHARE_WRITE | Win32.FILE_SHARE_DELETE, 0, Win32.OPEN_EXISTING, 0, 0);

if (handlePtr == IntPtr.Zero - 1)
    return 0;

var iosb = new Win32.IO_STATUS_BLOCK();
var buffer = Marshal.AllocHGlobal(273);

var result = Win32.NtQueryVolumeInformationFile(handlePtr, out iosb, buffer, 273,
    Win32.FSINFOCLASS.FileFsVolumeInformation);
 // result=0xC0000003 , should be zero

Код работает садминистративная привилегия.

Описание кода ошибки: STATUS_INVALID_INFO_CLASS

Но, насколько я могу судить, перечисление info-класса корректно.

Чего мне не хватает?

1 Ответ

0 голосов
/ 05 ноября 2019

Благодаря комментарию Джими я присвоил значение 1 элементу enum FileFsVolumeInformation, и это исправило эту ошибку.

Однако для полноценной работы требовалось больше исправлений. Полный рабочий код для импорта взаимодействия выглядит следующим образом:

 [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
        public static extern long NtQueryVolumeInformationFile(IntPtr FileHandle, out IO_STATUS_BLOCK IoStatusBlock, IntPtr FsInformation,
            uint Length, FSINFOCLASS FsInformationClass);
 [StructLayout(LayoutKind.Sequential, Pack = 0)]
        public struct FILE_FS_VOLUME_INFORMATION
        {
            public long VolumeCreationTime;
            public uint VolumeSerialNumber;
            public uint VolumeLabelLength;
            public bool SupportsObjects;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
            public string VolumeLabel;
        }
   public enum FSINFOCLASS
        {
            FileFsVolumeInformation = 1,
            FileFsLabelInformation,
            FileFsSizeInformation,
            FileFsDeviceInformation,
            FileFsAttributeInformation,
            FileFsControlInformation,
            FileFsFullSizeInformation,
            FileFsObjectIdInformation,
            FileFsDriverPathInformation,
            FileFsVolumeFlagsInformation,
            FileFsSectorSizeInformation,
            FileFsDataCopyInformation,
            FileFsMetadataSizeInformation,
            FileFsFullSizeInformationEx,
            FileFsMaximumInformation
        }
[StructLayout(LayoutKind.Sequential, Pack = 0)]
        public struct IO_STATUS_BLOCK
        {
            public uint status;
            public IntPtr information;
        }
 public uint GetVolumeSerialNumber(string volumePath)
        {
            var handlePtr = Win32.CreateFile($@"\\.\{volumePath.TrimEnd('\\')}", Win32.GENERIC_READ, Win32.FILE_SHARE_READ | Win32.FILE_SHARE_WRITE | Win32.FILE_SHARE_DELETE,
                0, Win32.OPEN_EXISTING, 0, 0);

            if (handlePtr == IntPtr.Zero - 1)
                return 0;

            var iosb = new Win32.IO_STATUS_BLOCK();
            var fsInfo = new Win32.FILE_FS_VOLUME_INFORMATION();
            var bufferSize = Marshal.SizeOf(fsInfo) + 32; //32 =maximum ntfs volume label length
            var buffer = Marshal.AllocHGlobal(bufferSize);

            var result = Win32.NtQueryVolumeInformationFile(handlePtr, out iosb, buffer, (uint)bufferSize,
                Win32.FSINFOCLASS.FileFsVolumeInformation);
            if (result != 0)
            {
                Marshal.FreeHGlobal(buffer);
                Win32.CloseHandle(handlePtr);
                return 0;
            }

            fsInfo = Marshal.PtrToStructure<Win32.FILE_FS_VOLUME_INFORMATION>(buffer);
            Marshal.FreeHGlobal(buffer);
            return fsInfo.VolumeSerialNumber;
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...