带有FSCTL_SET_ZERO_DATA的DeviceIoControl返回ERROR_INVALID_PARAMETER

时间:2017-02-23 11:57:37

标签: c# windows deviceiocontrol

我正在尝试在C#中使用DeviceIoControlFSCTL_SET_ZERO_DATA控制代码。

我创建了文件C:\tmp\test.txt,在里面我把文字“aaaa”。

我运行了代码并收到了错误编号:87
根据{{​​3}}:“参数不正确。”

MSDN

我认为问题是因为我在没有任何数据的情况下发送输入缓冲区(DeviceIoControl中的参数编号3)。

DeviceIoControl返回false 如何使用DeviceIoControl将有效参数插入FSCTL_SET_ZERO_DATA,这将使其返回true

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program2
    {
        [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
 IntPtr lpInBuffer, uint nInBufferSize,
 IntPtr lpOutBuffer, uint nOutBufferSize,
 out uint lpBytesReturned, IntPtr lpOverlapped);

        [Flags]
        public enum EMethod : uint
        {
            Buffered = 0,
            InDirect = 1,
            OutDirect = 2,
            Neither = 3
        }

        [Flags]
        public enum EFileDevice : uint
        {
            FileSystem = 0x00000009
        }

        [Flags]
        public enum EIOControlCode : uint
        {
            FsctlSetZeroData = (EFileDevice.FileSystem << 16) | (50 << 2) | EMethod.Buffered | (FileAccess.Write << 14),
        }

        [StructLayout(LayoutKind.Sequential)]
        struct FILE_ZERO_DATA_INFORMATION
        {
            public FILE_ZERO_DATA_INFORMATION(long offset, long count)
            {
                FileOffset = offset;
                BeyondFinalZero = offset + count;
            }

            public long FileOffset;
            public long BeyondFinalZero;
        }

        [DllImport("kernel32.dll")]
        public static extern uint GetLastError();

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CreateFile(
        [MarshalAs(UnmanagedType.LPTStr)] string filename,
        [MarshalAs(UnmanagedType.U4)] FileAccess access,
        [MarshalAs(UnmanagedType.U4)] FileShare share,
        IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        uint flagsAndAttributes,
        IntPtr templateFile);

        static void Main(string[] args)
        {
            IntPtr handle = CreateFile(@"C:\tmp\test.txt", FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, (int)FileAttributes.Normal, IntPtr.Zero);

            long length = 2;
            FILE_ZERO_DATA_INFORMATION data = new FILE_ZERO_DATA_INFORMATION(0, length);
            uint structSize = (uint)Marshal.SizeOf(data);
            IntPtr pBuffer = Marshal.AllocHGlobal((int)structSize);


            uint bytesReturned = 0;
            bool succeed = DeviceIoControl(handle, (uint)EIOControlCode.FsctlSetZeroData, pBuffer, 5, IntPtr.Zero, 5, out bytesReturned, IntPtr.Zero);

            // bool succeed = DeviceIoControl(handle, (uint)EIOControlCode.FsctlSetZeroData, IntPtr.Zero, 0, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
            if (succeed)
            {
                Console.WriteLine("Works fine");
            }
            else
            {
                uint err = GetLastError();
                Console.WriteLine("Error number: {0}", err);
            }
        }

    }
}

1 个答案:

答案 0 :(得分:1)

归功于@Aybe。

修复方法是:

uint pBufferSize = 16; 
Marshal.StructureToPtr(data, pBuffer, false);
bool succeed = DeviceIoControl(handle, (uint)EIOControlCode.FsctlSetZeroData, pBuffer, pBufferSize, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);  
  • 添加Marshal.StructureToPtr(data, pBuffer, false);
  • 非常重要

如果您不添加它,有时该函数将返回true并且有时会返回false。

Here是对使用FSCTL和C#的代码的引用。