Im having a bit of trouble with a dll that uses memory mapped files. Since my application must receive key presses when out of focus, I used a small bit of delphi code I found on the net to build a keyhook. The dll in in the apps resources as a piece of rcdata, and is unpacked to a temporary file, then loaded, and finally deleted when the app is done. Or it should be. If I just open the app, then close it, the file is deleted fine. But if I trigger a keypress, then close it, nu-uh. After reading the sdk doc for DeleteFile, I figured it was the memory mapped files doing this. But I cant figure what I am doing wrong. Heres the applicable code:
{ Dll loading code }
var
DllHandle, MemFile: THandle;
Receiver: PHandle;
HookOn, HookOff: procedure; stdcall;
...
MemFile := CreateFileMapping($FFFFFFF
F, nil, PAGE_READWRITE, 0, SizeOf(Integer), 'KeyReceiver');
if (MemFile = 0) then
raise Exception.Create('Error while creating file');
Receiver := MapViewOfFile(MemFile, FILE_MAP_WRITE, 0, 0, 0);
Receiver^ := Handle;
// Load the keyhook
DllHandle := LoadLibrary(PChar(DllFile)
); //DllFile contains the temp name
if DllHandle = 0 then
raise Exception.Create('Unable to load the required DLL');
@HookOn := GetProcAddress(DllHandle, '_HookOn@0');
@HookOff := GetProcAddress(DllHandle, '_HookOff@0');
if (not Assigned(HookOn)) or (not Assigned(HookOff)) then
raise Exception.Create('Unable to locate the required DLL functions');
HookOn;
Heres the DLL init code:
HHOOK Keybrd;
HANDLE MemFile, DllInst;
HWND *Receiver;
...
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DllInst = hModule;
MemFile = OpenFileMapping(FILE_MAP_R
EAD, FALSE, "KeyReceiver");
if (MemFile != 0)
Receiver = MapViewOfFile(MemFile, FILE_MAP_READ, 0, 0, 0);
break;
case DLL_PROCESS_DETACH:
if (MemFile != 0) {
UnmapViewOfFile(Receiver);
CloseHandle(MemFile);
}
break;
}
Hook activation code:
Keybrd = SetWindowsHookEx(WH_KEYBOA
RD, &HookCallBack, DllInst, 0);
Deactivation code:
UnhookWindowsHookEx(Keybrd
);
The code to send a message to the app:
if (Code == HC_ACTION)
PostMessage(*Receiver, CM_SEND_KEY, wParam, lParam);
return CallNextHookEx(Keybrd, Code, wParam, lParam);
And the code that frees the apps vars and deletes (or tries to) the dll:
if Assigned(HookOff) then
HookOff;
if (DllHandle > 0) then
FreeLibrary(DllHandle);
if (MemFile > 0) then begin
UnmapViewOfFile(Receiver);
CloseHandle(MemFile);
end;
if FileExists(DllFile) then
DeleteFile(DllFile);
The most I can find is that windows reports Access is denied when it tries to delete the file (if I have pressed a key, if not, it deletes fine). Also, the file can be deleted manually once the app is closed.
If any more info is needed, just say.
Thanks!