Looking for an alternative to windows messages used in inter-process communication

前端 未结 7 499
执念已碎
执念已碎 2020-12-08 03:51

I a have a multithread application (MIDAS) that makes uses of windows messages to communicate with itself.

MAIN FORM

The main form receives windows messages

相关标签:
7条回答
  • 2020-12-08 03:55

    The creators of the madExcept library etc provide IPC functionality which can be used instead of Windows messages.

    http://help.madshi.net/IPC.htm

    I developed a Windows screensaver at one stage, and I wanted to get my screensaver to send some notification to another program, and while the screensaver was active, I was unable to get window messages to work between the two apps.

    I replaced it with the IPC functionality mentioned above.

    Worked a treat.

    0 讨论(0)
  • 2020-12-08 03:58

    Windows Messages CAN still be used in Windows Vista! The issue at hand is that a technology in vista called User Interface Privilege Isolation (UIPI) prevents processes with a lower integrity level (IL) from sending messages to a proccess with a high IL (e.g. a windows service has a high IL and user-mode apps have medium IL).

    However, this can be bypassed and medium IL apps can be allowed to send wm's to high IL processes.

    Wikipedia says it best:

    UIPI is not a security boundary, and does not aim to protect against all shatter attacks. UI Accessibility Applications can bypass UIPI by setting their "uiAccess" value to TRUE as part of their manifest file. This requires the application to be in the Program Files or Windows directory, as well as to be signed by a valid code signing authority, but these requirements will not necessarily stop malware from respecting them.

    Additionally, some messages are still allowed through, such as WM_KEYDOWN, which allows a lower IL process to drive input to an elevated command prompt.

    Finally, the function ChangeWindowMessageFilter allows a medium IL process (all non-elevated processes except Internet Explorer Protected Mode) to change the messages that a high IL process can receive from a lower IL process. This effectively allows bypassing UIPI, unless running from Internet Explorer or one of its child processes.

    Someone over at Delphi-PRAXIS (link is in German. Use Google to Translate the page) has already tackled this problem and posted their code using ChangeWindowMessageFilter. I believe their issue is that WM_COPYDATA would not work on Vista until they modified their code to bypass UIPI for WM_COPYDATA.

    Original Link (German)

    unit uMain; 
    
    interface 
    
    uses 
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs, ExtCtrls, StdCtrls, uallHook, uallProcess, uallUtil, uallKernel; 
    
    type 
      TfrmMain = class(TForm) 
        lbl1: TLabel; 
        tmrSearchCondor: TTimer; 
        mmo1: TMemo; 
        procedure FormCreate(Sender: TObject); 
        procedure tmrSearchCondorTimer(Sender: TObject); 
        procedure FormDestroy(Sender: TObject); 
      private 
        { Private-Deklarationen } 
        fCondorPID : DWord; 
        fInjected : Boolean; 
        fDontWork : Boolean; 
        procedure SearchCondor; 
        procedure InjectMyFunctions; 
        procedure UnloadMyFunctions; 
        function GetDebugPrivileges : Boolean; 
        procedure WriteText(s : string); 
        procedure WMNOTIFYCD(var Msg: TWMCopyData); message WM_COPYDATA; 
      public 
        { Public-Deklarationen } 
      end; 
    
    var 
      frmMain: TfrmMain; 
      ChangeWindowMessageFilter: function (msg : Cardinal; dwFlag : Word) : BOOL; stdcall; 
    
    implementation 
    
    {$R *.dfm} 
    
    type Tmydata = packed record 
           datacount: integer; 
           ind: boolean; 
         end; 
    
    const cCondorApplication = 'notepad.exe'; 
          cinjComFuntionsDLL = 'injComFunctions.dll'; 
    
    var myData : TMydata; 
    
    procedure TfrmMain.WMNOTIFYCD(var Msg: TWMCopyData); 
    begin 
      if Msg.CopyDataStruct^.cbData = sizeof(TMydata) then 
      begin 
        CopyMemory(@myData,Msg.CopyDataStruct^.lpData,sizeof(TMyData)); 
        WriteText(IntToStr(mydata.datacount)) 
      end; 
    end; 
    
    procedure TfrmMain.WriteText(s : string); 
    begin 
      mmo1.Lines.Add(DateTimeToStr(now) + ':> ' + s); 
    end; 
    
    procedure TfrmMain.InjectMyFunctions; 
    begin 
      if not fInjected then begin 
        if InjectLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)) then fInjected := True; 
      end; 
    end; 
    
    procedure TfrmMain.UnloadMyFunctions; 
    begin 
      if fInjected then begin 
        UnloadLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)); 
        fInjected := False; 
      end; 
    end; 
    
    procedure TfrmMain.SearchCondor; 
    begin 
      fCondorPID := FindProcess(cCondorApplication); 
      if fCondorPID <> 0 then begin 
        lbl1.Caption := 'Notepad is running!'; 
        InjectMyFunctions; 
      end else begin 
        lbl1.Caption := 'Notepad isn''t running!'; 
      end; 
    end; 
    
    procedure TfrmMain.FormDestroy(Sender: TObject); 
    begin 
      UnloadMyFunctions; 
    end; 
    
    function TfrmMain.GetDebugPrivileges : Boolean; 
    begin 
      Result := False; 
      if not SetDebugPrivilege(SE_PRIVILEGE_ENABLED) then begin 
        Application.MessageBox('No Debug rights!', 'Error', MB_OK); 
      end else begin 
        Result := True; 
      end; 
    end; 
    
    procedure TfrmMain.FormCreate(Sender: TObject); 
    begin 
      @ChangeWindowMessageFilter := GetProcAddress(LoadLibrary('user32.dll'), 'ChangeWindowMessageFilter'); 
      ChangeWindowMessageFilter(WM_COPYDATA, 1); 
      fInjected := False; 
      fDontWork := not GetDebugPrivileges; 
      tmrSearchCondor.Enabled := not fDontWork; 
    end; 
    
    procedure TfrmMain.tmrSearchCondorTimer(Sender: TObject); 
    begin 
      tmrSearchCondor.Enabled := False; 
      SearchCondor; 
      tmrSearchCondor.Enabled := True; 
    end; 
    
    end.
    
    0 讨论(0)
  • 2020-12-08 04:10

    I use this library for IPc (uses shared memory + mutex): http://17slon.com/gp/gp/gpsync.htm

    It has TGpMessageQueueReader and TGpMessageQueueWriter. Use "Global\" in front of the name, so you can use it to communicate between a Windows Service and a "Service GUI Helper" when a user logs in. (the Global\ prefix is needed for Vista because of session security rings, but also for Windows XP/2003 between user sessions).

    It is very fast, multithreaded, etc. I would use this one instead of WM_COPYDATA (slow & much overhead if you use it a lot, but for small things messages can be OK)

    0 讨论(0)
  • 2020-12-08 04:11

    OmniThreadLibrary contains very efficient message queue in OtlComm.pas unit.

    Documentation is not very good at the moment (start here) but you can always use the forum.

    0 讨论(0)
  • 2020-12-08 04:12

    Option 1: Custom Message Queue

    You can build a custom message queue, and push messages to the queue, sort the queue based on business rules, and pop messages from queue from the main thread for processing. Use a critical section for synchronization.

    Option 2: Callbacks

    Use callbacks to send data back and forth from the threads. Again, use a critical section for synchronization.

    0 讨论(0)
  • 2020-12-08 04:14

    Yes – Gabr you can use windows messages in a service.

    ==============================

    Before Windows Vista, you could have configured your service to interact with the desktop. That makes the service run on the same desktop as a logged-in user, so a program running as that user could send messages to your service's windows. Windows Vista isolates services, though; they can't interact with any user's desktop anymore.

    =============================

    A Quote from Rob Kennedy answer to ‘TService won’t process messages’

    But I will not able to use 'frmMain.Handle' to post messages from the RDM to the main form in windows Vista.

    All I need to do is find a different way of posting & receive the message

    0 讨论(0)
提交回复
热议问题