1

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

我创建了文件C:\tmp\test.txt并在其中放置了文本“aaaa”。

我运行代码并收到错误号:87
根据MSDN:“参数不正确。”

在此处输入图像描述

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

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);
            }
        }

    }
}
4

1 回答 1

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。

是对也将 FSCTL 与 C# 一起使用的代码的参考。

于 2017-02-23T16:36:15.377 回答