Interprocess Communication on Windows CE


Assume you have two processes running on the same WinCE device.  You want ProcB to give ProcA some data.  Or you want ProcB to tell ProcA to take some action on its behalf.  How do you do it?  I will describe 2 questionable and 2 good interprocess communication mechanism below.  I'm sure there's other ways - some of them good and some of them very hackish - that I'm not thinking of.  This is not an exhaustive list.


* Windows Sockets
One possible option is to open up a TCP/IP socket, bind it to localhost, and call accept() in ProcA.  When ProcB wants to communicate, it will create a socket of its own and connect() to the localhost socket.  Once the communication has been established, the apps can use standard Winsock APIs send/recv to pass data back and forth.


I do not recommend this mechanism.  There is extra overhead here you have to go through the TCP/IP stack to do the interproc communication, rather than a faster built-in mechanism.  There is also the danger that ProcA, if not coded properly, will allow remote network clients to connect to it.  This is a huge security concern.  A malicious user could remotely access your process, which probably does not have any authentication built-in, and take control.  It can also be quite clunky to program to this model.


* DCOM
Windows CE supports DCOM as an optional component.  When DCOM (not just "base COM") is included, then it is possible to access a COM object created in a "local server" running on the same device.  See CoCreateInstance and the CLSCTX_LOCAL_SERVER flag for more details.  Programming to this model lets DCOM handle a lot of ugly details for you and provides a programming model that may be familiar to people who have worked with Windows desktop programs.


This approach is not recommended either.  DCOM is optional and is not available on PocketPCs or SmartPhones.  Including DCOM in your image (if you're an OEM with Platform Builder) adds +500KB to your ROM size.


* Light-weight message queues
For completeness I listed sockets and DCOM.  I promise from now on we'll stick to good interprocess mechanisms :). 


The first is light-weight message queues.  Basically ProcA opens up a message queue and ProcB sends messages to it.  If ProcB wants a response, it creates its own message queue.  Since these were designed specifically for interproc communication on CE, they have a very usable API, take up minimal ROM, and are very fast.


Check out CreateMsgQueue, OpenMsgQueue, ReadMsgQueue, and WriteMsgQueue for more details.


* Services.exe
If you have a client/server relationship between ProcA and ProcB, it may make sense to put the "ProcA" into services.exe.  Services.exe is a system process that loads up service DLLs.  Services.exe makes it very easy for applications on the device to communicate to a service.  So in this model, ProcA isn't a process at all anymore.  Instead of ProcA.exe, you'd have ServiceA.dll.


I wrote a white paper on services.exe, including interproc communication, here.


* Services.exe versus light-weight message queues
When do you use services and when do you use message queues?  I'm biased in favor of services.exe since I wrote it :).  But I'll do my best to be impartial:


Services.exe PROs:
* By making "procA" as a service DLL, you don't take up one of the limited process slots.  It's also cheaper in terms of RAM to load a service DLL than to create a new process.
* Calls out the fact that "procA" is a server and that there is not a stand-alone application.  This can make the implementation cleaner and clearer.
* Also allows the service to be configured through a standard set of APIs.  This includes stopping, starting, refreshing, etc...


Services.exe CONs:
* On devices like newer versions of smartphone and PocketPC, your service DLL has to be signed to be trusted and loaded by services.exe.  This can be a hassle.  No such restrictions exist for the message queues.
* Again on trusted devices, code in services.exe will run with higher privelege than a user-mode application using the message queues would.  Code should be made to run with as low a security privelege as possible.
* If your application is not a true client/server model, but is more of a peer-to-peer (i.e. ProcA and ProcB both need to send messages to other, not just ProcB always calling ProcA to do work for it).  Services DLLs are not designed for the "peer-to-peer" model.


* Another good way to do interproc comm -- shared memory via file mapping (added 7/14/05)


Thanks to Paul Tobey for reminding me of another good way to do interproc communication - via the CreateFileMapping and related APIs.  Two processes open up the same memory mapped file and can share information that way.


[Author: John Spaith]

Comments (12)

  1. Daniel Moth says:

    Another CON of the services approach is that you cannot use it from managed code (whereas p2p queues are fine 🙂

  2.  

    I wanted to make a client-server application that would run both on WinCE/Windows Mobile 5.0…

  3. Daniel W says:

    I read the paper on services.exe, and I wonder… Can multiple IOCTLs be in progress at once via handles from separate calls to createfile("SVC0:"…), and can they each take an arbitrarily long time?

    Also, does Daniel Moth mean that you can’t write a client of a service in .NET, or just that you can’t write a service in .NET?

  4. cenet says:

    Daniel – Yes, multiple apps can be simultaneously blocked in one "SVC0: " for arbitrary amounts of time.  There’s mechanisms for unblocking these for say an app shutdown (or crash), but the service has to be smart.  My services.exe white paper, referenced on this blog but published on MSDN proper, deals with this to some extent.

    You can absolutely write clients of services in .Net — for instance the System.Messaging stuff is just an elaborate P/Invoke into the MSMQ API’s, which is itself just an elaborate wrapper into services.exe DeviceIoControl calls.  Writing services in .Net is not allowed.

    John Spaith

  5. Daniel W says:

    Mr Spaith, thanks for the clarification. I’ve got another question that has cropped up while considering the proper use of DeviceIOControl…

    Is there a size limit on either the BufIn or BufOut? I ask because I’d like to send a big bit of data back and forth  and want to use the packetising behaviour of DeviceIOControl to avoid having to specify a stream protocol and implementing xxx_Read/Write as well as xxx_IOControl. I couldn’t see any statement either way at MSDN.

  6. Daniel W says:

    I’ve looked at IOCTL_PSL_NOTIFY, but pkfuncs.h is not present in the windows mobile 5.0 pocket pc SDK and the text string "IOCTL_PSL_NOTIFY" isn’t present in the SDK at all. Also, the DEVICE_PSL_NOTIFY structure that should be passed in tells you which process is dying but there is no way I can see to link that to the xxx_IOControl calls that are blocked when implementing a service, so no way to terminate them prematurely.

    Is there a solution to this problem for folks that aren’t an OEM?

  7. cenet says:

    Daniel – sorry for delay, as you can probably guess I don’t check blog feedback enough.  In future, newsgroups are the best place to catch me.  Issue is I haven’t trained myself to use the blog and I’m a creature of habit, and I don’t like the interface as much as I like newsgroup reader.

    I know about the IOCTLs & structs not being defined in SDK.  I think there’s ways you can get the OEM header files, which is all you need to kickstart your development.  I don’t really know how you can do this (legally) though, but someone on newsgroup may.

    There’s no limit of DeviceIoControl() that I know of — it’s just a pointer that gets mapped with the same mechanism ReadFile & WriteFile pointers are marshalled.

    John Spaith

  8. COM on Windows Mobile only supports creating in-proc COM objects, not out-of-proc or COM objects on remote

  9. Igor says:

    What about named pipes? I thought of using RAPI and named pipes to communicate to my processes on the device. What do you think?

  10. cenet says:

    Igor – WinCE has no named pipe support at all, even on the builds that include full DCOM interproc.  I don’t know how RAPI works, they may use some sort of named pipes to talk from the app on desktop calling into whatever desktop service it is that communicates to the CE device.  But the protocol between desktop & CE is something custom, or if it looks like named pipes it’s only for RAPI<->CE scenarios (and isn’t something you can get at from app space on CE device).

    John

  11. cenet says:

    Thanks MD for alerting me to the broken link – I’ve cleaned it up.  John

Skip to main content