When injecting a DLL into other processes,
your DLL usually needs to contact your base application somehow. This can be
quite a difficult task, because you have to communicate over process
boundaries here. The easiest way to do such IPC (inter process communication)
is to use the message APIs like FindWindow + PostMessage. Unfortunately
messages may not work inside of non interactive service/system processes.
So we need different methods to build up a reliable IPC
connection. Since this is a quite basic problem which will touch most
madCodeHook users, I've decided to add some nice and easy to use IPC
functions to madCodeHook.
Let's say your application injects a DLL into all processes system wide. Now
the DLL(duplicate)s loaded into all the different processes want to contact
your application and send some information. Maybe the DLLs even want to get
an answer from the application. This all can be realized easily by using
madCodeHook's IPC functionality. Before injecting the DLL, the application
should create an IPC queue, giving in a unique IPC name and an appropriate
IPC message handling function. This function will later be called for each
incoming message.
CAUTION: When using the default parameters each IPC message is handled by a
seperate thread, as a result your handler will be called in the context of a
different thread each time. This is has some advantages and some
disadvantages. One problem is that when using multiple threads Windows' time
scheduler will do whatever it likes. This may result in that the order of
the incoming messages is slightly different to how they were sent. If that
is a problem for you, please specifiy a maximum thread count of "1". This
will make sure that the order of the messages stays the same.
 |
type
TIpcCallback = procedure (name : pchar;
messageBuf : pointer;
messageLen : dword;
answerBuf : pointer;
answerLen : dword;
context : pointer); stdcall;
function CreateIpcQueue (ipc : pchar;
callback : TIpcCallback;
context : pointer = nil;
maxThreadCount : dword = 16;
maxQueueLen : dword = $1000) : bool; stdcall;
function DestroyIpcQueue (ipc: pchar) : bool; stdcall;
procedure GetMsgFromDLL(name : pchar;
messageBuf : pointer; messageLen : dword;
answerBuf : pointer; answerLen : dword;
context : pointer); stdcall;
begin
boolean(answerBuf^) := MessageBox(0, pchar(messageBuf), 'question', MB_YESNO) = ID_YES;
end;
initialization
CreateIpcQueue('JustAnExample', GetMsgFromDLL);
end.
|
|
In order to send an IPC message to the application, the DLL just needs to
call "SendIpcMessage". If no answer is needed, only the first 3 parameters
need to be filled. If the message sender wants to get a reply, it can
specify a wait timeout value. Also it can specify whether the current thread
shall handle window messages while waiting for the IPC message answer.
If you call SendIpcMessage in the initialization (DLL_PROCESS_ATTACH) of a
hook dll, then please set "handleMessages" to false. Because otherwise your
hook dll might eat DDE messages. Besides, during hook dll initialization
it doesn't make much sense to handle messages while waiting, anyway.
 |
function SendIpcMessage(ipc : pchar;
messageBuf : pointer;
messageLen : dword;
answerBuf : pointer = nil;
answerLen : dword = 0;
answerTimeOut : dword = INFINITE;
handleMessages : bool = true ) : bool; stdcall;
function AskApplication(question: string) : boolean;
begin
result := false;
SendIpcMessage('JustAnExample', pchar(question), Length(question), @result, sizeOf(result));
end;
|
|