2017-02-23 35 views
1

我試圖使用DeviceIoControl在C#FSCTL_SET_ZERO_DATA控制代碼。的DeviceIoControl與FSCTL_SET_ZERO_DATA返回ERROR_INVALID_PARAMETER

我創建的文件C:\tmp\test.txt和裏面我把文本「AAAA」。

我跑的代碼,我收到錯誤號:87
根據MSDN:「該參數不正確。」

enter image description here

我認爲,這個問題是因爲我(在DeviceIoControl參數號3)沒有任何數據發送輸入緩衝器。

DeviceIoControl回報false
我怎樣才能插入有效的參數DeviceIoControlFSCTL_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

'nInBufferSize'是'FILE_ZERO_DATA_INFORMATION'的大小,所以'16','nOutBufferSize'應該爲零,請參閱文檔。 – Aybe

+0

謝謝,現在它工作。提交它作爲答案,我會將其標記爲答案。 我改變了調用:'uint pBufferSize = 16; bool succeed = DeviceIoControl(handle,(uint)EIOControlCode.FsctlSetZeroData,pBuffer,pBufferSize,IntPtr.Zero,0,out bytesReturned,IntPtr.Zero);' – E235

回答

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和某個假的。

Here是代碼的引用也使用FSCTL用C#。

+0

這裏有一些額外的代表。爲你點:) – Aybe