Inter Process Communication via WM_COPYDATA

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

This is a series of articles that will cover various techniques supported by Inter Process Communication (IPC) IPC is a mechanism by which the various processes share data among themselves. The application that uses the IPC mechanism can be placed in two categories: client and server application. A client is an application or a process that uses the services of some other application or a process. A server is an application or a process that responds to or processes the client request. The same application can act as both a server and a client.

The WIN32 SDK provides various ways to achieve an IPC. These are the following techniques through which IPC can be achieved:

  • WM_COPYDATA
  • Clipboard
  • FileMapping Objects
  • MailSlots
  • Pipes
  • Sockets
  • COM
  • RPC

This series of articles will cover each technique in detail, along with the source code. We will cover WM_COPYDATA message that an application can use to send data to an another application. In this technique, the client application sends a message to a window that is in the server application.

A client application sends a WM_COPYDATA message to pass the data to the server application. To send this message, the client application calls SendMessage, which has the prototype described in the next section.

The SendMessage Function

The SendMessage function sends the specified message to the specified window. The function doesn't return until the window procedure of that specified window has processed the message.

SendMessage((HWND) hWnd,      // handle to destination window
WM_COPYDATA,                  // message to send
(WPARAM) wParam,              // handle to window
(HWND)  (LPARAM) lParam       // data (PCOPYDATASTRUCT));

SendMessage Parameters

  • hWnd: Handle to destination window that will receive the WM_COPYDATA message.
  • wParam: Handle to Window (passes the hWnd by typecasting it into WPARAM).
  • lParam: Pointer to COPYDATASTRUCT that contains the data to be transferred to another application.

The COPYDATASTRUCT Structure

The COPYDATASTRUCT structure contains the data that is to be passed to another application.

typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD     cbData;
PVOID     lpData; } COPYDATASTRUCT, *PCOPYDATASTRUCT

COPYDATASTRUCT Structure Parameters

  • cbData: Specifies the size in bytes.
  • lpData: Pointer to data that is to be passed to another application.

The source code has been divided into two parts—a client application and a server application. In this, the client application takes the string and the operation to be performed on that string from the user. The client application passes the necessary information to the server application so that the server can perform the requested operation on that string. The server application performs the requested operation on the data and displays the results on its console.

The WM_DATASTRUCTURE Structure

typedef struct _WM_DATASTRUCTURE{
DWORD cbSize;         // size of the string entered by user.
DWORD iMessage;       // operation being requested by user.
HWND hClient;         // handle to a client window. It is for
                      // further use. Currently, it is NULL.
_TCHAR Data[_WM_MAXMESSAGE_SIZE - _WM_HEADER_SIZE];
} WM_DATASTRUCTURE, *LPWM_DATASTRUCTURE;

The TransferData function makes a call to the LocalAlloc function to allocate the specified number of bytes from the heap. If the heap doesn't have the sufficient memory to allocate the requested bytes, it returns NULL. The lpData data member of COPYDATASTRUCT points to the WM_DATASTRUCTURE structure, which contains the information to be passed to the server application. After filling the COPYDATASTRUCT structure, the client application makes a call to SendMessage with the address of this structure as a last argument.

The Server Application

The server application registers the window class by calling the RegisterClass function. A window class is a set of properties that the operating system uses to create the window. Each window class has an associated window procedure that processes the messages being sent to the window of that window class. The server application retrieves the message from the message queue by calling GetMessage, and then calls DispatchMessage function, which dispatches the message to the window procedure for the further processing. After registering the window class with the operating system, the application can create many windows of that specific class; all the windows of that class share the same window procedure.

The window procedure WMCOPYWNDPROC performs the specified operation on the data, which is being sent by the client application. The window procedure typecast the lParam parameter to LPWM_DATASTRUCTURE to get the data being sent by the client application.

//Server side code . . . . .
LPWM_DATASTRUCTURE lpMsg;
(LPWM_DATASTRUCTURE)((COPYDATASTRUCT*)lParam)->lpData;

In this, lParam is a pointer to a COPYDATASTRUCT structure that exists in the address space of the receiving process. The lpData of the COPYDATASTRUCTURE is pointing to the _WM_DATASTRUCTURE, so it is telecast to the LPWM_DATASTRUCTURE.

Unicode Support

Unicode is a set of standards for a character-coding system. In Unicode, each character is two bytes, instead of being a single-byte ANSI character. A wide character is a two-byte character. The wide character is of the wchar_t type. Any ASCII character can be represented as a wide character by prefixing the letter L to the character. The L'M' is a wide character. Similarly, the ASCII string can be represented as a wide character string by prefixing the L to the string. The L"Unicode" is a wide character string. The wide characters take much more space than the multi-byte characters, but they are faster to process as compared to multi-byte characters. This is because the wide characters are always of a fixed size.

The wchar_t is defined as follows in stdio.h:

typedef  unsigned short wchar_t;
wchar_t* pStr=L"Hello! I am a wide character literal string."
wchar_t wcsCh= L'A';    //wide character.

Windows 95 and 98 don't support Unicode. An operating system such as Windows NT, 2000, and XP supports Unicode. The application that runs on the NT system should be Unicode. The Window NT provides supports a conversion between ANSI and Unicode. This support can make an ANSI application run on the Windows NT system. The operating system internally converts the ANSI strings to Unicode and vice versa.

The use of two macros, UNICODE and _UNICODE, makes your application Unicode-compatible. The UNICODE header is used in a Windows header file and _UNICODE is used in a C/C++ runtime library. Select the Settings menu item under the Project menu, and then select the C/C++ tab. Type _UNICODE, UNICODE in the Preprocessor definitions edit box.

Generic Macros

The generic macros make the life of a programmer easier because they provide support to write a single source code that can be compatible with both Unicode and the ANSI character set.

We have used two macros that are defined in Tchar.h:

  1. #ifdef UNICODE
    typedef wchar_t _TCHAR;
    #else
    typedef char _TCHAR;
    #endif
    
  2. _T macros expand to L if _UNICODE is defined; otherwise, it is ignored by the preprocessor.

These provide the automatic mapping to the correct character data type depending upon the Preprocessor directive used in project settings.

Notes

  1. The ascending and descending algorithms are meant only for ASCII characters and not for wide characters. In the next article, we will implement these algorithms for the wide characters. I have to explore much more regarding the wide character internals so that I can implement these algorithms on them.
  2. GetModuleHandle is implemented as both a Unicode and an ANSI version on Windows NT/2000, so the use of GetModuleHandle will fail if you try to run it with _UNICODE and UNICODE on Windows 95/98. To make it run on Windows 95/98, change the preprocessor directive to _MBCS or _SBCS.

Downloads

Download demo client project - 13 Kb
Download demo server project - 15 Kb


Comments

  • WM_COPYDATA ?bug

    Posted by Legacy on 04/14/2003 12:00am

    Originally posted by: Rivaborn

    MSDN documentation says -

    The receiving application should consider the data read-only. The pcds parameter is valid only during the processing of the message. The receiving application should not free the memory referenced by pcds. If the receiving application must access the data after SendMessage returns, it must copy the data into a local buffer.

    But I would advise anyone writing an WM_COPYDATA handler to copy his data to a local buffer as soon as possible.

    In the project code consider replacing

    SETSTRLEN(lpMsg->Data,(lpMsg->cbSize));

    with

    char cs[_WM_MAXMESSAGE_SIZE] ;
    memcpy(cs, lpMsg->Data, lpMsg->cbSize) ;
    cs[lpMsg->cbSize] = 0 ;

    My app was working perfectly then suddenly started throwing exceptions (Priviledged Instruction) till I made this change. Can't explain it, but I should mention I was sending several WM_COPYDATA messages one after another. And I was using it for inter-thread communication within the same application.... Go figure.

    Caveat Emptor!!!

    Reply
  • wParam error?

    Posted by Legacy on 03/31/2003 12:00am

    Originally posted by: Eric Sanders

    Nice article Dinesh!
    My understanding is that the wParam is the windows handle of the client window, not the server window, although it appears to work fine either way. Any idea why this is or what the wParam is even used for, (unless you yourself makes use of it). In fact, as an afterthought, is there anything wrong with client simply sending a registered message, passing it's own hWnd, then the server performs WM_GETTEXT command got get the text in the clients window for simply text data transfer?

    TIA
    Eric Sanders
    www.compufoil.com


    Reply
  • Inter Process Communication via WM_COPYDATA

    Posted by Legacy on 03/29/2003 12:00am

    Originally posted by: Mini

    Good Article, expect the next article in the series soon. BTW, could you please give some comments on areas where each technique is more appropriate or not good?
    Mini.

    Reply
  • Inter Process Communication via WM_COPYDATA

    Posted by Legacy on 03/27/2003 12:00am

    Originally posted by: Mamta

    its very nice article n i wish all the best wishes to Dinesh.
    
    

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date