using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace BoxedAppSDK
{
    internal sealed class NativeMethods
    {
		[DllImport("BoxedAppSDK.dll")]
        internal static extern bool BoxedAppSDK_Init();

		[DllImport("BoxedAppSDK.dll")]
		internal static extern void BoxedAppSDK_Exit();

		[Flags]
			public enum EFileAccess : uint
		{
			/// <summary>
			/// 
			/// </summary>
			GenericRead = 0x80000000,
			/// <summary>
			/// 
			/// </summary>
			GenericWrite = 0x40000000,
			/// <summary>
			/// 
			/// </summary>
			GenericExecute = 0x20000000,
			/// <summary>
			/// 
			/// </summary>
			GenericAll = 0x10000000
		}

		[Flags]
			public enum EFileShare : uint
		{
			/// <summary>
			/// 
			/// </summary>
			None = 0x00000000,
			/// <summary>
			/// Enables subsequent open operations on an object to request read access. 
			/// Otherwise, other processes cannot open the object if they request read access. 
			/// If this flag is not specified, but the object has been opened for read access, the function fails.
			/// </summary>
			Read = 0x00000001,
			/// <summary>
			/// Enables subsequent open operations on an object to request write access. 
			/// Otherwise, other processes cannot open the object if they request write access. 
			/// If this flag is not specified, but the object has been opened for write access, the function fails.
			/// </summary>
			Write = 0x00000002,
			/// <summary>
			/// Enables subsequent open operations on an object to request delete access. 
			/// Otherwise, other processes cannot open the object if they request delete access.
			/// If this flag is not specified, but the object has been opened for delete access, the function fails.
			/// </summary>
			Delete = 0x00000004
		}

		public enum ECreationDisposition : uint
		{
			/// <summary>
			/// Creates a new file. The function fails if a specified file exists.
			/// </summary>
			New = 1,
			/// <summary>
			/// Creates a new file, always. 
			/// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, 
			/// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
			/// </summary>
			CreateAlways = 2,
			/// <summary>
			/// Opens a file. The function fails if the file does not exist. 
			/// </summary>
			OpenExisting = 3,
			/// <summary>
			/// Opens a file, always. 
			/// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
			/// </summary>
			OpenAlways = 4,
			/// <summary>
			/// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
			/// The calling process must open the file with the GENERIC_WRITE access right. 
			/// </summary>
			TruncateExisting = 5
		}

		[Flags]
			public enum EFileAttributes : uint
		{
			Readonly         = 0x00000001,
			Hidden           = 0x00000002,
			System           = 0x00000004,
			Directory        = 0x00000010,
			Archive          = 0x00000020,
			Device           = 0x00000040,
			Normal           = 0x00000080,
			Temporary        = 0x00000100,
			SparseFile       = 0x00000200,
			ReparsePoint     = 0x00000400,
			Compressed       = 0x00000800,
			Offline          = 0x00001000,
			NotContentIndexed= 0x00002000,
			Encrypted        = 0x00004000,
			Write_Through    = 0x80000000,
			Overlapped       = 0x40000000,
			NoBuffering      = 0x20000000,
			RandomAccess     = 0x10000000,
			SequentialScan   = 0x08000000,
			DeleteOnClose    = 0x04000000,
			BackupSemantics  = 0x02000000,
			PosixSemantics   = 0x01000000,
			OpenReparsePoint = 0x00200000,
			OpenNoRecall     = 0x00100000,
			FirstPipeInstance= 0x00080000
		}	

		[DllImport("BoxedAppSDK.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern IntPtr BoxedAppSDK_CreateVirtualFile(
			string lpFileName,
			EFileAccess dwDesiredAccess,
			EFileShare dwShareMode,
			IntPtr lpSecurityAttributes,
			ECreationDisposition dwCreationDisposition,
			EFileAttributes dwFlagsAndAttributes,
			IntPtr hTemplateFile);

		internal delegate UInt32 FileProc(IntPtr Param, UInt32 Command, IntPtr Info);

		[DllImport("BoxedAppSDK.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern IntPtr BoxedAppSDK_CreateVirtualFileEx(
			string lpFileName,
			EFileAccess dwDesiredAccess,
			EFileShare dwShareMode,
			IntPtr lpSecurityAttributes,
			ECreationDisposition dwCreationDisposition,
			EFileAttributes dwFlagsAndAttributes,
			IntPtr hTemplateFile, 
			IntPtr Param, 
			FileProc pFileProc);

		public const UInt32 DEF_FILEPROC_COMMAND_CREATE_CONTEXT = 1;
		public const UInt32 DEF_FILEPROC_COMMAND_DELETE_CONTEXT = 2;
		public const UInt32 DEF_FILEPROC_COMMAND_READ = 3;
		public const UInt32 DEF_FILEPROC_COMMAND_WRITE = 4;
		public const UInt32 DEF_FILEPROC_COMMAND_SEEK = 5;
		public const UInt32 DEF_FILEPROC_COMMAND_GETSIZE = 6;

		[StructLayout(LayoutKind.Sequential)] 
		internal struct SFileProcCreateContext
		{
			public IntPtr m_pContext;
		}

		[StructLayout(LayoutKind.Sequential)] 
		internal struct SFileProcDeleteContext
		{
			public IntPtr m_pContext;
		}

		[StructLayout(LayoutKind.Sequential)] 
		internal struct SFileProcRead
		{
			public IntPtr m_pContext;

			public IntPtr m_pBuffer;
			public UInt32 m_dwBufferSize;
			public UInt32 m_nReadBytes;
			public Int32 m_bRes;
		}

		[StructLayout(LayoutKind.Sequential)] 
		internal struct SFileProcWrite
		{
			public IntPtr m_pContext;

			public IntPtr m_pBuffer;
			public UInt32 m_dwBufferSize;
			public UInt32 m_nWrittenBytes;
			public Int32 m_bRes;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct LARGE_INTEGER
		{
			public UInt32 LowPart;
			public UInt32 HighPart;
		}

		[StructLayout(LayoutKind.Sequential)] 
		internal struct SFileProcSeek
		{
			public IntPtr m_pContext;

			public LARGE_INTEGER m_Distance;
			public UInt32 m_dwMoveMethod;
			public LARGE_INTEGER m_NewPos;
			public Int32 m_bRes;
		}

		[StructLayout(LayoutKind.Sequential)] 
		internal struct SFileProcGetSize
		{
			public IntPtr m_pContext;

			public LARGE_INTEGER m_Size;
		}

		[DllImport("BoxedAppSDK.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern int BoxedAppSDK_RegisterCOMLibraryInVirtualRegistry(string lpFileName);
	
        [DllImport("BoxedAppSDK.dll", SetLastError = true, CharSet = CharSet.Ansi)]
        internal static extern void BoxedAppSDK_SetContext(string code);

		public const UInt32 DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL = 1;
	
        [DllImport("BoxedAppSDK.dll", SetLastError = true)]
        internal static extern void BoxedAppSDK_EnableOption(UInt32 dwOptionIndex, bool bEnable);

        [DllImport("BoxedAppSDK.dll", SetLastError = true)]
        internal static extern bool BoxedAppSDK_IsOptionEnabled(UInt32 dwOptionIndex);

		[DllImport("BoxedAppSDK.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern IntPtr BoxedAppSDK_CreateVirtualFileBasedOnIStream(
			string lpFileName,
			EFileAccess dwDesiredAccess,
			EFileShare dwShareMode,
			IntPtr lpSecurityAttributes,
			ECreationDisposition dwCreationDisposition,
			EFileAttributes dwFlagsAndAttributes,
			IntPtr hTemplateFile, 
			IStream Stream);
	}

    //// Summary:
    ////     Contains statistical information about an open storage, stream, or byte-array
    ////     object.
    //public struct STATSTG
    //{
    //    // Summary:
    //    //     Specifies the last access time for this storage, stream, or byte array. 
    //    public FILETIME atime;
    //    //
    //    // Summary:
    //    //     Specifies the size, in bytes, of the stream or byte array.
    //    public long cbSize;
    //    //
    //    // Summary:
    //    //     Indicates the class identifier for the storage object.
    //    public Guid clsid;
    //    //
    //    // Summary:
    //    //     Indicates the creation time for this storage, stream, or byte array.
    //    public FILETIME ctime;
    //    //
    //    // Summary:
    //    //     Indicates the types of region locking supported by the stream or byte array.
    //    public int grfLocksSupported;
    //    //
    //    // Summary:
    //    //     Indicates the access mode that was specified when the object was opened.
    //    public int grfMode;
    //    //
    //    // Summary:
    //    //     Indicates the current state bits of the storage object (the value most recently
    //    //     set by the IStorage::SetStateBits method).
    //    public int grfStateBits;
    //    //
    //    // Summary:
    //    //     Indicates the last modification time for this storage, stream, or byte array.
    //    public FILETIME mtime;
    //    //
    //    // Summary:
    //    //     Represents a pointer to a null-terminated string containing the name of the
    //    //     object described by this structure.
    //    public string pwcsName;
    //    //
    //    // Summary:
    //    //     Reserved for future use.
    //    public int reserved;
    //    //
    //    // Summary:
    //    //     Indicates the type of storage object, which is one of the values from the
    //    //     STGTY enumeration.
    //    public int type;
    //}

    //[ComImport, Guid("0000000c-0000-0000-C000-000000000046"),
    //InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    //public interface IStream
    //{
    //    void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);
    //    void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);
    //    void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);
    //    void SetSize(long libNewSize);
    //    void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);
    //    void Commit(int grfCommitFlags);
    //    void Revert();
    //    void LockRegion(long libOffset, long cb, int dwLockType);
    //    void UnlockRegion(long libOffset, long cb, int dwLockType);
    //    void Stat(out STATSTG pstatstg, int grfStatFlag);
    //    void Clone(out IStream ppstm);
    //}
}
