What's Wrong with Detours?
Detours is a developer library provided by Microsoft to hook (re-routing) functions, so you can intercept all calls to, for example, CreateFile in an application.
Unfortunately, the free version of Detours supports 32-bit applications only. If one needs to work with 64-bit code, Detours Professional Edition is available, and it costs $10000.
BoxedApp SDK to the Rescue
BoxedApp SDK provides other means to hook functions; both 32-bit and 64-bit code are supported. There are a lot of bindings: for C++, C#, VB.Net, VB6, Delphi, and others.
Take a look at the following code, which demonstrates how to prevent the opening of a file with a certain name:
typedef HANDLE (WINAPI *P_CreateFileW)( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); P_CreateFileW g_pCreateFileW; HANDLE WINAPI My_CreateFileW( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { if (0 == lstrcmpiW(lpFileName, L"1.txt")) { SetLastError(ERROR_FILE_EXISTS); return INVALID_HANDLE_VALUE; } else return g_pCreateFileW( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } ... BoxedAppSDK_Init(); PVOID pCreateFileW = GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "CreateFileW"); HANDLE hHook__CreateFileW = BoxedAppSDK_HookFunction(pCreateFileW, &My_CreateFileW, TRUE); g_pCreateFileW = (P_CreateFileW)BoxedAppSDK_GetOriginalFunction(hHook__CreateFileW); FILE* f = fopen("1.txt", "r"); // f is NULL ... BoxedAppSDK_UnhookFunction(hHook__CreateFileW);
[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 IntPtr 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 IntPtr 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 new IntPtr(-1); } return pCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } ////// The main entry point for the application. /// [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); } }
type TCreateFileW = function(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: Integer; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; var OriginalCreateFileW: TCreateFileW; function My_CreateFileW( lpFileName: PWideChar; dwDesiredAccess, dwShareMode: Integer; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; begin if 0 = lstrcmpiW(lpFileName, '1.txt') then begin Result := INVALID_HANDLE_VALUE; SetLastError(ERROR_ALREADY_EXISTS); end else Result := OriginalCreateFileW( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); end; var pCreateFileW: Pointer; hHook__CreateFileW: THandle; begin Application.Initialize; BoxedAppSDK_Init; pCreateFileW := GetProcAddress(GetModuleHandle('kernel32.dll'), 'CreateFileW'); hHook__CreateFileW := BoxedAppSDK_HookFunction(pCreateFileW, @My_CreateFileW, TRUE); OriginalCreateFileW := BoxedAppSDK_GetOriginalFunction(hHook__CreateFileW); // This line produces an exception because we prevent creating / opening '1.txt' TFileStream.Create('1.txt', fmCreate or fmOpenRead); BoxedAppSDK_UnhookFunction(hHook__CreateFileW); end.