The Windows NT Kernel-Mode Device Driver FAQ

Back to Kernel Mode Systems home page


Summary: DRAFT Description and primer on Windows NT kernel-mode drivers
Last-modified:  Aug. 27, 1996

Posting-Frequency: monthly
Version: 0.1
Editor and principal author:  Jamie Hanrahan, Kernel Mode Systems

(jeh@cmkrnl.com)



0  Welcome
WELCOME to the VERY FIRST *DRAFT* EDITION of the Windows NT Kernel-Mode

Device Driver FAQ.
If the dates on the directories in my news spool can be trusted, the

newsgroup comp.os.ms-windows.programmer.nt.kernel-mode has been in

existence for nearly a year now, and still no FAQ has appeared.  I have

therefore fearlessly and foolishly volunteered to write and maintain it.
Like all FAQs, this one is very much a work in progress, and volunteers

are strongly encouraged.  If you want to suggest questions to be

included, please feel free to e-mail me:  jeh@cmkrnl.com .  If you want

to provide *answers* to be included, or additions or (heaven forbid)

corrections to what's already here, that's even better!  I will of

course maintain full author credit in the text on all submissions.  On

the other hand, I reserve the right to not include certain items.  For

example, information on writing Windows 95 VxDs, NT display and printer

drivers, or NT Virtual Device Drivers probably doesn't belong here.

0.1  Where To Find This FAQ
This FAQ will be posted to the newsgroups

comp.os.ms-windows.programmer.nt.kernel-mode,

microsoft.public.win32.programmer.kernel, and (once approved by the

moderators) news.answers.  I will also upload it to the CompuServe Win32

forum, section 13 (NT DDK), and make it available on my web site,

http://www.cmkrnl.com/ .

0.2  Just Who Told You You Could Do This?
No one.  I have simply stepped into the void, in an attempt to fill it.

That's how most FAQs happen here on Usenet.  Isn't anarchy wonderful?

(Strange, there seems to be no air here.  Choke...)
I do have some credentials in the field (you'll find them if you read

the following closely enough).  If someone else wants the job of NT

Kernel Driver FAQ maintainer badly enough, let me know and we'll talk

about it.  For now, I am clearly making far too many nickels by writing,

editing, and distributing this thing for free to ever give it up.
Yes, I do do business in this field...  but I think I've kept the

blatant commercialism to a minimum, and I've even included pointers to

my competitors, on a pretty equal footing.  All of which you'll find if

you read this closely enough.  If you have complaints in this area, just

as if you have any other comments on this FAQ, please let me know.  (The

alternative -- having someone write it who *doesn't* work in the

field -- does not seem to me to be preferable.)

0.3  What's Coming in the Next Version?
Sections on specific programming techniques, such as providing for "IRP

extensions", and some conceptual background on IRQLs, spinlocks, and

DPCs.  For now, I have to stop writing and post this thing.

1  Basic questions
1.1  Help, I need a driver for...
Sorry, wrong FAQ, wrong newsgroup, and/or wrong web page.  This is about

*writing* drivers.

1.2  What is a "device driver"?
In terms of computer software, a "driver" is a routine or set of

routines that implements the device-specific aspects of generic I/O

operations.  For example, an application calls a system function that

says "write this buffer to that device".  The driver for the device

handles the device-specific parts of the job.  By substituting other

drivers, other devices can be substituted without changing the rest of

the operating system or the application.
In primitive PC operating environments such as MS-DOS, drivers were

specific to individual applications.  For example, Word Perfect got

pretty successful by including drivers that supported a wide variety of

printers.  But none of those drivers would work with any other

applications, so when you installed Autocad, you had to install

Autocad's printer drivers as well.  Under the Windows environment, the

display and printer drivers became the province of the "operating

system", such as it was.  Under Windows NT, operating system drivers

handle *all* I/O devices.

1.3  What types of device drivers does WNT use?
Three types:
"Virtual device drivers" (VDDs) allow 16-bit applications (DOS and Win16

applications) to access certain I/O ports when running under Windows NT.
"GDI drivers" are called by Win32's GDI services and implement the video

controller-specific card printer-specific aspects of GDI functions.
"Kernel mode drivers" implement the device-specfic aspects of

CreateFile, CloseHandle (for file objects), ReadFile, WriteFile, and

DeviceIoControl functions (speaking in Win32 terms).  Kernel mode

drivers are the only drivers that can service interrupts or initiate DMA

transfers.
SCSI miniport and netcard (NDIS) drivers are special cases of kernel

mode drivers.  So are SCSI class drivers, file system drivers,

redirectors, and transport-layer network components, although these do

not touch I/O hardware directly.
Note that as of NT 4.0, GDI drivers also run in kernel mode, but they

have a substantially different architecture from the drivers we call

"kernel mode drivers."
This FAQ is mostly about kernel mode drivers.  Other types of WNT

drivers may eventually be covered in other FAQs, though I know of none

at the moment.

1.4  So, how do I know if I need a kernel mode driver?
If you have an I/O device controller for which NT doesn't have a driver,

or for which the NT-supplied driver doesn't implement the functions you

need, you'll need to find or write a kernel mode driver for your device.

1.4.1  But do I *really* need a kernel mode driver?
This question usually appears something like this:  "Look, my

application just wants to reference a few IO ports a few times.  Are you

telling me that I absolutely cannot do this directly from my

application, that I have to provide a driver and issue DeviceIoControl

calls?"
To be rigorous about it, yes.  Under Windows NT, applications run in

user mode (ring 3 on Intel).  Under WNT, code executing in user mode is

not allowed to issue IN or OUT instructions, nor can it access adapter

RAM space.  To preserve system security, WNT requires that these

functions be performed from kernel mode.

1.4.2  I thought heard about an article in Dr. Dobbs' Journal that

       showed a way around this.
There was indeed an article in DDJ, April 1996, about allowing Win32

applications under NT to directly access I/O ports.  The technique works

by changing the privilege context of the desired process to allow it to

issue IN and OUT instructions.  This works only on Intel platforms.

This is not really a counterexample to the statement that "you need a

kernel mode driver", since it takes code running in kernel mode --

supplied by a kernel mode driver -- to change the privilege context.  It

does not allow you to service interrupts, initiate DMA, or do anything

else with the device other than reference I/O ports.  You can actually

get that functionality with the GENPORT.C example from the DDK, and it

is platform-independent.

1.4.3  What about VDDs?
The Virtual Device Drivers do not actually do any I/O.  They simply

provide routines which the NTVDM calls when it traps a 16-bit app's

attempts to reference IO ports.  The routines in the vDD then issue

ordinary Win32 ReadFile, WriteFile, or DeviceIoControl calls, which in

turn are implemented by a corresponding kernel-mode driver.  That

kernel-mode driver might be one that was specially written to accompany

the VDD, or it might be one that already exists within NT.  In any case

the VDD does not actually do any I/O.

1.5  Okay, so I need a driver.  But can I get away without *writing* a

     driver?
Depending on your requirements, there are two commercial products that

may allow you to avoid writing a driver for your device:
      o  "WinRT", from BlueWater Systems, 206-771-3610,

         http://www.bluewatersystems.com/
      o  "DeviceX", from WinStar Technologies, 415-647-2815,

         http://www.wintech.com/
Each of these products provides a kernel mode driver that implements a

variety of DeviceIoControl functions for accessing random I/O devices,

which are configured through convenient GUI tools.  The DeviceIoControl

functions are "wrapped" by convenient APIs in a supplied DLL.  There are

also GUI tools for experimenting with the device.
If you have more time than money, there are two example drivers supplied

with the DDK that allow you to access I/O port and physical memory

space:
      o  \ddk\src\general\portio - implements DeviceIoControl calls that

         issue simple IN or OUT instructions to selected I/O ports.  You

         select the I/O ports through registry changes.
      o  \ddk\src\general\mapmem - implements DeviceIoControl calls that

         map any range of physical memory (including adapter RAM space)

         into a process's user-mode address space.
Both of these drivers require some knowledge of NT kernel drivers to

compile, install, and use, and are probably not something you want to

put in the field as part of a production system.  But they're fine for

experimenting, and they serve as good simple illustrations of many

essential techniques for all drivers.

1.6  What about "driver wizards"?
Yes, some of these have appeared in various magazines, in Microsoft

Developer Network (MSDN) articles, etc.
It is my opinion that, first, most of the drivers that can be written by

"wizards" have already been written, and second, that overreliance on

such tools fosters an ignorance of underlying principles -- principles

which MUST be thoroughly understood when it's time to fill in the parts

of the code that the wizard doesn't supply.  (Of course, I can defend

this opinion against all objections simply by supplying appropriate

definitions of "most" and "overreliance".  :-)

1.7  What is this new "Windows Driver Model" that Microsoft has been

     talking about?
It is the NT driver model, plus hooks for plug-n-play and power

management.  The NT driver model is not changing, it is merely being

adopted by a future version of Windows 95.

2  Driver Development
2.1  What hardware do I need to develop WNT KMDs?
Two systems running WNT are needed, one to exercise the driver and one

to run the kernel debugger UI.  They are referred to as the target and

host, respectively.  These need not be the same processor architecture

(Intel, Alpha, etc.).
The driver must be compiled and linked on a system of the same processor

architecture as that on which it will be tested, as there are no

cross-compilers available.  This may be the target system or any other

system of the same processor architecture, including the debug host.

2.1.1  I thought I heard somewhere that you could use a Windows 95

       system as the host for the debugger.
Not today.  Microsoft has unofficially stated that Windows 95 might be

usable in the near future, but as of this writing the kernel debugger

seems to be dependent not just on Windows NT but on the specific version

of Windows NT.

2.1.2  I thought I heard somewhere that you could use a serial terminal

       for the debugger UI.
Nope.

2.2  What software tools do I need to develop WNT KMDs?
Windows NT (free and checked build), Device Driver Kit (DDK), Software

Development Kit (SDK, for WinDbg only), and Visual C++ (VC++).

2.2.1  Where do I get all this stuff?

      o  NT free build:  Retail, or MSDN >= "Professional" level
      o  NT checked build, SDK, DDK:  MSDN >= "Professional" level
      o  VC++:  Retail, or MSDN "Universal" level

2.2.2  Can't I use someone else's 32-bit C compiler?
Maybe.  The technical answer is:  As long as it generates essentially

the same code, supports all of the MS extensions to C, and takes all of

the same command line options, it should work fine.  Same for the

linker.
Opinion:  VC++ is part of the driver build environment supported by MS,

and using anything else feels too much to me like swimming upstream with

a brick in each hand, a practice I try to avoid.

2.2.3  What about other languages like Pascal?
In theory, as long as you adhere to C calling conventions, don't use too

much stack space, etc., you should be fine.  In practice, there are

several tens of thousands of lines of header files in \DDK\INC which you

will have to translate to your language of choice.

2.3  What's this about C++ and drivers?
Although we use the VC++ compiler to compile drivers, MS has stated many

times that C++ language extensions should not be used in writing NT

drivers.  It is true that a few people have written about their

successes in using C++.  However, C++ language features tend to use

large amounts of stack space, and large amounts of stack space are not

available under WNT in kernel mode.

2.4  What about building drivers?  Do we use the VC++ IDE to build

     drivers?  What "project type" in the VC++ IDE do I select?
None of the above.  You build drivers using the "build" utility that

comes with the DDK.
Some people have successfully configured the VC++ IDE to build drivers,

through careful editing of the project options.  If you want to do this

to gain access to the Browser and other tools availalble in the IDE,

fine, but for building the production driver, I stick with "build".

2.5  Why are you so (cautious, cowardly, unimaginative) about using

     MS-recommended tools and techniques?
Considering how important it is to get drivers exactly, precisely,

positively right, I am reluctant to experiment with other compilers,

other languages or language dialects, or anything else that MS does not

recommend...  especially when I'm shipping a driver to a client.  MS's

tools may be buggy and their recommendations may be wrong, but at least

if I adhere to them I can point back to MS as the culprit.  If I ignore

their recommendations, problems are solely on my head.

2.6  What other information sources are available for kernel driver

     writers?
2.6.1  What MSDN articles exist?
The MSDN Library has a number of articles with relevant information,

although I would ignore their advice about writing drivers using C++

features.  A good place to start is "The Windows NT Device Driver

Resource Book".  It contains links to many other relevant articles along

with references to magazine articles.
One useful article that he missed is Q113996, Mapping NT Status Error

Codes to Win32 Error Codes".  This relates NT kernel STATUS_xxxxx error

codes to their corresponding Win32 ERROR_xxxxx codes.

2.6.2  What newsgroups exist?
The main discussion point for NT kernel driver writers is

comp.os.ms-windows.programmer.nt.kernel-mode .  Please note, this is

*not* a place to ask about the availability of off-the-shelf drivers.

Nor is it the place to ask about any Win32 programming issues, unless

they are directly related to a driver you're working on.
There is no newsgroup in the microsoft hierarchy (accessed officially

through the nntp server at nntp.microsoft.com) specifically for NT

kernel driver writers.  Many have been using

microsoft.public.win32.programmer.kernel, although this was originally

intended for discussion of the Win32 APIs exported by Kernel32.DLL.

2.6.3  What mailing lists exist?
There are three mailing lists that are relevant, though none focus

exclusively on NT kernel-mode drivers:
SEND 

(in message body)   TO

--------------------------------------------------------------------


subscribe ntdev     majordomo@atria.com

                    Peer support for sw development on NT,

                    including device drivers
subscribe ntfsd     majordomo@atria.com

                    Peer support for those doing file system 

                    driver development (low activity)
subscribe           ddk-l-request@albany.net

                    Peer support for driver writers on all MS

                    operating systems (not NT only).  $15/year fee.

--------------------------------------------------------------------

2.6.4  What courses exist?
To my knowledge, the following companies offer courses in the field:
      o  David Solomon Expert Seminars, http://www.solsem.com/ ,

         800-492-4898.  Yes, this is the company through which I offer

         my seminars.  This is my FAQ, so I get to list my offerings

         first!  Actually, I'll rotate the list each time I update the

         FAQ.
      o  Open Systems Resources, http://www.osr.com/ , 603-595-6500.
      o  Art Baker offers an NT driver course through Cydonix (no

         contact information available).

2.6.5  What World Wide Web sites exist?
My web site, http://www.cmkrnl.com/ , maintains a copy of this FAQ and,

soon, additional free information and source examples.
Open Systems Resources, http://www.osr.com/ , has copies of articles and

related source code from past issues of their "NT Insider" newsletter.
To my knowledge there are no other web sites that focus exclusively on

Windows NT device drivers.  Several others focus on various aspects of

Windows programming, sometimes including Win 3.1 and Windows 95 drivers.

If you are interested in these areas, you might start with the Windows

driver FAQ, available at

http://www.smartpages.com/faqs/windows/programming/device-drivers/faq.html

2.6.6  What other FAQs exist?
From ms-windows/programmer.how-to-find-faqs (posted weekly to

comp.os.ms-windows.programmer.misc):
There is one general Windows NT FAQ; you can find it at:

http://www.iea.com/~daler/nt/faq/toc.html
There are also three specialized Windows NT FAQs:
Windows NT Admin FAQ:     http://www.iftech.com/classes/admin/admin.htm

Windows NT Fax FAQ:       http://www.mcs.com/~sculptor/NTFAX-FAQ.HTML

Windows NT Internet FAQ:  http://www.mcs.com/~thomas/www/ntfaq/

2.6.7  What books exist?
There are no books currently on the market on this topic.  I'm in the

process of writing one with co-authors Ruth Goldenberg and Jim Fraser;

it will be published by O'Reilly and Associates and is not due to be

turned into to the publisher until near the end of 1996.  Please do not

write me to ask about when the book will be published, nor to be

notified of publication, nor to volunteer to review it (we have far more

volunteers than we can use already).  If you want to be notified of its

publication, your best bet is to contact O'Reilly and Associates and ask

to be put on their mailing list.
Another book has reportedly been in progress by Art Baker.  The

publisher will be Prentice-Hall.

2.6.8  What conference materials are available?
From the Windows Driver FAQ, maintained by Stephen T. Lewin-Berlin,

Berlin@vireo.com:
The video and audio tapes and handouts from Microsoft's October '92 NT

Driver Developer's Conference are still available.  Contact:
    MobilTape Co. Inc.

    address: 25061 W. Stanford, Suite 70; Valencia, CA 91355, USA

    phone (orders): 800.369.5718

    phone (info): 805.295.0504

    fax: 805.295.8474
ask for the order form for the event:
    Microsoft Windows NT Device Driver Developer's Conference

    October 26-28, 1992

    Anaheim, CA

2.6.9  What other related products exist?
Open Systems Resources, http://www.osr.com/ , 603-595-6500, has a File

System Filter Driver kit and a forthcoming File System Driver Kit

available.
For applications needing simple access to I/O ports, investigate these

products:
      o  "WinRT", from BlueWater Systems, 206-771-3610,

         http://www.bluewatersystems.com/
      o  "DeviceX", from WinStar Technologies, 415-647-2815,

         http://www.wintech.com/
For driver debugging, "SoftICE for NT" by NuMega Technologies,

800-4-NU-MEGA, http://www.numega.com/ provides single-machine debugging

capability, for Intel platforms only.

3  Building and Debugging Drivers
3.1  What is the role of the NT checked build in driver development and

     debugging?
All drivers should be exercised under the checked build, to the extent


of traversing all code paths at least once.  The checked build has a

large amount of internal consistency and constraint checking code, which

the free build omits.  In addition, the checked build goes through the

motions of spinlock acquisition and release, even on a single-processor

system, which the free build avoids.
Final long-duration stress testing should be done with the target system

running under the free build.
Routine driver debugging may be done with the target system running

under either the free or the checked build.  I prefer the free build

most of the time, simply because it is so much faster.
There is no reason as far as driver development is concerned to run the

host system under anything except the free build.

3.2  What is the role of the "Checked Build Environment" program item in

     driver development and debugging?
You use the two "Build Environment" program items to create console

windows in which to run the BUILD utility to build drivers.
You use the "Free Build Environment" to build the "retail" version of

the driver, with compiler optimizations enabled and without full

symbolic debugging information in the driver.SYS file.
You use the "Checked Build Environment" to build the "debug" version of

the driver, with compiler optimizations DISabled and WITH full symbolic

debugging information in the driver.SYS file.
A driver built under either "environment" will run on either build of

Windows NT.

3.3  I'm having problems getting the kernel debugger extensions to

     WinDbg to work.  What's wrong?
TBD
(I posted a checklist on this to

comp.os.ms-windows.programmer.nt.kernel-mode.  Did anyone save it?  I

apparently didn't.)

4  Basic Kernel Driver Development
4.1  Okay, I need to write a kernel mode driver.  Tell me how.
The answer to this question would fill a fair-sized book (and will).

4.2  What is the basic structure of a kernel mode driver?
Every kernel mode driver must have a DriverEntry routine, and for all

practical purposes, at least one Dispatch routine is required also.  The

DriverEntry routine must be called "DriverEntry", other routines can

have any name you like.  Drivers should also have an Unload routine,

which permits the driver to be (guess what) unloaded, or removed from

the system.

4.3  The NT driver doc talks about all these different types of drivers.

     How do they all relate to one another?
4.3.1  Basic driver structure
Let's define a "canonical" driver first.  This will be a monolithic

(non-layered) driver for a single-device controller that can handle only

one I/O request at a time.  In such a driver, I/O requests, which are

described by data structures known as I/O Request Packets (IRPs), are

handled by Dispatch, StartIo, InterruptService, and DpcForIsr routines,

in that order.  Unless the device is very well-behaved and can never

interrupt unexpectedly, a SynchCritSection routine is also needed.
If the device controller can be programmed for more than one I/O request

at a time, the StartIo routine is usually replaced by one or more

IrpQueueing routines.
Any driver that holds I/O requests (ie that does not complete them right

away or pass them on to other drivers) should have a Cancel routine.

This includes any driver with a StartIo routine or an IrpQueueing

routine.
Drivers that use controller objects and/or adapter objects will usually

have ControllerControl and/or AdapterControl routines, respectively.

4.3.2  What about layered drivers?
NT allows drivers to be layered on top of one another.  You can start

with a monolithic (self-contained) driver and put an upper-layer driver

above it.  I/O requests to the device(s) controlled by the lower-layer

driver now come to the upper-layer driver first.  You can layer on top

of any existing driver, but you cannot install a layer under a

lowest-layer driver.  The lowest-layer driver is the one that actually

talks to the I/O hardware, and NT offers no mechanism for "hooking" or

intercepting those operations and doing something else instead.
Other driver layers are generically called "highest-layer" (the first

driver that handles a particular IRP), "upper-layer" (any layer except

the lowest), and "lower-layer" (any layer except the highest).
In terms of routines, an upper-layer driver puts its own Dispatch

routine(s) "ahead of" another driver's Dispatch routine(s).  Hence, of

all the routines in a driver that handle I/O, upper-layer drivers

generally have only Dispatch routines.  (They still have DriverEntry and

Unload routines.) They may also have IoCompletion routines, which are

invoked when the lower-layer driver completes an IRP that has come

through the upper-layer driver.
If an upper-layer driver does its own IRP queueing, it adds either

StartIo or IrpQueueing routines, plus one or more Cancel routines.  In

that case, the flow of an I/O request is:  Upper-layer driver, Dispatch

and (StartIo or IrpQueueing), then lower-layer driver's Dispatch and

subsequent routines.
Upper-layer drivers do not handle interrupts, so they do not generally

need an InterruptService routine, nor a DpcForIsr routine.  They may

have TimerDpc routines.
A good "starter" example for an upper-layer driver is the DISKPERF

driver.  This driver collects disk I/O performance statistics and makes

them available to Performance Monitor and related tools.
NT driver layering is not at all like the Unix Streams environment.
The NT driver layering mechanism is not completely generalized, and

probably works best in environments where drivers at all layers are

written by the same team, or at least by people who can speak with each

other easily.  It is not really possible or advisable to layer a driver

on top of an existing driver unless you know quite a bit about how the

driver you're on top of does things.  For example, drivers that use

buffered I/O are usually incompatible with the associated IRP mechanism.

How do you know if your soon-to-be-lower-layer driver uses buffered I/O?

You just have to attach to its device object and look.  For that matter,

the associated IRP mechanism is incompatible with itself; only one

driver in a stack of layered drivers can safely IoMakeAssociatedIrp.

4.3.3  What about file system drivers?
A file system driver is generally a highest-layer driver sitting atop

the driver for random-access mass storage devices.  It implements the

semantics of file-system-oriented I/O requests, such as requests to

create, open, extend, and delete files and directories.  Different file

system drivers exist for different on-disk structures, such as FAT,

NTFS, and the CD-ROM file system.  File system drivers are presently

difficult to write, conceptually because they have complex jobs to do

and have intricate interactions with the cache and the memory manager,

and practically because Microsoft has not put much information about

them in the DDK documentation, and some necessary header files and

libraries are missing from the DDK.
Open Systems Resources ( http://www.osr.com/ ) has a forthcoming File

System Developers Kit which should address these issues.

4.3.4  What are class and port drivers?
Class and port drivers exist for I/O hardware in which a number of

substantially different types, or classes, of I/O devices are accessed

through a common I/O device controller.  The class drivers implement the

semantics of the different types of devices, such as disks vs. tapes,

while the port driver deals with programming the controller's I/O ports

(hence "port driver") or register.

4.3.5  What about NIC miniport drivers?
A NIC miniport driver is a lowest-layer driver which is "wrapped" by

support routines provided by the NDIS port driver.  It provides support

for a specific network interface card (NIC).

4.3.6  What about SCSI miniport drivers?
An SCSI miniport driver is a lowest-layer driver which is "wrapped" by

support routines provided by the SCSI port driver.  It provides support

for a specific SCSI controller.

4.3.7  What is this port/miniport thing?
Microsoft realized that all SCSI port drivers would have a great deal of

common code, because they would all have to interface with the existing

SCSI class drivers.
Similarly, all NIC drivers would have a great deal of common code,

because they would all have to interface with the existing

transport-layer drivers.
The SCSI port driver and NDIS port driver, respectively, attempt to pull

all of this common code into common modules within NT.
The port drivers also abstract the NT I/O support routines.  For

example, a NIC miniport driver does not call IoMapTransfer, but rather

NdisMSetupDmaTransfer.  They do this to such an extent that other

operating systems, such as Windows 95, can supply a NDIS port driver and

SCSI port driver and hence allow the miniport drivers to be compatible

with those other systems.

5  Data Structures and Objects
TBD

6  Specific Programming Techniques
TBD

7  Principles:  Synchronization, IRQLs, Spinlocks, and DPCs
TBD

8  Legal Stuff, For What It's Worth
8.1  DISCLAIMER
This article is provided as is without any express or implied

warranties.  While every effort has been taken to ensure the accuracy of

the information contained in this article, the author and contributors

assume no responsibility for errors or omissions, or for damages

resulting from the use of the information contained herein.

8.2  COPYRIGHT NOTICE
Copyright (c) 1996 by Jamie Hanrahan.  All rights reserved.
This article may be posted to any USENET newsgroup, on-line service, or

BBS as long as it is posted in its entirety and includes this copyright

statement.
This FAQ may not be distributed for financial gain.  This FAQ may not be

included in commercial collections or compilations without express

permission from the primary author and editor.

8.3  VESTED INTEREST DISCLAIMER
Yes, I teach seminars and offer consulting services in this field.
        --- Jamie Hanrahan, Kernel Mode Systems, San Diego CA

        Internet: jeh@cmkrnl.com (JH645)  CompuServe: 74140,2055  

drivers, internals, networks, applications, and training for VMS and Windows NT

NT driver seminars:  email seminars@solsem.com , or see http://www.solsem.com/

NT driver information:  http://www.cmkrnl.com/

-------------------------------------------------------------------------------

  We are dreamers, shapers, singers and makers.  We study the mysteries of 

  laser and circuit, crystal and scanner, holographic demons, and invocations 

  of equations.  These are the tools we employ.  And we know... many things. 

           --- J. Michael Straczynski, "Babylon 5"
(end)

Back to Top