This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


March 1998

Microsoft Systems Journal Homepage

The Windows 95 Connection

If you're writing kernel-mode drivers for both the Windows NT and Windows 95 and Windows 98 platforms, one of your goals should be unifying a common interface between your user mode application and the supporting kernel mode drivers. With a little knowledge and some forethought, you can easily supply a single Win32-based application that depends on specific kernel mode services supplied by your device drivers.
Seeing the coolness of the Windows NT device driver interface from user mode, the Windows 95 team implemented similar functionality for VxDs. Windows 95 introduced both dynamically loadable VxDs (largely for Plug and Play) and a DeviceIoControl interface. Much like Windows NT, VxDs can be dynamically loaded by Win32 user mode apps by calling CreateFile. But there are a few minor differences that make true unification mildly irritating.
First, even though both Windows 95 and Windows NT utilize CreateFile, passing \\.\drivername as the VxD name or Windows NT driver name, each takes slightly different parameters, making a single call for either OS impossible. As a result, you'll first need to conditionally call CreateFile depending on the environment in which you are running (see Figure A). You end up with a file handle that you can then use to call ReadFile, WriteFile, or DeviceIoControl.
What does this mean? You can have the same piece of user mode code utilizing the same IOCTLs under either OS. However, Windows NT utilizes bits within the IOCTL value to determine various characteristics about the operation. Windows 95 has no such concept. Therefore, you should make your IOCTL values conform to your needs under Windows NT, and just reuse those values for your VxD. Let's put this into practice.
Figure B contains the source code to MSJDrvr.VxD. As you can see in MSJ_DeviceIOControl, the IOCTL_MSJDRVR_GET_STRING IOCTL is copying "Hello from VxD-land!" into the caller's buffer. If you run Testapp.exe under Windows 95, you'll see that it successfully calls DeviceIoControl, just as it does under Windows NT, albeit with slightly different results.
The only other consideration is in regard to asynchronous processing. In Windows NT, signaling of the user mode event is handled for you automatically by the I/O Manager. Under Windows 95, it's your responsibility to signal the user's event upon completion. This is done by calling:


 VWIN32_DIOCCompletionRoutine((DWORD)((OVERLAPPED *)  
     lpDIOCParms->lpoOverlapped)->O_Internal);
O_Internal? Yes, Windows 95 uses this normally reserved field to allow the VxD to signal the user mode event (stored in hEvent). Rest assured that the user mode handle will indeed be signaled on the return trip to user mode.
As you can see, with some simple planning, you can easily have a single Win32-based user mode codebase that depends on highly OS-specific drivers. It simply requires a little insight.