title: Delphi - hook\bypass\catch all the OutputDebugString from the system into my application with process id and name
body: <p>Based on <a href="https://stackoverflow.com/questions/6384785/how-can-i-receive-outputdebugstring-from-service">this question</a> I've created a small application which is catching all debug strings into my application. Code of the thread is shown below.</p>
  
  <p>I want to get the process id and its name for each debug string I got. After I've made some research I got <a href="http://philondev.blogspot.ro/2009/12/monitoring-outputdebugstring-on-windows.html" rel="nofollow noreferrer">this article</a> where it says: "The first 4 bytes (32-bit DWORD) is the process ID of the process that wrote the text using OutputDebugString.". I have tried to get the process by calling the functions below, but the result is null.</p>
  
  <pre><code>TempString := '';
  CopyMemory(PChar(TempString), SharedMemory, sizeof(SharedMemory)); // - returns 0....
  TempString := String(PAnsiChar(SharedMemory) + SizeOf(DWORD));
  </code></pre>
  
  <p>I do not know what it is wrong.</p>
  
  <p>Also is it possible to get the name of the process which has sent the debug string?</p>
  
  <p>Thread code:</p>
  
  <pre><code>interface
  
  uses Classes,
       windows,
       Forms,
       StdCtrls,
       SysUtils;
  
  type
    TDebugStringThread = class(TThread)
      private
        FMemo : TMemo;
      protected
        procedure Execute; override;
        procedure DoShowData;
        procedure DoShowErrors;
      public
       constructor Create(aMemo : TMemo);
    end;
  
  implementation
  
  var SharedMessage: string;
      ErrsMess      : String;
  
  constructor TDebugStringThread.Create(aMemo: TMemo);
  begin
    FMemo := aMemo;
    FreeOnTerminate := True;
    inherited Create(False);
  end;
  
  procedure TDebugStringThread.DoShowData;
  begin
   FMemo.Lines.Add(SharedMessage);
  end;
  
  procedure TDebugStringThread.DoShowErrors;
  begin
   FMemo.Lines.Add('Error ' + ErrsMess);
   ErrsMess := '';
  end;
  
  procedure TDebugStringThread.Execute;
  var SharedMem: Pointer;
      SharedFile: THandle;
      WaitingResult: DWORD;
      DataReadyEvent: THandle;
      BufferReadyEvent: THandle;
      SecurityAttributes: SECURITY_ATTRIBUTES;
      SecurityDescriptor: SECURITY_DESCRIPTOR;
      SharedMemory : Pointer;
      TempString : String;
  begin
    ErrsMess := '';
  
    SecurityAttributes.nLength := SizeOf(SECURITY_ATTRIBUTES);
    SecurityAttributes.bInheritHandle := True;
    SecurityAttributes.lpSecurityDescriptor := @SecurityDescriptor;
  
    if not InitializeSecurityDescriptor(@SecurityDescriptor,       SECURITY_DESCRIPTOR_REVISION) then
      Exit;
  
    if not SetSecurityDescriptorDacl(@SecurityDescriptor, True, nil, False) then
      Exit;
  
    BufferReadyEvent := CreateEvent(@SecurityAttributes, False, True, 'DBWIN_BUFFER_READY');
  
    if BufferReadyEvent = 0 then
      Exit;
  
    DataReadyEvent := CreateEvent(@SecurityAttributes, False, False, 'DBWIN_DATA_READY');
  
    if DataReadyEvent = 0 then
      Exit;
  
    SharedFile := CreateFileMapping(THandle(-1), @SecurityAttributes, PAGE_READWRITE, 0, 4096, 'Global\DBWIN_BUFFER');
  
    if SharedFile = 0 then
    begin
      ErrsMess := SysErrorMessage(GetLastError);
      Synchronize(DoShowErrors);
      Exit;
    end;
  
    SharedMem    := MapViewOfFile(SharedFile, FILE_MAP_READ,  0, 0, 512);
    SharedMemory := MapViewOfFile(SharedFile, SECTION_MAP_READ, 0, 0, 1024);
  
    if not Assigned(SharedMem) then
    begin
      ErrsMess := SysErrorMessage(GetLastError);
      Synchronize(DoShowErrors);
      Exit;
    end;
  
    if not Assigned(SharedMemory) then
    begin
      ErrsMess := SysErrorMessage(GetLastError);
      Synchronize(DoShowErrors);
    end;
  
    while (not Terminated) and (not Application.Terminated) do
      begin
        SetEvent(BufferReadyEvent);
        WaitingResult := WaitForSingleObject(DataReadyEvent, INFINITE);
  
        case WaitingResult of
          WAIT_TIMEOUT: Continue;
          WAIT_OBJECT_0:
            begin
            try
              TempString := '';
              //CopyMemory(PChar(TempString), SharedMemory, sizeof(SharedMemory)); // - returns 0....
              TempString := String(PAnsiChar(SharedMemory) + SizeOf(DWORD));
              SharedMessage := TempString + ' ' + String(PAnsiChar(SharedMem) + SizeOf(DWORD));
              Synchronize(DoShowData);
            finally
            end;
            end;
  
         WAIT_FAILED: Continue;
       end;
     end;
  
     UnmapViewOfFile(SharedMem);
     CloseHandle(SharedFile);
  end;
  </code></pre>
  
  <p>end.</p>