The most common driver model in Windows CE is the stream interface driver. This driver model has roots in the earliest implementations of Unix. A stream driver exports functions to open, close, read, write, seek, or control the underlying hardware.
The stream interface is appropriate for any I/O device that can be thought of logically as a data source or a data sink. That is, any peripheral that produces or consumes streams of data as its primary function is a good candidate to expose the stream interface. A good example is a serial port device. An example of a device that does not produce or consume data in the traditional sense would be a display device, and indeed, the stream interface is not exposed for controlling display hardware.
A stream interface driver receives commands from the Device Manager and from applications by means of file system calls. The driver encapsulates all of the information that is necessary to translate those commands into appropriate actions on the devices that it controls.
All stream interface drivers, whether they manage built-in devices or installable devices, or whether they are loaded at boot time or loaded dynamically, have similar interactions with other system components.
The following illustrations show the interactions between system components for a generic stream interface driver that manages a built-in device, and for a stream interface driver for a PC Card Client device. Figure below, shows the architecture for stream interface drivers for built-in devices that are loaded by the Device Manager at boot time.

Stream Interface Driver Entry PointsHere and elsewhere,
XXX refers to a three character prefix you choose for your device driver. When implementing a stream interface driver replace
XXX with a prefix appropriate for your specific implementation.
You can implement a driver with only Init and Deinit entry points and no device prefix. You cannot access this driver using CreateFile.
If DEVFLAGS_NAKEDENTRIES is specified in the driver's Flags registry subkey, the entry point names can be undecorated; for example, Open, Close, and so on. The sample battery driver, which is in %_WINCEROOT%\Public\Common\OAK\Drivers\Battdrvr, is an example of a driver that uses undecorated entry points. The battery driver's registry settings still must include a prefix.
Your implementations of these entry points must be declared for export from your DLL by placing
__declspec(dllexport) in front of your function declaration. If you are developing in C++, your entry points must also be declared
extern "C" as well.
Single Access and Multiple AccessA stream interface driver can implement either single access or multiple access by using the
hOpenContext parameter passed to all file I/O functions.
To enable multiple access, each call to the
XXX_Open function should return a different value for
hOpenContext. The device driver must track which return values from
XXX_Open are in use.
To enforce single access, only the first call to
XXX_Open should return a valid
hOpenContext value. As long as this value remains valid, which is until
XXX_Close is called for the value, subsequent calls to
XXX_Open should return NULL to the calling application to indicate failure.
Stream Interface Driver FunctionsXXX_InitCalled when an instance of the driver is loaded. This function is required by drivers loaded by ActivateDeviceEx, ActivateDevice, or RegisterDevice.
The following list shows the tasks this function can perform:
- Initialize the installed device to a default state.
- Allocate resources used globally by the device driver.
- Register a status callback function with PC Card Services.
When the status of the device changes, the operating system calls this status callback function. For example, the status of a PC Card changes when you insert it or remove it.
- Map system memory and I/O space to a PC Card device memory and I/O space.
- Request notification on specific callback events.
- Register an interrupt callback function for an interrupt-driven device.
When the device generates an interrupt, the operating system calls this interrupt callback function.
XXX_DeinitCalled when an instance of the driver is unloaded. This function is required by drivers loaded by ActivateDeviceEx, ActivateDevice, or RegisterDevice.
If you have threads blocked in your driver, resources associated with the handle or device instance might not be able to be released. To avoid this, implement the
XXX_PreClose (Device Manager) and
XXX_PreDeinit (Device Manager) entry points.
XXX_OpenCalled when a driver is opened by an application with CreateFile.
When this function executes, your device should allocate the resources that it needs for each open context and prepare for operation. This might involve preparing the device for reading or writing and initializing data structures it uses for operation.
XXX_CloseCalled when a driver is closed by the application with
CloseHandle.
An application calls the
CloseHandle function to stop using a stream interface driver. The
hFile parameter specifies the handle associated with the device context. In response to
CloseHandle, the operating system invokes
XXX_Close.
The file handle specified for hOpenContext is no longer valid after this function returns; if an application tries to perform stream I/O operations on that handle after calling CloseHandle, those operations fail.
XXX_IOControlCalled when the application calls DeviceIoControl. This function might or might not be required, depending on the device capabilities that the driver exposes. This function requires an implementation of
XXX_Open and
XXX_Close.
XXX_ReadCalled when the application calls
ReadFile.
XXX_WriteCalled when the application calls
WriteFile.
XXX_SeekCalled when the application calls
SetFilePointer.
After an application calls the
SetFilePointer function to move the data pointer in the device, the operating system invokes this function. If your device is capable of opening more than once, this function modifies only the data pointer for the instance specified by
hOpenContext.
XXX_PowerUpCalled just before the system resumes. Optional.
The power handler functions,
XXX_PowerUp and
XXX_PowerDown, execute in kernel mode, and they cannot be pre-empted
XXX_PowerDownCalled just before the system suspends. Optional. It is useful only with devices that can be shut off under software control. Such devices are typically, but not exclusively, PC Cards.
XXX_PreCloseOptional. This function marks the closing handle as invalid and wakes any sleeping threads.
XXX_PreDeinitThis function marks the device instance as invalid and wakes sleeping threads. Required if the
XXX_PreClose function is implemented.