using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Sample6_CreateFileHooking
{
    public static class Program
    { 
        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        static extern TCreateFile GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32.dll")]
        static extern void SetLastError(uint dwErrCode);

        public const Int32 ERROR_FILE_NOT_FOUND = 2;

        public delegate uint TCreateFile(
            [MarshalAs(UnmanagedType.LPWStr)]string lpFileName,
            [MarshalAs(UnmanagedType.U4)]int dwDesiredAccess,
            [MarshalAs(UnmanagedType.U4)]int dwShareMode,
            IntPtr lpSecurityAttributes,
            [MarshalAs(UnmanagedType.U4)]int dwCreationDisposition,
            [MarshalAs(UnmanagedType.U4)]int dwFlagsAndAttributes,
            IntPtr hTemplateFile);

        static TCreateFile pCreateFileW = null;

        static uint My_CreateFileW(
            [MarshalAs(UnmanagedType.LPWStr)]string lpFileName,
            [MarshalAs(UnmanagedType.U4)]int dwDesiredAccess,
            [MarshalAs(UnmanagedType.U4)]int dwShareMode,
            IntPtr lpSecurityAttributes,
            [MarshalAs(UnmanagedType.U4)]int dwCreationDisposition,
           [MarshalAs(UnmanagedType.U4)]int dwFlagsAndAttributes,
            IntPtr hTemplateFile)
        {
            if (lpFileName.Contains(@"\1.txt"))
            {
                SetLastError(ERROR_FILE_NOT_FOUND);
                return 0xFFFFFFFF;
            }
            return pCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
                        dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
        }


        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {            
            BoxedAppSDK.NativeMethods.BoxedAppSDK_Init();
            pCreateFileW = GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateFileW");
            
            IntPtr hookCreateFileW =
                    BoxedAppSDK.NativeMethods.BoxedAppSDK_HookFunction(pCreateFileW, new TCreateFile(My_CreateFileW), true);

            pCreateFileW = (TCreateFile)BoxedAppSDK.NativeMethods.BoxedAppSDK_GetOriginalFunction(hookCreateFileW, typeof(TCreateFile));            
            
            try
            {
                System.IO.File.WriteAllText(Application.StartupPath+ "\\1.txt", "some data...");
            }
            catch (Exception ex)
            {
                MessageBox.Show("It works! You got exception:\r\n " + ex.Message);
            }

            BoxedAppSDK.NativeMethods.BoxedAppSDK_UnhookFunction(hookCreateFileW);            
        }
    }
}