Skip to main content

Hello,

please help. I have 2 applications - managed and native - and need to use WM_COPYDATA message to pass (in this case just one string) data from managed to the native one. The most important is to fill the structure COPYDATASTRUCT correctly but until this moment I haven't been successful. The window procedure of the window in the native code receives the message WM_COPYDATA, the address of the COPYDATASTRUCT structure is also ok and cbData and dwData members too. The only thing I don't know is how to pass the string. There're many examples on the internet in C or C# but those didn't help me.

The sending managed code is following:

method-id OnRibbonItemClick (ln-item-name as string) public.
01 COPYDATASTRUCT is typedef.
   03 dwdata            ULONG.
   03 cbdata            ULONG.
   03 lpdata            pointer.
78 WM-COPYDATA          value h"004a".
01 cds                  COPYDATASTRUCT.
01 l-data.
   03 l-name            pic x(64).
set dwdata of cds       to 1
set cbdata of cds       to length of l-data
set lpdata of cds       to address of l-data
set l-name              to ln-item-name
declare l-result as binary-long
call WAPI "SendMessageA" using by value w-send-hwnd
                               by value WM-COPYDATA size 4
                               by value w-receive-hwnd
                               by reference cds
                     returning l-result
end-call

goback.
end method.

The receiving native code is this:

method-id. "WindowProc".

local-storage section.
01 l-ptr                pointer.
01 l-item-name          pic x(64).

linkage section.
01 ln-wnd               HWND.
01 ln-msg               INT.
01 ln-wParam            INT.
01 ln-lParam            INT.
01 ln-ptr               pointer
                        redefines ln-lParam.
01 ln-result            LRESULT.
*>
01 ln-cds               COPYDATASTRUCT.
01 ln-data.
   03 ln-item-name      pic x(64).
procedure division using ln-wnd ln-msg ln-wParam ln-lParam
               returning ln-result.
evaluate ln-msg
   when WM-COPYDATA
        set address of ln-cds  to ln-ptr
        set address of ln-data to lpdata of ln-cds
        move ln-item-name      to l-item-name
   when other
        invoke super "WindowProc"
               using ln-wnd ln-msg ln-wParam ln-lParam
           returning ln-result
end-evaluate

goback.
end method "WindowProc".

The application fails on the bold underlined line with error MEMORY VIOLATION, resp. 114 Attempt to access beyond bounds of memory. Appreciate any suggestions.


#SendMessageWM-COPYDATACOPYDATASTRUCTmanagednative

Hello,

please help. I have 2 applications - managed and native - and need to use WM_COPYDATA message to pass (in this case just one string) data from managed to the native one. The most important is to fill the structure COPYDATASTRUCT correctly but until this moment I haven't been successful. The window procedure of the window in the native code receives the message WM_COPYDATA, the address of the COPYDATASTRUCT structure is also ok and cbData and dwData members too. The only thing I don't know is how to pass the string. There're many examples on the internet in C or C# but those didn't help me.

The sending managed code is following:

method-id OnRibbonItemClick (ln-item-name as string) public.
01 COPYDATASTRUCT is typedef.
   03 dwdata            ULONG.
   03 cbdata            ULONG.
   03 lpdata            pointer.
78 WM-COPYDATA          value h"004a".
01 cds                  COPYDATASTRUCT.
01 l-data.
   03 l-name            pic x(64).
set dwdata of cds       to 1
set cbdata of cds       to length of l-data
set lpdata of cds       to address of l-data
set l-name              to ln-item-name
declare l-result as binary-long
call WAPI "SendMessageA" using by value w-send-hwnd
                               by value WM-COPYDATA size 4
                               by value w-receive-hwnd
                               by reference cds
                     returning l-result
end-call

goback.
end method.

The receiving native code is this:

method-id. "WindowProc".

local-storage section.
01 l-ptr                pointer.
01 l-item-name          pic x(64).

linkage section.
01 ln-wnd               HWND.
01 ln-msg               INT.
01 ln-wParam            INT.
01 ln-lParam            INT.
01 ln-ptr               pointer
                        redefines ln-lParam.
01 ln-result            LRESULT.
*>
01 ln-cds               COPYDATASTRUCT.
01 ln-data.
   03 ln-item-name      pic x(64).
procedure division using ln-wnd ln-msg ln-wParam ln-lParam
               returning ln-result.
evaluate ln-msg
   when WM-COPYDATA
        set address of ln-cds  to ln-ptr
        set address of ln-data to lpdata of ln-cds
        move ln-item-name      to l-item-name
   when other
        invoke super "WindowProc"
               using ln-wnd ln-msg ln-wParam ln-lParam
           returning ln-result
end-evaluate

goback.
end method "WindowProc".

The application fails on the bold underlined line with error MEMORY VIOLATION, resp. 114 Attempt to access beyond bounds of memory. Appreciate any suggestions.


#SendMessageWM-COPYDATACOPYDATASTRUCTmanagednative

What you are trying to do will not work as the address you are setting in your .NET application using set pointer to address of...does not generate a usable native pointer.

There is no built in support for converting a managed data object to a native pointer so you will have to do this the hard way.

The type will need to be changed to a native pointer System.IntPtr and then you need to use Marshal.AllocHGlobal/FreeGlobal

Then to get the memory to/from the IntPtr, you need to use Marshall.Copy, I would use a byte[] for the managed memory.

As the native memory may move, the code will have to consider the “Pinning” the memory, see/use GCHandleType.Pinned.

Lastly, a string is a Unicode and the native code may well be expecting non-unicode.

I will put together an example if you still require one but if you have worked around this requirement let me know and I won't bother.

Thanks.