P/调用ReadFile不工作(错误87:无效参数)

本文关键字:无效 参数 错误 调用 ReadFile 工作 | 更新日期: 2023-09-27 18:08:37

我正在使用p/Invoke从c#访问原始驱动器。我遇到了一个问题,ReadFile失败,错误87,但我无法找出哪个参数是不正确的:我对我的缓冲区和我正在访问的驱动器都有很好的处理,并且整数参数的类型是正确的。

我把相关的代码放在这里
Also, Here:
从Drive.cs

public Boolean TryOpen(){
 .
 .
 .
 _hDrive = FileIO.Methods.CreateFile(
                    Info.PhysicalPath,
                    FileIO.FileAccess.GenericRead | FileIO.FileAccess.GenericWrite,
                    FileIO.FileShare.Read | FileIO.FileShare.Write,
                    IntPtr.Zero,
                    FileIO.CreationDisposition.OpenExisting,
                    FileIO.FileAttributes.NoBuffering | FileIO.FileAttributes.Write_Through | FileIO.FileAttributes.RandomAccess,
                    IntPtr.Zero);
                    .
                    .
                    .
}
private const Int32 DRIVE_PAGEBUFFER_SIZE = 0x0000FFFF;
private unsafe Boolean _bufferFrom(UInt32 pageIdx)
        {
            bool success = false;
            long retPtr;
            uint retBytes;
            if (FileIO.Methods.SeekFile(_hDrive, pageIdx * DRIVE_PAGEBUFFER_SIZE, out retPtr, FileIO.FileSeekMethod.FileBegin))
            {
                _curPageIdx = pageIdx;
               
                if (FileIO.Methods.ReadFile(_hDrive,_pageBuffer, 65535, out retBytes, null))
                {
                    success = true;
                }
                else
                {
                    Console.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                    
                    //read failed.
                }
            }
            else
            {
                //seek failed.
            }
            return success;
        }
从FileIO.cs:

public static class Methods
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern SafeFileHandle CreateFile(
             string lpFileName,
            [MarshalAs(UnmanagedType.U4)] FileAccess access,
            [MarshalAs(UnmanagedType.U4)] FileShare share,
            [Optional] IntPtr security,
            [MarshalAs(UnmanagedType.U4)] CreationDisposition disposition,
            [MarshalAs(UnmanagedType.U4)] FileAttributes attributes,
             IntPtr template
            );
        [DllImport("kernel32.dll", SetLastError = true)]
        public static unsafe extern Boolean WriteFile(
            SafeFileHandle hFile,
            SafeBuffer lpBuffer,
            UInt32 nNumberOfBytesToWrite,
            out UInt32 lpNumberOfBytesToWrite,
             NativeOverlapped* lpOverlapped
            );
        [DllImport("kernel32.dll", SetLastError = true)]
        public static unsafe extern Boolean ReadFile(
             SafeFileHandle hFile,
             SafeBuffer lpBuffer,
             UInt32 nNumberOfBytesToRead,
             out UInt32 lpNumberOfBytesRead,
             NativeOverlapped* lpOverlapped
            );
        [DllImport("kernel32.dll", EntryPoint = "SetFilePointerEx", SetLastError = true)]
        public static extern Boolean SeekFile(
            [In] SafeFileHandle hFile,
            [In] Int64 liDistanceToMove,
            [Out] out Int64 lpNewFilePointer,
            [In][MarshalAs(UnmanagedType.U4)] FileSeekMethod seekMethod
            );
    }
从MemBuffer.cs:

class MemBuffer:SafeBuffer
    {
        public MemBuffer(Int32 size):base(true)
        {
            this.SetHandle(Marshal.AllocHGlobal(size));
            this.Initialize((ulong)size);
        }
        protected override bool ReleaseHandle()
        {
            Marshal.FreeHGlobal(this.handle);
            return true;
        }
    }

我已经尝试重新定义ReadFile和WriteFile工作与标准IntPtrs(而不是SafeFileHandle和SafeBuffer),但它没有区别。

我做错了什么?

P/调用ReadFile不工作(错误87:无效参数)

原始驱动器访问和访问用FILE_FLAG_NO_BUFFERING (FileIO.FileAttributes.NoBuffering)打开的文件需要查找到的偏移量是底层设备扇区大小的倍数(通常是512字节或4096字节),并且读写的数量是扇区大小的倍数。

你的代码正在试图寻找是0xFFFF的倍数的偏移量,并试图读取65535字节。它们不是512或4096的倍数,因此会出现"Invalid argument"错误。

改变你的代码使用对齐的大小(即0x10000/65536),它应该工作。在所有可能的情况下,您试图读取的结构实际上是65536字节,而不是65535。