You've all been such a great help here in the past I figured I'd post this one.
I've tried to dumb it down to an ultra-simple program, but it still seems to behave in an unexpected way.
Bug, or am I wrong?
Essentially, there is a hook and a monitor app. The hook looks for all data outgoing on winsock and sends it to the monitor app.
It works fine...EXCEPT...in the following situation:
In Outlook or Outlook Express, when you send an email where the total contents are greater than 8192 bytes, Outlook likes to chunk the data into bits of 8192. So, the sendHookProc will get called a certain number of times, each with len = 8192.
However, no matter how I try it, the data duplicates itself! In otherwords, some of the 8192 byte chunks come in twice!
Between each chunk I put a [~], so you can easily see where each chunk separates.
Here's the code...
Hook:
Code: Select all
library Simple;
uses madCodeHook;
var
sendNextHook: function(s: Integer; Buf: Pointer; len, flags: Integer): Integer; stdcall;
function sendHookProc(s: Integer; Buf: Pointer; len, flags : Integer): Integer; stdcall;
begin
SendIPCMessage('madIPC', PChar('[~]'), 3);
SendIPCMessage('madIPC', PChar(buf), len);
Result := sendNextHook(s, buf, len, flags);
end;
begin
HookAPI('ws2_32.dll', 'send', @sendHookProc, @sendNextHook);
end.
Code: Select all
unit Form1
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, madCodeHook, SyncObjs, ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
end;
var
Form1: TForm1;
TheStr: String;
TheLock: TCriticalSection;
implementation
{$R *.dfm}
procedure ProcessIPC(name: pchar; messageBuf: pointer; messageLen : dword; answerBuf : pointer; answerLen : dword); stdcall;
var
S: String;
begin
SetLength(S, messageLen);
CopyMemory(@S[1], messageBuf, MessageLen);
TheLock.Acquire;
try
TheStr := TheStr + S;
finally
TheLock.Release;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
TheLock.Acquire;
try
If Memo1.Text <> TheStr Then Begin
Memo1.Text := TheStr;
End;
finally
TheLock.Release;
end;
end;
initialization
CreateIpcQueue('madIPC', ProcessIPC);
TheLock := TCriticalSection.Create;
finalization
TheLock.free;
end.
Thanks so much in advance!
Gary