title: C# call WinApi?
body: <p>I am trying to call a WinAPI function <code>DeviceIoControl</code> in C# with code <a href="https://docs.microsoft.com/en-us/windows/desktop/api/WinIoCtl/ni-winioctl-ioctl_disk_set_disk_attributes" rel="nofollow noreferrer"><code>IOCTL_DISK_SET_DISK_ATTRIBUTES</code></a> and pass struct <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-_set_disk_attributes" rel="nofollow noreferrer"><code>SET_DISK_ATTRIBUTES</code></a>. I am trying do it with this code:</p>
  
  <pre class="lang-cs prettyprint-override"><code>const uint GENERIC_READ = 0x80000000;
  const uint GENERIC_WRITE = 0x40000000;
  const int FILE_SHARE_READ = 0x1;
  const int FILE_SHARE_WRITE = 0x2;
  
  const uint IOCTL_DISK_SET_DISK_ATTRIBUTES = 0x0007c0f4;
  const ulong DISK_ATTRIBUTE_READ_ONLY = 0x0000000000000002;
  
  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  private static extern IntPtr CreateFile(
      string lpFileName,
      uint dwDesiredAccess,
      uint dwShareMode,
      IntPtr SecurityAttributes,
      uint dwCreationDisposition,
      uint dwFlagsAndAttributes,
      IntPtr hTemplateFile
  );
  
  [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
  private static extern bool DeviceIoControl(
      IntPtr hDevice,
      uint dwIoControlCode,
      IntPtr lpInBuffer,
      uint nInBufferSize,
      IntPtr lpOutBuffer,
      uint nOutBufferSize,
      out uint lpBytesReturned,
      IntPtr lpOverlapped
  );
  
  struct SET_DISK_ATTRIBUTES
  {
      public uint Version;
      public bool Persist;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
      public byte[] Reserved1;
      public ulong Attributes;
      public ulong AttributesMask;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
      public uint[] Reserved2;
  };
  
  private bool SetReadonly(IntPtr handle)
  {
      var sda = new SET_DISK_ATTRIBUTES();
      sda.AttributesMask = DISK_ATTRIBUTE_READ_ONLY;
      sda.Attributes = DISK_ATTRIBUTE_READ_ONLY;
  
      int nPtrQryBytes = Marshal.SizeOf(sda);
      sda.Version = (uint)nPtrQryBytes;
  
      IntPtr ptrQuery = Marshal.AllocHGlobal(nPtrQryBytes);
      Marshal.StructureToPtr(sda, ptrQuery, false);
  
      uint byteReturned;
      var res = DeviceIoControl(handle, IOCTL_DISK_SET_DISK_ATTRIBUTES, ptrQuery, (uint)nPtrQryBytes, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
  
      var ex = new Win32Exception(Marshal.GetLastWin32Error());
      MessageBox.Show(ex.Message);
  
      return res;
  }
  </code></pre>
  
  <p>I receive error "Parameter incorrect". What is the right way to call <code>DeviceIoControl</code> function passing structure <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-_set_disk_attributes" rel="nofollow noreferrer"><code>SET_DISK_ATTRIBUTES</code></a>?</p>