With the book and CEDriverWiz I've been having a good look and think about context in a stream driver.  There is the device context that gets set up when the driver loads in XXX_Init.  There is also the open context when an application opens the stream in XXX_Open 

The device context is per instance of the loaded driver.  You need to implement shared memory in the driver DLL (or use a custom registry setting)  to implement context across multiple instances of the same driver (eg COM1, COM2 etc).  For exmaple keeping a count of the number of instances of teh driver (or limiting it to one).

XXX_Init can create structures on the heap but these need to be pointed to in the device context.  Device context is returned as the return value of XXX_Init.  It is input to XXX_DeInit and XXX_Open.

XXX_Open can create open context and return this as a pointer that is then input to XXX_Write, XXX_Read and XXX_Close.

Global variables are an issue as to when they are carried between calsl to teh driver and when not.  The safest way (particularly for structures created on the heap) is to pass them in the device and driver contetx (or put in shared memory).

Also there may need to be some synchronisation.  Device context should be guarded in Open and Open context may need to guarded in Read and Write.

The books discusses some of this and the new version (coming) of CEDriverWiz optionally implements some of this (or provides commented place holders).

I'll do a detailed paper on this soon in the embedded101 articles.