I want to find out when any file on the machine is closed.
These shell change notifiers don't seem to work very well so I am thinking about hooking the CloseHandle API.
Am I going about this the right way ?
Also is there any way to find out if a THandle is a file handle and if so how to get the filename from it.
Another thing, what happens if someone else's program also hooks the same API ?
Thanks for any help.
Hook when any file is closed
I have just come to the same conclusion. Hook all versions of CreateFile and keep a list of Handles. Then hook CloseHandle and if its in my list I send IPC to my app with the filename. I have a working test program now.
My big worry is that I assume CloseHandle will be used rather a lot for many things so will it slow the system down to be scanning my list of handles every time it gets called ?
It would be interesting to see your code.
Also what happens of some other app decides to try and hook these API calls also ?
My big worry is that I assume CloseHandle will be used rather a lot for many things so will it slow the system down to be scanning my list of handles every time it gets called ?
It would be interesting to see your code.
Also what happens of some other app decides to try and hook these API calls also ?
My hook isn't systemwide, I hook only ONE specific app. So I don't know about overhead, although I think you may be right that IS quite an overhead! And you may experience a systemlockups, as your app will prolly use CreateFile too. Also, my code only hooks CreateFileA. For a systemwide hook, you may need to hook CreateFileW as well. Anyhow, here is the code - I hope you find it useful.
I use an initialization unit, that sets the global var Closing. Without this variable, the code will crash when you exit the targetapp. This unit is also responsible for creating and freeing the list of files.
Code: Select all
library Hook;
uses
Windows,
Classes,
SysUtils,
madCodeHook,
madStrings,
HookInit;
{$R *.res}
var
CreateFileNext: function(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
hTemplateFile: THandle): DWORD; stdcall;
CloseHandleNext: function(hObject: THandle): BOOL; stdcall;
function CreateFileCallback(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
hTemplateFile: THandle): DWORD; stdcall;
begin
Result :=
CreateFileNext(lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
if not Closing then
if IsTextEqual(ExtractFilePath(lpFileName), SaveDir) then
if Files.IndexOfObject(TObject(Result)) < 0 then
Files.AddObject(lpFileName, TObject(Result));
end;
function CloseHandleCallback(hObject: THandle): BOOL; stdcall;
var
I: Integer;
begin
if not Closing then
begin
I := Files.IndexOfObject(TObject(hObject));
if I >= 0 then
begin
StrPCopy(MessageBuf.FileName, Files.Strings[I]);
MessageBuf.FileHandle := DWORD(Files.Objects[I]);
Files.Delete(I);
SendIpcMessage(DLLName, @MessageBuf, SizeOf(MessageBuf));
end;
end;
Result := CloseHandleNext(hObject);
end;
begin
HookAPI('kernel32.dll', 'CreateFileA', @CreateFileCallback, @CreateFileNext);
HookAPI('kernel32.dll', 'CloseHandle', @CloseHandleCallback, @CloseHandleNext);
end.
Code: Select all
unit HookInit;
interface
uses
Windows, Classes, SysUtils, AnotherUnit;
type
TMessageBuf = record
FileName: array [0..MAX_PATH] of Char;
FileHandle: DWORD;
end;
const
DLLName = 'Hook.dll';
var
Files: TStringList;
MessageBuf: TMessageBuf;
SaveDir: string;
Closing: Boolean;
implementation
initialization
Closing := False;
Files := TStringList.Create;
SaveDir := IncludeTrailingPathDelimiter(AnotherUnit.GetDir);
finalization
Closing := True;
Files.Free;
end.
When hooking APIs like CreateFile + CloseHandle system wide you have to very careful with what you do. Performance might be a problem, if your hook callback functions do too much work. The hook itself should not be a problem, though. Please make sure that you follow all hooking rules (see madCodeHook documentation). Also don't transport each and every call via SendIpcMessage. madCodeHook's IPC message functions do work, but they're not the fasting thing on earth.