// Wrapper for Platform SDK File functions
// w32device.cs
// compile with: /unsafe

using System;
using System.Runtime.InteropServices;
using System.Text;
 
public class W32Device
{
      const uint GENERIC_READ = 0x80000000;
      const uint GENERIC_WRITE = 0x40000000;
      const uint OPEN_EXISTING = 3;
      const int INVALID_HANDLE_VALUE = (-1);
      IntPtr handle = (IntPtr)INVALID_HANDLE_VALUE;
 
      [DllImport("kernel32", SetLastError=true)]
      static extern unsafe IntPtr CreateFile(
            string FileName,                    // file name
            uint DesiredAccess,                 // access mode
            uint ShareMode,                     // share mode
            uint SecurityAttributes,            // Security Attributes
            uint CreationDisposition,           // how to create
            uint FlagsAndAttributes,            // file attributes
            int hTemplateFile                   // handle to template file
            );
 
       [DllImport("kernel32", SetLastError=true)]
      static extern unsafe bool ReadFile(
            IntPtr hFile,                       // handle to file
            void* pBuffer,                      // data buffer
            int NumberOfBytesToRead,            // number of bytes to read
            int* pNumberOfBytesRead,            // number of bytes read
            int Overlapped                      // overlapped buffer
            );
 
      [DllImport("kernel32", SetLastError=true)]
      static extern unsafe bool WriteFile(
            IntPtr hFile,                       // handle to file
            void* pBuffer,                      // data buffer
            int NumberOfBytesToWrite,           // number of bytes to write
            int* pNumberOfBytesWrittn,          // number of bytes written
            int Overlapped                      // overlapped buffer
            );
  
      [DllImport("kernel32", SetLastError=true)]
      static extern unsafe bool CloseHandle(
            IntPtr hObject   // handle to object
            );

      ~W32Device()
      {
          if( handle != (IntPtr)INVALID_HANDLE_VALUE )
          {
              CloseHandle( handle );
              handle = (IntPtr)INVALID_HANDLE_VALUE;
          }
      }

      public bool Open(string FileName)
      {
            // open the existing file for reading and writing
            handle = CreateFile(
                  FileName,
                  (GENERIC_READ | GENERIC_WRITE),
                  0, 
                  0, 
                  OPEN_EXISTING,
                  0,
                  0);
      
            if (handle != (IntPtr)INVALID_HANDLE_VALUE)
                  return true;
            else
                  return false;
      }
 
      public unsafe bool Read(byte[] buffer, int count, ref int nread) 
      {
            int n = 0;
            fixed (byte* p = buffer) 
            {
                  if (!ReadFile(handle, p, count, &n, 0))
                  {
                        nread = 0;
                        return false;
                  }
            }
            nread = n;
            return true;
      }

      public unsafe bool Write(byte[] buffer, int count, ref int nwritten) 
      {
            int n = 0;
            fixed (byte* p = buffer) 
            {
                  if (!WriteFile(handle, p, count, &n, 0))
                  {
                        nwritten = 0;          
                        return false;
                  }
            }
            nwritten = n;
            return true;
      }

      public bool Close()
      {
            // close file handle
            bool retval = false;
            if( handle != (IntPtr)INVALID_HANDLE_VALUE )
            {
              retval = CloseHandle(handle);
              handle = (IntPtr)INVALID_HANDLE_VALUE;
            }
            return retval;
      }
}