Home > Store

Developing Windows NT Device Drivers: A Programmer's Handbook

Register your product to gain access to bonus material or receive a coupon.

Developing Windows NT Device Drivers: A Programmer's Handbook

Book

  • This product currently is not for sale.
Not for Sale

Description

  • Copyright 1999
  • Dimensions: 7-3/8x9-1/4
  • Pages: 1280
  • Edition: 1st
  • Book
  • ISBN-10: 0-201-69590-1
  • ISBN-13: 978-0-201-69590-8

Developing Windows NT Device Drivers: A Programmer's Handbook offers programmers a comprehensive and in-depth guide to building device drivers for Windows NT. Written by two experienced driver developers, Edward N. Dekker and Joseph M. Newcomer, this book provides detailed coverage of techniques, tools, methods, and pitfalls to help make the often complex and byzantine "black art" of driver development straightforward and accessible.

This book is designed for anyone involved in the development of Windows NT Device Drivers, particularly those working on drivers for nonstandard devices that Microsoft has not specifically supported. Because Windows NT does not permit an application program to directly manipulate hardware, a customized kernel mode device driver must be created for these nonstandard devices. And since experience has clearly shown that superficial knowledge can be hazardous when developing device drivers, the authors have taken care to explore each relevant topic in depth.

This book's coverage focuses on drivers for polled, programmed I/O, interrupt-driven, and DMA devices. The authors discuss the components of a kernel mode device driver for Windows NT, including background on the two primary bus interfaces used in today's computers: the ISA and PCI buses. Developers will learn the mechanics of compilation and linking, how the drivers register themselves with the system, experience-based techniques for debugging, and how to build robust, portable, multithread- and multiprocessor-safe device drivers that work as intended and won't crash the system. The authors also show how to call the Windows NT kernel for the many services required to support a device driver and demonstrate some specialized techniques, such as mapping device memory or kernel memory into user space. Thus developers will not only learn the specific mechanics of high-quality device driver development for Windows NT, but will gain a deeper understanding of the foundations of device driver design.



0201695901B04062001

Downloads

Source Code

Untitled Document Get the Source Code for this book.

Sample Content

Table of Contents



Preface.

Welcome to the World of Device Drivers.

How This Book Happened.

What We Cover.

What We Don't Cover.

The Physics Model for Software.

About URLs.

Documents on the Web.

Icons for insertions.

A Note on “Hungarian Notation.”

NULL and NUL.

The INs and OUTs of Parameters.

Unicode.

Indentation Style.

Acknowledgments.

About the Authors: Joseph M. Newcomer and Edward N. Dekker.

Contacting Us.

Further Reading/Software Sources.

For More Help.

Course Description: Windows NT 4.0: Device Drivers.



1. Driver Overview.

Historical Overview.

NT Architecture Overview.

The Priority System.

NT System Architecture.

User vs. Kernel mode.

The Hardware Abstraction Layer (HAL).

The BIOS and ARC.

The Kernel.

The Executive Services.

Getting From Here to There.

Overview of Device Drivers.

There's Lots More.

Driver Writing: Getting Started.

Using C++.

Planning a Device Driver.

Further Reading.



2. I/O: User Level Overview.

User Level I/O Basics.

Synchronous vs. Asynchronous I/O.

User Level APIs.

Other I/O Operations.

Further Reading.



3. Planning a Device Driver.

Planning the User Level Interface.

Windows NT Is Not a Real-Time System.

Understanding the Application(s).

Understanding the Hardware.

How Does It Work, Really?

ReadFile, WriteFile, DeviceIoControl, and CancelIo.

Address Mapping.

Paged and Non-Paged Memory.

Buffered and Direct Access.

Handling I/O Requests.

Devices and Device Objects.

Devices and Controllers.

Handling Interrupts.

The Deferred Processing Routine.

Synchronization and Serialization.

Driver Threads.

Polled Devices and Interrupt Frequency.

Full-Duplex Devices.

Device Enumeration.

Power Management.

Unloading Drivers.

The Registry.

Event Logging and Journalling.

International Drivers.

Driver Coding.

Driver Testing.

Further Reading.



4. I/O Hardware: Internal Busses.

Device Registers.

Memory Mapped Device Registers.

Shared Memory.

Bus Structures.

ISA Bus.

The MicroChannel (MCA) Bus.

The EISA Bus.

The PCI Bus.

PCI Bridges.

Planning a Device Driver.

Further Reading.



5. Device Driver Basics.

A Taxonomy of Drivers.

Driver Limitations.

The Registry.

Always Preemptible, Always Interruptible.

Multiprocessor Considerations.

I/O Request Packets (IRPs).

Layered Drivers and IRPs.

Asynchronous I/O.

Object-Oriented Structures.

Further Reading.



6. Overview of Kernel Memory: Caching, Paging and Pipelining.

The Virtual Address Space.

The Physical Memory System.

More Sophisticated Caching.

Cache Management on Intel Hardware.

Pipelining: A Form of Caching.

Caching Page Table Information.

Cache Line Alignment.

Memory Management in NT.

LRU, Working Set, and Thrashing.

Non-paged memory.

Memory Management for Device Drivers: Overview.

The File Cache.

Further Reading.



7. Driver Data Structures.

Loading and Starting a Driver.

Driver Objects.

Driver Loading.

Driver Load Order.

Adding a Driver.

Driver Object Structure.

Device Objects.

Device Object Structure.

Adapter and Controller Objects.

Interrupt Objects.

Timer Objects.

DPC Objects.

Device Queue Objects.

File Objects.

Event Semaphore and Mutex Objects.

I/O Request Packets (IRPs).

IRP_MJ_CREATE.

IRP_MJ_CLEANUP.

IRP_MJ_CLOSE.

IRP_MJ_READ.

IRP_MJ_WRITE.

IRP_MJ_FLUSH_BUFFERS.

IRP_MJ_SHUTDOWN.

IRP_MJ_DEVICE_CONTROL.

IRP_MJ_INTERNAL_DEVICE_CONTROL.

Summary.



8. Device Driver Structure.

The Hello World Driver.

Doing Debug Printout.

The hello.h File.

The hello.c File.

The Test Program.

Building the Driver.

The Checked and Free Build environments.

The BUILD command.

Output from the BUILD Process.

Registry Entries for Hello World.

REGEDIT/REGEDT32.

REGINI.

Running the Hello World Test Program and Driver.

Starting the Driver.

Running the Test Program.

The I/O Explorer.

Further Reading.



9. Debugging a Device Driver.

Debugging Tools Overview.

Application Level: The IDE Debugger.

Application Level: Bounds Checker for Windows.

Kernel: WinDbg.

Kernel: Soft-ICE.

Kernel: kd.

Retail and Checked Builds.

Using the Debugging Tools.

Physical Configuration.

Using AutoLogin.

Installing Your Driver.

Modifying the BOOT.INI File.

Configuring WinDbg.

Starting a Debug Session.

Loading the Driver.

It Crashed. Now What?

Restarting after an Error.

Reading a Crash Dump.

Unhandled Exceptions.

WinDbg Reference.

If in Doubt — Get Hardware Debug Assistance.

Use a PCI Bus Monitor.

Use a Logic Analyzer.

Use an Oscilloscope.

If Still in Doubt Rent an ICE — It's Expensive but So Are You.

Product List.



10. Approaching Reality: Moving Data.

Moving Data.

IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL.

Buffers for Device Control.

Completion of the Request.

Example: Buffered IOCTL.

Declarations and Interface.

Sample Usage: Application Level.

IRP_MJ_READ and IRP_MJ_WRITE.

Buffers for Read and Write.

Completion of the Request.

Example: Buffered IRP_MJ_READ and IRP_MJ_WRITE Completed in Dispatch.

Example: Birect I/O IRP_MJ_READ and IRP_MJ_WRITE Completed in Dispatch.



11. Approaching Reality: Synchronization.

Synchronization.

Spin Locks.

KeInitializeSpinLock.

KeAcquireSpinLock.

KeReleaseSpinLock.

KeAcquireSpinLockAtDpcLevel.

KeReleaseSpinLockFromDpcLevel.

Mutexes.

ExAcquireFastMutex.

ExTryToAcquireFastMutex.

ExReleaseFastMutex.

ExAcquireFastMutexUnsafe.

ExReleaseFastMutexUnsafe.

KeReleaseMutex.

KeReadStateMutex.

KeWaitForMutexObject.

Semaphores.

KeInitializeSemaphore.

KeReleaseSemaphore.

KeReadStateSemaphore.

The Executive Resource.

ExInitializeResourceLite.

ExAcquireResourceExclusiveLite.

ExTryToAcquireResourceExclusiveLite.

ExAcquireResourceSharedLite.

ExAcquireSharedStarveExclusive.

ExAcquireSharedWaitForExclusive.

ExReleaseResourceForThreadLite.

ExReinitializeResourceLite.

ExIsResourceAcquiredExclusiveLite.

ExIsResourceAcquiredSharedLite.

ExGetExclusiveWaiterCount.

ExGetSharedWaiterCount.

ExConvertExclusiveToSharedLite.

ExGetCurrentResourceThread.

ExReleaseResourceForThreadLite.

ExDeleteResourceLite.

Wait Routines.

KeWaitForSingleObject.

KeWaitForMultipleObjects.

SyncCritSect Routine.

Device Consistency: KeSynchronizeExecution.

The Cancel Spin Lock.



12. Achieving Reality: Memory Management.

Memory Management within the driver.

Mapping Adapter memory and I/O space.

Zone Buffers.

Lookaside lists.

Memory Allocation/Management Operations.



13. Achieving Reality: Touching the Hardware.

Touching the Hardware.

Accessing Ports.

Mapping Ports.

Mapping Device Memory.

The Joy Of Hardware.



14. Achieving Reality: Interrupts and the Driver.

Role of the low-level driver.

Interrupt Processing.

What Is an Interrupt?

Interrupt Levels.

ISR Synchronization: The ISR Spin Lock.

ISR levels and device priority.

Overview of an Interrupt Service Routine.

The Interrupt Service Routine Prototype.

Interrupt Service Routine Requirements.

Registering the Interrupt Service Routine.

Processing the Interrupt.

The Deferred Procedure Call Overview.

DPC for ISR vs. Custom DPC.

Multiple DPC Routines.

DpcForIsr.

Custom DPC routines.

Writing an Interrupt Service Routine.

ISR Prototype.

ISRs and Shared Interrupts.

The Deferred Procedure Call.

ISRs and the Unload Routine.

SyncCritSect Routine.

Resource Allocation Interlocks.



15. Achieving Reality: Timers.

Time Delay.

KeQueryPerformanceCounter.

KeStallExecutionProcessor.

KeDelayExecutionThread.

IoTimer Routines.

IoInitializeTimer.

IoStartTimer.

IoStopTimer.

Example: Use of IoTimer.

Custom Timer Routines.

Waiting on a Custom Timer Object.

Polling a Custom Timer Object.

The CustomTimerDpc routine.

Notification Timers and Synchronization Timers.

KeInitializeTimer.

KeInitializeTimerEx.

KeSetTimer.

KeSetTimerEx.

KeCancelTimer.

KeReadStateTimer.

Example: IoTimer routine.

Time of Day Functions.

KeQuerySystemTime.

KeQueryTickCount.

KeQueryTimeIncrement.



16. Achieving Reality: Driver Initialization.

Initialization Functions.

Driver Initialization Prototype.

DriverEntry.

Setting up the Interrupt Service Routine.

A Discussion of the Functions Used by Initialization.

The Unload Routine.



17. Achieving Reality: Direct Memory Access.

DMA Operations.

Use of DMA.

Scatter/Gather.

Adapter Objects.

Adapter Control.

Doing DMA: overview.

Cache Consistency.

DMA Channel Allocation.

Controller Objects.

Multiple Synchronization Objects and Deadlock.

Creating and Managing Controller Objects.



18. Achieving Reality: The Rest of the Details.

The Unload Function.

Parameterizing a Driver: The Registry.

BugCheck!.

Surviving a Blue Screen of Death.

Summary.



19. Mapping Device Memory to User Space.

Mapping Non-Paged Pool to User Space.

An Overview of the MapMem Driver.

The Registry Entry.

Reading the Registry.

Using the Registry Values.

Initializing the Driver Object.

The mapMem IRP_MJ_CREATE Handler.

The IRP_MJ_CLOSE Handler.

The MJ_IRP_DEVICE_CONTROL Handler.

The mapMem Unload Handler.

The mapSystemLogicalMemory Function.



20. I/O Hardware: The ISA Bus.

ISA Bus Overview.

ISA Bus History.

ISA Architecture Overview.

ISA Bus Problems.

ISA Interrupt Structure.

ISA Plug-and-Play.

Claiming Resources.

ISA DMA.

Further Reading.



21. I/O Hardware: The PCI Bus.

PCI Bus Overview.

The PCI Bus Hardware.

PCI Transactions.

The North Bridge.

Windows NT Support of the PCI Bus.

PCI Device Enumeration.

PCI Configuration Space.

HalGetBusData in More Detail.

Assigning Resources.

Using HalAssignSlotResources.

Claiming Resources.

Using IoAssignResources.

Overriding Assignments.

Mapping Memory.

The PCI Explorer.

The PCISCAN Driver.

The PCI Explorer Source.

Further Reading.



22. Serialization within the Driver.

Introduction to Serialization.

Basic Serialization: StartIo.

Driver Managed queues.

Low Level Primitives.

The Device Queue.

A substitute for StartIo.

A multiqueue Device.

Non-Exclusive Devices.

Cancelling an I/O Request.

Cancel and Layered Drivers.

The Cancel Routine.

Cancel and Cancel Spin Lock Functions.

Cancelling StartIo-Managed IRPs.

Cancelling Device-Managed IRPs.



23. Layered Drivers.

Layered Drivers.

Filter Drivers.

Object Manager.

Reference Counts.

Object Name Space.

The Object Manager Entries.

Creating Object Manager Entries.

Objects and Waiting.

Layered Drivers — Implementation.

Functions.

DriverEntry.

Unload.

Filter Drivers — Implementation.

Functions.

DriverEntry.

Unload.

Implementation Techniques.

The IRP Stack.

IRP Processing.

Calling Lower-Level Drivers.

Passing Buffers to Lower Level Drivers.

Completion routines.

Direct Calls from Driver to Driver.

Layered Driver Examples.

Passing an Allocated IRP to a Lower Level.

Passing the IRP to a Lower Level Driver with a Completion Routine.



24. Driver Threads.

System Worker Thread WorkItems.

Dedicated Driver Threads.

Multi-Processor Systems and Threads.

Waits.

Alertable and Non-Alertable Waits.

Asynchronous Procedure Call.

The Wait Routines.

Event Objects.

Semaphore Objects.

Mutexes.

Resources.

Synchronizing on Thread Objects.

A Multiple Queue Example Using Threads.

Finite-State Machines and Drivers.

Cancelling the Active IRP.

Further Reading.



25. Specialized Drivers in NT: An Overview.

Graphics Drivers.

Display Drivers.

The Miniport.

Surfaces.

OpenGL.

DirectDraw and Direct3D.

Printer Driver.

The SCSI Bus.

The SCSI Physical Bus.

The SCSI Command Set.

SCSI Drivers.

The Class Driver.

The Miniport Driver.

ASPI.

Further Reading.



26. Useful Driver Techniques.

Deferred Procedure Calls.

Threads and DPC Queueing — A Fatal Problem.

Example: DPC Queueing Failure.

The Registry.

Registry Access Functions.

The Windows NT Event Log.

The Event Viewer Utility.

The Message Table.

Creating Driver Events.

Reading and Writing Files.

ZwCreateFile.

Example: Opening a File for Reading.

Discussion: Rebooting.

ZwQueryInformationFile.

FILE_STANDARD_INFORMATION.

Example: Reading the File Size.

ZwReadFile.

ZwWriteFile.

ZwClose.

Pageable Drivers.

Why a Pageable Driver?

Creating a Pageable Driver.

Validating Pageability.

Locking Down Data.

Improving Performance: Locking Down Code.

Paging Entire Drivers.

Product Driver Installation.

The Service Control Manager.

The Registry.

Programming the Service Control Manager.

Further Reading.



27. A Hardware Simulator.

Why a Simulator?

Basic Design of a Simulator.

The Simulator Driver.

Driver Simulator Source Code.

The Simulator Control Panel.

Simulator State Diagram.

Using the Simulator Controller.

The I/O Explorer.

A Sample Driver.

Testing State: Macros, Bitmaps, and Offsets.

A Polled Device Driver.

A Simple Interrupt-Driven Device Driver.



28. NT 5.0 Drivers Overview.

Windows NT 5.0 Enhancements.

New Driver Support Routines.

Obsolete Driver Support Routines.

New DMA Programming Techniques.

DMA Routines Added.

DMA Routines Deleted.

Power Management.

Plug and Play.

The Windows Driver Model (WDM).

The Hardware Installer Wizard.

Other Changes.

The NT 5.0 DriverEntry (and Friends).

Handling IRP_MJ_POWER.

The DEVICE_CAPABILITIES Structure.

The PoCallDriver Function.

The IRP_MJ_PNP Message.

A “Simple” NT 5.0 Driver.

The DriverEntry Handler.

The AddDevice Handler.

The IRP_MJ_PNP Handler.

The IRP_MJ_POWER Handler.

The Unload Handler.



29. I/O Hardware: The Universal Serial Bus.

External Bus Overview.

The Universal Serial Bus (USB).

USB Architecture.

The Root Hub.

Endpoints.

Pipes.

Transfer Types.

Packet Bandwidth.

USB Packet Protocols.

Transaction Details.

Plug and Play Hardware.

Power Management.

USB Device States.

USB Device Requests.

USB Descriptors.

Device Communication.

USB Device Configuration.

Isochronous Transfers.

USB Hubs.

Further Reading.



30. The Windows Driver Model.

How WDM Extends the Basic Driver Model.

The Driver Hierarchy.

The WDM Classes.

The HID Class Driver.

The Streams Class Driver.

The Audio Class Driver.

The Video Class Driver.

The Still Image Class Driver.

Loading WDM Drivers.

A “Monolithic” WDM Driver.

Important Differences.

Design of a Monolithic USB Driver.

A WDM/USB DriverEntry Function.

A WDM/USB AddDevice Function.

Creating a WDM Device Object.

Calling the USB Driver.

USB and WDM.

The USB Subsystem.

The USB Card MiniDriver.

UHCD/OHCI Drivers.

The USB Class Driver.

The USB Hub Class Driver.

The HID/USB Interface.

Communicating to the USBDI.

USB Request Blocks (URBs).

USB and Power Management.

A USB Filter Driver.

The ValueAdd.c file.

The DriverEntry Routine.

The Pass-Thru Routine.

The Create/Close Function.

The AddDevice Function.

The Unload Function.

The PnP.c File.

The Power Dispatch Function.

The Plug and Play Handler.

The Plug and Play Completion Routine.

Starting the Device.

Stopping the Device.

Sending Down the USB Request.

The USB Completion Handler.

Processing the USB Descriptor.

The usb.c File.

The IRP_MJ_INTERNAL_DEVICE_CONTROL Handler.

The URB Handler Completion Routine.

The URB Printout Routine.

USB Support Functions and Structures.

UsbBuildGetDescriptorRequest.



A: Reference.

Support Function Overview.

Support Function and Data Structure Reference.

ASSERT.

ASSERTMSG.

CM_FULL_RESOURCE_DESCRIPTOR.

CM_PARTIAL_RESOURCE_DESCRIPTOR.

CM_PARTIAL_RESOURCE_LIST.

CM_RESOURCE_LIST.

CONFIGURATION_INFORMATION.

CONTAINING_RECORD.

CONTROLLER_OBJECT.

DbgBreakPoint.

DbgPrint.

DEVICE_DESCRIPTION.

DEVICE_OBJECT.

DriverEntry.

DRIVER_OBJECT.

ExAcquireFastMutex.

ExAcquireFastMutexUnsafe.

ExAcquireResourceExclusiveLite.

ExAcquireResourceSharedLite.

ExAcquireSharedStarveExclusive.

ExAcquireSharedWaitForExclusive.

ExAllocateFromNPagedLookasideList.

ExAllocateFromPagedLookasideList.

ExAllocatePool.

ExAllocatePoolWithQuota.

ExAllocatePoolWithQuotaTag.

ExAllocatePoolWithTag.

ExConvertExclusiveToSharedLite.

ExDeleteNPagedLookasideList.

ExDeletePagedLookasideList.

ExDeleteResourceLite.

ExFreePool.

ExFreeToNPagedLookasideList.

ExFreeToPagedLookasideList.

ExGetCurrentResourceThread.

ExInitializeFastMutex.

ExInitializeNPagedLookasideList.

ExInitializePagedLookasideList.

ExInitializeResourceLite.

ExInitializeWorkItem.

ExInterlockedInsertHeadList.

ExInterlockedInsertTailList.

ExInterlockedRemoveHeadList.

ExIsResourceAcquiredExclusiveLite.

ExIsResourceAcquiredSharedLite.

ExQueueWorkItem.

ExReleaseFastMutex.

ExReleaseFastMutexUnsafe.

ExReleaseResourceForThreadLite.

ExTryToAcquireFastMutex.

ExTryToAcquireResourceExclusiveLite.

HalAssignSlotResources.

HalGetAdapter.

HalGetBusData.

HalGetBusDataByOffset.

HalGetInterruptVector.

HalSetBusData.

HalSetBusDataByOffset.

HalTranslateBusAddress.

HKEY_LOCAL_MACHINE.

InitializeListHead.

InitializeObjectAttributes.

InsertHeadList.

InsertTailList.

INTERFACE_TYPE.

InterlockedDecrement.

InterlockedExchange.

InterlockedExchangeAdd.

InterlockedIncrement.

IoAcquireCancelSpinLock.

IoAllocateAdapterChannel.

IoAllocateController.

IoAllocateErrorLogEntry.

IoAllocateIrp.

IoAllocateMdl.

IoAssignResources.

IoAttachDevice.

IoAttachDeviceToDeviceStack.

IoBuildAsynchronousFsdRequest.

IoBuildDeviceIoControlRequest.

IoBuildPartialMdl.

IoBuildSynchronousFSDRequest.

IoCallDriver.

IoCancelIrp.

IoCompleteRequest.

IoConnectInterrupt.

IoCopyCurrentIrpStackLocationToNext.

IoCreateController.

IoCreateDevice.

IoCreateNotificationEvent.

IoCreateSymbolicLink.

IoCreateSynchronizationEvent.

IoDeleteController.

IoDeleteDevice.

IoDeleteSymbolicLink.

IoDetachDevice.

IoDisconnectInterrupt.

IO_ERROR_LOG_PACKET.

IoFlushAdapterBuffers.

IoFreeAdapterChannel.

IoFreeController.

IoFreeIrp.

IoFreeMapRegisters.

IoFreeMdl.

IoGetConfiguationInformation.

IoGetCurrentIrpStackLocation.

IoGetCurrentProcess.

IoGetDeviceObjectPointer.

IoGetNextIrpStackLocation.

IoInitializeDpcRequest.

IoInitializeIrp.

IoInitializeTimer.

IoMakeAssociatedIrp.

IoMapTransfer.

IoMarkIrpPending.

IoRegisterShutdownNotification.

IoReleaseCancelSpinLock.

IoRequestDpc.

IO_RESOURCE_DESCRIPTOR.

IO_RESOURCE_LIST.

IO_RESOURCE_REQUIREMENTS_LIST.

IoSetCancelRoutine.

IoSetCompletionRoutine.

IoSetNextIrpStackLocation.

IoSizeOfIrp.

IoSkipCurrentIrpStackLocation.

IO_STACK_LOCATION.

IoStartNextPacket.

IoStartNextPacketByKey.

IoStartPacket.

IoStartTimer.

IO_STATUS_BLOCK.

IoStopTimer.

IoUnregisterShutdownNotification.

IoWriteErrorLogEntry.

IsListEmpty.

IRP.

KdPrint.

KeAcquireSpinLock.

KeAcquireSpinLockAtDpcLevel.

KeBugCheck.

KeBugCheckEx.

KeCancelTimer.

KeClearEvent.

KeDelayExecutionThread.

KeDeregisterBugCheckCallback.

KeFlushIoBuffers.

KeGetCurrentIrql.

KeGetCurrentProcessorNumber.

KeGetDcacheFillSize.

KeInitializeCallbackRecord.

KeInitializeDeviceQueue.

KeInitializeDpc.

KeInitializeEvent.

KeInitializeMutex.

KeInitializeSemaphore.

KeInitializeSpinLock.

KeInitializeTimer.

KeInitializeTimerEx.

KeInsertByKeyDeviceQueue.

KeInsertDeviceQueue.

KeInsertQueueDpc.

KeLowerIrql.

KeNumberProcessors.

KeQueryPerformanceCounter.

KeQuerySystemTime.

KeQueryTickCount.

KeQueryTimeIncrement.

KeRaiseIrql.

KeReadStateEvent.

KeReadStateMutex.

KeReadStateSemaphore.

KeReadStateTimer.

KeRegisterBugCheckCallback.

KeReleaseMutex.

KeReleaseSemaphore.

KeReleaseSpinLock.

KeReleaseSpinLockFromDpcLevel.

KeRemoveByKeyDeviceQueue.

KeRemoveDeviceQueue.

KeRemoveEntryDeviceQueue.

KeRemoveQueueDpc.

KeResetEvent.

KeSetEvent.

KeSetPriorityThread.

KeSetTimer.

KeSetTimerEx.

KeStallExecutionProcessor.

KeSynchronizeExecution.

KeWaitForMultipleObjects.

KeWaitForMutexObject.

KeWaitForSingleObject.

KEY_BASIC_INFORMATION.

KEY_FULL_INFORMATION.

KEY_NODE_INFORMATION.

KEY_VALUE_BASIC_INFORMATION.

KEY_VALUE_FULL_INFORMATION.

KEY_VALUE_PARTIAL_INFORMATION.

KIRQL.

KSYNCHRONIZE_ROUTINE.

LARGE_INTEGER.

MmAllocateContiguousMemory.

MmAllocateNonCachedMemory.

MmCreateMdl.

MmFreeContiguousMemory.

MmFreeNonCachedMemory.

MmGetMdlByteCount.

MmGetMdlByteOffset.

MmGetMdlVirtualAddress.

MmGetPhysicalAddress.

MmGetSystemAddressForMdl.

MmInitializeMdl.

MmIsAddressValid.

MmMapIoSpace.

MmMapLockedPages.

MmPrepareMdlForReuse.

MmProbeAndLockPages.

MmQuerySystemSize.

MmSizeOfMdl.

MmUnlockPages.

MmUnlockPagableImageSection.

MmUnmapIoSpace.

MmUnmapLockedPages.

NTSTATUS.

ObDereferenceObject.

ObReferenceObjectByHandle.

ObReferenceObjectByPointer.

PCI_COMMON_CONFIG.

PCI_SLOT_NUMBER.

PDRIVER_CONTROL.

PIO_DPC_ROUTINE.

PIO_TIMER_ROUTINE.

PKDEFERRED_ROUTINE.

PKSTART_ROUTINE.

PsCreateSystemThread.

PsGetCurrentProcess.

PsGetCurrentThread.

PsTerminateSystemThread.

READ_PORT_BUFFER_type.

READ_PORT_type.

READ_REGISTER_BUFFER_type.

READ_REGISTER_type.

RemoveEntryList.

RemoveHeadList.

RemoveTailList.

RtlInitUnicodeString.

RtlMoveMemory.

RTL_QUERY_REGISTRY_ROUTINE.

RTL_QUERY_REGISTRY_TABLE.

RtlQueryRegistryValues.

RtlUnicodeStringToAnsiString.

RtlZeroMemory.

UNICODE_STRING.

_URB_CONTROL_DESCRIPTOR_REQUEST.

_URB_HEADER.

UsbBuildGetDescriptorRequest.

WRITE_PORT_BUFFER_type.

WRITE_PORT_type.

WRITE_REGISTER_BUFFER_type.

WRITE_REGISTER_type.

ZwClose.

ZwCreateFile.

ZwCreateKey.

ZwDeleteKey.

ZwEnumerateKey.

ZwEnumerateValueKey.

ZwFlushKey.

ZwMapViewOfSection.

ZwOpenKey.

ZwOpenSection.

ZwQueryKey.

ZwQueryValueKey.

ZwSetInformationThread.

ZwSetValueKey.

ZwUnmapViewOfSection.

Further Reading.



B: Error Codes and Associated NTSTATUS Codes.

Mapping Application Errors to NTSTATUS Codes.

Mapping NTSTATUS Codes to Application Error Codes.

The NTSTATUS Explorer.

The STATUSR Driver.



Index. 0201695901T04062001

Preface

Welcome to the World of Device Drivers

This is a book on how to write Device Drivers. Device Drivers are those very specialized pieces of software that live inside the operating system and allow it, and thus your programs, to communicate to the outside world. Every communication NT makes to the outside world, including the keyboard, mouse, display, disks, CD-ROMS, and printers requires a Device Driver. Most of the key ones have been written by Microsoft, and NT supports all the "standard" devices.

But what about "nonstandard" devices? This doesn't mean the devices don't conform to a standard; what it means is that these are devices that are not found on "standard" PCs. Often they are specialized devices whose market is far too small for Microsoft to devote any energy to supporting. These could be devices such as drivers that support IEEE-488 communications (used for laboratory equipment and test equipment), analog-to-digital data input boards, digital-to-analog data output boards, specialized communications boards, and the like.

The core problem in Windows NT is that if you don't have a Device Driver you can't talk to a device. In Windows 3.x and Windows 9x you can cheat; you can write an application program that goes "for the bare metal" and directly manipulates the hardware interface to the device. But in Windows NT, because of the requirements for being certified at C2 Security (an important certification commercially and for government sales), an application program is simply not permitted to manipulate the hardware directly. So you are confronted with the problem of writing a device driver.

That's what this book is all about.

How This Book Happened

One evening after a long day at Comdex, Ed and I (jmn) were sitting around discussing our Latest Adventures. Ed was telling me about all the really cool, largely non-obvious (not undocumented, but obscurely documented) things he'd learned about writing device drivers. I said to him, "Ed, you should write a book". (At this point I was well into the writing of Win32 Programming, so writing books was at the top of my consciousness). He looked at me and said "Joe, I don't know how to write a book". I immediately responded "Well, I don't know how to write a device driver!" The conclusion was obvious. So we wrote a proposal to Addison-Wesley, and you are holding the result.

What We Cover

The purpose of this book is to allow you to write NT Device Drivers for a new device that you would want to connect to an NT machine. These include polled, programmed I/O, interrupt-driven, and DMA devices. Modern interrupt drivers add complexity, because interrupts may be shared by several devices. DMA has changed from the use of the PC's onboard DMA controller to external DMA controllers and Bus Mastering controllers. Many drivers for modern devices need access to onboard memory, and we show how to do that. In some cases, you might want to write a "user level" system that does most of the work, calling the I/O subsystem only to initiate certain input or output transactions, and using it to handle interrupts. We show how to construct these drivers.

We talk about how to build robust, portable, multithread- and multiprocessor-safe drivers. We talk about what you have to do to ensure that your driver won't bring the system crashing down around the user. We lay out the protocols you must use in communicating to the rest of the system; if you don't follow these fairly exactly, the system won't work as expected. It may crash, it may corrupt the disk, it may ignore the device, it may lose information on input or output, or it may misinterpret the intention of the application programmer who calls the services of the driver. Writing a Device Driver is fairly exacting. We try to capture much of the Art of building a device driver here, as well as the Technology.

In addition, we talk about how to actually build drivers, that is, the mechanics of compilation and linking; what they have to do to register themselves with the system, and most importantly, how to debug them. Most of the useful techniques for debugging device drivers is either undocumented or difficult to find; we've summarized our experiences in this book.

What We Don't Cover

There is only so much that one book or set of books can cover. We've chosen our goals to cover what most device driver writers want or need. But there are several aspects we don't cover at all:

Graphics drivers. These include display drivers and printer driver. The Graphics Driver contains the code to render an image into the internal frame buffer of the Video Adapter or printer engine. Most of the effort goes into understanding the incredibly clever hacks needed to get optimal efficiency on a particular piece of hardware. Graphics drivers are in the range of tens of thousands of lines of code. Generally, unless you work for a display card vendor or printer vendor, you will never encounter a need to write one of these. And while there is often a desire to support some old printing or plotting device, frankly, the cost of developing one of these drivers would buy several modern equivalents of those old printers. Chapter 25 contains a very high-level overview of graphics drivers. To do them justice would take another book about this size.

File System Drivers would be worthy of an entire book on their own. In fact, this has already been done (see Further Reading). To write an entire file system is far more complex and is beyond the scope of this book. We've never written a file system, and are not now qualified to write about how to do it. Network Drivers. Network drivers are worthy of an entire book devoted just to that subject (there is a pattern here). The chances that most device writers will ever need to write a full network driver are fairly slim. At the lowest level (for example, the card driver) a network card driver bears a strong resemblance to most other devices, but there are some additional complications that require a deep understanding of network protocols. There is just not enough space available in this book to cover network drivers.

In addition, recognize that this is software. There are dozens of ways to do anything. We present the core methods, and possibly one or two interesting alternatives. We cannot tell you every possible way to do every possible thing (for one thing, we haven't done every possible thing in every possible way ourselves!) Many techniques are unique to particular devices, and in some cases our ability to talk about some of the more interesting advanced techniques is circumscribed by various Non-Disclosure Agreements we have signed. What we hope to give you here is a sound footing in basic driver technology and illustrate a few of the more interesting advanced techniques that you may need. But the coverage here is not "complete". If we started to write a "complete" book on version n of NT, we would not have delivered the manuscript before version n+1 was released. This wouldn't help anyone.

The Physics Model for Software

No, not "Software Physics". That's something else entirely. The "Physics Model" refers to a comment by a physics professor, who said "We have an advantage in physics; we teach it by an ever more refined set of lies". What he was referring to is that when physics is first taught, you learn about Newtonian physics. In this model, we have phenomena such as the wave model of light, the particle model of light, and so on. Physical objects are real, and their masses interact according to specified laws of gravity or of energy transfer. But relativity theory tells us that Newtonian physics is really relative to a particular inertial frame, and what is really going on is something different. In Quantum Mechanics, you learn that at a certain scale, physical objects don't exist, and phenomena like the Heisenberg Uncertainty Principle come into play, and you get an explanation of what is really going on. Then there's Quantum Electrodynamics, in which the real model of what is going on is explained, and then...well, it's been too long since our physics courses and anyway you should have the idea by now.

We apply this same principle to teaching software. So don't be surprised if there are some apparent discrepancies between the illustrations and text on one page and the illustrations and text on a later page. We're trying to avoid giving you infinite detail too early and thus avoid being too confusing. Ideally, the earlier text or illustration is a subset of the later one.

About URLs

While many people know about URLs, not everyone might be familiar. A URL is a Universal Resource Locator, a designator for a page of information on the World Wide Web. A URL has a form like

http://www.mumble.com/here/and/there/and/everywhere.html
http://www.mumble.com/here/and/there/and/everywhere.htm
http://www.mumble.com

To access a Web page for which we give a URL, you must have a Web Browser, such as Microsoft Internet Explorer or NetScape (to name the two most popular browsers for Win32 platforms), and a connection to the Internet. We are not going to explain those details here, but if you don't have access, you want to find an Internet Service Provider (ISP) who can provide this service to you. We have investigated a number of interesting Web sites that provide useful information for Device Driver writers. We have included these URLs in various places in the book.

Once you have your Internet connection, you bring up your browser and you type the URL, and as if by magic, the Internet tells you it doesn't exist. Well, actually, if you typed it correctly, and the Web page wasn't removed, you will actually get the page. We can't guarantee that all of the URLs we give will continue to exist. We're giving you the best information we have as we went to press, but the Web changes daily, and it is impossible to be instantly current in a print publication.

Documents on the Web

We often cite URLs as a source of documents. The Web page will usually give you a link, such as the name of the document or a button, that allows you to download the document. Documents come down in a variety of formats, but the most popular formats are Microsoft Word (.doc) files and Adobe Acrobat (.pdf) files. If you have Microsoft Word, it is easy to read the documents; if you don't, you will need to download the Microsoft Word Viewer. For Acrobat, you need an Acrobat Viewer. This is available as a download from Adobe. We give the URLs under Further Reading.

Documents on the Web are often compressed, usually using the PKZip utility from PKWare. We have uncompressed all the information we included on the CD-ROM, but if you download a document you will need the PKZip utility. This is available in both public-domain versions and registered versions. The folks at PKWare have done Good Things for the computing community. Support them by buying a licensed version. The licensed version is not that expensive; if you're a device driver writer, you can recover the cost very quickly.

Icons for insertions

We have done a number of text insets. These elaborate on points that have specific audiences, and rather than put everything inline in the text, we have pulled some discussions out into these sidebar-like annotations. To clue you as to their relevance, we have a series of icons that we use to indicate the contents.

One indicates a potential bug. Sometimes it is a bug in the documentation, sometimes it is a bug in a particular release of the operating system.

Another indicates some informational aside.The information may be useful to you, but it is not as important as the main-line text.

Yet another indicates a potential pitfall. Often it is a compatibility issue, such as a Win16/Win32 difference that is otherwise undocumented, or obscurely documented, or a difference between two Win32 versions. Occasionally, we use it to indicate other possible failures that would otherwise be hard to discover. These failures include obscure or undocumented limitations, or places where you are likely to get into trouble In some cases, the behavior of a Windows operation is not "intuitively obvious", and if you do what you think is "right", it won't work as expected.

Another icon indicates that there is a potential hazard. You should take note of this when using the related material.

Finally, yet another icon indicates the authors are expressing a (usually controversial) opinion. We want you to know it is an opinion, rather than a statement of some fact. You may even disagree with the opinion, but one advantage of being an author is that we get to say, in public, how we feel about certain issues.

A note on "Hungarian Notation"

This whole section should have one of the "flame" insets, but it is too long and too important to reduce to a mere sidebar.

The so-called "Hungarian Notation" (developed by a Hungarian programmer at Microsoft) is one of the worst ideas to have hit software development in many years. This is that horrid notation that tries to encode the data type in the name, for example, "nCount" indicating an integer count. This is a mistake; only two other popular languages in history ever encoded data type in a name, FORTRAN and BASIC, and both of them abandoned it as a fundamentally bad idea. Fortunately, the coders of the NT kernel had the good sense to avoid this notation. You will not find it used in any of our examples, except those user-level examples where we have to interface to Microsoft's data structures that use the convention, or when some published standard has fallen prey to this insidious notation.

Why is Hungarian Notation bad? Aesthetics aside (it is singularly ugly), it creates maintenance nightmares, which is a cardinal sin in our opinion. Software is hard enough to maintain without introducing artifices that make that more difficult. For example, you might declare a short signed integer counter and call it "nCount". But you may then discover that you need more than 32,767 values, but less than 65,535 values in the counter. So in a sane world, you would do the obvious: change the declaration from "short" to "unsigned short" or equivalently "WORD" (the declaration WORD always means "unsigned short"). But according to Microsoft's standards, you now need to change the name to "wCount". A global substitution won't work, because there may be other contexts in which the variable "nCount" is simply a short. If you don't change it, you'll wonder why you get a compiler warning if you compare what is "obviously" a signed number with another signed value. And if you need more than 64K values, you might want to redeclare it a "long" or "unsigned long" ("DWORD") in which case you need to change the name to "lCount" or "dwCount". If you don't change the name, you'll wonder why assigning a 16-bit variable wCount to another 16-bit variable wOldCount or passing it to a function that requires a 16-bit parameter generates a compiler warning about value truncation. If the names did not encode the type, you would not make this kind of error because you would have to refer to the declaration to find the type. You say that changing a single name is trivial? Not so. And the possibility of making an error and not changing the name, or perhaps changing the name in too many places, introduces a complication to maintenance that is unnecessary. It is important to understand how real maintenance is done by real programmers in the real world, rather than legislating how a theoretical model of maintenance ought to be, in some ideal but unrealizable world.

But there are other, even more significant, maintenance headaches. If this value was in a structure, you can't change the name because this would force all the users of the structure to change their code. So you will find in the Microsoft interfaces names like "wCount" that were 16-bit unsigned integers in Win16, but changed to 32-bit unsigned integers in Win32. But for compatibility, the prefix had to remain the same (the classic one for GUI programmers is "wParam", which the prefix suggests is a 16-bit unsigned value but which is really a 32-bit unsigned value! And, in the world of 64-bit NT, will be a 64-bit unsigned value!) It is not uncommon in the Microsoft interfaces to find declarations in structures like "int dwCount", "LPVOID dwData", "DWORD lpszData", "WORD nCount", and "int wCount". Many of these represent the failure to fully transition from the 16-bit world to the 32-bit world. None of these would have been a problem if Hungarian Notation had not existed. By using a naming convention that says the name does encode the type, then violating that convention, you create programs that require additional care in maintenance. If that additional care, which should be completely unnecessary, is not exercised, you can get unmaintainable code, or code that contains subtle bugs.

Historically, this naming convention arose in the days before compilers did cross-module type checking on function calls, and it made it possible for the programmers to "visually check" that parameters had the correct types. Using ANSI compilers with full function prototypes, this need is gone (and has been gone for many years) and there is little reason to use this convention. We strongly discourage introducing any Hungarian Notation to any component you write. It is an unfortunate historical aberration that has no place in modern programming practice.

Perhaps the best summary we saw of this was in a book on programming, where the author titled the section "Hungarian Notation: Just Say No". We loved this heading, and considered plagiarizing it, but decided not to. It is too good, and he deserves to have it to himself. But we'll leave you with our expression: "Friends don't let friends program in Hungarian Notation".

NULL and NUL

The value NULL is a pointer to nothing. Although traditionally zero, in fact the ANSI C Standard does not require it to be zero. And while nearly every C program would break if it were changed from zero, that is because people like to write code of the form "if(!pointer)" instead of the (actually, only correct) form "if(pointer == NULL)". (The reason for the former is that on the first PDP-11 compilers, which had no optimization, the compiler could generate one fewer instructions for that form, which was important when the application had only 64K of address space to share for code and data. In modern compilers on modern architectures there is no difference in the code generated, and the former is simply a type-unsafe computation based on a tradition that a NULL pointer is the same as a 0 value).

NUL, on the other hand, is a character value. There is no character value NULL. In fact, the use of the NULL macro to represent a character NUL is incorrect, although we see it all the time. For example, the assignment stringi = NULL when string is a char (ANSI) or wchar_t (Unicode) array. The value NUL is the 3-letter abbreviation for the character whose value is 0x00. When used in the context of Unicode, it represents the character whose value is 0x0000. In fact, many C compilers formally define NULL as ((void *)0), in conformance with the ANSI standard, which makes it impossible to actually assign it to a character lvalue. Thus the assignment we just gave would actually cause a compilation error, and in any decent C compiler this would be an error, not a warning. Instead, the correct assignment would be either stringi = '\0' (ANSI) or stringi = L'\0' (Unicode).

The INs and OUTs of parameters

You will find all of the function headers specified by Microsoft have an apparent keyword attached to each: IN, OUT, or both. Starting with NT 5.0, some parameters may be followed by the keyword OPTIONAL. These keywords don't really exist; in fact, they are macros that have empty bodies, so they are effectively thrown away by the preprocessor. They are, however, incredibly useful as documentation aids. A reference parameter that is declared OUT means that it will be written but not read; but if it is declared IN OUT it means you must initialize it before making the call, and it will be updated upon return. Little things like this help a lot. You will find that much of our code uses them also.

Unicode

Internally, Windows NT uses the Unicode character set. This is a 16-bit "universal" character code designed to support multiple languages concurrently. The familiar 8-bit character set is referred to as the ANSI character set, and is a proper subset of the Unicode set. This introduces some interesting wrinkles you will have to be conscious of, for example, that there is no longer a one-to-one relationship between the number of bytes and the number of characters. Furthermore, even Microsoft is a bit inconsistent at the driver level. At the application level, the phrase "characters" always means "the number of characters", and an application running as a native Unicode application requires two bytes per character, but the APIs always use or return character counts. In the kernel, sometimes character counts are used and sometimes byte counts are used. We even point out where Microsoft has incorrectly confused characters and bytes in documenting a critical data structure (the UNICODE_STRING). But basically, you will want to "think Unicode" while within the kernel.

Unicode is not the same as the "multibyte character set" mechanism (MBCS) supported by Microsoft and other C libraries. The MBCS allows for embedded "shift" bytes that indicate whether the string is current in one-byte, two-byte, or potentially longer encodings. Unicode strings are always 16-bit characters, and contain no embedded shift sequences.

Indentation Style

Yes, we recognize this is an issue of deeply-held beliefs, defended in general with incredible ferocity. The style used largely throughout the book is one which was developed by one of the authors (jmn) over many years. I (jmn) strongly favor this style. Ed and I actually have quite different styles of indentation (but since I got to annotate all the code I got to choose the style). I believe that unlike many of the competing styles of indentation, this is the only one based on fundamental principles of human cognition. While I don't expect to convert anyone to this style, I believe that understanding the principles may encourage thinking more deeply about indentation styles and how they are used in practice.

Think about this: how many times have you had to draw little arrows connecting the { }s of a C program? How many times have you had to print out hardcopy solely for this purpose? How many times have you gotten it wrong? Many years ago, I used a compiler for a language called SAIL, developed at the Stanford AI Lab. It was a classic Algol-class language with additional features of supporting backtracking search, associative memory, and many other bells and whistles. The compiler, and its executables, ran on a 256Kword (roughly 1MByte) DECSystem-10 or DECSystem-20. This language had an incredibly useful feature: you could follow any begin keyword with a string which was the "block name", and any end keyword with the same string. If the strings didn't match, the compiler complained, including both names and line numbers in the error message. This Was Wonderful.

After struggling with trying to find a "C style" that was right for me, I recalled how useful the block name feature was, and programmed my editor so that when I typed an open-brace I got a comment following it, into which I could type the "block name". When I typed a close-brace, the editor would find the matching open brace, indent the close brace to be directly under it, and copy the comment. While not as good as the checking done by the compiler it has greatly reduced brace errors in my code to virtual non-existence even on the first compilation, and has made finding the mismatched braces in those few cases where I get sloppy to time expressed in single digit seconds. But more significantly, it makes it possible to easily read large blocks of code, such as switch statements and loops, that span many screens or printed pages. I know that if I see a comment on a closing brace that there is a corresponding open brace with the same comment. It is trivial to find it. This conforms to the human cognitive processes which don't handle counting and nesting very well but can trivially match "flat" patterns. Since many of our examples span many pages, a bare close-brace is virtually incomprehensible without these annotations.

So think about it. Does your indentation style match human perception, or is it a representation of a machine-oriented perception? I, for one, have little interest in making life easy for machines; I'd rather optimize my own time.

-jmn

Acknowledgments

No book this complex can be written by two people in the time we had to write it. We are grateful to a large number of people for their help, support, suggestions, and tolerance during this process.

Mike Hendickson and Ben Ryan of Addison Wesley Longman, who between them saw the book through its initial stages.

Carter Shanklin, our current editor, who helped us through to completion.

Laura Michaels for copy editing and style suggestions.

Avinash Chopde, Scott Thieret, Ron Reeves, and Bruce Rosen whose comments on the book helped us write more clearly on some topics.

Special thanks to Rick Jones and Richard Page whose suggestions and comments helped make this a far better book.

The folks at OSR, whose NT Newsletter is full of useful tips.

Jim McCollum for use of his example of a driver that detected a subtle problem in DPC queuing that would cause a system crash (and the entire driver community should all thank him for having discovered this, and the workaround! A Nice Bit Of Work).

Brian Bussey and Frank de Alderete of Technology Exchange Company who provided the support to develop a course based on this book.

The folks in the comp.os.ms-windows.programmer.nt.kernel-mode newsgroup, many of our questions have been answered without asking, just by searching the archives. Jim Boemler (jboemler@halcyon.com) who maintains the file pcicode.h, which we used for our PCI Explorer.

And especially the folks of MindShare, most notably Tom Shanley and Don Anderson, who have done an utterly invaluable series of books on PC architecture. We needed some of that data to get our explanations right. (I think that we now each own the complete series, and as they extend it we will extend our collections. This is a great set of books! Run, do not walk, to your nearest technical bookstore and get them). We also thank them for their permission to include much of the detailed technical data that appears in our USB chapter from their book on the USB Architecture.

We also want to particularly thank Jeff Ross, of VMetro, Incorporated, for the loan of the VMetro board we used for illustrations in the debugging chapter.

I need to thank my co-author, without whose encouragement (and strong push) I never would have started this project. Joe has clearly done the hard part of this book. I also need to thank Joe for all he has taught me over the years we have worked together. I can name few people who have taught me as much. I also thank my parents; they started me on the path to this book. When I was a small boy, long before first grade, my father started asking me how things work. This would continue for many years. We would see a machine. Sometimes we would be in the car and drive past something, a road building machine or a factory, he would ask me to explain how the machine works, or the factory builds a product, or how the product the factory builds works. After I answered the question he would give his answer. When he started, he didn't expect me to have the right answer. He taught me how to come up with possible answers. This also inspired me to read more so I would know the answers to the next question. My answers have been getting better as I got older. (He may have regretted this, by the time I started college he observed that if asked for the time I would give instructions on building clocks).

My mother, who put up with my early book addiction (three trips to the library a week was about right, they only let me take 10 books at a time) as well as my electronics habit and the need for small electronic parts (not all of them were tangled in the carpet).

It seems to be tradition for an author to thank his dog, so I will thank my dog who has been as understanding as possible. He would clearly have preferred walking (well, running in circles for him) through the woods instead of sleeping in my office as I worked on this book. He helped provide the comic relief I needed at times. He has appeared with his Kong at the times I needed a break from the book, and be satisfied if I spend just a few minutes playing fetch. Well it resembles fetch, I throw the Kong once and he runs past me with the Kong and he is happy if I move my arm to attempt to take it from him as he runs past at high speed.

--end

As usual, I need to thank my Little Gray Cat (a.k.a. Bernadette G. Callery) for her patience and endurance during Yet Another Book (this is my third). Mew! She also provided invaluable assistance for this book by providing the lower trace shown on the oscilloscope of Figure 9.25 (by holding the Channel 2 probe).

And my co-author for some truly amazing spicy meals during the assorted weeks we spent working together at his place. His years of experience in writing NT Device Drivers are what made this book possible, and his many hours of research on the topics we covered has been invaluable. He has clearly done the hard part of this book.

Like Ed, my parents and my Uncle Bill set me on this path many years ago by encouraging reading and experimentation; Erector sets and TinkerToy sets were an important part of my life, as were the salvaged TV sets (for parts). I just have a bigger toy set to play with these days.

--jmn

About the Authors: Joseph M. Newcomer and Edward N. Dekker

Dr. Joseph M. Newcomer is a consultant, instructor, and author with 33 years' experience in computer science. Joe has been a contributor to Dr. Dobb's Journal, published over 70 articles and technical reports, and written several books, including Win32 Programming (co-authored with Brent Rector; Addison-Wesley, 1997). He has worked on operating systems, device drivers, compilers, computer music (MIDI), real-time and embedded systems, and programming tools. Joe has been active in the Microsoft online forums and has been named a Most Valuable Professional (MVP) by Microsoft.

Edward N. Dekker offers consulting services through his company Eclectic Engineering, Inc. Ed specializes in systems programming and real-time systems. Ed has over 20 years' computer software experience. Ed has spent the majority of his time in the past few years focusing on device driver work for Windows NT. He has written device drivers for a variety of operating systems including: Windows NT, Windows (3.0 and 3.1), DOS, VMS, RSX-11M, UNIX, and VXWORKS. Ed's experience also includes programming and design of real-time systems, networking, data-base, programming tools, electronic mail systems, application programs, and consulting on software design.

Contacting Us

If you find errors, or have suggestions for clarifications or material you'd like to see, we'd love to hear from you. We will probably be putting up errata sheets, new software, and the like on our Web sites as well. While we've done our best to interpret some very complex documentation on a very complex problem, we too are fallible. And while we think we've found all the problems (especially with those paragraphs written late at night or early in the morning, depending on your viewpoint), a book, like the software it describes, can't be proven correct, it can only be tested. We hope we have made your job of writing a device driver easier.

Joseph M. Newcomer, Pittsburgh PA, newcomer@flounder.com, http://www3.pgh.net/~newcomer
Edward N. Dekker, New Ipswich NH, dekker@eclectic-eng.com, http://www.eclectic-eng.com

Further Reading/Software Sources

Adobe Systems, Acrobat Viewer. Available from http://www.adobe.com/prodindex/acrobat

Campbell, Mary K. (ed.), Legacies, Institute of Electrical and Electronic Engineers, 1994. ISBN 0-7803-9996-X.

Hummel, Robert L., Programmer's Technical Reference: Data and Fax Communication, Ziff-Davis, 1993. ISBN 1-56276-077-7.

Microsoft Corporation, Word Viewer. Available from http://www.microsoft.com/word/internet/viewer/viewer97

Nagar, Rajeev, Windows NT File System Internals, O'Reilly and Associates, 1997. ISBN 1-56592-249-2.

Newcomer, Joseph M., Letter to the Editor, Post-Gazette, November 27, 1991, quoted in Legacies. Legacies was a special publication of the IEEE celebrating their life members. One of the contributors lives in Pittsburgh, saw my letter, and said that it characterized much of how engineers became engineers. He asked permission to reprint it. I was particularly pleased because this book is a set of interviews with some of the greatest engineers of the century, all of whom are Life Members of the IEEE, on how they became engineers and what their careers meant.

Open System Resources, Inc., The NT Insider, currently available by free subscription from: Open System Resources, Inc., 105 State Route 101A, Suite 19, Amherst, New Hampshire, 03031.

PKWARE, Incorporated, PKZip. Available from: PKWARE, Inc., 9025 N. Deerwood Dr., Brown Deer, WI 53223, (414) 354-8699, http://www.pkware.com.

Schildt, Herbert, The Annotated ANSI C Standard, Osborne/McGraw-Hill, publication date unknown but suspected to be 1993 from the notes in the Introduction. ISBN 0-07-881952-0.

VMetro, Inc., VMETRO Inc., 1880 Dairy Ashford, Suite 535, Houston, TX 77077, http://www.vmetro.com.

For More Help

The authors hope you will get an introduction to NT drivers from this book. If you need additional help, the authors of this book are consultants and instructors. In addition to this book we have also written and teach a course on Windows NT device drivers. The course is offered through Technology Exchange Company. We offer consulting and software development services through our own companies.

For information about this course, contact: Technology Exchange Company, 20 Burlington Mall Road, Suite 210, Burlington MA 01830-4123, http://www.TechnologyExchange.com.

Course Description

Windows NT 4.0: Device Drivers, A 5-day course.

Key Benefits

  • Learn the basic principles of Windows NT Device Driver programming.
  • Understand how device drivers fit into the Windows NT system.
  • Use the Microsoft driver build environment and Numega's SoftIce to produce a device driver.
  • Develop strategies for solving driver problems.
  • Write demonstration Windows NT Device Drivers.

Who Should Attend

This course is designed for programmers responsible for developing new Windows NT drivers. Students must be fluent in C and an understanding of peripheral interface hardware and I/O programming for at least one hardware platform is necessary. Knowledge of operating systems principles is helpful, but issues such as Interrupt Services, Memory Management, DMA, Intel and Digital Alpha Hardware Architecture, Symmetric Multiprocessor (SMP) machines, caches, and virtual memory are covered during the course overview.

Course Overview

This course presents an accelerated introduction to programming Windows NT device drivers. Students learn the basic principles of Windows NT I/O system architecture. Course content encompasses Drivers, Class Drivers, MiniDrivers, the Hardware Abstraction Layer (HAL), I/O Request Packets (IRPs), Deferred Procedure Calls (DPCs), Interrupt Service Routines (ISRs), the I/O manager, and the use of the Registry to maintain device information. Knowledge gained in this course is a prerequisite for writing WDM Drivers for Windows NT 5 and Windows 98.



0201695901P04062001

Updates

Errata

Untitled Document Read the Errata for this book.

Submit Errata

More Information

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020