program Sample01_CreateFileHooking;

uses
  Forms,
  BoxedAppSDK_Static in '..\..\!Common\BoxedAppSDK_Static.pas', 
  Windows, SysUtils, Classes;

{$R *.RES}

type
TCreateFileW =
   function(lpFileName: PWideChar;
            dwDesiredAccess, dwShareMode: Integer;
            lpSecurityAttributes: PSecurityAttributes;
            dwCreationDisposition, dwFlagsAndAttributes: DWORD;
            hTemplateFile: THandle): THandle; stdcall;

type
TCreateFileA =
   function(lpFileName: PAnsiChar;
            dwDesiredAccess, dwShareMode: Integer;
            lpSecurityAttributes: PSecurityAttributes;
            dwCreationDisposition, dwFlagsAndAttributes: DWORD;
            hTemplateFile: THandle): THandle; stdcall;

var
   OriginalCreateFileA: TCreateFileA;
   OriginalCreateFileW: TCreateFileW;

function My_CreateFileA(
         lpFileName: PAnsiChar;
         dwDesiredAccess, dwShareMode: Integer;
         lpSecurityAttributes: PSecurityAttributes;
         dwCreationDisposition, dwFlagsAndAttributes: DWORD;
         hTemplateFile: THandle): THandle; stdcall;
begin
   if 0 = lstrcmpiA(lpFileName, '1.txt') then
   begin
      Result := INVALID_HANDLE_VALUE;
      SetLastError(ERROR_ALREADY_EXISTS);
   end
   else
      Result :=
        OriginalCreateFileA(
           lpFileName,
           dwDesiredAccess,
           dwShareMode,
           lpSecurityAttributes,
           dwCreationDisposition,
           dwFlagsAndAttributes,
           hTemplateFile);
end;

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
   pCreateFileA: Pointer;
   pCreateFileW: Pointer;
   hHook__CreateFileA: THandle;
   hHook__CreateFileW: THandle;

begin
  Application.Initialize;

  BoxedAppSDK_Init;
  // Hook CreateFileA
  pCreateFileA := GetProcAddress(GetModuleHandle('kernel32.dll'), 'CreateFileA');
  hHook__CreateFileA := BoxedAppSDK_HookFunction(pCreateFileA, @My_CreateFileA, TRUE);
  OriginalCreateFileA := BoxedAppSDK_GetOriginalFunction(hHook__CreateFileA);

  // Hook CreateFileW
  pCreateFileW := GetProcAddress(GetModuleHandle('kernel32.dll'), 'CreateFileW');
  hHook__CreateFileW := BoxedAppSDK_HookFunction(pCreateFileW, @My_CreateFileW, TRUE);
  OriginalCreateFileW := BoxedAppSDK_GetOriginalFunction(hHook__CreateFileW);

  MessageBox(0, 'The sample shows how to prevent creating a file "1.txt"' + #13#10 + 'We hook function kernel32.dll!CreateFileW and return INVALID_HANDLE_VALUE when "1.txt" passed as a path. ' + #13#10 + 'Click to OK to test: it will produce an exception' + #13#10 + 'Click to Cancel to exit', 'Sample01_CreateFileHooking ', MB_OK);

  TFileStream.Create('1.txt', fmCreate or fmOpenRead);

  BoxedAppSDK_UnhookFunction(hHook__CreateFileA);
  BoxedAppSDK_UnhookFunction(hHook__CreateFileW);
end.
