Suppose that you have a device driver that needs to communicate to another device driver on WinCE. How should you make them communicate? (The same discussion is true of a service in services.exe communicating to another DLL hosted in services.exe.)
I'm a firm believer in the idea of KISS - keep it simple stupid. Ideally you just have the drivers pass pointers to buffers around between them and do direct call of exported functions. It's not always this simple though... in fact in rarely is.
There are times when you actually want the device driver to call DeviceIoControl() on another device driver. The best reason is that most of the time the callee driver already has an IOCTL channel written for applications to call it, so that the calling device driver goes through already existing code paths. Creating an intra-device.exe channel can complicate things (though if you really really care about perf in this scenario it may be needed).
Another good reason to stick to DeviceIoControl is that there are times when device drivers come from different companies, so it can be easier to use the standard DeviceIoControl() mechanism rather than having to roll your own set of function pointers/buffers to be called into.
The final good reason to use DeviceIoControl is that there's a future proofing. It allows for drivers to move to different processes and keep working with each other. With CE 6.0 and the new kernel, we're going to be doing some reshuffling of drivers to get them out of the kernel and into services(d).exe. GPSID for instance is moving out of the (soon to be retired) device.exe and into servicesd.exe. If some device driver managed to hackup GPSID to access it directly and not via its IOCTL channel (and hack is the main word - you'd better not be doing this :)) it would break in CE 6.0 if the device driver stayed in the kernel.
Also note one day I want to support multiple copies of servicesd.exe running simultaneously in order to add to stability (so you can have your service run in its own copy of servicesd), and in this case intra-service communication would also need to go through DeviceIoControl. For instance when the MSMQ ISAPI extension receives an SRMP message over HTTP (basically a SOAP msg) it calls into the MSMQ service with a DeviceIoControl() rather than calling an MSMQ fcn pointer directly (even though they're in the same process).
In a future blog I'll discuss why services.exe is going to become servicesd.exe (I'm sure everyone is waiting with baited breath :))
[Author: John Spaith]