MFC: How to pass ASCII data from DLL thread to main code

Hi, experts.

I have inherited an old-school MFC Windows CE program, and am having to make some modifications to it.  As part of this I have to pass additional data between disparate parts.  What we have is a Main program that calls into a DLL.  The DLL starts a background process that acts as a TCP server.  When that TCP server received data I need to push it all the way back up to the Main program.

After some research it seems the WINAPI PostMessage function (see FIGURE 1) is the way to go.  When Main launches the DLL it passes in its own HWND.  After the spawned TCP server process receives the data it calls PostMessage with (1) this saved HWND (2) a message ID, (3) wParam is the length of the received data, and (4) the lParam is a pointer to the received data itself.    Pseudocode for both the DLL thread caller, and the main code callee, are shown below in FIGURES 2 and 3.

What I'm seeing is that the function IS called in  my RemoteControlTCPMsg function, and the length is correct, BUT my string data is not correct -- weird, corrupted data.  The way I'm packaging the string data is mixed and matched from a few examples, but apparently something was lost in translation.

Could someone please provide a line or two of code that would properly preserve a char buffer when passed via PostMessage from a DLL thread to a main app such as mine?  

Thanks VERY much, I'm sort of at my wits end here.  Any thoughts/insight are appreciated.


*******************
*** FIGURE 1: PostMessage doc from MSDN

BOOL WINAPI PostMessage(
  _In_opt_  HWND hWnd,
  _In_      UINT Msg,
  _In_      WPARAM wParam,
  _In_      LPARAM lParam
);
(https://msdn.microsoft.com/en-us/library/windows/desktop/ms644944%28v=vs.85%29.aspx)


*******************
*** FIGURE 2: Pseudocode for the calling code in the DLL background thread:

#define RC_COMMAND_BUFFER_SIZE = 256;
char m_Cmd[RC_COMMAND_BUFFER_SIZE];
int m_CmdLen = 0;

(when event occurs, m_Cmd and and m_CmdLen are populated and this is called:)

PostMessage(m_hWnd, MSG_ID, m_CmdLen,(LPARAM)(new CString(m_Cmd, m_CmdLen)));

*******************
*** FIGURE 3: Code for the receiving code in the main code:

int CWAMPropertySheet::RemoteControlTCPMsg(WPARAM wParam, LPARAM lParam)
{

int length = = (int)wParam;
CString * rx_string = (CString*) lParam;

// handler code for the received text data and length

}
RonMexicoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Janusz CzopowikCommented:
If I understood your explanation properly, you are trying to pass data between processes: one main and the other spawned by the dll.
You will not succeed using post/send message, since memory in two processes is mapped differently.
Even if you manage using windows handle, you are passing the pointer to a memory in the second process.
The pointer main process receives, is pointing to some memory of your main process, not to a memory location in the secondary process.
Use WM_COPYDATA or see this: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx
0
jkrCommented:
You need to cast 'lParam' to a 'char*', not to a 'CString*' - the latter cast causes the ASCII text to be interpreted as a CString object, and that's not what you want. E.g.

int CWAMPropertySheet::RemoteControlTCPMsg(WPARAM wParam, LPARAM lParam)
{

int length = (int)wParam; // just a single '=' here
char* rx_string = (char*) lParam;

// handler code for the received text data and length

} 

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RonMexicoAuthor Commented:
@JohnCz:  Thanks.  I believe WM_COPYDATA goes through the windows "message pump", correct?  Like mouse clicks?  Seems very roundabout and asynchronous, and doesn't seem appropriate for what is essentially fast-streaming, serial data, (TCP data); do you disagree?  

Certainly this can't be an exotic thing -- I swear I've come across a way to package/unpackage string data for DLLs, and also a way to go across threads.  There must be a way for both?
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

RonMexicoAuthor Commented:
@jkr: thanks!  We'll try that and post back...
0
jkrCommented:
>>Certainly this can't be an exotic thing

It for sure isn't. BTW, why not passing the buffer to the thread directly and just send a notification when the data has arrived?
0
RonMexicoAuthor Commented:
Interesting question... I'm actually working with someone who made that decision.  I will challenge him on it.  :)
0
jkrCommented:
Well, the 'pro' clearly is that you don't have to create a buffer in the thread and take care of disposing that properly later on. 'Con': The buffer is off-limits until you receive the notification message.
0
jkrCommented:
.... um, having said that, I should add that you wouldn't have to rely on a message, e.g. an event handle would work as well ;o)
0
Janusz CzopowikCommented:
@RonMexico,

I think you are confusing two things.

I believe WM_COPYDATA goes through the windows "message pump", correct?  Like mouse clicks?  Seems very roundabout and asynchronous, and doesn't seem appropriate for what is essentially fast-streaming, serial data, (TCP data); do you disagree?

Windows does not have any message pump. This term was introduced by MFC where message pump is a part that handles idle processing.
Windows use message loop that is called from MFC CWinApp Run function.
This message loop dispatches messages as usual returning only when message received belongs to the idle group.
After message pump handles idle, it enters the message loop again until another idle message is received.
I do not quite understand your question about WM_COPYDATA message.
Depending how do deliver message to a window, message is placed in a window’s message queue (PostMessage) or system calls window’s procedure directly (SendMessage).

Certainly this can't be an exotic thing -- I swear I've come across a way to package/unpackage string data for DLLs, and also a way to go across threads.  There must be a way for both?
Another confusing thing: you mention communication between different threads; this is OK to send data between different threads.
But in your case (again if I understood your question correctly) you are dealing with exchanging data between two different processed and this requires different approach in comparison to data exchange between threads.
0
RonMexicoAuthor Commented:
jkr, that worked!  Thanks so much.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.