library HookFunc;

uses
  SysUtils, Types, Windows, WinSock, Classes;

type
  TCAPIINFO = record
  module_name,func, c_func_name:PChar;
  end;
{$R *.res}
var
  c_api_info:array[1..5] of TCAPIINFO;

function cSocket(af:integer; stype:integer; protocol:integer):integer;stdcall;
var
  ret:integer;
  err:integer;
  p:PChar;
  temp:String;
  temp1:array[1..256] of Char;
  i:integer;
begin

  temp :='af='+IntToStr(af)+',type='+IntToStr(stype)+',protocol='+IntToStr(protocol)+#0;
  for i:=1 to Length(temp) do
    temp1[i] :=temp[i];
  p :=@temp1;
  MessageBox(0, p, 'HookFunc-cSocket', MB_OK);

  ret :=socket(af, stype, protocol);

  err :=WSAGetLastError(); //GetLastError()
  temp :='socket ok. ret='+IntToStr(ret)+',err='+IntToStr(err)+#0;
  for i:=1 to Length(temp) do
    temp1[i] :=temp[i];
  p :=@temp1;
  MessageBox(0, p, 'HookFunc-cSocket', MB_OK);

  WSASetLastError(err);
  Result := ret;
end;

function cConnect(s:integer; name:PSockAddrIn; namelen:integer):DWORD;stdcall;
var
  ret:integer;
  err:integer;
  temp:String;
  temp1:array[1..256] of Char;
  p:PChar;
  i:integer;
begin

  temp :='s='+IntToStr(s)+',port='+IntToStr(ntohs(name.sin_port))+',addr='+Inet_Ntoa(name.sin_addr)+',namelen='+IntToStr(namelen)+#0;
  for i:=1 to Length(temp) do
    temp1[i] :=temp[i];
  p :=@temp1;
  MessageBox(0, p, 'HookFunc-cConnect', MB_OK);

  ret :=connect(s, name^, namelen);
  err :=WSAGetLastError();
  temp :='ret='+IntToStr(ret)+',err='+IntToStr(err)+#0;
  for i:=1 to Length(temp) do
    temp1[i] :=temp[i];
  p :=@temp1;
  MessageBox(0, p, 'HookFunc-cConnect', MB_OK);
  WSASetLastError(err);
  Result := DWORD(ret);
end;

function cRecv(s:integer; buf:PChar; len:integer; flags:integer):DWORD;stdcall;
var
  p:PChar;
  temp:String;
  temp1:array[1..256] of Char;
  buf_temp:array[1..5000] of Char;
  i,ret,err:integer;
begin

  err :=0;
  if len >4096 then
    len :=4096;

  ret :=recv(s, buf_temp, len, flags);
  if ret <=0 then
  begin
    err :=WSAGetLastError();
    temp :='ret='+IntToStr(DWORD(ret))+',err='+IntToStr(err)+#0;
    for i:=1 to Length(temp) do
      temp1[i] :=temp[i];
    p :=@temp1;
    MessageBox(0, p, 'HookFunc-cRecv', MB_OK);
  end;
  if ret >0 then
  begin
    for i :=1 to ret do
    begin
      (buf+i-1)^ :=buf_temp[i];
    end;
  end;
  MessageBox(0, 'cRecv ok', 'cRecv', MB_OK);

  // For the binary data, please do not show as below
  //MessageBox(0, buf, 'cRecv', MB_OK);
  if ret <=0 then
    WSASetLastError(err);
  result :=DWORD(ret);
end;

function cSend(s:integer; buf:PChar; len:integer; flags:integer):DWORD;stdcall;
var
  p:PChar;
  temp:String;
  temp1:array[1..256] of Char;
  buf_temp:array[1..4096] of Char;
  i,ret,err:integer;
begin

  for i :=1 to len do
  begin
    buf_temp[i] :=(buf+i-1)^;
  end;
  //if len >4096...
  ret :=send(s, buf_temp, len, flags);
  err :=WSAGetLastError();
  //MessageBox(0, 'send ok', 'cSend', MB_OK);
  temp :='ret='+IntToStr(ret)+',err='+IntToStr(err)+#0;
  for i:=1 to Length(temp) do
    temp1[i] :=temp[i];
  p :=@temp1;
  MessageBox(0, p, 'HookFunc-cSend', MB_OK);
  WSASetLastError(err);
  result :=DWORD(ret);
end;

Function GetCAPIINFO():Pointer;stdCall;
begin
	GetCAPIINFO :=Addr(c_api_info);
end;

exports
  GetCAPIINFO,
  cSocket,
  cConnect,
  cSend,
  cRecv;

begin
  c_api_info[1].module_name :='WSOCK32.DLL';
  c_api_info[1].func :='socket(integer, integer, integer)';
  c_api_info[1].c_func_name :='cSocket';
  c_api_info[2].module_name :='WSOCK32.DLL';
  c_api_info[2].func :='connect(integer, sockaddr_in, integer)';
  c_api_info[2].c_func_name :='cConnect';
  c_api_info[3].module_name :='WSOCK32.DLL';
  c_api_info[3].func :='send(SOCKET, anyname, int, int)';
  c_api_info[3].c_func_name :='cSend';
  c_api_info[4].module_name :='WSOCK32.DLL';
  c_api_info[4].func :='recv(SOCKET, buf, int, int)';
  c_api_info[4].c_func_name :='cRecv';
  c_api_info[5].module_name :=nil;
  c_api_info[5].func :=nil;
  c_api_info[5].c_func_name :=nil;
end.

