从winsock recv hook(PChar到AnsiString)保存缓冲区

时间:2014-07-13 03:27:28

标签: delphi

我知道这是一个愚蠢的问题,但有时候我真的陷入了这个Ansi / Unicode的事情,我尝试了每个该死的转换(PChar / AnsiString / PAnsiChar ....),但仍然无法读取缓冲区。这就是我的情况。我正在挂钩“recv”函数,我只是想将缓冲区内容保存到文件中,但我只将中文/不可读的字符存入该文件。我的回调函数是:

function Interceptrecv(s: TSocket;
            Buffer: Pointer;
            BuffLength: integer;
            Flags: integer): Integer; stdcall;
  var
    MyBuff: PChar;
    pFileHandle, dWrite: cardinal;
    sText: string;
  begin
    Result:= recvNext(s, Buffer, BuffLength, Flags);
    GetMem(MyBuff,sizeof(Buffer));
    ZeroMemory(MyBuff, sizeof(Buffer));
    CopyMemory(MyBuff,Buffer,sizeof(Buffer)-1);
    SetLength(sText, SizeOf(MyBuff));
    CopyMemory(@sText[1], MyBuff, SizeOf(MyBuff));
    pFileHandle := CreateFile(PChar('C:\' + 'log.txt'),GENERIC_WRITE,0,nil,OPEN_ALWAYS , FILE_ATTRIBUTE_NORMAL,0);
    if pFileHandle <> INVALID_HANDLE_VALUE then
    begin
      SetFilePointer(pFileHandle,0,nil, FILE_END);
      Windows.WriteFile(pFileHandle,sText,SizeOf(sText),dWrite,nil);
      CloseHandle(pFileHandle);
    end;
  end;

如何使这个缓冲区清晰可辨?

1 个答案:

答案 0 :(得分:2)

您的代码失败的原因是您完全滥用SizeOf()。您需要使用recvNext()的返回值:

function Interceptrecv(s: TSocket;
            Buffer: Pointer;
            BuffLength: integer;
            Flags: integer): Integer; stdcall;
  var
    MyBuff: PAnsiChar;
    pFileHandle: THandle;
    dWrite: DWORD;
    sText: AnsiString;
  begin
    Result := recvNext(s, Buffer, BuffLength, Flags);
    if Result <= 0 then Exit;
    GetMem(MyBuff, Result);
    try
      ZeroMemory(MyBuff, Result);
      CopyMemory(MyBuff, Buffer, Result);
      SetLength(sText, Result);
      CopyMemory(PAnsiChar(sText), MyBuff, Result);
      pFileHandle := CreateFile(PChar('C:\log.txt'), GENERIC_WRITE, 0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
      if pFileHandle <> INVALID_HANDLE_VALUE then
      begin
        SetFilePointer(pFileHandle, 0, nil, FILE_END);
        Windows.WriteFile(pFileHandle, PAnsiChar(sText), Result, dWrite, nil);
        CloseHandle(pFileHandle);
      end;
    finally
      FreeMem(MyBuff);
    end;
  end;

如果您的目的是按原样保存接收的数据,那么您已经使代码变得比它需要的更复杂。你在内存中制作的数据不是一份而是两份,这是浪费和不必要的。您可以将代码简化为以下内容:

function Interceptrecv(s: TSocket;
            Buffer: Pointer;
            BuffLength: integer;
            Flags: integer): Integer; stdcall;
  var
    pFileHandle: THandle;
    dWrite: DWORD;
  begin
    Result := recvNext(s, Buffer, BuffLength, Flags);
    if Result <= 0 then Exit;
    pFileHandle := CreateFile('C:\log.txt', FILE_APPEND_DATA, 0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if pFileHandle <> INVALID_HANDLE_VALUE then
    begin
      Windows.WriteFile(pFileHandle, Buffer^, Result, dWrite, nil);
      CloseHandle(pFileHandle);
    end;
  end;