Interprocess communication (IPC): Using WM_COPYDATA or WM_GETTEXT

Started by jj2007, January 25, 2010, 10:21:11 AM

Previous topic - Next topic

jj2007

As an add-on to the WinHelp32 thread, here an example on how to use WM_COPYDATA for sending data between processes. I post this because there seems no good example in the forum so far.

I attach a complete working example. Here are the essential snippets:
Server side (assuming the data to send is the text of an edit control):
Quote            push eax               ; handle to the slave window obtained with FindWindowEx
            lea edi, buffer         ; pointer to a local buffer
            invoke SendMessage, hEdit, WM_GETTEXT, LocBufSize, edi
            lea edx, cds            ; a local copydatastruct
            mov [edx.COPYDATASTRUCT.dwData], Magic   ; a user-defined password ;-)
            mov [edx.COPYDATASTRUCT.cbData], eax   ; the length returned by WM_GETTEXT
            mov [edx.COPYDATASTRUCT.lpData], edi   ; pointer to the text
            pop eax
            invoke SendMessage, eax, WM_COPYDATA, Magic, edx
(You may or may not use a "Magic" value for identification.)

Now the client side:
Quote  SWITCH uMsg
  CASE WM_COPYDATA
  mov edx, lParam
  lea edi, buffer   ; a local buffer
  mov esi, [edx.COPYDATASTRUCT.lpData]
  mov ecx, [edx.COPYDATASTRUCT.cbData]
  rep movsb
  mov [edi], cl   ; we add a delimiter (ecx is zero after movsb)
  invoke SendMessage, hEdit, WM_SETTEXT, 0, addr buffer   ; we display the data

The second option, sending a handle to an editbox containing the source text, is also available in the attached source.

jj2007

The example above can be shortened on the client side by inserting an "inc eax" in the server side code:
Quote            push eax               ; handle to the slave window obtained with FindWindowEx
            lea edi, buffer         ; pointer to a local buffer
            invoke SendMessage, hEdit, WM_GETTEXT, LocBufSize, edi
            lea edx, cds            ; a local copydatastruct
            mov [edx.COPYDATASTRUCT.dwData], Magic   ; a user-defined password ;-)
            inc eax               ; if omitted, Windows will forget to copy the zero delimiter
            mov [edx.COPYDATASTRUCT.cbData], eax   ; the length returned by WM_GETTEXT, plus one for delimiter
            mov [edx.COPYDATASTRUCT.lpData], edi   ; pointer to the text
            pop eax
            invoke SendMessage, eax, WM_COPYDATA, hWnd, edx   ; optional: hWnd for feedback
Now the client side handler is just two lines:
Quote;  SWITCH uMsg
;  CASE WM_COPYDATA
   mov edx, lParam
   invoke SendMessage, hEdit, WM_SETTEXT, 0, [edx.COPYDATASTRUCT.lpData]   ; we display the data
Full code attached.

jj2007

Inspired by Joseph M. Newcomer's warning about HWND_BROADCAST, here a macro that allows checking for validity:

CopyData$ MACRO magic
mov edx, lParam
ifnb <magic>
cmp [edx.COPYDATASTRUCT.dwData], magic ; sets zero flag: .if not Zero? then error
endif
EXITM <[edx.COPYDATASTRUCT.lpData]>
ENDM


Usage:
SWITCH uMsg
CASE WM_COPYDATA
mov edx, CopyData$(54321)
.if Zero?
MsgBox 0, edx, "Data, hooray:", MB_OK
.else
MsgBox 0, "Data is not valid", "Hi", MB_OK
.endif


Corresponding server code:
push eax ; handle to the client window obtained e.g. with FindWindowEx
lea edi, buffer ; pointer to a local buffer
invoke SendMessage, hEdit, WM_GETTEXT, LocBufSize, edi
lea edx, cds ; a local copydatastruct
magic = 54321
mov [edx.COPYDATASTRUCT.dwData], Magic ; a user-defined password ;-)
inc eax ; if omitted, Windows will forget to copy the zero delimiter
mov [edx.COPYDATASTRUCT.cbData], eax ; the length returned by WM_GETTEXT, plus one for delimiter
mov [edx.COPYDATASTRUCT.lpData], edi ; pointer to the text
pop eax ; handle to the client window
mov eax, HWND_BROADCAST  ; ######### playing foul here #########
invoke SendMessage, eax, WM_COPYDATA, hWnd, edx ; optional: hWnd for feedback


By the way, on my machine (XP SP2), sending data with HWND_BROADCAST makes Firefox open a new instance. Weird...