Vous êtes sur la page 1sur 376

Controlador de

Dispositivos
Ingeniería en Sistemas Computacionales

Salvador Gurrola Velazquez


Salvador.gurrola@yahoo.com.mx
Device Drivers
Aportación de la asignatura al
perfil del egresado
◦ Conocer, desarrollar y administrar
software para el control de
dispositivos.
◦ Identificar y evaluar características para
desarrollar software para los
controladores
OBJETIVO GENERAL DEL
CURSO
◦ Proporcionar los conocimientos
necesarios, los cuales le permitan al

Device Drivers
Conceptos Introductorias
◦ Antecedentes y avances de los Arquitectura del Software
controladores. Controlador
 Escenario actual. Descripción de la
◦ Definición de controlador. arquitectura.
◦ Campo de aplicación. Análisis de los
◦ Importancia en el mercado. requerimientos para el
◦ Importancia de la independencia de la desarrollo del software
plataforma. controlador.
 Tipos de controladores. Diseño de los
◦ Tipos de controladores. requerimientos del
 Controlador Abierto (Libre). desarrollo del software
 Definición.
 Aplicación.
controlador.
 Controlador cerrado (privado). Tipos de la arquitectura.
 Definición. El enfoque arquitectónico.
 Aplicación. Patrones de arquitectura.
 Normas y estándares. (Diseño)
◦ Gestión avanzada de accesos. Estilos Arquitectónicos.
 Concurrencia.
Planos Arquitectónicos.
 Dos o más peticiones a la vez.
Proyecto Final
◦ Seguridad.
 Acceso a datos.
Desarrollar un sistema que
 Acceso a recursos. administre un controlador de
 Autenticación. dispositivos.
 Administración de la concurrencia.
Device Drivers
 Agenda
◦ Semana1 Agosto -27 Conceptos Introductorias
◦ Semana2 Septiembre -3
◦ Semana3 Septiembre- 10
◦ Semana4 Septiembre- 17
◦ Semana5 Septiembre – 24 Tipos de controladores.
◦ Semana6 Octubre - 1
◦ Semana7 Octubre - 8
◦ Semana8 Octubre - 15
◦ Semana9 Octubre – 22 Arquitectura del Software Controlador
◦ Semana10 Octubre - 29
◦ Semana11 Noviembre- 5
◦ Semana12 Noviembre - 12
◦ Semana13 Noviembre - 19
◦ Semana14 Noviembre – 26 Proyecto Final
◦ Semana15 Diciembre - 3
◦ Semana16 Diciembre - 10
◦ Semana17 Diciembre – 17 Examenes de Regularizacion y
Extraordinarios
Device Drivers
Evaluación
◦ Asistencia 10%
◦ Examenes 90%
Evaluación ultima unidad
◦ Documentación 50%
◦ Proyecto 50%

Device Drivers
Proyecto
 Desarrollar un sistema que administre un
controlador de dispositivos.

Device Drivers
 FUENTES DE INFORMACIÓN
 1. http://es.wikipedia.org/wiki/Controlador_de_dispositivo
 2. http://www.amazings.com/ciencia/noticiasn/breves.html
 3. http://www.fimee.ugto.mx/webfimee2006/temario_electric.html
 4.
http://msdn.microsoft.com/library/spa/default.asp?url=/library/SPA/dv
 5.
http://www.getronics.com/NR/rdonlyres/egqe44mqr3eiwp65mn6hllxw
 6.
http://www.levelfour.com/pressreleases/2004/12/15/spanish/?PHPSES
 7.
http://www.fujitsu.com/es/services/sectors/bank/solutionsbank/mdcs.
 8. http://insecure.org/tools/tools-es.html
 9.
http://www.imheguia.com/izaro_2005/index_imhe.php?modulo=redac
 10. http://www.smartmatic.com/noticias_2006.htm
 11. http://gforge.puj.edu.co/
Libros
  Programming the Microsoft Windows
Driver Model / Walter Oney -- 2nd ed.
    ISBN 0-7356-1803-8
 The Windows 2000 Device Driver Book,
A Guide for Programmers, Second
Edition Art Baker Jerry Lozano
Publisher: Prentice Hall PTR Second
Edition November 20, 2000
ISBN: 0-13-020431-5
 http://www.microsoft.com/whdc/devtools
/wdk/default.mspx
 http://msdn.microsoft.com/en-us/library

Unidad I
◦ Antecedentes y avances de los
controladores.
 Escenario actual.
◦ Definición de controlador.
◦ Campo de aplicación.
◦ Importancia en el mercado.
◦ Importancia de la independencia de la
plataforma.

Controlador de
dispositivo
 Un controlador de dispositivo
(llamado normalmente controlador,
o, en inglés, driver) es un
programa informático que permite al
sistema operativo interactuar con un
periférico, haciendo una abstracción
del hardware y proporcionando una
interfaz posiblemente estandarizada
para usarlo.
 Se puede esquematizar como un
manual de instrucciones que le indica
cómo debe controlar y comunicarse
con un dispositivo en particular.
Tipos de controladores
Existen tantos tipos de
controladores como tipos de
periféricos, y es común encontrar
más de un controlador posible
para el mismo dispositivo, cada
uno ofreciendo un nivel distinto de
funcionalidades.
Por ejemplo, aparte de los oficiales
(normalmente disponibles en la
página web del fabricante), se
pueden encontrar también los
proporcionados por el sistema
Tipos de controladores
Debido que el software de
controladores de dispositivos se
ejecuta como parte del sistema
operativo, con acceso sin
restricciones a todo el equipo,
resulta esencial que sólo se
permitan los controladores de
dispositivos autorizados.
La firma y el almacenamiento
provisional de los paquetes de
controladores de dispositivos en
los equipos cliente, mediante las
Tipos de controladores
• Seguridad mejorada.
◦ Puesto que los usuarios estándar no
pueden instalar controladores de
dispositivos que no estén firmados o
que estén firmados por un editor que
no es de confianza, los
administradores tendrán un control
riguroso respecto a los controladores
de dispositivos que pueden usarse
en una organización.
◦ Podrán impedirse los controladores de
dispositivos desconocidos, así como
cualquier controlador de dispositivo
Tipos de controladores
• Reducción de los costes de
soporte técnico.
◦ Los usuarios sólo podrán instalar
los dispositivos que hayan sido
probados y admitidos por la
organización.
◦ En consecuencia, el sistema
permite mantener la seguridad del
equipo, al tiempo que se reducen
las solicitudes del departamento
de soporte técnico.
Tipos de controladores
• Experiencia de usuario
mejorada.
◦ Un paquete de controladores
firmado por un editor de confianza
y almacenado provisionalmente
en el almacén de controladores
funciona de modo automático,
cuando el usuario conecta el
dispositivo al equipo.
◦ No se requiere acción alguna por
parte del usuario.
Creación de
controladores
 Normalmente son los fabricantes del
hardware quienes escriben sus
controladores, ya que conocen mejor
el funcionamiento interno de cada
aparato, pero también se encuentran
controladores libres, por ejemplo en
los sistemas operativos libres.
 En este caso, los creadores no son de la
empresa fabricante, aunque a veces
hay una cooperación con ellos, cosa
que facilita el desarrollo.
 Si no la hay, el procedimiento necesita
de ingeniería inversa y otros métodos
Creación de
controladores
Los controladores de dispositivo
(device drivers en inglés) son
programas añadidos al núcleo
del sistema operativo,
concebidos inicialmente para
gestionar periféricos y
dispositivos especiales.
Creación de
controladores
Los controladores de dispositivo han
sido tradicionalmente programas
binarios puros, similares a los COM
aunque ensamblados con un ORG
0, a los que se les colocaba una
extensión SYS.
Sin embargo, no hay razón para que
ello sea así ya que un controlador
de dispositivo puede estar incluido
dentro de un programa EXE, con la
condición de que el código del
controlador sea el primer
Fallos de controladores
Alser una parte crítica del sistema
operativo, el fallo de un
controlador puede ser más grave
que otros errores de software,
pudiendo bloquear la computadore
o incluso dañar el hardware.
Debido a que el hardware es
(necesariamente) indeterminista,
encontrar y solucionar un fallo en
un controlador es una tarea
complicada ya que no sólo hay que
monitorear el programa, sino
Unit I Device Driver
Understand Driver and Operating Sy
Determine Device-Specific Driver Re

Make Driver Design Decisions


Build, Test, and Debug the Driver
Provide a Driver Package
Distribute a Driver

Device Driver

Device Hardware

Device Driver

Driver Software
Windows Operating
System
Drivers Modes
run in the non privileged processor
mode

User Mode

Use Win32 API

run as part of the operating system


can perform certain protected operations and
can access system structures

Kernel Mode more difficult debugging


greater chance of system corruption
Overview of Windows
Driver Development
Steps to develop a driver through
the planning and decision-making
process involved in developing a
Windows device driver, starting
with design and continuing
through distribution.
Given the wide variation among
devices and the intricate nature of
driver operations, no single driver
design or development plan can
cover every possible technology.

Overview of Windows
Driver Development
However, any driver development
project will proceed more smoothly
and efficiently if you:
◦ Follow industry standards for
hardware and drivers
◦ Understand important operating
system and driver concepts
◦ Decide early in the design process
which operating system platforms to
support
◦ Test for device and driver
compatibility with all Windows
operating systems you plan to
Overview of Windows
Driver Development
 Steps in Driver Development
◦ Step 1:
Understand Driver and Operating System Basics
Before starting design, you should understand the
fundamentals of how drivers work in Windows
operating systems. Knowing the fundamentals will
help you make appropriate design decisions and
streamline your development process.
◦ Step 2:
Determine Device-Specific Driver Requirements
Each Windows device class has specific hardware
and software requirements. Devices and drivers
should conform to these requirements to operate
correctly with other system components.
Understanding and following these requirements
during hardware and software design can save you
time and money.
◦ Step 3: Make Driver Design Decisions Before you
Overview of Windows
Driver Development(99)
 Steps in Driver Development
◦ Step 4: Build, Test, and Debug the Driver Building a
driver is not the same as building a user-mode
application. This section gives tips on how to use
the "free" and "checked" operating system builds
and how to configure the build environment for a
driver. Iterative testing and debugging on as many
hardware configurations as possible helps to
ensure a working driver.
◦ Step 5: Provide a Driver Package Exactly how a
driver must be installed depends on the type of
driver and device. This section helps you
determine which device installation components
you must provide, and outlines what Windows
expects during device installation.
◦ Step 6: Distribute a Driver The final step in driver
development is to distribute the driver. If your
driver meets the quality standards defined for the
Understanding Driver and
Operating System Basics
Overview of System Components
User-Mode Drivers and Kernel-Mode
Layered Driver Architecture
Device Drivers and File System Driv

Windows Driver Model (WDM) Defin


Operating System Concepts for Driv


Understanding Driver and
Operating System Basics
 Overview of System Components for Driver Writers

 Windows Component
Overview
◦ The figure shows, the operating
system includes kernel-mode
components and user-mode
components.
◦ User-mode drivers and applications
can use the routines defined in the
Microsoft Win32 application
programming interface (API. The
Win32 API, in turn, calls exported
driver and operating system
kernel routines.
◦ Kernel-mode drivers can use support
routines that are defined and
exported by various components
of the operating system kernel.
These routines support I/O,
configuration, Plug and Play,
power management, memory
management, and numerous other
operating system features.
Understanding Driver and
Operating System Basics
◦ User-Mode Drivers and Kernel-Mode
Drivers
 Windows drivers can run in either user mode
or kernel mode.
User-mode drivers run in the non
privileged processor mode
User-mode drivers cannot gain access to
system data except by calling the Win32
API which, in turn, calls system services.
Kernel-mode drivers run as part of the
operating system's executive.
User-mode and kernel-mode drivers have
different structures, different entry points,
Understanding Driver and
Operating System Basics
◦ Windows Driver Model (WDM)
Defined
 Any kernel-mode device driver that
conforms to the Windows Driver Model
(WDM) is called a WDM driver.
WDM defines an approach to writing
kernel-mode device drivers for all
Windows operating systems.
Any device driver that will run on
Windows 2000 and later operating
systems must be a WDM driver.
With a few special-case statements in the
code, WDM drivers can be source-
Understanding Driver and
Operating System Basics
◦ Layered Driver
Architecture
Windows operating
systems support a
layered driver
architecture. Every
device is serviced by a
chain of drivers,
typically called a
driver stack. Each
driver in the stack
isolates some
hardware-dependent
features from the
drivers above it.
The following figure
Understanding Driver and
Operating System Basics
◦ Layered Driver
Architecture
◦ Above the driver stack is an application. The
application handles requests from users and
other applications, and calls either the Win32
API or a routine that is exposed by the user-
mode client driver.
◦ A user-mode client driver handles requests from
applications or from the Win32 API. For
requests that require kernel-mode services, the
user-mode client driver calls the Win32 API,
which calls the appropriate kernel-mode client
or support routine to carry out the request.

Understanding Driver and
Operating System Basics
◦ Layered Driver
Architecture
◦ A kernel-mode client driver handles
requests similar to those handled
by the user-mode client, except
that these requests are carried
out in kernel mode, rather than in
user mode.
◦ A device class and miniclass driver
pair provides the bulk of the
device-specific support.
Making Driver Design Decisions
After you determine what kind of driver
your device requires, you can begin
designing your driver. The following
topics describe several design issues
that you should consider:
 Choosing a Driver Model
Choosing a Programming Language
Driver Design and Implementation Strategies
Creating Reliable and Secure Drivers
Using the WDK Samples
Upgrading a Legacy Driver
Writing Drivers for Multiple Platforms and Operating
Planning for 64 Bits
Providing Driver Localization

Making Driver Design Decisions
◦ Choosing a Driver Model
 Most Windows drivers are kernel-mode
drivers .
Drivers use a set of interfaces that enable
the driver to communicate with kernel-
mode Windows components, such as the
I/O manager and the Plug and Play (PnP)
manager.
Making Driver Design
Decisions
◦ Choosing a Programming
Language
 For maximum portability, drivers should
be written in a high-level language,
typically C for kernel-mode drivers,
and C or C++ for user-mode drivers.
Making Driver Design
Decisions
◦ Creating Reliable and Secure
Drivers
Validate input parameters.
Validate registry
contents.
Use safe string functions.
Provide secure device
installations.
Making Driver Design
Decisions
◦ Using the DDK Samples
 The Windows DDK includes sample source code for a variety
of drivers. The samples can be useful guides for writing
your own drivers. When you install the DDK, samples are
installed in subdirectories of the \src directory.
 If you choose to base your code on one or more of the
samples, keep in mind the following:
 Some samples are not complete drivers, but
instead provide guidelines for how such drivers
could be written. For instance, samples might
omit error-handling code in the interest of
brevity and clarity.
Make sure to use a driver sample that was written
for the type of driver that you are writing. For
example, if you are writing a function driver, use
a sample function driver. If you are writing a
storage filter driver, use a sample storage filter
driver.
Making Driver Design
Decisions
◦ Upgrading a Legacy Driver
Although Microsoft Windows 2000 and
later versions of the operating system
continue to support some legacy drivers
written for Windows NT, new drivers
should be WDM drivers.
The system-supplied device drivers have
been modified to support WDM, which
includes Plug and Play and power
management.

Making Driver Design
Decisions
◦ Upgrading a Legacy Driver
 If you choose to try to upgrade a
driver, your driver will require the
following types of changes:
Updating or replacing the driver
INF file.
support for Plug and
Supporting power management

Making Driver Design
Decisions
◦ Planning for 64 Bits
 Whether you are writing a new driver or
modifying an existing driver, you should
consider making it compatible with 64-bit
Windows. The Windows Driver Kit (WDK)
includes 64-bit build environments that
you can use to create 64-bit drivers.
Many of the driver samples included with
the WDK are designed for 64-bit
compatibility, as noted in the Readme
files for the individual samples.

Building, Debugging, and
Testing Drivers

This section provides basic


information and guidance on
building, debugging and testing
drivers.
Signing Software for Use in
a Driver Development
Environment
◦ New uses of code-signing technology in
Windows Vista include the following:
 A new Windows Vista feature, User
Account Control (UAC), verifies
signatures and prompts users before
allowing executables to run with
administrator privileges or exercise
administrator privileges.
Installation packages and
executables that are downloaded
with Microsoft Internet Explorer have
a default setting of "don’t run" when
Signing Software for Use in a
Driver Development
Environment
◦ New uses of code-signing technology in
Windows Vista include the following:
Windows Defender is a feature of
Windows Vista that protects
Windows computers against
spyware and malicious code.
Plug and Play (PnP) driver installation
policy requires that a system
administrator manually authorizes
the installation of an unsigned
driver.
Kernel-mode code signing policy on
Signing Drivers During
Development and Test
◦ On Windows Vista, you should test sign drivers
during development and test with a digital
signature for the following reasons:
 To facilitate and automate installation.
If a driver is not signed, Plug and Play
(PnP) driver installation policy requires
that a system administrator manually
authorize the installation of an unsigned
driver, adding a extra step to the
installation process.
To be able load kernel-mode drivers on x64-
based editions of Windows Vista.
By default, kernel-mode code signing
policy for x64-based versions of
Windows Vista requires that a kernel-
Building, Debugging, and
Testing Drivers
◦ Building, testing, and debugging a driver
is an iterative process that involves the
following steps:
 Writing the driver code, which should
include debugging routines and
macros that are flagged for
conditional compilation
Creating a driver package to install the
driver
Building a checked version of the
driver
Building, Debugging, and
Testing Drivers

Building a production version of the driver
that does not include debugging
information (commonly referred to as a
free version)
Test signing the driver package
Installing, testing, and debugging the
installation of the driver on each target
operating system
Installing, testing, and debugging the free
version of the driver on each target
Building Drivers
◦ The WDK includes an environment for
building drivers that closely matches the
build environment used internally at
Microsoft.
◦ This environment includes various tools that
are useful in developing drivers, including
build utilities
 build.exe and nmake.exe
a C compiler (cl.exe), and a
linker (link.exe).
◦ The WDK no longer includes build
environments for Windows 98 and
Windows Me.
◦ If you intend to build drivers on these
systems, install the Windows XP Service
Building Drivers

Header Files in the Windows


Driver Kit
◦ WDK contains all of the header files (.h
files) that you need to build kernel-
mode and user-mode drivers.
◦ After you have installed the WDK, you
can find the header files under the
\inc subdirectory.

Building Drivers

Header Files in the Windows


Driver Kit
◦ Starting with the Windows Vista version
of the WDK, the following changes
have been made to the content,
structure, and organization of the
header files:
 Header files contain version information.
Including version information in header
files helps to support development of
drivers for multiple operating system
versions.
Debugging Drivers
◦ The Microsoft Windows Driver
Development Kit (DDK) includes the
Debugging Tools for Windows
package.
◦ Debugging kernel-mode drivers
requires two computers − a host
computer that runs the debugger and
a target computer that runs the
driver.
◦ The Microsoft Visual Studio debugger
can be used to debug user-mode
programs on all Windows operating
Testing Drivers
◦ Windows Logo Testing
Microsoft's Windows Hardware Quality
Labs (WHQL) tests drivers for compliance
with the requirements of the Windows
Logo Program for hardware.
Through this program, device
manufacturers can license the Windows
logo for use on product packaging,
advertising, and other marketing
materials for all systems and
components that pass compliance
testing.
Hardware and drivers must pass WHQL
testing to receive a Windows logo, to
Testing Drivers
◦ Tips for Testing Drivers
 Run the "Designed for Windows" logo
program tests for your device type, even if
you do not intend to submit your device
and driver for the "Designed for Windows"
logo.
Test your driver and device on as many
different hardware configurations as you
possibly can.
Varying the hardware can help you find
conflicts between devices and other errors
in device interactions.
Test your driver and device on
multiprocessor systems.
Race conditions and other timing problems
Testing Drivers

◦ Tips for Testing Drivers


Test your driver and device for specific
system and hardware conditions,
particularly edge conditions.
For example, these conditions might include
"D3 hot" and "D3 cold." Make sure your
driver and device can return correctly from
device power state "D3 hot" (without
losing power) and "D3 cold" (when power
is removed from the device).


Providing a Driver
Package
◦ A driver package consists of all
the hardware and software
components you must supply in
order for your device to be
supported under Windows.
◦ Installing a device or driver
involves system-supplied and
vendor-supplied components.
◦ The system provides generic
installation software for all
device classes.
Providing a Driver
Package

◦ Components of a Driver Package


The device
Driver files
Installation files
Other files



Providing a Driver
◦ Package
Components of a Driver Package
◦ The Device
 If you're involved in designing and building a new device,
follow industry hardware standards. Building devices that
conform to industry standards can streamline your driver
development process as well as reduce support costs. .
◦ Driver Files
 The driver is the part of the package that provides the I/O
interface for a device.
 Typically, a driver is a dynamic-link library with the .sys file
name extension.
 Long file names are allowed, except for boot drivers.
 When a device is installed, Setup copies the .sys file to the
%windir%\system32\drivers directory.
 The software required to support a particular device
depends on the features of the device and the bus or port
to which it connects.
 Microsoft ships drivers for many common devices and nearly
all buses with the operating system.
Providing a Driver
Package
◦ Components of a Driver Package
 Installation Files
In addition to the device and the driver, a driver
package also contains one or more of the
following files, which provide driver installation:
 A device setup information file (INF file)
 An INF file contains information that the system Setup
components use to install support for the device.
Setup copies this file to the %windir%\inf directory when it
installs the device.
Every device must have an INF file.
A driver catalog (.cat) file
A driver catalog file contains a cryptographic hash of each
file in the driver package.
Windows uses these hashes to verify that the package was
not altered after it was published.
To ensure that the catalog file is not altered, it should be
digitally signed.
One or more co-installers
A co-installer is a Microsoft Win32 DLL that assists in device
Providing a Driver
Package
◦ Installation Component Overview
To install a device or a driver, the
operating system requires the following
information at a minimum:
The name and version number of each
operating system on which the device or
drivers are supported
The device's setup class GUID and setup class
Driver version information
The names of the driver files along with their
source and destination locations
Device-specific information, including
hardware ID and compatible IDs
The name of a catalog (.cat) file
information about how and when to load the
services provided by each driver

Unit II

Windows NT Operating

System
Windows Architecture
System Processes Services Applications Environment
Subsystems
Service
Control Mgr .
Windows
LSASS SvcHost . Exe Task Manager
WinMgt . Exe Explorer
WinLogon
SpoolSv . Exe User OS / 2
User Application
Mode Services . Exe
Session POSIX
Manager
Subsystem DLLs Windows DLLs

System NTDLL . DLL


Threads

Kernel
Mode System Service Dispatcher

( kernel mode callable interfaces ) Windows


USER ,
I / O Mgr GDI

Configura -
( registry )
Reference

Processes

Procedure
Play Mgr .
Plug and

Security

tion Mgr
Monitor

Virtual

Threads
Object

Memory
System

Power

Local
Cache
File

Call
Mgr .

Mgr .

Device &

&
File Sys . Graphics
Drivers
Drivers

Kernel

Hardware Abstraction Layer ( HAL )

hardware interfaces ( buses , I / O devices , interrupts ,


interval timers , DMA , memory cache control , etc ., etc .)
Windows NT Architecture
 User Level
Applications/
Login POSIX MS-DOS Win-32 Win-16 OS/2
Processes

 Security
Subsystem
POSIX
Subsystem
OS/2
Subsystem


Win 32
Subsystem


Kernel Level

Windows NT Executive Services

I/O Manager Local


Object Security Process Procedure Virtual
Cache Mgr Manager Reference Manager Call Memory
Monitor Facility Manager
File System

N’work Drv.s

Device Drv.s
Microkernel (NT Kernel)

Hardware Abstraction Layer

MACHINE HARDWARE
Executive
 The executive is the main part of the kernel layer and
performs most of the traditional operating system
functions.
 It is made up of a group of components, the main ones
being:
◦ The I/O Manager,
◦ Object Manager,
◦ Security Reference Monitor,
◦ Process Manager,
◦ Local Procedure Call Facility and the
◦ Virtual Memory Manager.



The Object Manager
 The Object Manager is used to define and manage objects
which represent resources within the computer system.
 An example is where the Process Manager uses the object
manager to define an object which tracks all the
processes which are running.
 Part of the object management duties include identifying
the objects corresponding to resources and tracking how
many systems are accessing a resource.
 When no system is accessing a resource then the object
representing the resource can be deleted.
 As most of the native system services are resource related
they almost always invoke the object manager functions.
 The object manager can also call other executive
subsystems when necessary.


Object Manager
 The Windows kernel-mode object manager component manages objects.
Files, devices, synchronization mechanisms, registry keys, and so on, are
all represented as objects in kernel mode. Each object has a header
(containing information about the object such as its name, type, and
location), and a body (containing data in a format determined by each
type of object).
 Windows has more than 25 types of objects. A few of the types are:
◦ Files
◦ Devices
◦ Threads
◦ Processes
◦ Events
◦ Mutexes
◦ Semaphores
◦ Registry keys
◦ Jobs
◦ Sections
◦ Access tokens
◦ Symbolic links
The Process Manager
 The Process Manager works with the kernel, which carries
out scheduling, to define the process and thread objects.
 It adds the process identifier (PID) to each of the kernel's
process objects.




The Security Reference Monitor
 The Security Reference Monitor (SRM) is closely associated
with the object manager and is responsible for the strong
security capabilities in Windows NT.
 The object manager calls the SRM to provide a security
check whenever an application wishes to open an object
or perform an operation on an object like a read or write.
 The SRM uses the NT security procedures to validate
whether the operation can go ahead and whether it
should be logged.
 The SRM uses a security model based on Security
Identifiers (SID) and Discretionary Access Control Lists
(DACL).




Security Reference Monitor
 An increasingly important aspect of operating systems
is security.
 Before an action can take place, the operating system
must be sure that the action is not a violation of
system policy.
 For example, a device may or may not be accessible
to all requests.
 When creating a driver, you may want to allow some
requests to succeed or fail, depending on the
permission of the entity making the request.
 Windows uses an access control list (ACL) to
determine which objects have what security.
 The Windows kernel-mode security reference monitor
provides routines for your driver to work with access
control.
The Virtual Memory Manager
 The Virtual Memory Manager creates and manages memory
maps for processes and controls physical memory allocation.
 NT can address up to 4GB of memory and this is split between
user and kernel mode memory with the first 2GB going to
user mode applications.
 The memory is managed in pages of 4kB in Intel x86 systems,
different page sizes are used in other systems.
 The VMM allows the total memory required by an application to
exceed the memory available in the computer.
 This is done by using physical memory such as the hard disk,
and memory from a paging file when it is required by an
application.
 The VMM allows programs to share individual files and data.
 When any one then wishes to write to the shared data it gets
its own individual copy.
 The VMM also tunes the memory available to programs by
allocating extra memory where it is needed and ensuring all
Memory Manager
 The Windows kernel-mode memory manager
component manages physical memory for the
operating system.
 This memory is primarily in the form of RAM
(Random Access Memory).
 The memory manager manages memory by
performing the following major tasks:
◦ Managing the allocation and de-allocation of
memory virtually and dynamically.
◦ Supporting the concepts of memory-mapped
files, shared memory, and copy-on-write.



The I/O Manager
 The I/O Manager integrates all the add-on devices with NT.
 Drivers are dynamically loaded components designed to
provide hardware and network support.
 They are designed to run within the kernel and use the extra
functionality that this can provide.
 The drivers are usually supplied by the manufacturer of the
hardware and control the specific item by translating
commands from NT and applications to the device and then
manipulating the device to carry them out.
 NT uses asynchronous, packet based I/O for hardware
communication. Interrupt Request Packets (IRP) are used to
describes everything the device driver needs to know to
handle an applications requests.
 It includes the location of the buffer to read to, a pointer to the
open file object, offsets to where the data resides and the
amount of data the program has to read.
I/O Manager
 A computer consists of various devices that provide input and output (I/O)
to and from the outside world.
 Typical devices are keyboards, mice, audio controllers, video controllers,
disk drives, networking ports, and so on.
 Device drivers provide the software connection between the devices and
the operating system.
 For this reason, I/O is very important to the device driver writer.
 The Windows kernel-mode I/O manager manages the communication
between applications and the interfaces provided by device drivers.
 Because devices operate at speeds that may not match the operating
system, the communication between the operating system and device
drivers is primarily done through I/O request packets (IRPs).
 These packets are similar to network packets or Windows message
packets.
 They are passed from operating system to specific drivers and from one
driver to another.
 The Windows I/O system provides a layered driver model called stacks.
 Typically IRPs go from one driver to another in the same stack to facilitate
communication.
 For example, a joystick driver would need to communicate to a USB hub,
which in turn would need to communicate to a USB host controller,
The Local Procedure Call
Facility
The Local Procedure Call Facility optimises communications

for applications, including the operating system
environments.
 Communication between functions and objects in the
operating system is done via messages which are passed
in different ways depending on their size.
 Small messages of less than 256 bytes are copied directly
while larger ones are transferred using shared memory.
 This code has been highly optimised to ensure efficiency as
a slow call method would badly affect performance.
 From NT 3.51 to NT 4.0 Microsoft moved the GDI (graphics
device interface) out of the user mode and into the kernel
to reduce to number of calls using the LPC.
 This led to much improved responsiveness, especially for
graphics operations but at the cost of some stability.
The Kernel
 The kernel contains the NT thread scheduler called the
dispatcher.
 The dispatcher is a pre-emptive scheduler, time is divided
into slices called quantums and each thread can operate
for a quantum and then is pre-empted to allow another
thread to run.
 The kernel operates more closely with hardware than the
executive, and hence contains processor specific code.
 If the computer has multiple CPUs the kernel synchronises
activity between them to optimise performance.
 Kernel code does not run in threads
 The kernel also implements synchronisation and mutual
exclusion.
 It has it's own object types so applications can access them
from user mode via the native API.
Kernel Library
 Modern operating systems use the term kernel to
describe the core functionality that everything
else in the system depends upon.
 The Microsoft Windows kernel provides basic low-
level operations such as scheduling threads or
routing hardware interrupts.
 It is the heart of the operating system and all
tasks it performs must be fast and simple.
 Routines that provide a direct interface to the
kernel library are usually prefixed with "Ke", for
example, KeGetCurrentThread.


Hardware Abstraction Layer
 The HAL provides NT's interface to the CPU.
 To make NT portable as much of the processor specific code
as possible was restricted to here.
 So the HAL together with the kernel are dynamically
replaceable between processors families.
 The HAL exports a common processor model which hides
the differences in processor types. This common
processor used by device drivers.




Processes and Threads
 NT is a multithreading operating system.
 It runs multiple threads at once and can stop any particular thread
from executing.

 NT views applications as processes which have to be executed.


 A process will consist of a virtual address space, executable
instructions and a set of resources.
 Typically an application will consist of only one process and each
process will consist of one or more threads which are the parts of an
application that execute.
 Usually there is one thread per process though applications can have
more.
 Multiple threads allow a program to have several parts operating at
once.
 Deciding how to execute the threads and in what order is the job of
the operating system scheduler.
 In NT the scheduler is called the dispatcher and it is based in the
kernel.
 The dispatcher must allow several threads to appear to run
Process and Thread Manager
 A process is a software program that is currently running in Windows.
 Every process has an ID, a number that identifies it.
 A thread is an object that identifies which part of the program is running.
 Each thread has an ID, a number that identifies it.
 A process may have more than one thread.
 The purpose of a thread is to allocate processor time.
 On a machine with one processor, more than one thread can be allocated, but only
one thread can run at a time.
 Each thread only runs a short time and then the execution is passed on to the next
thread, giving the user the illusion that more than one thing is happening at once.
 On a machine with more than one processor, true multi-threading can take place.
 If an application has multiple threads, the threads can run simultaneously on different
processors.
 The Windows kernel-mode process and thread manager handles the execution of all
threads in a process.
 Whether you have one processor or more, great care must be taken in driver
programming to make sure that all threads of your process are designed so that
no matter what order the threads are handled, your driver will operate properly.
 If threads from different processes attempt to use the same resource at the same
time, problems can occur.
 Windows provides several techniques to avoid this problem.
 The technique of making sure that threads from different processes don't touch the
The NTFS File System
 From the start NTFS was designed as a 32-bit file system which made it more
scaleable.
 A key parameter for a file system is how it addresses a hard disk.
 FAT uses a 16 bit entry to address clusters on the disk. For a modern Giga-Byte size
hard disks this means the clusters, which are the minimum size storage unit on
the disk, have to be quite large in size.
 On a 4GB disk the clusters will be 64k.
 This leads to wasted space on the disk when smaller files are used.
 NT though has 32-bit entries so it can allow much smaller (less than 10k) cluster
sizes even with much larger hard disk sizes.
  
 NT uses a different character set to FAT.
 Instead of the 8-bit ASCII set NTFS uses 16-bit Unicode which allows a much greater
range of character types.
 This is particularly important for international users who wish to name files in their
native languages.
 Microsoft also built a security system into NTFS,
 The model used is the same as in the operating system and uses Discretionary
Access Control Lists (DACL) and System Access Control Lists (SACL).
 These control who can perform particular operations on a file and determine what file
actions are logged when they occur. And there is improved fault tolerance over
FAT by logging transactions.
The Remote Procedure Call
 The Remote Procedure Call (RPC) functions allow applications to carry out
distributed computing and access resources on other computers across
a network.
 With the RPCs you can create distributed applications which consist of a
client that presents data to the user and a server which collates data
and carries out most of the computing tasks for the client.
 The distributed application makes procedure calls to be executed on
another computer.
 To the application they appear the same as a local procedure call.
 But they invoke procedures which call the RPC library which executes the
calls in the remote address space on another machine across the
network.
 The RPC handles all the necessary steps to execute the calls so
applications need little or no network specific code.



Configuration Manager
 In the earlier days of Microsoft Windows, applications and the
operating system stored configuration values in "INI"
(initialization) files.
 This provided a simple way to store state values that could be
preserved from one Windows session to the next.
 However, as the Windows environment became more complex, a
new system of storing persistent information about the
operating system and applications was needed.
 The Windows Registry was created to store data about hardware
and software.
 The Windows kernel-mode configuration manager manages the
registry.
 If your driver needs to know about changes in the registry, it can
use the routines of the configuration manager to do so by
registering callbacks on specific registry data.
 Then, when the data in the registry changes, the callback is
triggered and you can run code to process the callback
information in your driver.
 Routines that provide a direct interface to the configuration
Kernel Transaction Manager
 When you are dealing with multiple reads and writes on one
or more data stores, and the operations must all
atomically succeed or fail to preserve the integrity of the
data, you might want to group the operations together as
a single transaction.
 If all of the operations within the transaction succeed, the
transaction can be committed so that all the changes
persist as an atomic unit.
 If a failure occurs, the transaction can be rolled back so that
the data stores are restored to their original state.
 The kernel transaction manager (KTM) is the Windows
kernel-mode component that implements transaction
processing in kernel mode.
 KTM allows kernel mode components, such as drivers, to
perform transactions.
Power Manager
 Windows uses power management technology to reduce power consumption for
PCs in general and for battery-powered laptops in particular.
 For example, a Windows computer can be put in a sleep or hibernation state.
 A complex power management system for computer devices has evolved so
that when the computer begins to shut down or go to lower power
consumption, the attached devices can also be powered down in a proper
manner so that no data is lost.
 But these devices need a warning that the power status in changing and they
may also need to be part of a communications loop that tells the controlling
device to wait until they can shut down down properly.
 The Windows kernel-mode power manager manages the orderly change in
power status for all devices that support power state changes.
 This is often done through a complex stack of devices controlling other devices.
 Each controlling device is called a node and must have a driver that can handle
the communication of power state changes up and down through a device
stack.
 If you are writing a driver that can be affected by power-state changes, you
must be able to process the following types of information in your driver
code:
◦ System activity level.
◦ System battery level.
◦ Current requests to shut down, sleep, or hibernate.
Plug and Play Manager
 Plug and Play (Pnp) is a combination of hardware
technology and software techniques that
enables a PC to recognize when a device is
added to the system.
 With PnP, the system configuration can change
with little or no input from the user.
 For example, when a USB drive is plugged in,
Windows can detect the drive and add it to the
file system automatically.
 However, to do this, the hardware must follow
certain requirements and so must the driver.
 The PnP manager is actually a subsystem of the
I/O manager.
Windows Kernel Prefixes
 The abbreviated prefixes refer to the individual  components of the
Windows kernel-mode operating system.
 Each component represents a specific functionality that the operating
system provides.
 The prefixes are a useful shorthand for quickly recognizing the basic
functionality and location of each routine.
 This is particularly useful for reading source code. For example, if you see a
routine that is prefixed “Mm”, you will know that it manages memory.

Aux - Auxiliary Library
Routines that allow access to system capabilities not available directly
from the kernel

Clfs –Common Log File System (CLFS) Library Routines that allow access to
the CLFS library

Cc – Cache Manager
Routines that allow access to the Cache Manager

Cm – Configuration Manager
Routines that allow access to the Configuration Manager
Windows Kernel Prefixes
 Ex – Executive Library
Routines that allow access to the system Executive library. This
library provides general policy
decisions not covered by other kernel-mode managers or
libraries.

Flt – Filter Manager


Routines that allow access to the filter manager

Hal – Hardware Abstraction Layer (HAL)


Routines that allow access to the low-level Hardware
Abstraction Layer

Io – I/O Manager
Routines that allow access to the I/O Manager

Ke – Core Kernel Library


Routines that allow access to the core Kernel Library
Windows Kernel Prefixes
 Mm – Memory Manager
Routines that allow access to the Memory Manager

Nt – User-mode Native Services


Routines that allow access to user-mode Native
Services

Ob – Object Manager
Routines that allow access to the Object Manager

Po – Power Manager
Routines that allow access to the Power Manager

Ps – Process and Thread Library


Routines that allow access to the Process and    
Thread Library
Windows Kernel Prefixes

Rtl – Run-Time Library


Routines that allow access to the kernel-mode     Run-time
Library, also includes the Safe String     Library
  
FsRtl – File System Run-time Library
Routines that allow access to the File System Run-time
Library

Se – Security Reference Monitor


Routines that allow access to the Security Reference
Monitor

Wmi – Windows Management Instrumentation Library


Routines that allow access to the Windows Management
Instrumentation Library

Zw – Kernel-mode wrappers for Native Services


Routines that provide kernel-mode access to   user-mode
Object Manager Routines

 InitializeObjectAttributes
ObDereferenceObject
ObDereferenceObjectDeferDelete
ObDereferenceObjectDeferDeleteWithTa
g
ObDereferenceObjectWithTag
ObGetObjectSecurity
ObReferenceObject
ObReferenceObjectWithTag
ObReferenceObjectByHandle
ObReferenceObjectByHandleWithTag
ObReferenceObjectByPointer
ObReferenceObjectByPointerWithTag
ObRegisterCallbacks
ObReleaseObjectSecurity
ObUnRegisterCallbacks

Object Memory Routines

 MmAdvanceMdl

 MmAllocateContiguousMemory

 MmAllocateContiguousMemorySpecifyCache

 MmAllocateContiguousMemorySpecifyCacheNode

 MmAllocateMappingAddress

 MmAllocateNonCachedMemory

 MmAllocatePagesForMdl

 MmAllocatePagesForMdlEx

 MmBadPointer

 MmBuildMdlForNonPagedPool

 MmCreateMdl

 MmFreeContiguousMemory

 MmFreeContiguousMemorySpecifyCache

 MmFreeMappingAddress

 MmFreeNonCachedMemory

 MmFreePagesFromMdl

 MmGetMdlByteCount
Object Memory Routines
 MmLockPagableCodeSection
 MmLockPagableDataSection
 MmLockPagableSectionByHandle
 MmMapIoSpace
 MmMapLockedPages
 MmMapLockedPagesSpecifyCache
 MmMapLockedPagesWithReservedMapping
 MmPageEntireDriver
 MmPrepareMdlForReuse
 MmProbeAndLockPages
 MmProtectMdlSystemAddress
 MmQuerySystemSize
 MmResetDriverPaging
 MmSecureVirtualMemory
 MmSizeOfMdl
 MmUnlockPagableImageSection
 MmUnlockPages
 MmUnmapIoSpace
 MmUnmapLockedPages
 MmUnmapReservedMapping
 MmUnsecureVirtualMemory
 Mm64BitPhysicalAddress
 ADDRESS_AND_SIZE_TO_SPAN_PAGES
 ARGUMENT_PRESENT
 BYTE_OFFSET
Process and Thread Manager Routines
 PsCreateSystemThread
PsGetCurrentProcess
PsGetCurrentProcessId
PsGetCurrentThread
PsGetCurrentThreadId
PsGetProcessCreateTimeQuadPart
PsGetProcessId
PsGetVersion
PsInitialSystemProcess
PsIsSystemThread
PsRemoveCreateThreadNotifyRoutine
PsRemoveLoadImageNotifyRoutine
PsSetCreateProcessNotifyRoutine
PsSetCreateProcessNotifyRoutineEx
PsSetCreateThreadNotifyRoutine
PsSetLoadImageNotifyRoutine
PsTerminateSystemThread

I/O Manager Routines
 IoAcquireCancelSpinLock
 IoAcquireRemoveLock
 IoAcquireRemoveLockEx
 IoAdjustPagingPathCount
 IoAllocateAdapterChannel
 IoAllocateController
 IoAllocateDriverObjectExtension
 IoAllocateErrorLogEntry
 IoAllocateIrp
 IoAllocateMdl
 IoAllocateWorkItem
 IoAssignArcName
 IoAssignResources
 IoAttachDevice
 IoAttachDeviceByPointer
 IoAttachDeviceToDeviceStack
 IoBuildAsynchronousFsdRequest
 IoBuildDeviceIoControlRequest
 IoBuildPartialMdl
 IoBuildSynchronousFsdRequest
 IoCallDriver
 IoCancelIrp
 IoCheckShareAccess
 IoCompleteRequest
 IoConnectInterrupt
 IoConnectInterruptEx
 IoCopyCurrentIrpStackLocationToNext
 IoCreateController
 IoCreateDevice
I/O Manager Routines
 IoCreateDeviceSecure

 IoCreateFile

 IoCreateNotificationEvent

 IoCreateSymbolicLink

 IoCreateSynchronizationEvent

 IoCreateUnprotectedSymbolicLink

 IoCsqInitialize

 IoCsqInitializeEx

 IoCsqInsertIrp

 IoCsqInsertIrpEx

 IoCsqRemoveIrp

 IoCsqRemoveNextIrp

 IoDeassignArcName

 IoDeleteController

 IoDeleteDevice

 IoDeleteSymbolicLink

 IoDetachDevice
I/O Manager Routines
 IoFreeWorkItem

 IoGetAffinityInterrupt

 IoGetAttachedDeviceReference

 IoGetBootDiskInformation

 IoGetConfigurationInformation

 IoGetContainerInformation

 IoGetCurrentIrpStackLocation

 IoGetCurrentProcess

 IoGetDeviceInterfaceAlias

 IoGetDeviceInterfaces

 IoGetDeviceNumaNode

 IoGetDeviceObjectPointer

 IoGetDeviceProperty

 IoGetDevicePropertyData

 IoGetDeviceToVerify

 IoGetDmaAdapter

 IoGetDriverObjectExtension
I/O Manager Routines
 IoInitializeRemoveLock

 IoInitializeRemoveLockEx

 IoInitializeTimer

 IoInitializeWorkItem

 IoInvalidateDeviceRelations

 IoInvalidateDeviceState

 IoIs32bitProcess

 IoIsErrorUserInduced

 IoIsWdmVersionAvailable

 IoMakeAssociatedIrp

 IoMapTransfer

 IoMarkIrpPending

 IoOpenDeviceInterfaceRegistryKey

 IoOpenDeviceRegistryKey

 IoQueryDeviceDescription

 IoQueueWorkItem

 IoQueueWorkItemEx
I/O Manager Routines
 IoReleaseRemoveLockAndWait

 IoReleaseRemoveLockAndWaitEx

 IoReleaseRemoveLockEx

 IoRemoveShareAccess

 IoReportDetectedDevice

 IoReportResourceForDetection

 IoReportResourceUsage

 IoReportTargetDeviceChange

 IoReportTargetDeviceChangeAsynchronous

 IoRequestDeviceEject

 IoRequestDpc

 IoReuseIrp

 IoSetCancelRoutine

 IoSetCompletionRoutine

 IoSetCompletionRoutineEx

 IoSetDeviceInterfaceState

 IoSetDevicePropertyData
I/O Manager Routines
 IoStartTimer

 IoStopTimer

 IoUnregisterContainerNotification

 IoUninitializeWorkItem

 IoUnregisterPlugPlayNotification

 IoUnregisterPlugPlayNotificationEx

 IoUnregisterShutdownNotification

 IoUpdateShareAccess

 IoValidateDeviceIoControlAccess

 IoVerifyPartitionTable

 IoVolumeDeviceToDosName

 IoWithinStackLimits

 IoWMIAllocateInstanceIds

 IoWMIDeviceObjectToProviderId

 IoWMIDeviceObjectToInstanceName

 IoWMIExecuteMethod

 IoWMIHandleToInstanceName
Power Manager Routines

 PoCallDriver
 PoClearPowerRequest
 PoCreatePowerRequest
 PoDeletePowerRequest
 PoEndDeviceBusy
 PoGetSystemWake
 PoQueryWatchdogTime
 PoRegisterDeviceForIdleDetection
 PoRegisterPowerSettingCallback
 PoRegisterSystemState
 PoRequestPowerIrp
 PoSetDeviceBusy
 PoSetDeviceBusyEx
 PoSetPowerRequest
 PoSetPowerState
 PoSetSystemState
 PoSetSystemWake
 PoStartDeviceBusy
 PoStartNextPowerIrp
 PoUnregisterPowerSettingCallback
 PoUnregisterSystemState
Configuration Manager Routines
CmCallbackGetKeyObjectID
CmGetBoundTransaction
CmGetCallbackVersion
CmRegisterCallback
CmRegisterCallbackEx
CmSetCallbackObjectContext
CmUnRegisterCallback




Kernel Transaction Manager (KTM) Routines

Transaction Manager Object
Routines
Transaction Object Routines
Enlistment Object Routines
Resource Manager Object
Routines
KTM Structures
KTM Enumerations




Security Reference Monitor Routines
SeAccessCheck
SeAssignSecurity
SeAssignSecurityEx
SeDeassignSecurity
SeSinglePrivilegeCheck
SeValidSecurityDescriptor




Core Kernel Library Support Routines
 KeAcquireSpinLockRaiseToSynch
 KeBreakinBreakpoint
 KeEnterKernelDebugger
 KeFlushWriteBuffer
 KeGetBugMessageText
 KeRaiseIrqlToSynchLevel
 KeRemoveByKeyDeviceQueueIfBusy
 KeSetTimeUpdateNotifyRoutine




Executive Library Support Routines
 ExAcquireFastMutex
ExAcquireFastMutexUnsafe
ExAcquireResourceExclusive
ExAcquireResourceExclusiveLite
ExAcquireResourceShared
ExAcquireResourceSharedLite
ExAcquireSharedStarveExclusive
ExAcquireSharedWaitForExclusive
ExAllocateFromLookasideListEx
ExAllocateFromNPagedLookasideList
ExAllocateFromPagedLookasideList
ExAllocateFromZone
ExAllocatePool
ExAllocatePoolWithQuota

Windows Kernel-Mode Run-Time Library
 Windows provides a set of common utility
routines needed by various kernel-mode
components.
 For example, RtlCheckRegistryKey is used to
see if a given key is in the registry.
 Most of the run-time library (RTL) routines are
prefixed with the letters "Rtl";




Run-Time Library (RTL) Routines
FirstEntrySList
InitializeListHead
InsertHeadList
InsertTailList
IsListEmpty
PopEntryList
PushEntryList
RemoveEntryList
RemoveHeadList
RemoveTailList
RtlAnsiCharToUnicodeChar
RtlAnsiStringToUnicodeSize
RtlAnsiStringToUnicodeString
RtlAppendUnicodeStringToString
RtlAppendUnicodeToString

Windows Kernel-Mode Safe String Library
 One of the major problems in software security is
related to the vulnerability of working with
strings.
 To provide greater security, Windows provides a
safe string library.
 Safe string library routines are prefixed with the
letters "Rtl"; for a list of all safe string library
routines for the kernel,




Safe String Library Routines
 Safe String Functions for Unicode and ANSI
Characters
 Safe String Functions for UNICODE_STRING
Structures




Windows Kernel-Mode DMA Library
 To enhance performance, a device may need
direct access to memory in a way that bypasses
the central processing unit (CPU).
 This technology is called direct memory access
(DMA). Windows provides a DMA library for
device driver developers.




DMA Library Routines
AllocateAdapterChannel
AllocateCommonBuffer
BuildMdlFromScatterGatherList
BuildScatterGatherList
CalculateScatterGatherList
FlushAdapterBuffers
FreeAdapterChannel
FreeCommonBuffer
FreeMapRegisters
GetDmaAlignment
GetScatterGatherList
MapTransfer
PutDmaAdapter
PutScatterGatherList
ReadDmaCounter

Windows Kernel-Mode HAL Library
 Windows runs on many different configurations of
the personal computer.
 Each configuration requires a layer of software
that interacts between the hardware and the
rest of the operating system.
 Because this layer abstracts (hides) the low-level
hardware details from drivers and the operating
system, it is called the hardware abstraction
layer (HAL).
 Developers are not encouraged to write their own
HAL.
 If you need hardware access, the HAL library
provides routines that can be used for that
purpose.
 Routines that interface with the HAL directly are
HAL Library Routines
 HalAllocateCommonBuffer
 HalAllocateHardwareCounters
 HalAssignSlotResources
 HalExamineMBR
 HalFreeCommonBuffer
 HalFreeHardwareCounters
 HalGetAdapter
 HalGetBusData
 HalGetBusDataByOffset
 HalGetDmaAlignmentRequirement
 HalGetInterruptVector
 HalReadDmaCounter
 HalReturnToFirmware
 HalSetBusData
 HalSetBusDataByOffset
 HalTranslateBusAddress
 READ_PORT_BUFFER_UCHAR
 READ_PORT_BUFFER_ULONG
 READ_PORT_BUFFER_USHORT
 READ_PORT_UCHAR
 READ_PORT_ULONG
HAL Library Routines
 READ_PORT_BUFFER_USHORT
 READ_PORT_UCHAR
 READ_PORT_ULONG
 READ_PORT_USHORT
 READ_REGISTER_BUFFER_UCHAR
 READ_REGISTER_BUFFER_ULONG
 READ_REGISTER_BUFFER_ULONG64
 READ_REGISTER_BUFFER_USHORT
 READ_REGISTER_UCHAR
 READ_REGISTER_ULONG
 READ_REGISTER_ULONG64
 READ_REGISTER_USHORT
 WRITE_PORT_BUFFER_UCHAR
 WRITE_PORT_BUFFER_ULONG
 WRITE_PORT_BUFFER_USHORT
 WRITE_PORT_UCHAR
 WRITE_PORT_ULONG
 WRITE_PORT_USHORT
 WRITE_REGISTER_BUFFER_UCHAR
 WRITE_REGISTER_BUFFER_ULONG
 WRITE_REGISTER_BUFFER_ULONG64
 WRITE_REGISTER_BUFFER_USHORT
 WRITE_REGISTER_UCHAR
 WRITE_REGISTER_ULONG
 WRITE_REGISTER_ULONG64
 WRITE_REGISTER_USHORT


Windows Kernel-Mode CLFS Library
 Windows provides a transactional logging system
for system files.
 This system is called the Common Log File
System (CLFS).
 Routines that provide a direct interface for CLFS
are prefixed with the letters "Clfs";



CLFS Library Routines
 ClfsAddLogContainer
ClfsAddLogContainerSet
ClfsAdvanceLogBase
ClfsAlignReservedLog
ClfsAllocReservedLog
ClfsCloseAndResetLogFile
ClfsCloseLogFileObject
ClfsCreateLogFile
ClfsCreateMarshallingArea
ClfsCreateScanContext
ClfsDeleteLogByPointer
ClfsDeleteLogFile
ClfsDeleteMarshallingArea
ClfsFlushBuffers
ClfsFlushToLsn
ClfsGetContainerName
Windows Kernel-Mode WMI Library
 Windows provides a general mechanism for
managing components.
 This system is called Windows Management
Instrumentation (WMI). To satisify Windows
Driver Model (WDM) requirements, you should
implement WMI for your driver so that your
driver can be managed by the system.
 Routines that provide a direct interface to the
WMI library are prefixed with the letters "Wmi";



WMI Library Routines

WmiCompleteRequest
WmiFireEvent
WmiQueryTraceInformation
WmiSystemControl
WmiTraceMessage
WmiTraceMessageVa
WMI Library Callback Routines



The WIN32 API
 The Win32 API was developed by Microsoft as their own 32-bit API to
compete with the POSIX and OS/2 APIs and has proved to be extremely
successful.
 Win32 provides a set of functions, messages and structures to give
applications access to the features of the operating system in a
standard and consistent fashion.
 The Win32 API can be split into five general functional categories.
  
◦ Windows Management
◦ GDI - Graphics Device Interface
◦ System Services
◦ Multimedia
◦ Remote Procedure Calls




The Windows Management
 The Windows Management set of functions allow applications to use the
standard Windows graphic user interface features.
 Usually there is one window per application and this can be used for
display output and user input.
 The API defines window classes and procedures to be used by the
applications and these give the appearance and behaviour of the
windows.
 Input from the mouse and keyboard is passed as messages by message
functions to the correct application in the window and to the appropriate
window procedure.
 The functions also provided for dialog boxes, scrolling text, entering text
and all the other features used in the Windows GUI.
  
 The functions also generate the output for the windows.
 This is done using the GDI functions to provide the instructions to the
display hardware.
 Some of the things involved are: applications shouldn't take all the screen
and when a window is resized the API will request the application to

paint the new window or window position.


The Graphics Device Interface
 The Graphics Device Interface (GDI) provides functions and related
structures to allow applications to generate graphical output for displays
and devices like printers.
 The GDI functions allow lines, curves, bitmaps, text etc to be drawn and be
passed to hardware devices.
 Applications direct output to a device by creating a 'context' for that
device.
 A handle for the device is returned by the GDI.
 Handles are used by the application to identify the device and get
information on it and it's capabilities.
 Applications use attribute functions to set selections and operating modes
for the selected device.


Operating modes includes things like brush types, background colours etc.



The System Services
 The System Services were mentioned before but additional information on
them is given here.
 The system services are the set of functions which give applications access
to the resources of a computer, and the features of the underlying
operating system, like memory, files systems and processes.
 An application uses the system services to manage and monitor the
resources it needs to complete it's task.
 They support file I/O functions and provide methods for applications to
share resources with other applications using Dynamic Link Libraries
(DLLs).
 Useful procedures are put in a DLL and applications can access them with
DLL functions.
 System information functions allow applications get information about the
computer such as what input devices are present and what size the
screen is.



Multimedia Functions
 The range of Multimedia Functions give applications access to audio and
video and provide services for file I/O, media control, joysticks and
timers.
 The different types of multimedia functions include audio functions to play
and record audio data.
 This is done with a variety of formats including waveform, MIDI, etc.
 The audio functions have the capability to use compression and
decompression and sound mixing.
 Video functions are used to capture video, compress the clips and control
payback. Playback can be done using the Media Control Interface (MCI)
which is controlled with the video functions.
 There also are a range of file I/O functions which are used to store and
retrieve the different types of multimedia files.



Windows API
 The functionality provided by the Windows API can be
grouped into eight categories
◦ Base Services
Provide access to the fundamental resources
available to a Windows system. Included are
things like file systems, devices, processes and
threads, and error handling. These functions
reside in kernel.exe, krnl286.exe or krnl386.exe
files on 16-bit Windows, and kernel32.dll on 32-
bit Windows.
◦ Advanced Services
Provide access to functionality that is an addition
on the kernel. Included are things like the
Windows registry, shutdown/restart the system
(or abort), start/stop/create a Windows service,
manage user accounts. These functions reside in
advapi32.dll on 32-bit Windows.

Windows API
 Graphics Device Interface
◦ Provides functionality for outputting graphical
content to monitors, printers and other
output devices. It resides in gdi.exe on 16-bit
Windows, and gdi32.dll on 32-bit Windows in
user-mode. Kernel-mode GDI support is provided
by win32k.sys which communicates directly with
the graphics driver.
 User Interface
◦ Provides the functionality to create and manage
screen windows and most basic controls, such as
buttons and scrollbars, receive mouse and
keyboard input, and other functionality
associated with the GUI part of Windows. This
functional unit resides in user.exe on 16-bit
Windows, and user32.dll on 32-bit Windows.
Windows API
 Common Dialog Box Library
◦ Provides applications the standard dialog boxes for
opening and saving files, choosing color and font,
etc. The library resides in a file called commdlg.dll on
16-bit Windows, and comdlg32.dll on 32-bit Windows.
It is grouped under the User Interface category of the
API.
 Common Control Library
◦ Gives applications access to some advanced controls
provided by the operating system. These include
things like status bars, progress bars, toolbars and
tabs. The library resides in a DLL file called
commctrl.dll on 16-bit Windows, and comctl32.dll on
32-bit Windows. It is grouped under the User
Interface category of the API.


Windows API
 Windows Shell
◦ Component of the Windows API allows applications to
access the functionality provided by the
operating system shell, as well as change and
enhance it. The component resides in shell.dll on 16-
bit Windows, and shell32.dll on 32-bit Windows. The
Shell Lightweight Utility Functions are in shlwapi.dll.
It is grouped under the User Interface category of the
API.
 Network Services
◦ Give access to the various networking capabilities of
the operating system. Its sub-components include
NetBIOS, Winsock, NetDDE, RPC and many others.


Windows API
 Web
◦ The Internet Explorer web browser also exposes many API's
that are often used by applications, and as such could be
considered a part of the Windows API. Internet Explorer has
been included with the operating system since
Windows 98 Second Edition, and has provided web related
services to applications since Windows 98. Specifically, it is
used to provide:
 An embeddable web browser control, contained in
shdocvw.dll and mshtml.dll.
The URL monitor service, held in urlmon.dll, which
provides COM objects to applications for resolving
URLs. Applications can also provide their own URL
handlers for others to use.
A library for assisting with multi-language and
international text support (mlang.dll).
DirectX Transforms, a set of image filter components.
XML support (the MSXML components, held in
msxml*.dll).
Windows API
 Multimedia
◦ Microsoft has provided the DirectX set of APIs as part of every
Windows installation since Windows 95 OSR2. DirectX provides a
loosely related set of multimedia and gaming services, including:
 Direct3D for access to 3D hardware accelerated graphics.
 DirectDraw for hardware accelerated access to the 2D frame
buffer. As of DirectX 9, this component has been deprecated
in favor of Direct3D, which provides more general high-
performance graphics functionality (as 2D rendering is a
subset of 3D rendering).
 DirectSound for low level hardware accelerated sound card
access.
 DirectInput for communication with input devices such as
joysticks and gamepads.
 DirectPlay as a multiplayer gaming infrastructure. This
component has been deprecated as of DirectX 9 and Microsoft
no longer recommends its use for game development.
 DirectShow which builds and runs generic multimedia pipelines.
It is comparable to the GStreamer framework and is often
used to render in-game videos and build media players (
Windows Media Player is based upon it). DirectShow is no
longer recommended for game development.
Windows API
 Program interaction
◦ The Windows API mostly concerns itself with the
interaction between the operating system and an
application.
◦ For communication between the different Windows
applications among themselves, Microsoft has
developed a series of technologies alongside the
main Windows API.
◦ This started out with Dynamic Data Exchange (DDE),
which was superseded by
Object Linking and Embedding (OLE) and later by the
Component Object Model (COM), Automation Objects,
ActiveX controls, and the .NET Framework.
◦ There is not always a clear distinction between these
technologies, and there is quite a lot of overlap.

Unit III
Windows

Driver Model


Introduction to WDM
 Toallow driver developers to write device
drivers that are source-code compatible
across all Microsoft Windows operating
systems, the Windows Driver Model
(WDM) was introduced.
 Kernel-mode drivers that follow WDM rules
are called WDM drivers. All WDM drivers
must:
◦ Include wdm.h, not ntddk.h.
◦ Be designed as a bus driver, a function driver,
or a filter driver, as described in Types of
WDM Drivers.
◦ Create device objects as described in WDM
Device Objects and Device Stacks.
kernel-mode drivers
Highest-level drivers. Highest-level drivers include file
system drivers (FSDs) that support file systems, such as:
NTFS
File allocation table (FAT)
CD-ROM file system (CDFS)

Intermediate drivers, such as a virtual disk, mirror, or


device-type-specific class driver.
Function drivers control specific peripheral
devices on an I/O bus.
Filter drivers insert themselves above or below
function drivers.
Software bus drivers
class driver

Lowest-level drivers control an I/O bus to which


peripheral devices are connected.
Hardware bus drivers are system-supplied and
usually control dynamically configurable I/O buses.
Legacy drivers that directly control a physical
device are lowest-level drivers.
Types of WDM Drivers
There are three kinds of WDM
drivers:
◦ Bus drivers, which drive an individual
I/O bus device and provide per-slot
functionality that is device-
independent.
◦ Function drivers, which drive an
individual device.
◦ Filter drivers, which filter I/O requests
for a device, a class of devices, or a
bus.

Types of WDM Drivers
Upper-level filter drivers typically provide added-value
features for a device. They are optional .

A function driver is the main driver for a device. A function


driver is typically written by the device vendor and is
required.
A function driver can service one or more devices.
A function driver provides the operational interface for its
device.
Typically the function driver handles reads and writes to the
device and manages device power policy.
The function driver for a device can be implemented as a
driver/minidriver pair, such as a port/miniport driver pair or a
class/miniclass driver pair.
Lower-level filter drivers typically modify the behavior of
device hardware. There can be any number of lower-level filter
drivers for a device.

A bus filter driver typically adds value to a bus and is


supplied by Microsoft. There can be any number of bus filter
drivers for a bus.

A bus driver services a bus controller, adapter, or bridge.


Bus drivers are required drivers; there is one bus driver for
each type of bus on a machine.
Bus Drivers
A bus driver services a bus controller, adapter,
or bridge.
 Microsoft provides bus drivers for most common
buses, such as PCI, PnpISA, SCSI, and USB.
 Other bus drivers can be provided by IHVs or
OEMs.
 Bus drivers are required drivers; there is one
bus driver for each type of bus on a machine.
 A bus driver can service more than one bus if
there is more than one bus of the same type
on the machine.
 The primary responsibilities of a bus driver are
to:
◦ Enumerate the devices on its bus.
Function Drivers
A function driver is the main driver for a device .
 A function driver is typically written by the device
vendor and is required .
 The PnP manager loads at most one function driver for
a device.
 A function driver can service one or more devices.
 A function driver provides the operational interface for
its device.
 Typically the function driver handles reads and writes
to the device and manages device power policy.
 The function driver for a device can be implemented
as a driver/minidriver pair, such as a port/miniport
driver pair or a class/miniclass driver pair.
 In such driver pairs, the minidriver is linked to the
second driver, which is a DLL.
Filter Drivers
Filterdrivers are optional drivers that
add value to or modify the behavior
of a device. A filter driver can
service one or more devices.
Bus Filter Drivers
◦ Bus filter drivers typically add value to
a bus and are supplied by Microsoft or
a system OEM. Bus filter drivers are
optional. There can be any number of
bus filter drivers for a bus.
◦ A bus filter driver could, for example,
implement proprietary enhancements
Filter Drivers
Lower-Level Filter Drivers
◦ Lower-level filter drivers typically modify
the behavior of device hardware. They
are typically supplied by IHVs and are
optional. There can be any number of
lower-level filter drivers for a device.
◦ A lower-level device filter driver monitors
and/or modifies I/O requests to a
particular device. Typically, such filters
redefine hardware behavior to match
expected specifications.
◦ A lower-level class filter driver monitors
and/or modifies I/O requests for a class
of devices. For example, a lower-level
Filter Drivers
Upper-Level Filter Drivers
◦ Upper-level filter drivers typically
provide added-value features for a
device. Such drivers are usually
provided by IHVs and are optional.
There can be any number of upper-
level filter drivers for a device.
◦ An upper-level device filter driver adds
value for a particular device. For
example, an upper-level device filter
driver for a keyboard could enforce
additional security checks.
◦ An upper-level class filter driver adds
Hardware Configuration
for a USB Joystick
 In this figure, the USB
joystick plugs into a
port on a USB hub.
 The USB hub in this
example resides on
the USB Host
Controller board and
is plugged into the
single port on the
USB host controller
board.
 The USB host controller
plugs into a PCI bus.
 From a PnP
perspective, the USB
hub, the USB host
PnP Hardware USB
Joystick
The kernel-mode and user-mode HID clients and the
application are not drivers but are shown for
completeness.

upper-level class filter that adds a macro button feature


is written by someone who needs to filter the joystick I/O
The function driver, the main driver for the joystick
device, is the HID class driver/HID USB miniclass driver
pair. (HID represents "Human Interface Device".) The HID
USB miniclass driver supports the USB-specific semantics
of HID devices, relying on the HID class driver DLL for
general HID support.
lower-level device filter that enables the joystick to
emulate a mouse device. is written by the joystick vendor.

The USB hub bus driver that drives the USB hub. The USB
hub driver is provided with the system by Microsoft.

The bus driver for the USB host controller is implemented


as a class/miniclass driver pair. The USB host controller
class and miniclass drivers are provided with the system
by Microsoft.
A PCI driver that drives the PCI bus. This is a PnP bus
driver. The PCI bus driver is provided with the system by
Microsoft.
Object Based

Likethe operating system, drivers


are also object-based.
◦ File objects represent a user-mode
application's connection to a device.
◦ Device objects represent each driver's
logical, virtual, or physical devices.
◦ Driver objects represent each driver's
load image.

Objects Names()
 Drivers use objects by calling kernel-mode support
routines that the I/O manager and other system
components export.
 Kernel-mode support routines generally have names
that identify the specific object that each routine
manipulates and the operation that each routine
performs on that object.
 PrefixOperationObject
 where
 Prefix
Identifies the kernel-mode component that exports the
support routine and, usually, the component that defined
the object type. Most prefixes have two letters.
 Operation
Describes what is done to the object.
 Object
Identifies the type of object.
 For example, the I/O manager's IoCreateDevice
Device Objects
◦ create these device objects by calling an
I/O support routine (IoCreateDevice)..
Device Objects
 Forthe keyboard and mouse devices, both their
respective port and class drivers create device
objects.
◦ The port driver creates a physical device object (PDO) to
represent the physical port.
◦ Each class driver creates its own functional device object
(FDO) to represent the keyboard or mouse device as a
target for I/O requests.
 Each class driver calls an I/O support routine to
get a pointer to the next-lower-level driver's
device object, so the class driver can chain
itself above that driver, which is the port driver.
 Then the class driver can send I/O requests down
to the port driver for the target PDO
representing its physical device.
 An optional filter driver added to the
Device Objects and Device
Stack
◦ The device objects for a device are
organized into a device stack. Whenever
an operation is performed on a device,
the system passes an IRP data structure
to the driver for the top device object in
the device stack.
◦ Each driver either handles the IRP or
passes it to the driver that is associated
with the next-lower device object in the
device stack.
◦ Device objects are represented by
DEVICE_OBJECTstructures, which are
Device Objects and Device
Stack
◦ The following figure illustrates the
relationship between device objects
and the I/O manager.
I/O request packets
 (IRPs)
The I/O manager, Plug and Play
manager, and power manager use I/O
request packets (IRPs) to
User Mode Application
communicate with kernel-mode
drivers, and to allow drivers to I/o request to IRP’s
communicate with each other.
Driver
 The I/O manager performs the following
steps: Track IRP’s
◦ Accepts I/O requests, which usually User Mode Application
originate from user-mode
applications.
◦ Creates IRPs to represent the I/O
requests. File System Driver
Drive
r
◦ Routes the IRPs to the appropriate Stack Interm.Mirror Driver
drivers.
Disk Driver
◦ Tracks the IRPs until they are
completed. PnP Hardware bus Driver

◦ Returns the status to the original


requester of each I/O operation.
 An IRP might be routed to more than
one driver. For example, a request to
I/O request packets
(IRPs)
 Eeach IRP has a fixed part, and I/O stack
location for each driver that controls the
device:
◦ In the fixed part (or header), the I/O manager
maintains information about the original
request, such as the
 caller's thread ID and parameters,
the address of the device.
I/O status block, in which drivers set information
about the status of the requested I/O operation.
◦ I/O stack location, the I/O manager sets driver-
specific parameters, such as
the function code of the requested operation and
the context that the corresponding driver uses to
determine what it should do.
Asynchronous I/O
◦ The I/O manager provides asynchronous I/O
support so that the originator of an I/O request
can continue executing, rather than wait for
its I/O request to be completed.
◦ Asynchronous I/O support improves both the
overall system throughput and the
performance of any code that makes an I/O
request.
◦ With asynchronous I/O support, kernel-mode
drivers do not necessarily process I/O requests
in the same order in which they were sent to
the I/O manager.
◦ The I/O manager, or a higher-level driver, can
reorder I/O requests as they are received.
◦ A driver can split a large data transfer request
Asynchronous I/O

◦ A driver does not necessarily process each
IRP to completion before it starts
processing the next incoming I/O request.
◦ If the driver supports asynchronous IRP
processing, it can send an IRP to the next
driver, if necessary, and begin processing
the next IRP without waiting for the first
one to be completed.
◦ The driver can register a "completion
routine” when another driver has finished
processing an IRP.
◦ Drivers can maintain state information
about their current I/O operations in a
Basic Structure of a WDM
Driver
Device Drivers
A driver doesn’t contain a main program.
Instead, it contains a collection of
subroutines that the system can call
when the system thinks it’s time to.
These subroutines can use helper
subroutines in the driver, in static
libraries, and in the operating system,
but the driver isn’t in charge of anything
except its own hardware: the system is in
charge of everything else, including the
decisions about when to run your driver
code.

How the System Finds and
Loads Drivers
Thesystem uses two slightly different
methods, depending on whether the
hardware is Plug and Play compatible:
◦ A Plug and Play device has an electronic
signature that the system can detect.
◦ For Plug and Play devices, a system bus driver
detects the existence of the hardware and
reads the signature to determine what kind
of hardware it is.
◦ Thereafter, an automatic process based on the
registry and INF files allows the system to
load the right driver.
How the System Finds and
Loads Drivers
◦ A legacy device does not have any
electronic signature, so the system
can’t detect it automatically.
◦ The end user must therefore initiate the
“detection” process by invoking the
Add New Hardware Wizard, which
ends with the system knowing that a
certain new piece of hardware exists.
◦ Thereafter, the system uses the same
automatic registry-and-INF-file process
that’s used for Plug and Play devices
to load the right driver.

Plug and Play Devices
A Plug and Play device is one that has an
electronic signature that a bus driver can
interrogate to learn the identity of a device.
Here are some examples of these signatures:
◦ A PCI card has a configuration space that the PCI bus
driver can read via dedicated memory or I/O port
addresses. The configuration space contains vendor
and product identification information.
◦ A USB device returns a device descriptor in response to
a standardized control-pipe transaction. The device
descriptor contains vendor and product identification
information.
◦ A Personal Computer Memory Card International
Association (PCMCIA) device has attribute memory
that the PCMCIA bus driver can read in order to
determine the identity of the card.

Standard Driver
Routines
Device Drivers
Here’s a brief snapshot of how the
operating system might call subroutines
in your driver:
1.The user plugs in your device, so the system loads your
driver executable into virtual memory and calls your
DriverEntry routine. DriverEntry does a few things and
returns.
2.The Plug and Play Manager (PnP Manager) calls your
AddDevice routine, which does a few things and
returns.
3.The PnP Manager sends you a few IRPs. Your dispatch
function processes each IRP in turn and returns.
4.An application opens a handle to your device, where
upon the system sends you another IRP. Your
dispatch routine does a little work and returns.

Device Drivers
 5.- The application tries to read some data, whereupon the
system sends you an IRP. Your dispatch routine puts the IRP in
a queue and returns.
 6.- A previous I/O operation finishes by signaling a hardware
interrupt to which your driver is connected. Your interrupt
routine does a little bit of work, schedules a DPC, and returns.
 7.- Your DPC routine runs. Among other things, it removes the
IRP you queued at step 5 and programs your hardware to read
the data. Then the DPC routine returns to the system.
 8.- Time passes, during which the system makes many other
brief calls into your subroutines.
 9.- Eventually, the end user unplugs your device. The PnP
Manager sends you some IRPs, which you process and return.
The operating system calls your DriverUnload routine, which
usually just does a tiny amount of work and returns. Then the
system removes your driver code from virtual memory.

Drivers and Kernel-Mode
Objects
Driver Objects
 DriverEntry is the only driver routine with an exported name.
 When the I/O Manager needs to locate other driver functions, it
uses the Driver object associated with a specific device.
 This object is basically a catalog that contains pointers to various
driver functions.
 The life of a driver object is explained below.
1.The I/O Manager createsa driver object whenever it loads a
driver. If the driver fails during initialization, the I/O
Manager deletes the object.
2.During initialization, the DriverEntry routine loads pointers to
other driver functions into the driver object.
3.When an IRP is sent to a specific device, the I/O Manager uses
the associated driver object to find the right Dispatch
routine.
4.If a request involves an actual device operation, the I/O
Manager uses the driver object to locate the driver's Start
I/O routine.
5.If the driver is unloaded, the I/O Manager uses the driver
object to find an Unload routine. When the Unload routine
Layout of a Driver
 ThereObject
is a unique driver object for each driver currently loaded in
the system.
 The Figure illustrates the structure of the driver object.
 As you can see, the driver object also contains a pointer to a
linked list of devices serviced by this driver.
 A driver's Unload routine can use this list to locate any devices it
needs to delete.
Device Objects
 Both the I/O Manager and a driver need to know what's going on
with an I/O device at all times.
 Device objects make this possible by keeping information about
the device's characteristics and state.
 There is one device object for each virtual, logical, and physical
device on the system.
 The life cycle of a device object is shown below.
1.The DriverEntry routine creates a device object for each of
its devices. For WDM drivers, the Device object is created
by the AddDevice Plug and Play routine.
2.The I/O Manager uses a back-pointer in the device object to
locate the corresponding driver object.
3.Various driver routines use the device object to locate the
corresponding device extension..
4.The driver's Unload routine deletes the device object when
the driver is unloaded. For WDM drivers, RemoveDevice
performs the task of deleting the Device object.
Layout of the Device
 Object
The Figure illustrates the structure of the device object and its
relationship to other structures.
 Although the device object contains a lot of data, much of it is the
exclusive property of the I/O Manager
Device Extensions
 Connected to the device object is another important data
structure, the device extension.
 The extension is simply a block of nonpaged pool that the I/O
Manager automatically attaches to any device object created.
 The driver author specifies both the size and contents of the
device extension.
 Typically, it is used to hold any information associated with a
particular device.
 The device extension typically includes
◦ A back-pointer to the device object
◦ Any device state or driver context information
◦ A pointer to the interrupt object and an interrupt-expected flag
◦ A pointer to a controller object
◦ A pointer to an adapter object and a count of mapping registers
Device Extensions
 Since the device extension is driver-specific, its structure
must be defined in a driver header file.
 Although the extension's exact contents depend on what a
driver does, its general layout looks something like the
following:

 typedef struct _DEVICE_EXTENSION


 {
 PDEVICE_OBJECT DeviceObject; // back pointer
 :
 // other driver-specific declarations
 :
 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
Manipulating Device
 Objects
The Table lists many of the I/O Manager functions that operate on
device objects. The I/O Manager also passes a device object
pointer as an argument to most of the routines in a driver.
Kernel: Controller
 SomeObjects
peripheral adapters manage more than
one physical device using the same set of
control registers.
 The floppy disk controller is one example of this
architecture.
 This kind of hardware poses a synchronization
dilemma.
 If the driver tries to perform simultaneous
operations on more than one of the connected
devices without first synchronizing its access to
the shared register space, the control registers
receive confusing values.
 To help with this problem, the I/O Manager
provides controller objects.
Kernel: Controller
 Objects
The life cycle of a typical controller object
1.The DriverEntry (or AddDevice) routine creates the
Controller object and usually stores its address in a field
of each device's Device Extension.
2.Before it starts a device operation, the Start I/O routine
asks for exclusive ownership of the controller object on
behalf of a specific device.
3.When the controller object becomes available, the I/O
Manager grants ownership and calls the driver's
ControllerControl routine. This routine sets up the
device's registers and starts the I/O operation. As long as
this device owns the controller object, any further
requests for ownership block at step 2 until the object is
released.
4.When the device operation is finished, the driver's DpcForIsr
routine releases the Controller object, making it
available for use by other pending requests.
5.The driver's Unload routine deletes the controller object
when the driver is unloaded.
Layout of the Controller
Object
 Figure shows the relationship of a Controller object to
other system data structures. The only externally visible
field in a Controller object is the PVOID
ControllerExtension field, which contains a pointer to
the extension block.
Controller Extensions
 Like device objects, controller objects contain a pointer to an
extension structure that can be used to hold any controller-
specific data. The extension is also a place to store any
information that's global to all the devices attached to a
controller.

S in ce th e co n tro lle r exte n sio n is d rive r-sp e cific , its stru ctu re m u st b e
d e fin e d in a d rive r h e a d e r file . A lth o u g h th e exte n sio n 's exa ct
co n te n ts d e p e n d o n w h a t a d rive r d o e s, its g e n e ra l la yo u t lo o ks
so m e th in g like th is:
typ e d e f stru ct _C O N T R O LLE R _E X T E N S IO N
{
// back pointer
PC O N T R O LLE R _O B JE C T C o n tro lle rO b je ct
:
// other driver-specificdeclarations
:
Kernel: Adapter Objects
 Just as multiple devices on the same controller need to coordinate
their hardware access, so it is that devices that perform DMA
need an orderly way to share system DMA resources.
 The I/O Manager uses adapter objects to prevent arguments over
DMA hardware. There is one adapter object for each DMA data
transfer channel on the system.
 Like a controller object, an adapter object can be owned by only
one device at a time.
 Before starting a DMA transfer, the Start I/O routine asks for
ownership of the adapter object.
 If the hardware is free, ownership is granted.
 If not, the device's request is put on hold until the current owner
releases the hardware.
 Obviously, if the device supports only programmed I/O, it has no
need for an adapter object.
Kernel: Adapter Objects
 The life cycle of the adapter object is described below.
1.The HAL creates Adapter objects for any DMA data channels
detected at boot time.
2.The DriverEntry or AddDevice routine locates the adapter
object for its device and stores that pointer in the device
or controller extension.
3.The Start I/O routine requests ownership of the adapter
object on behalf of a specific device.
4.When ownership is granted, the I/O Manager calls the driver's
Adapter Control routine. This routine then uses the
adapter object to set up a DMA transfer.
5.The driver's DpcForIsr routine may use the adapter object
to perform additional operations in the case of a split
transfer.
6.When a transfer is finished, DpcForIsr releases the adapter
object.
Layout of an Adapter
 FigureObject
illustrates the relationship of adapter objects to other
structures. As the diagram shows, the adapter object is
completely opaque and has no externally visible fields. When
working with DMA devices, the pointer to the adapter object, as
well as the number of mapping registers it supports, should be
stored in the device extension or controller extension structure.
Kernel: Interrupt
 Objects
Interrupt objects simply give the kernel's interrupt
dispatcher a way to find the right service routine when
an interrupt occurs.
 The life cycle of an interrupt object is described below.
1.The DriverEntry or AddDevice routine creates an interrupt
object for each interrupt vector supported by the device or
the controller.
2.When an interrupt occurs, the kernel's interrupt dispatcher
uses the Interrupt object to locate the Interrupt Service
routine.
3.The Unload or RemoveDevice routine deletes the interrupt
object after disabling interrupts from the device.
 A driver does not interact with interrupt objects other than
to create and delete them.
 A pointer to the interrupt object is typically stored in the
device extension or controller extension.
Layout of an Interrupt
 Object
Figure illustrates the structure of an interrupt object. Like adapter objects,
they are completely opaque and have no externally visible fields.
Unit IV
Driver Routines
Initialization and Cleanup
Routines
DriverEntry Routine
 What a DriverEntry Routine Does
◦ DriverEntry locates hardware that it will be controlling. That
hardware is allocated—it is marked as under the control of this
driver.
◦ The driver object is initialized by announcing other driver entry
points. The announcements are accomplished by storing function
pointers directly into the driver object.
◦ If the driver manages a multiunit or multifunction controller,
IoCreateController is used to create a controller object. A
controller extension is then initialized.
◦ IoCreateDevice is used to create a device object for each physical
or logical device under the control of this driver. A device
extension is then initialized.
◦ The created device is made visible to the Win32 subsystem by
calling IoCreateSymbolicLink.
◦ The device is connected to an interrupt object. If the ISR requires the
use of a DPC object, it is created and initialized in this step.
◦ Steps 4 to 6 are repeated for each physical or logical device
controlled by this driver.
◦ If successful, DriverEntry should return STATUS_SUCCESS to the I/O
Manager.
DriverEntry Routine
Announcing DriverEntry
Points
The I/O Manager is able to locate the
DriverEntry routine because it has a
well-known name.
Other driver routines don't have fixed
names, so the I/O Manager needs some
other way to locate them.
The linkage mechanism is the driver
object, which contains pointers to other
driver functions.
A DriverEntry routine is responsible for
setting up these function pointers.

Announcing DriverEntry
Points
The following code fragment shows how a
DriverEntry routine initializes both kinds
of function pointers.
 pDO->DriverStartIo = StartIo;
 pDO->DriverUnload = Unload;
 // // Initialize the MajorFunction Dispatch table //
 pDO->MajorFunction[ IRP_ MJ_CREATE ] =
DispatchCreate;
 pDO->MajorFunction[ IRP_MJ_CLOSE ] = DispatchClose;
Creating Device Objects
Once hardware is identified and allocated,
the next step is to create a device object
for each physical or virtual device that is
to be exposed to the rest of the system.
Most of the work is done by the
IoCreateDevice function, which takes a
description of the device and returns a
device object, complete with an
attached device extension.

Creating Device Objects
IoCreateDevicealso links the new device
object into the list of devices managed
by this driver object. Table contains a
description of this function.
◦ The DeviceType parameter of IoCreateDevice is
simply a 16-bit value describing the class of device
being added.
◦ Microsoft reserves the first half of this range for
predefined device types. Above 32767, private
device types can be defined. Beware, though, that
conflict with another vendor's device is always
possible.
◦ Currently, Microsoft predefines about 30 device types.
◦ The predefined device type values are given symbolic
names of the form FILE_DEVICE_XXX (e.g.,
FILE_DEVICE_DVD).

Creating Device Objects
Code Example: Driver
Initialization
 The following example shows how a basic kernel-mode
device driver initializes itself.
 This first minimal driver must be manually loaded.
 It does not touch any hardware, but instead creates an
internal device name (MINIMAL0) and a symbolic link
name (MIN1).
 It consists of a single source module, Driver.cpp.
 A header file, Driver.h, declares driver-specific information
about our nonhardware device, such as the
DEVICE_EXTENSION.
 DRIVERENTRY
◦ In our first non-WDM driver example, the DriverEntry
routine is small and straightforward. The
responsibilities include
◦ Announcing other DriverEntry points.
◦ For the Minimal driver, the only other routine to
announce is the driver's Unload function.
Code Example:
 DriverEntry
//++
// Function: DriverEntry
// Ifthis driver controlled real hardware ,
// code would be placed here to locate it.

 // Description: // Using IoReportResourceUsage , the


p o rts,
 // Initializes the driver, locating and
// IRQs , and DMA channels would be
claiming
" marked " .
 // hardware resources. Creates the
// as " in use " and under the control of this
kernel objects
d rive r.

// needed to process I/O requests. // This minimal driver has no HW , so ...
 // Arguments: // Announce other driver entry points
 // pDriverObject - Passed from I/O pDriverObject -> DriverUnload =
Manager DriverUnload ;
 // pRegistryPath - UNICODE_STRING // Over time, the MajorFunction array will
pointer to be filled
// For each physical or logical device
 // registry info (service key) detected
 // for this driver // that will be under this Driver's
 // Return value: control,
// a new Device object must be created.
 // NTSTATUS signaling success or
failure status = CreateDevice ( pDriverObject ,
ulDeviceNumber );
 //—
// This call would be repeated until
 NTSTATUS DriverEntry ( IN // all devices are created. E.g.,
PDRIVER_OBJECT pDriverObject,
// ulDeviceNumber++;
 IN // status =
PUNICODE_STRING pRegistryPath
// CreateDevice(pDriverObject,
){ ulDeviceNumber);
 ULONG ulDeviceNumber = 0; return status;
Code Example:
CREATEDEVICE
 The work of actually creating the device object is
delegated to a module-private (static) routine
called CreateDevice.
 Although this routine doesn't do much,
modularizing this work is appropriate as this
driver evolves into a full WDM driver. Its
responsibilities include
◦ Choosing and forming an internal device name. This driver
hard-codes the name passed into the function.
◦ Creating the internal device object. The size of the
DEVICE_EXTENSION is specified in the call to
IoCreateDevice.
◦ Initializing the DEVICE_EXTENSION. In the case of this Minimal
driver, the DEVICE_EXTENSION holds a back pointer to the
device object and names for the device and symbolic link.
◦ Forming a symbolic link name and linking the name created.
Code Example:
 CREATEDEVICE
//++ if (! N T _S U C C E S S ( sta tu s))
 // Function: CreateDevice re tu rn sta tu s;
 // Description: // Initializethe Device Extension
 // Adds a new device p D e vE xt = ( PD E V IC E _E X T E N S IO N ) p D e vO b j-
> DeviceExtension ;
 // Arguments:
p D e vE xt-> p D e vice = p D e vO b j; // b a ck p o in te r
 // pDriverObject - Passed from I/O
Manager p D e vE xt-> D e vice N u m b e r = u lD e vice N u m b e r;
 // ulDeviceNumber - Logical device p D e vE xt-> u strD e vice N a m e = d e vN a m e ;
number (zero-based) // Form the symbolic linkname
 // Return value: C U S trin g sym Lin kN a m e (" \\??\\M IN " );
 // None sym Lin kN a m e + = C U S trin g ( u lD e vice N u m b e r+ 1 );
 //— // 1 based
 NTSTATUS CreateDevice ( IN p D e vE xt-> u strS ym Lin kN a m e = sym Lin kN a m e ;
PDRIVER_OBJECT pDriverObject, IN // Now create the linkname
ULONG ulDeviceNumber ) {
sta tu s =
 NTSTATUS status; Io C re a te S ym b o licLin k ( &( U N IC O D E _S T R IN G ) sym Li
 PDEVICE_OBJECT pDevObj; n kN a m e , &( U N IC O D E _S T R IN G ) d e vN a m e );
 PDEVICE_EXTENSION pDevExt; if (! N T _S U C C E S S ( sta tu s)) {
 // Form the internal Device Name // ifitfailsnow , must delete Device object
 CUString devName("\\Device\\MINIMAL"); Io D e le te D e vice ( p D e vO b j );
 // for "minimal" device re tu rn sta tu s;
 devName += CUString(ulDeviceNumber); }
 // Now create the device // Made it
 status = IoCreateDevice( pDriverObject, re tu rn S TAT U S _S U C C E S S ;
Writing an Unload
 Routine
By default, once the driver is loaded, it remains in the system until a reboot occurs. To
make a driver unloadable, an Unload routine is necessary. The Unload routine is
announced during DriverEntry. The I/O Manager then calls this routine whenever
the driver is manually or automatically unloaded.
 Execution Context
 The I/O Manager calls a driver's Unload routine just before removing the driver from
memory. Table shows that the Unload routine runs at PASSIVE_LEVEL IRQL, which
means it has access to paged system resources.
 What an Unload Routine Does
 Although the exact details vary from driver to driver, in general the following steps are
performed in an Unload routine.
1. For some kinds of hardware, the state of the device should be saved in the Registry. That way,
the device can be restored to its last known state the next time DriverEntry executes.
For example, an audio card driver might save the current volume setting of the card.
2. If interrupts have been enabled for the device, the Unload routine must disable them and
disconnect from its interrupt object. It is crucial that the device not generate any
interrupt requests once the interrupt object is deleted.
3. Hardware belonging to the driver must be deallocated.
4. The symbolic link name must be removed from the Win32 namespace. This is accomplished
using IoDeleteSymbolicLink.
5. The device object itself must be removed using IoDeleteDevice.
6. If managing multiunit controllers, repeat steps 4 and 5 for each device attached to the
controller. Then remove the controller object itself, using IoDeleteController.
7. Repeat steps 4 through 6 for all controllers and devices that belong to the driver.
8. Deallocate any pool memory held by the driver.
Writing an Unload
Routine
Code Example: Driver
Unload
 In the Minimal driver, an Unload routine is
supplied that undoes the work of DriverEntry.
 Its work is straightforward, as it must delete each
symbolic link and device object that has been
created.
 To perform this work, the Unload routine relies on
the fact that the driver object points to a linked
list of device objects controlled by the driver.
 The first device controlled by a driver is pointed to
by the field DeviceObject within the driver
object.
 Each device points to the next via the field
NextDevice. When examining the Unload
routine, remember that the Minimal
DEVICE_EXTENSION structure maintains a back
Code Example: Driver


Unload
//++
// Function: DriverUnload // a littletrickery...
 // Description: // we need to delete the device
 // Stops & Deletes devices controlled by this o b je ct, B U T
driver.
// the Device object is pointed to by
 // Stops interrupt processing (if any) // Releases
kernel resources consumed by driver p N extO b j
 // Arguments: // Ifwe delete the device object
 // pDriverObject - Passed from I/O Manager first,
 // Return value: // we can't traverse to the next
 // None D e vice in th e list
 //— // Rather than create another
 VOID DriverUnload ( IN PDRIVER_OBJECT p o in te r, w e ca n
pDriverObject ) {
// use the DeviceExtension's back
 PDEVICE_OBJECT pNextObj;
p o in te r
 // Loop through each device controlled by
Driver // to the device . // So , firstupdate
 pNextObj = pDriverObject->DeviceObject; th e n ext p o in te r...
 while (pNextObj != NULL) { p N extO b j = p N extO b j-> N extD e vice ;
// Dig out the Device Extension from the
// then delete the device using the

 // Device Object
E xte n sio n
 PDEVICE_EXTENSION pDevExt =
(PDEVICE_EXTENSION) pNextObj- Io D e le te D e vice ( p D e vE xt-
>DeviceExtension;
> pDevice );
 // This will yield the symbolic link name
 UNICODE_STRING pLinkName = pDevExt- }
>ustrSymLinkName;
 // ... which can now be deleted
// Finally, hardware that was allocated in
IoDeleteSymbolicLink(&pLinkName D rive rE n try
Writing Shutdown
 Routines
If a driver has special processing to do before the operating system
disappears, a driver should supply a Shutdown routine.
 Execution Context
 The I/O Manager calls a Shutdown routine during a system shutdown. As
described in Table the Shutdown routine runs at PASSIVE_LEVEL IRQL,
which means it has access to paged system resources.
 What a Shutdown Routine Does
 The main purpose of the Shutdown routine is to put the device into a
quiescent state and perhaps store some device information into the
system Registry. Again, saving the current volume settings from a sound
card is a good example of something a Shutdown routine might do.
 Unlike the driver's Unload routine, Shutdown routines don't have to worry
about releasing driver resources because the operating system is about to
disappear anyway.


Writing Shutdown
 Routines
Enabling Shutdown Notification
 There is no direct field in the Driver object for announcing the
Shutdown routine.
 Instead, the event of system shutdown is sent as a separate I/O
request to a driver.
 It is handled with an entry inside of the driver's MajorFunction
code array.
 Additionally, the I/O Manager must be notified that a driver is
interested in receiving shutdown notifications.
 This is done by making a call to
IoRegisterShutdownNotification. The following code fragment
shows how to enable shutdown notifications in a driver.
 NTSTATUS DriverEntry ( IN PDRIVER_OBJECT pDriverObject, IN
PUNICODE_STRING pRegistryPath ) {
 :
 pDriverObject->MajorFunction[ IRP_MJ_SHUTDOWN ] = Shutdown;
IoRegisterShutdownNotification( pDriverObject );
 :
 }
Driver Dispatch
Routines
Announcing Driver Dispatch
Routines
 Before a driver can process I/O requests, it must announce what
kinds of operations it supports.
 I/O Request Dispatching Mechanism

◦ Windows 2000 I/O operations are packet-driven.


◦ When an I/O request is initiated, the I/O Manager first builds
an IRP work-order to keep track of the request.
◦ Among other things, it stores a function code in the
MajorField field of the IRP's I/O stack location to uniquely
identify the type of request.
◦ The MajorField code is used by the I/O Manager to index the
Driver object's MajorFunction table.
◦ The table contains a function pointer to a Dispatch routine
specific to the I/O request.
◦ If a driver does not support the requested operation, the
MajorFunction table entry points to an entry within the I/O
Manager, _IopInvalidDeviceRequest, which returns an
error to the original caller.
Announcing Driver Dispatch
Routines
 Thus, it is the responsibility of the driver author to provide Dispatch
routines for each I/O function code that it supports. Figure
illustrates this process.
Enabling Specific Function

Codes
To enable specific I/O function codes, a driver must first
"announce" the Dispatch routine that responds to such a
request.
 The announcement mechanism is simply the work performed by
DriverEntry that stores the Dispatch routine function address
into the appropriate slot of the MajorFunction table of the
driver object.
 The I/O function code is the index used for the table.
 The following code fragment illustrates the process of
announcement.
 NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDO, IN PUNICODE_STRING
pRegPath ) {
 :
 pDO->MajorFunction[ IRP_MJ_CREATE ] = DispCreate;
 pDO->MajorFunction[ IRP_MJ_CLOSE ] = DispClose;
 pDO->MajorFunction[ IRP_MJ_CLEANUP ] = DispCleanup;
 pDO->MajorFunction[ IRP_MJ_READ ]= DispRead;
 pDO->MajorFunction[ IRP_MJ_WRITE ] = DispWrite;
 :
Writing Driver Dispatch

Routines
All Dispatch routines share the same function signature. (A function
signature includes the number and type of parameters, and its
calling convention.)
 Table shows the prototype for all Dispatch routines.
 Like the driver's initialization and unload routines, Dispatch
routines run at PASSIVE_LEVEL IRQL, which means they can
access paged system resources.

Writing Driver Dispatch
Routines
 What Dispatch Routines Do
 The exact behavior of a Dispatch routine will depend on the
function it supports. However, the general responsibilities
of these routines include the following.
1.Call IoGetCurrentIrpStackLocation to get a pointer to the
IRP stack location belonging to this driver.
2.Perform any additional parameter validation specific to this
request and device.
3.For an intermediate-level driver, consideration must be given
to the limitations of the underlying physical device (for
example, its maximum transfer size). The Dispatch routine
may need to split the caller's request into multiple requests
for the lower-level driver.
4.Continue processing the IRP until the request is complete or an
error condition prevents further processing.

Writing Driver Dispatch

Routines
Exiting the Dispatch Routine
 When a Dispatch routine processes an IRP, there are only three
possible outcomes.
◦ The request's parameters do not pass the driver's validation tests and
the request is rejected.
◦ The request can be handled entirely within the Dispatch routine
without need for any device operation. An example of such a
request would be a Read of zero bytes.
◦ The device must be started in order to complete the request.
 SIGNALING AN ERROR
 If a Dispatch routine uncovers a problem with the IRP, it needs to
reject the request and notify the caller. The following steps
describe how to reject an IRP.
1. Store an appropriate error code in the Status field of the IRP's
IoStatus block and clear the Information field.
2. Call IoCompleteRequest to release the IRP with no priority increment.
3. The Dispatch routine should return the same error code placed in the
Status field of the IRP.

Reject I/O request
 The code fragment below shows how a Dispatch routine rejects an
I/O request.
 NTSTATUS DispatchWrite( IN PDEVICE_OBJECT pDO, IN PIRP
pIrp ) {
 :
 // If the request is not supported by this device
 // report it and reject the request
 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
 // report that no bytes were transferred
 pIrp->IoStatus.Information = 0;
 // Mark the IRP as "complete", no priority increment
 IoCompleteRequest( pIrp, IO_NO_INCREMENT);
 return STATUS_NOT_SUPPORTED;
 }
COMPLETING A REQUEST
 Some I/O requests can be handled without performing any actual device
operations.
 Opening a handle to a device or returning information stored in the device
object are examples of these kinds of requests.
 To complete such a request in the Dispatch routine, do the following:
◦ Put a successful completion code in the Status field of the IRP's IoStatus
block, and set the Information field to some appropriate value.
◦ Call IoCompleteRequest to release the IRP with no priority increment.
◦ Exit the Dispatch routine with a value of STATUS_SUCCESS.
 The code fragment below shows how a Dispatch routine completes a
request.
 NTSTATUS DispatchClose( IN PDEVICE_OBJECT pDO, IN PIRP pIrp ) {
 :
 pIrp->IoStatus.Status = STATUS_SUCCESS;
 // Indicate that zero bytes of data were transferred
 pIrp->IoStatus.Information = 0;
 // "Mark" the IRP as complete - no further processing
 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 return STATUS_SUCCESS;
 }
SCHEDULING A DEVICE OPERATION
 The last action a Dispatch routine might take is the most likely—
that it will need to interact with the actual device to fulfill the
request.
 Examples include a data transfer, a control function, or an
informational query.
 In this case, the Dispatch routine must queue the IRP for ultimate
processing by the driver's Start I/O routine and then promptly
return to the I/O Manager stating that the request is pending.
 To schedule (queue) a device operation, do the following:

◦ Call IoMarkIrpPending to inform the I/O Manager that the


request is still in progress.
◦ Call IoStartPacket to queue the IRP for the Start I/O routine.
A driver can also provide its own custom queuing
mechanism in lieu of using the I/O Manager's routine.
◦ Exit the Dispatch routine with a value of STATUS_PENDING.
This allows the original requestor to continue its other
operations in parallel with the device's operation.
SCHEDULING A DEVICE OPERATION
 The following code fragment shows how a Dispatch routine
schedules a device operation.
 NTSTATUS DispatchWrite( IN PDEVICE_OBJECT pDO, IN PIRP pIrp ) {
 :
 // Mark the IRP as "in progress"
 IoMarkIrpPending( pIrp );
 // Now queue (schedule) the IRP for eventual passage
 // to the driver's Start I/O routine.
 // Third parameter allows insertion into the queue
 // other than at the tail // Fourth parameter allows specification of a
 // Cancel routine
 IoStartPacket( pDO, pIrp, 0, NULL );
 return STATUS_PENDING;
 }
Processing Read and Write
Requests
◦ The most basic of I/O requests is to exchange data
between a user buffer and a device, are Read and
Write
◦ The I/O Manager presents a traditional read/write
abstraction to requestors for such data transfers.
◦ The requests are presented to a driver in the form of an
IRP with major function code of either IRP_MJ_READ or
IRP_MJ_WRITE.
◦ Whether the buffer address is a direct virtual address or
an intermediate nonpaged pool buffer allocated and
maintained by the I/O Manager is determined by the
device object's Flags field.
◦ It is the responsibility of the read and write Dispatch
routines to transfer data between the buffer and the
actual device for the requested number of bytes.
Input/Output Techniques
Methods for Accessing Data
Buffers
 One of the primary responsibilities of driver stacks is
transferring data between user-mode applications and a
system's devices. The operating system provides the
following three methods for accessing data buffers:
◦ Buffered I/O The operating system creates a nonpaged system
buffer, equal in size to the application's buffer.
 For write operations, the I/O manager copies user data into the
system buffer before calling the driver stack.
 For read operations, the I/O manager copies data from the system
buffer into the application's buffer after the driver stack
completes the requested operation.
◦ Direct I/O The operating system locks the application's buffer in
memory.
 It then creates a memory descriptor list (MDL) that identifies the
locked memory pages, and passes the MDL to the driver stack.
 Drivers access the locked pages through the MDL.
◦ Neither Buffered Nor Direct I/O The operating system passes the
application buffer's virtual starting address and size to the
driver stack.
 The buffer is only accessible from drivers that execute in the
Using Buffered I/O
A driver that services an interactive or slow
device, or one that usually transfers relatively
small amounts of data at a time, should use
the buffered I/O transfer method.
 Using buffered I/O for small, interactive
transfers improves overall physical memory
usage, because the memory manager doesn't
need to lock down a full physical page for
each transfer, as it does for drivers that
request direct I/O.
 Generally, video, keyboard, mouse, serial, and
parallel drivers request buffered I/O.
BUFFERED I/O
 BUFFERED I/O
◦ At the start of either a read or write operation, the I/O Manager
validates that all virtual memory pages spanned by the user's
buffer are valid.
◦ For buffered I/O, it then allocates a nonpaged pool buffer of a size
sufficient to hold the user's request.
◦ The address of this temporary buffer is place in the IRP field
AssociatedIrp.SystemBuffer.
◦ This address remains valid for the duration of the transfer (i.e., until
the IRP is marked as complete).
◦ For read operations, the I/O Manager remembers the address of the
original user buffer in the UserBuffer field of the IRP.
◦ For write operations, the I/O Manager copies the user buffer into the
nonpaged buffer before invoking the write Dispatch routine.
◦ It then sets the UserBuffer field of the IRP to NULL, since there is no
additional need to retain this state.
Using Buffered I/O
Using Buffered I/O
1. Some range of user-space virtual addresses represents the current
thread's buffer, and that buffer's contents might be stored
somewhere within a range of page-based physical addresses
(dark shading in the previous figure).
2. The I/O manager services the current thread's read request, for which
the thread passes a range of user-space virtual addresses
representing a buffer.
3. The I/O manager checks the user-supplied buffer for accessibility and
calls ExAllocatePoolWithTag to create a resident system-space
buffer (SystemBuffer) the size of the user-supplied buffer.
4. The I/O manager provides access to the newly allocated
SystemBuffer in the IRP it sends to the driver. If the figure
showed a write request, the I/O manager would copy data from
the user buffer into the system buffer before it sent the IRP to the
driver.
5. For the read request shown in the figure, the driver reads data from
the device into the system-space buffer. When the read request
has been satisfied, the driver calls IoCompleteRequest with the
IRP.
6. When the original thread is again active, the I/O manager copies the
read-in data from the system buffer into the user buffer. It also
calls ExFreePool to release the system buffer.
Using Direct I/O
 Drivers for devices that can transfer large amounts of
data at a time should use direct I/O for those transfers.
 Using direct I/O for large transfers improves a driver's
performance, both by reducing its interrupt overhead
and by eliminating the memory allocation and copying
operations inherent in buffered I/O.
 Generally, mass-storage device drivers request direct I/O
for transfer requests, including lowest-level drivers that
use direct memory access (DMA) or programmed I/O
(PIO), as well as any intermediate drivers chained
above them.
DIRECT I/O
 DIRECT I/O
◦ At the start of the operation, the I/O Manager validates the
page table entries spanned by the user's buffer.
◦ It then builds a data structure known as a Memory Descriptor
List (MDL) and stores the address of the MDL in the IRP's
MdlAddress field.
◦ Both the AssociatedIrp. SystemBuffer and UserBuffer
fields are set to NULL.
◦ For programmed I/O devices, the MDL can be used with the
function MmGetSystemAddressForMdl to get a system-
address view of the user buffer.
◦ Using this technique, the user's buffer is locked down into
physical memory
◦ When the I/O request is ultimately completed, the user buffer
is unlocked and unmapped from system address space.
Using Direct I/O
Using Direct I/O
1. Some range of user-space virtual addresses represents the current thread's
buffer, and that buffer's contents might actually be stored on some number
of physically discontiguous pages (dark shading in the previous figure). The
I/O manager creates an MDL to describe this buffer. An MDL is an opaque
data structure, defined by the Memory manager, that maps a particular
virtual address range to one or more page-based physical address ranges.
2. The I/O manager services the current thread's read request, for which the thread
passes a range of user-space virtual addresses that represent a buffer.
3. The I/O manager or FSD checks the user-supplied buffer for accessibility and calls
MmProbeAndLockPages with the previously created MDL.
MmProbeAndLockPages also fills in the corresponding physical address
range in the MDL. As the previous figure shows, an MDL for a virtual range
can have several corresponding page-based physical address entries, and
the virtual range for a buffer might begin and end at some byte offset from
the start of the first and last pages described by an MDL.
4. The I/O manager provides a pointer to the MDL (MdlAddress) in an IRP that
requests a transfer operation. Until the I/O manager or file system calls
MmUnlockPages after the driver completes the IRP, the physical pages
described in the MDL remain locked down and assigned to the buffer.
However, the virtual addresses in such an MDL can become invisible (and
invalid), even before the IRP is sent to the device driver or to any
intermediate driver that might be layered above the device driver.
5. If the driver uses packet-based system or bus-master DMA, its AdapterControl
routine calls MmGetMdlVirtualAddress with the IRP's MdlAddress
pointer to get the base virtual address for the MDL's page-based entries.
Writing Driver Dispatch

Write
NTSTATUS p D E -> d e vice B u ffe r = E xA llo ca te Po o l( Pa g e d Po o l,
DispatchWrite( INPDEVICE_OBJECT pDO xfe rS ize );
IN PIRP pIrp) { if ( p D E -> d e vice B u ffe r == N U LL ) {
 NTSTATUS status = STATUS_SUCCESS; // buffer didn't allocate???
sta tu s = S TA T U S _IN S U FFIC IE N T _R E S O U R C E S ;
 PDEVICE_EXTENSION pDE;
xfe rS ize = 0 ;
 PVOID userBuffer; } else {
 ULONG xferSize; // copy the buffer
p D E -> d e vice B u ffe rS ize = xfe rS ize ;
 // The stack location contains the user R tlC o p yM e m o ry ( p D E -> d e vice B u ffe r,
buffer info u se rB u ffe r, xfe rS ize );
 PIO_STACK_LOCATION pIrpStack; }
// Now complete the IRP no device operation needed
 pIrpStack =
IoGetCurrentIrpStackLocation( pIrp ); p Irp -> Io S ta tu s. S ta tu s = sta tu s;
 // The example assumes the device is p Irp -> Io S ta tu s. In fo rm a tio n = xfe rS ize ;
using BUFFERED_IO Io C o m p le te R e q u e st( p Irp , IO _N O _IN C R E M E N T );
 userBuffer = pIrp- re tu rn sta tu s;
>AssociatedIrp.SystemBuffer;
}
 xferSize = pIrpStack-
>Parameters.Write.Length;
 // The temporary buffer pointer is kept
 // in the DEVICE_EXTENSION (obtained
from Device obj)
 pDE = (PDEVICE_EXTENSION) pDO —>
deviceExtension;
 // If there is already a buffer, free it...
 if (pDE->deviceBuffer != NULL) {
 ExFreePool( pDE->deviceBuffer );
 PDE->deviceBuffer = NULL; xferSize
Writing Driver Dispatch Read
 NTSTATUS DispatchRead( IN PDEVICE_OBJECT
pDO, IN PIRP pIrp) { // Free the temporary paged pool buffer
 NTSTATUS status = STATUS_SUCCESS; ExFreePool( pDE->deviceBuffer );
 PDEVICE_EXTENSION pDE; pDE->deviceBuffer = NULL;
 PVOID userBuffer; pDE->deviceBufferSize = 0;
// and complete the I/O request...
 ULONG xferSize;
pIrp->IoStatus.Status = status;
 // The stack location contains the user buffer
pIrp->IoStatus.Information = xferSize;
info
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 PIO_STACK_LOCATION pIrpStack;
return status;
 pIrpStck =
}
IoGetCurrentIrpStackLocation( pIrp );
 
 userBuffer = pIrp-
>AssociatedIrp.SystemBuffer;
 xferSize = pIrpStack-
>Parameters.Read.Length;
 // The temporary buffer pointer is kept
 // in the DEVICE_EXTENSION (obtained from
Device obj)
 pDE = (PDEVICE_EXTENSION) pDO —>
DeviceExtension;
 // Don't transfer more than the user's request
 xferSize = (xferSize < pDE-
>deviceBufferSize) ? xferSize : pDE-
>deviceBufferSize;
 // Now copy the temporary buffer into user
space
 RtlCopyMemory(userBuffer, pDE-
>deviceBuffer, xferSize);
Extending the Dispatch
Interface
◦ Much of the I/O Manager operation supports a standard Read/Write
abstraction.
◦ The requestor supplies a buffer and transfer length, and data is
transferred from or to the device.
◦ For example, a disk format or repartition are requests that are not
well-suited to a normal Read or Write operation.
◦ Such kinds of requests are handled with one of two extensible I/O
function request codes.
◦ These codes allow any number of driver-specific operations, without
the restrictions of the Read/Write abstraction.
◦ The implementation of either of these Dispatch routines requires a
secondary dispatch based on the value of IoControlCode in the
IRP.
◦ This value is also known as the IOCTL device control code.
◦ Since the secondary dispatch mechanism is completely contained
within the driver's private routine(s), the interpretation of the
IOCTL value is driver-specific.

  

Defining Private IOCTL
Values
◦ The IOCTL values passed to a driver follow a specific structure. Figure illustrates
the fields of this 32-bit structure. The DDK includes a macro, CTL_CODE, that
offers a convenient mechanism to generate IOCTL values. Table describes
the arguments to this macro.

  

IOCTL Argument-Passing
Method
◦ The extended functions defined with an IOCTL value within a driver
often require an input or output buffer.
◦ For example, a driver might report performance data using an IOCTL
value.
◦ The data reported would be transferred through a buffer supplied by
the user.
◦ The Win32 DeviceIoControl function defines parameters for two
buffers, one for input, one for output.
◦ The buffer transfer mechanism provided by the I/O Manager is defined
within the IOCTOL value itself.
◦ It can be either buffered or direct I/O.
◦ As described previously, with buffered I/O, the I/O Manager copies the
user buffer (into or out of) nonpaged system memory, where driver
code can then conveniently operate.
◦ With direct I/O, the driver is given direct access to the user buffer.
◦ The buffer transfer mechanism is defined with each IOCTL value
specification and is a field within the IOCTL structure.
◦ This provides maximum flexibility when performing DeviceIoControl
operations.

  
IOCTL Argument-Passing

Method
The TransferType field of the IOCTL field is two-bits wide and
defines one of the following:
◦ METHOD_BUFFERED. 
◦ The I/O Manager copies the user buffer to and from an intermediate nonpaged
pool buffer on behalf of the driver.
◦ METHOD_IN_DIRECT. 
◦ The I/O Manager provides a list of pages that encompass the user buffer. The
driver uses this list to provide direct I/O (using DMA or programmed I/O) from
the device into user space (i.e., like a Read operation).
◦ METHOD_OUT_DIRECT. 
◦ The I/O Manager provides a list of pages that encompass the user buffer. The
driver uses this list to provide direct I/O from user space into the device (i.e.,
like a Write operation).
◦ METHOD_NEITHER. 
◦ The I/O Manager does not assist with the buffer transfer. The user's original
buffer address (presumably from paged memory) is provided to the driver.
 For faster, larger transfers, direct I/O is most suitable.

  

Writing IOCTL Header Files
◦ This header file should also contain any structure definitions that describe the
buffer contents of specific control operations.
◦ The following is an example of an IOCTL header file:

 #define IOCTL_MISSLEDEVICE_AIM CTL_CODE(
 FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ACCESS_ANY )
 // Structures used by IOCTL_MISSLEDEVICE_AIM

 typedef struct _AIM_IN_BUFFER {


 ULONG Longitude;
 ULONG Latitude;
 } AIM_IN_BUFFER, *PAIM_IN_BUFFER;

 typedef struct _AIM_OUT_BUFFER {


 ULONG ExtendedStatus;
 } AIM_OUT_BUFFER, *PAIM_OUT_BUFFER;

 #define IOCTL_MISSLEDEVICE_LAUNCH CTL_CODE( FILE_DEVICE_UNKNOWN, 0x802,


METHOD_NEITHER, FILE_ACCESS_ANY )
  

Processing IOCTL Requests
◦ Once a driver has announced Dispatch
routines for either IRP_MJ_DEVICE_CONTROL
or IRP_MJ_INTERNAL_DEVICE_CONTROL
function codes, the I/O Manager starts
passing IRPs directly to driver code.
◦ The interpretation of the IOCTL Device Control
code is strictly the responsibility of the
driver.
◦ Not even the various fields of the IOCTL code
itself are verified by the I/O Manager prior to
invocation of the driver's Dispatch routine.
  

Writing Driver Dispatch

Control
NTSTATUS DispatchIoControl( IN PDEVICE_OBJECT pDO, switch (controlCode) {
case IOCTL_MISSLEDEVICEAIM:
 IN PIRP pIrp ) { // Always validate parameters for each case...
if (inSize < sizeof(AIM_IN_BUFFER) ||
 NTSTATUS status = STATUS_SUCCESS; (outSize < sizeof(AIM_OUT_BUFFER ) )
{
 PDEVICE_EXTENSION pDE; status = STATUS_INVALID_BUFFER_SIZE;
break;
 PVOID userBuffer; }
// Valid IRP values - start the device
 ULONG inSize; IoMarkIrpPending( pIrp );
 ULONG outSize; IoStartPacket( pDO, pIrp, 0, NULL);
return STATUS_PENDING;
 ULONG controlCode; // will be the IOCTL request case IOCTL_DEVICE_LAUNCH:
if (inSize > 0 || outSize > 0)
 // The stack location contains the user buffer info {
status = STATUS_INVALID_PARAMETER;
 PIO_STACK_LOCATION pIrpStack; break;
}
 pIrpStack = IoGetCurrentIrpStackLocation( pIrp ); // Same kind of processing start the device
//
 // Dig out the IOCTL request :
 controlCode = pIrpStack-> return STATUS_PENDING;
default:
Parameters.DeviceIoControl.IoControlCode; // Driver received unrecognized control code
 // and the requested transfer sizes status = STATUS_INVALID_DEVICE_REQUEST;
break;
 inSize = pIrpStack- }
>Parameters.DeviceIoControl.InputBufferLength; // Valid control code cases returned above.
// Execution here means an error occurred.
 OutSize = pIrpStack- // Fail the IRP request...pIrp->IoStatus .Status = status ;
pIrp->IoStatus.Information= 0; // no data xfered
>Parameters.DeivceIoControl.OutputBufferLength; IoCompleteRequest( pIrp, IO_NO_INCREMENT )
 // return status;
}
 // Now perform the secondary dispatch
  
  

Initializing the Start I/O Entry
Point
◦ If a driver has a Start I/O routine, it must be announced
during DriverEntry.
◦ This is done by storing the address of the Start I/O routine
into the DriverStartIo field of the driver object, as in the
following code fragment.
 NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN
PUNICODE_STRING pRegistryPath) {
 :
 // Export other driver entry points
 //
 pDriverObject->DriverStartIo = StartIo;
 pDriverObject->DriverUnload = DriverUnload; 
 pDriverObject->MajorFunction[ IRP_MJ_CREATE ] = DispatchOpenClose;
 :
 }
Writing a Start I/O Routine
 Execution Context
 The I/O manager calls the driver's Start I/O routine (described in
Table) either when a Dispatch routine calls IoStartPacket (if
the device was idle), or when some other part of the driver
calls IoStartNextPacket.
What the Start I/O Routine Does
 StartI/O routine will do the following:
1.Call IoGetCurrentStackLocation to get a
pointer to the IRP's stack location.
 PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp
)

2.If a device supports more than one


IRP_MJ_XXX function code, examine the I/O
stack location's MajorFunction field to
determine the operation.
 switch( pIrpStack->MajorFunction ) {
 // Use a SynchCritSection routine to
 // start the write operation...
 case IRP_MJ_WRITE:
What the Start I/O Routine Does
 3.- Begin the actual device operation.
#if DBG==1

 DbgPrint("PPORT: StartIO: Transmitting first byte of %d\n", pDevExt-


>deviceBufferSize);
#endif

 if( !KeSynchronizeExecution( pDevExt->pIntObj, TransmitByte,


pDevExt ))
 {
 DpcForIsr( NULL, pDevObj, pIrp, pDevExt );
 }
 break;

Writing an Interrupt Service Routine
(ISR)
 What the Interrupt Service Routine Does
 The Interrupt Service routine is the real workhorse in a programmed I/O
driver. In general, one of these routines does the following:
1. Determine if the interrupt belongs to this driver. If not, immediately
return a value of FALSE.
 UCHAR status = ReadStatus( pDevExt );
 if ((status & STS_NOT_IRQ))
 return FALSE;
2. Perform any operations needed by the device to acknowledge the
interrupt.
 // its our interrupt, deal with it
 WriteControl( pDevExt, CTL_DEFAULT);
3. Determine if any more data remains to be transferred. If so, start the
next device operation. This eventually results in another interrupt.
 if (!TransmitByte( pDevExt ))
4. If all the data has been transferred (or if a device error occurred),
queue up a DPC request by calling IoRequestDpc.

IoRequestDpc( pDevObj, pIrp, (PVOID)pDevExt );
5. Return a value of TRUE.
Writing a DpcForIsr Routine
 What the DpcForIsr Routine Does
◦ Set the IRP's I/O status block. Put an appropriate
STATUS_XXX code in the Status field and the actual
number of bytes transferred in the Information field.
 pIrp->IoStatus.Information = pDevExt->xferCount;
 // This loopback device always works
 pIrp->IoStatus.Status = STATUS_SUCCESS;
◦ Call IoCompleteRequest to complete the IRP with an
appropriate priority boost. Once called, the IRP must not
be touched again.
 if( pDpc == NULL )
 IoCompleteRequest( pIrp, IO_NO_INCREMENT
);
 else
 IoCompleteRequest( pIrp,
IO_PARALLEL_INCREMENT );
◦ Call to send the next IRP to Start I/O.
 IoStartNextPacket( pDevObj, FALSE );
Projects
 Driver Development Part 2: Introduction to
Implementing IOCTLs

 Building and deploying a basic WDF Kernel
Mode Driver or (Unit6 and 7 from
Windows 2000 Device Drivers book)

 Simple WDM LoopBack Driver

A simple demo for WDM Driver
development

Unit 5 Plug and Play
Plug and Play
 Goals of Plug and Play
◦ The overall goal of the Plug and Play (PnP) architecture is to
provide automated support for the installation and
removal of system devices. To support this overall goal,
several features are necessary.
 Automatic detection of installed and removed hardware.
The device and the bus in which it inserts must notify
controlling software that a particular device
configuration has changed.
Devices must allow for software configuration. The port,
IRQ, and DMA resources used by a device must be
capable of assignment by controlling software. (In
other words, configuration of a board can no longer
come from DIP switches or jumpers.)
Necessary drivers for new hardware must be
automatically loaded as needed by the operating
system.
When devices and their interfacing buses permit, the
system should support hot plugging of the device.
That is, it should be possible to insert or remove the
PnP Components
1.

Plug and Play
 Components of Plug and Play
◦ PLUG AND PLAY MANAGER
 The PnP Manager consists of two parts, kernel-mode and user-mode. The kernel-
mode part interacts with hardware and other kernel-mode components to manage
proper detection and configuration of hardware. The user-mode part interacts with
user interface components to allow inter- active programs to query and alter the
configuration of installed PnP software.
◦ POWER MANAGER
 The Power Manager facilitates the management of power to devices. Depending
upon its nature, it may be possible to temporarily remove power from a device that
is not being used over a prolonged period of time. This component recognizes and
routes power events to appropriate drivers.
◦ REGISTRY
 The Windows 2000 Registry maintains a database of installed hardware and
software of PnP devices. The contents of the Registry assist drivers and other
components in identifying and locating the resources used by a device.
◦ INF FILES
 Each device must be fully described by a file used during installation of the
controlling driver. Each device/driver combination must supply a properly formatted
INF file.
◦ PLUG AND PLAY DRIVERS
 Drivers for PnP devices fall into two categories, WDM and NT drivers. NT PnP drivers
are legacy drivers that rely upon some aspects of the PnP architecture but do not
otherwise fully conform to the WDM model.

Plug and Play
 The Role of Driver Layers in Plug and Play
1.During the installation of the operating system, Windows
2000 discovers and enumerates all buses in the
system registry. The topology and interconnect of
the buses is also discovered and registered.
2.During the boot process, a bus driver for each known bus
is loaded. Typically, Microsoft supplies all bus drivers
but specialized drivers can also be supplied for
proprietary buses.
3.One of the prime responsibilities of a bus driver is to
enumerate all devices attached to the bus. A PDO is
created for each device found.
4.For each device discovered, a class of device is located
within the system registry that defines lower and
upper filters, if any, as well as the driver for the FDO.
5.If the filter or FDO driver is not yet loaded, the system
performs the load and invokes DriverEntry.
6.AddDevice is called for each FDO, which in turn invokes
IoCreateDevice and
Device Tree
Device Tree
S a m p le P n P D e v ice Tre e
The device tree contains information about the devices
present on the system.
The PnP manager builds this tree when the machine boots,
using information from drivers and other components, and
updates the tree as devices are added or removed.
Each node of the device tree is called a device node, or
devnode.
A devnode consists of the device objects for the device's
drivers, plus internal information maintained by the system.
There is a devnode for each device stack.
The PnP manager asks a bus driver for a list of its child
devices using an IRP_MN_QUERY_DEVICE_RELATIONS request.
The bus driver determines its list of children according
to its bus protocol.
The device tree is hierarchical, with devices on a bus
represented as "children" of the bus adapter, controller or
other bus device.
You can see the hierarchy of devices in the device tree
using Device Manager and choosing the view option that
allows you to view devices by connection.
Device Tree
The hierarchy of the device tree reflects the
structure in which the devices are attached in
the machine.
The The device tree is dynamic.
As devices are added to, and removed from the
machine, the PnP manager maintains a current
picture of the devices on the system.
There are other relationships between devices on
the machine besides the hierarchical
relationships represented in the device tree.
These include removal relations and ejection
relations.
You cannot make any assumptions about the order
in which the device tree is built, except that a
bus device is configured before any of its child
devices.
Hardware Resources
 Hardware resources are the assignable, addressable
bus paths that allow peripheral devices and system
processors to communicate with each other.
 Hardware resources typically include I/O port
addresses, interrupt vectors, and blocks of bus-
relative memory addresses.
 Before the system can communicate with a
device instance, the PnP manager must assign
hardware resources to the device instance based on
knowledge of which resources are available and
which ones the device instance is capable of using.
 Resources are assigned to each device node in the
device tree
 The PnP manager keeps track of hardware resources
using lists, which it associates with device nodes.
state diagram
 The states can be divided into two categories:
◦ the states traversed by a device while it is being inserted
◦ the states encountered after the device is started.
state diagram
state diagram
A Pn P d e vice is p h ysica lly p re se n t in th e syste m b e ca u se e ith e r th e u se r
ju st in se rte d th e d e vice o r th e d e vice w a s p re se n t a t b o o t tim e . T h e d e vice
is n o t ye t kn o w n to th e syste m so ftw a re .
To b e g in so ftw a re co n fig u ra tio n fo r th e d e vice , th e Pn P m a n a g e r a n d th e
p a re n t b u s d rive r e n u m e ra te th e d e vice . T h e Pn P m a n a g e r, p o ssib ly w ith
h e lp fro m u se r- m o d e co m p o n e n ts, id e n tifie s th e d rive rs fo r th e d e vice ,
in clu d in g th e fu n ctio n d rive r a n d a n y o p tio n a lfilte r d rive rs. T h e Pn P
m a n a g e r ca lls th e DriverEntry routine of each driver ifthe driver is not yet
loaded.
Once a driver is initialized, it must be ready to initialize its devices.
The PnP manager calls a driver's AddDevice routine for each device the
driver controls.
When a driver receives an IRP_MN_START_DEVICE request from the PnP manager,
the driver starts the device and is ready to process I/O requests for the
device.
If the PnP manager must reconfigure the hardware resources of an active
device, it sends IRP_MN_QUERY_STOP_DEVICE and IRP_MN_STOP_DEVICE requests to
the device's drivers. After it reconfigures the hardware resources, the PnP
manager directs the drivers to restart the device by sending an
IRP_MN_START_DEVICE request.
When a PnP device is being physically removed from the system or has
already been removed, the PnP manager sends various remove IRPs to the
device's drivers, directing them to remove the device's software
representation (device objects, and so forth).
At some point after all of a driver's devices have been removed, the PnP
manager calls the drivers Unload routine and unloads the driver.
Adding a PnP Device to a
Running System

1. A u se r p lu g s a Pn P d e vice in to a fre e slo t o n a Pn P b u s.


2. T h e fu n ctio n d rive r fo r th e b u s d e vice d e te rm in e s th a t a n e w
d e vice is o n its b u s.
3. T h e fu n ctio n d rive r fo r th e b u s d e vice n o tifie s th e Pn P m a n a g e r
th a t its se t o f ch ild d e vice s h a s ch a n g e d .
4. T h e Pn P m a n a g e r q u e rie s th e b u s's d rive rs fo r th e cu rre n t list o f
d e vice s o n th e b u s.
5. T h e fu n ctio n d rive r fo r th e b u s d e vice h a n d le s th e IR P.
Adding a PnP Device to a
Running System

6 .- T h e Pn P m a n a g e r cre a te s d e vn o d e s fo r a n y n e w ch ild d e vice s


o n th e b u s.
7 .- T h e Pn P m a n a g e r g a th e rs in fo rm a tio n a b o u t th e n e w d e vice
a n d b e g in s co n fig u rin g th e d e vice .
8 .- T h e Pn P m a n a g e r sto re s in fo rm a tio n a b o u t th e d e vice in th e
re g istry.
Adding a PnP Device to a
Running System

9 .- T h e ke rn e l- m o d e Pn P m a n a g e r
co o rd in a te s w ith th e u se r-m o d e
Pn P m a n a g e r a n d u se r- m o d e
S e tu p co m p o n e n ts to fin d th e
fu n ctio n a n d filte r d rive rs fo r th e
d e vice , if th e re a re a n y.
1 0 .- T h e u se r-m o d e S e tu p
co m p o n e n ts d ire ct th e ke rn e l-
m o d e Pn P m a n a g e r to lo a d th e
fu n ctio n a n d filte r d rive rs.
Adding a PnP Device to a
Running System

1 1 .- Lo w e r- filte r d rive rs
1 2 .- Fu n ctio n d rive r
1 3 .- U p p e r- filte r d rive rs
1 4 .-A ssig n in g re so u rce s a n d sta rtin g
th e d e vice
Postponing PnP IRP Processing Until
Lower Drivers Finish
1. T h e Pn P m a n a g e r ca lls th e I/ O
m a n a g e r to se n d a n IR P to th e
to p d rive r in th e d e vice sta ck .
2. T h e I/ O m a n a g e r ca lls th e
D isp a tch Pn P routine of the top
d rive r.
3. T h e fu n ctio n d rive r d e cla re s a n d
in itia lize s a ke rn e l-m o d e e ve n t,
se ts u p th e sta ck lo ca tio n fo r th e
n ext-lo w e r d rive r, a n d se ts a n
Io C o m p le tio n routine for this IRP.
4. T h e fu n ctio n d rive r p a sse s th e IR P
d o w n th e d e vice sta ck w ith
Io C a llD riv e r before performing
a n y o p e ra tio n s to h a n d le th e IR P.
5. T h e I/ O m a n a g e r se n d s th e IR P to
th e n ext-lo w e r d rive r in th e
d e vice sta ck b y ca llin g th a t
d rive r's D isp a tch Pn P routine .
6. T h e n ext-lo w e r d rive r in th is
exa m p le is th e lo w e st d rive r in
th e d e vice sta ck , th e p a re n t b u s
Postponing PnP IRP Processing Until
Lower Drivers Finish
7.-When the bus driver calls
IoCompleteRequest, the I/O manager examines
the stack locations of the higher drivers and
calls any IoCompletion routines it finds. In
this example, the I/O manager locates and
calls the IoCompletion routine for the next-
higher driver, the function driver.
8.-The function driver's IoCompletion routine
sets the kernel-mode event supplied in the
context parameter and returns
STATUS_MORE_PROCESSING_REQUIRED
9.-The I/O manager stops completing the IRP and
returns control to the routine that called
IoCompleteRequest, which in this example is
the bus driver's DispatchPnP routine .
10.-The bus driver returns from its
DispatchPnp routine with status indicating
the result of its IRP processing: either
STATUS_SUCCESS or an error status.
11 .- IoCallDriver returns control to its
caller, which in this example is the function
driver's DispatchPnP routine.
12.-The function driver's DispatchPnP routine
resumes processing the IRP.
13.-Once lower drivers have successfully
completed the IRP, the function driver
processes the IRP.
Starting a Device
 The PnP manager sends an
IRP_MN_START_DEVICE request to drivers
either to start a newly enumerated
device or to restart an existing device
that was stopped for resource
rebalancing.
 Function and filter drivers must set an
IoCompletion routine, pass the
IRP_MN_START_DEVICE request down the
device stack, and postpone their start
operations until all lower drivers have
finished with the IRP.
 The parent bus driver, the bottom driver in
the device stack, must be the first driver
to perform its start operations on a
device before the device is accessed by
other drivers.
 To ensure proper sequencing of start
operations, the PnP manager postpones
exposing device interfaces and blocks
Starting a Device
 If a driver for a device fails the
IRP_MN_START_DEVICE request, the
PnP manager sends an
IRP_MN_REMOVE_DEVICE request to
the device stack.
 In response to this IRP, the drivers for
the device undo their start
operations (if they succeeded the
start IRP), undo their AddDevice
operations, and detach from the
device stack.
 The PnP manager marks such a device
"failed start.“
 If a lower driver failed the IRP (
IoCallDriverreturned an error), do
not continue processing the IRP. Do
any necessary cleanup and return
from the DispatchPnP routine .
Starting a Device in a Function
Driver
1. If lower drivers processed the IRP
successfully, start the device.
◦ The exact steps to start a device
vary from device to device.
◦ Such steps might include
mapping I/O space, initializing
hardware registers, setting the
device in the D0 power state,
and connecting the interrupt
with IoConnectInterrupt.
◦ If the driver is restarting a
device after an
IRP_MN_STOP_DEVICE request,
the driver might have device
state to restore.
◦ The device must be powered on
before any drivers can access
it.
Stopping a Device to Rebalance
Resources(999)
1 . T h e Pn P m a n a g e r issu e s a n
IR P _M N _Q U E R Y _S T O P _D E V IC E to ask
w h e th e r th e d rive rs fo r a d e vice ca n sto p
th e d e vice a n d re le a se its h a rd w a re
re so u rce s.
2 . T h e Pn P m a n a g e r issu e s a n
IR P _M N _S T O P _D E V IC E to stop the device .
3 . A fte r su cce ssfu lly re b a la n cin g re so u rce s,
th e Pn P m a n a g e r issu e s
IR P _M N _S TA R T _D E V IC E requests to
re sta rt a n y d e vice s th a t it sto p p e d d u rin g
th e re b a la n ce .
4 . O th e rw ise , th e Pn P m a n a g e r ca n ce ls a
q u e ry -sto p IR P b y se n d in g a n
IR P _M N _C A N C E L_S T O P _D E V IC E .
5 . If a d rive r failsto restart the device after
re b a la n cin g re so u rce s, th e Pn P m a n a g e r
se n d s re m o ve IR Ps to th e d e vice sta ck
Handling an IRP_MN_QUERY_STOP_DEVICE
Request
Determine whether the device can be

stopped, and its hardware resources


released, without adverse affects.
◦ A driver might fail a query-stop IRP,:
 If the device cannot be stopped.
If the device can be stopped and the driver
queues IRPs.
◦ Ensure that any outstanding requests that
were passed to other driver routines and
to lower drivers have completed.
 Perform any other steps required to put
the device in the stop-pending state.
◦ After a driver succeeds a query-stop IRP, it
must be ready to succeed an
IRP_MN_STOP_DEVICE.
◦ Finish the IRP.
Handling an IRP_MN_STOP_DEVICE
Request

1.Ensure that the device is


paused.
2.Release the hardware resources
for the device.
3.Set Irp->IoStatus.Status to
STATUS_SUCCESS.
4.Pass the IRP to the next lower
driver or complete the IRP.
5.
Handling an
IRP_MN_CANCEL_STOP_DEVICE Request

1.Postpone restarting the device until


lower drivers have completed their
restart operations.
2.After lower drivers finish, return the
device to its started state.
3.Start IRPs in the IRP-holding queue.
4.Complete the IRP with
IoCompleteRequest.
Holding Incoming IRPs When A
Device Is Paused
1. In its AddDevice routine, define a flag in the
device extension with a name like
HOLD_NEW_REQUESTS. Clear the flag.
2. Create a FIFO queue for holding IRPs.
3. In its DispatchPnP code for
IRP_MN_QUERY_STOP_DEVICE (or
IRP_MN_STOP_DEVICE), finish any
outstanding requests and set the
HOLD_NEW_REQUESTS flag.
4. In a dispatch routine that accesses the device,
such as DispatchWrite or DispatchRead,
check whether the HOLD_NEW_REQUESTS
flag is set. If so, the driver must mark the
IRP pending and queue it.
5. In DispatchPnP, in response to a start or
cancel-stop IRP, clear the
HOLD_NEW_REQUESTS flag and start the
Removing a Device
1. Query remove
2. Remove after successful
query
3. Reenumerate the device
4. Cancel a query remove
5. Surprise remove
6. Remove after surprise
remove
7. Surprise remove (Windows
98/Me)
8. Remove after a failed start
9.
Handling an
IRP_MN_QUERY_REMOVE_DEVICE
Request
 The PnP manager sends this IRP to inform
drivers that a device is about to be
removed from the machine and to ask
whether the device can be removed
without disrupting the machine.
 It also sends this IRP when a user requests to
update drivers for the device.
 It does the following before sending this IRP
to the drivers for a device:
◦ Notifies all user-mode applications that
registered for notification on the
device by calling
RegisterDeviceNotifcation.
◦ In response to this notification, an
application either prepares for device
removal (closes handles to the
device) or fails the query.
◦ A driver registers for this notification by
calling
Handling an IRP_MN_QUERY_REMOVE_DEVICE
(999) Request
 In response to an IRP_MN_QUERY_REMOVE_DEVICE, a
driver must do the following:
1. Determine whether the device can be removed from
the machine without disrupting operation.
1. A driver must fail a query-remove IRP if any of
the following are true:
1.If removing the device could result in losing
data.
2.If a component has an open handle to the
device.
3.If a driver has been notified (through an
IRP_MN_DEVICE_USAGE_NOTIFICATION
IRP) that the device is in the path for a
paging, crash dump, or hibernation file.
4.If the driver has an outstanding interface
reference against the device. That is, the
driver provided an interface in response
to an IRP_MN_QUERY_INTERFACE request
and the interface has not been
dereferenced.
2. If the device cannot be removed, fail the query-
remove IRP.
3. Set Irp->IoStatus.Statusto an appropriate
Handling an IRP_MN_QUERY_REMOVE_DEVICE
Request 1. If the driver previously sent an IRP_MN_WAIT_WAKE request
to enable the device for wake-up, cancel the wait-wake
IRP.
2. Record the previous PnP state of the device.
 A driver should record the PnP state that the device
was in when the driver received the
IRP_MN_QUERY_REMOVE_DEVICE request because the
driver must return the device to that state if the
query is canceled
(IRP_MN_CANCEL_REMOVE_DEVICE).
3. Finish the IRP: In a function or filter driver:
1. Set Irp->IoStatus.Status to STATUS_SUCCESS.
2. Set up the next stack location with
IoSkipCurrentIrpStackLocation and pass the IRP
to the next lower driver with IoCallDriver.
3. Propagate the status from IoCallDriver as the return
status from the DispatchPnP routine.
4. Do not complete the IRP.
 In a bus driver:
◦ Set Irp->IoStatus.Status to STATUS_SUCCESS.
◦ Complete the IRP (IoCompleteRequest) with
IO_NO_INCREMENT.
Handling an IRP_MN_REMOVE_DEVICE
(oo) Request
The PnP manager uses this IRP to direct drivers to remove a device's

software representation (device objects, and so forth).
 The PnP manager sends this IRP when:
◦ a device has been removed in an orderly fashion,
◦ by surprise (a user pulls the device from its slot without prior
warning),
◦ or when the user requests to update drivers.
 The PnP manager does the following before sending this IRP to the
drivers for a device:
◦ Sends IRP_MN_REMOVE_DEVICE requests to the device's children,
if any.
◦ Notifies any user-mode components and kernel-mode drivers that
registered for notification that the device is being removed.
 The top driver in a device stack handles a remove IRP and passes it to
the next lower driver.
 The parent bus driver for a device is the last driver to perform its
remove-device operations.
 A driver handles remove IRPs in its DispatchPnP routine.
 Before a driver returns success for an IRP_MN_REMOVE_DEVICE request,
it must ensure that all resources for the device have been released.
 This IRP could be the last call before the driver is unloaded.
 Removing one device can create the need to remove a series of other
devices.
◦ The PnP manager coordinates the removal of the additional
Removing a Device in a
Function Driver
1. Is this a function driver for a bus device?
If so, possibly delete any PDOs for devices on the bus.

2. Has the driver already handled a previous


IRP_MN_SURPRISE_REMOVAL request for this FDO?
 If so, perform any remaining clean-up and skip to step
(7), IoCallDriver.
3. If the driver previously enabled the device for wake-up,
cancel the IRP_MN_WAIT_WAKE request.
4. Ensure that the device is inactive.
5. Perform any power-down operations.
6. Disable any device interfaces by calling
IoSetDeviceInterfaceState.
7. Free any hardware resources for the device in use by the
driver.
8. Pass the IRP_MN_REMOVE_DEVICE request down to the next
driver.
9. Remove the device object from the device stack with
IoDetachDevice.
10.Clean up any device-specific allocations, memory, events,
and so forth.
Removing a Device in a Bus
Driver
1.Has the driver handled a previous
IRP_MN_SURPRISE_REMOVAL request
for this PDO?
 If so, perform any remaining clean-
up and skip to step (4).
2.Complete any requests queued in the
driver.
3.Remove power from the device, if the bus
driver is capable of doing so, and notify
the power manager by calling
PoSetPowerState.
4.
Handling an IRP_MN_CANCEL_REMOVE_DEVICE
Request In a function or filter driver,
◦ Sets an IoCompletion routine,
◦ Passes the IRP_MN_CANCEL_REMOVE_DEVICE down the
device stack,
◦ and postpones its restart operations until all lower drivers
have finished with the IRP.
◦ Lower drivers
 The drivers return the device to the previous PnP state
it was in prior to receiving the
IRP_MN_QUERY_REMOVE_DEVICE request.
 Typically, drivers return the device to the started state.
 Exact operations depend on the device and the driver.
 If the device was previously enabled for wake-up,
should send an IRP_MN_WAIT_WAKE request to
reenable wake-up.
 Set Irp->IoStatus.Status to STATUS_SUCCESS and
complete the IRP with IoCompleteRequest.
◦ A function or filter driver also completes the IRP
◦ Drivers must succeed this IRP. If any driver fails this IRP,
the device is left in an inconsistent state.
1.
Handling an
IRP_MN_SURPRISE_REMOVAL
 The PnP manager sends an
Request
IRP_MN_SURPRISE_REMOVAL request for the following
reasons:
◦ If the bus has hot-plug notification, it notifies the
device's parent bus driver that the device has
disappeared.
 The bus driver calls
IoInvalidateDeviceRelations.
In response, the PnP manager queries the bus
driver for its children (
IRP_MN_QUERY_DEVICE_RELATIONS for
BusRelations).
The PnP manager determines that the device
is not in the new list of children and initiates
its surprise-removal operations for the
device.
◦ The bus is enumerated for another reason and the
surprise-removed device is not included in the
Handling an
IRP_MN_SURPRISE_REMOVAL Request to
All PnP drivers must handle this IRP and must set Irp->IoStatus.Status

STATUS_SUCCESS.
 A driver for a PnP device must be prepared to handle IRP_MN_SURPRISE_REMOVAL at
any time after the driver's AddDevice routine is called.
 Proper handling of the IRP enables the drivers and the PnP manager to:
1. Disable the device, in case it is still connected.
1. If the driver stack successfully completed an IRP_MN_STOP_DEVICE
request but then, for some reason, failed a subsequent
IRP_MN_START_DEVICE request, the device must be disabled.
2. Release hardware resources assigned to the device and make them available to
another device.
1. As soon as a device is no longer available, its hardware resources should
be freed.
2. The PnP manager can then reassign the resources to another device,
including the same device, which a user might hot-plug back into the
machine.
3. Minimize the risk of data loss and system disruption.
1. When a user removes a hot-plug device without first using the Unplug or
Eject Hardware program, the surprise-removal can hang the machine,
crash the machine, and/or cause data loss.
 The best way to avoid such disruption is for the device vendor to
implement a locking mechanism for hot-plug devices.
 Such a mechanism ensures that the device is removed in a controlled
fashion.
 The PnP manager alerts components accessing the device that the
device is being removed, so that they can perform orderly clean-up
and removal.
Handling an
IRP_MN_SURPRISE_REMOVAL Request
 In response to IRP_MN_SURPRISE_REMOVAL, a driver must do
the following, in the listed order:
◦ Determine if the device has been removed.
 The driver must always attempt to determine if the
device is still connected.
If it is, the driver must attempt to stop the device
and disable it.
◦ Release the device's hardware resources (interrupts, I/O
ports, memory registers, and DMA channels).
◦ In a parent bus driver, power down the bus slot if the
driver is capable of doing so. Call PoSetPowerState
to notify the power manager.
◦ Prevent any new I/O operations on the device.
A driver should process subsequent
IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_POWER,
and IRP_MJ_PNP requests, but the driver must
prevent any new I/O operations.
◦ A driver can set a bit in the device extension to indicate
that the device has been surprise-removed. The
driver's dispatch routines should check this bit.
Project Toaster Sample
Toaster
 Description
◦ The Toaster sample provides a starting point for
Microsoft Windows driver development. 
◦ This sample contains annotated code to illustrate
the functionality of a:
bus driver
function driver
assorted class
Device driver
bus filter drivers
class installer
device-specific co-installer for a hypothetical
Toaster bus and its devices.
Toaster
 Theory of Operation
◦ Every device driver stack for a Plug and
Play (PnP) device on a Microsoft Windows
Server 2003, Windows XP, or Windows
2000 operating system typically consists
of a
 bus driver,
a function driver, and
zero or more filter drivers.
◦ These drivers must support PnP, power
management, and Windows Management
Instrumentation (WMI) to provide a better
user experience and greater satisfaction.
Toaster
 Theory of Operation
◦ Imagine a system with a new type of PnP I/O bus called a
toaster bus.
◦ A controller chip on the motherboard initializes and
manages the bus.
◦ The bus has a couple of ports that you can plug your
toasters into.
◦ To provide support for this bus on Windows NT 4.0, you
must modify the hardware abstraction layer (HAL) to
recognize and initialize the I/O bus during system
startup, and you must provide a set of HAL functions
for scanning the bus and accessing the configuration
space of the devices by other drivers.
◦ Next, you must write drivers for every type of toaster
device that loads along with the system, and then use
the exported HAL functions to scan the bus to detect
the device, read the I/O resource requirements, and
configure and initialize the device.
◦ These drivers are loaded regardless of whether or not a
Toaster
 Theory of Operation
◦ To support this bus and its devices under Windows,
however, you do not have to modify the HAL or export
a new set of functions.
◦ Instead, you need only to write a bus driver that has
knowledge of bus architecture, identifies (that is,
enumerates) devices on the bus, reads their resource
requirements, and configures them.
◦ This driver model also makes the operating system
independent of its I/O bus, so you do not need help
from Microsoft if you design a new I/O bus to modify
the HAL.
◦ Then, you write function drivers to control individual
devices that are connected to the bus.
◦ Later on, you can write one or more filter drivers to add
or modify the features that are supported by the bus, a
specific device, or class of devices.
◦ There can be any number of lower-level or upper-level
filter drivers for a bus, a device, or a class of devices.
Toaster
 Theory of Operation
◦ To make the sample code closer to a real-world
driver, the sample defines a new class of devices
called the TOASTER class and includes a bus
driver, function driver, and all possible class,
device, and bus filter drivers for this hypothetical
TOASTER bus and its devices. 
◦ There is also a sample coinstaller DLL to show how
you can parse a custom section from an INF file
and perform some special operations before and
after the installation of a device and how you can
create FriendlyName for a device.
◦ The function and bus driver also show how you can
provide power manager and WMI support.
Toaster
 Pre-compiled Module Information
Power Management
Introduction to Power
Management
 Power management is a system-wide, integrated approach to the
use and conservation of power.
 Computer systems that include hardware and software support
for power management provide for the following:
1.Minimal startup and shutdown delays.
2.The system can sleep in a low-power state from which it can
resume operation without a complete reboot.
3.Greater overall power efficiency and battery life Power is
applied to devices only when they are delivering function
to the user.
4.If a device is not in use, it can be powered off and then
powered up later, on demand.
5.Quieter operation Powering down unused devices reduces
noise.
6.In addition, hardware and software can manage electrical
current load and thermal load, resulting in computers that
are nearly inaudible when sleeping.
Introduction to Power
Management
 In systems that support power management, the computer
and its peripheral devices are maintained at the lowest
feasible power level to accomplish the tasks at hand.
 Drivers cooperate with the operating system to manage
power for their devices.
 If all drivers support power management, the operating
system can manage power consumption on a system-
wide basis,
◦ thus conserving power,
◦ shutting down and resuming quickly, and
◦ waking up when required.

Introduction to Power
Management
 This integrated approach to power management — involving the
operating system, system hardware, device drivers, and device
hardware — results in the following:
◦ More intelligent power management decisions. At each level,
the best-informed component directs power usage.
◦ Greater reliability. Better power management decisions
reduce the chance of ill-timed shutdowns and loss of data.
◦ Platform independence. The operating system manages
power in a controlled, uniform way across different
hardware platforms, allowing maximum conservation of
power on various devices.
◦ Better device integration. Device drivers that conform to
industry-wide specifications ensure maximum
conservation regardless of the hardware platform.
 Combined, these advantages result in greater power conservation
and more efficient usage than has previously been possible.

System-Wide Overview of
Power Management
Power States
 A power state indicates the level of power consumption — and
thus the extent of computing activity — by the system or by a
single device.
 The power manager sets the power state of the system as a
whole.
 Device drivers set the power state of their individual devices.
 The ACPI (Advanced Configuration and Power Interface)
specification defines two sets of discrete power states −
system power states and device power states.
 Each power state has a unique name.
 System power states are named Sx, where x is a state number
between 0 and 5.
 Device power states are named Dx, where x is a state number
between 0 and 3.
 The state number is inversely related to power consumption:
higher numbered states use less power.
 States S0 and D0 are the highest-powered, most functional, fully
on states.
ACPI BIOS
 The integrated power management features supported by
Microsoft Windows operating systems are available only
on computers that have an Advanced Configuration and
Power Interface (ACPI) BIOS.
 An ACPI BIOS provides features at the hardware level that
make software power management possible.
 At boot time, the operating system loader checks whether
such a BIOS is loaded.
 ACPI is enabled in the operating system.
 If such a BIOS is not loaded, ACPI is disabled and the less
robust Advanced Power Management (APM) model is
used instead.

ACPI Driver
 Microsoft supplies the ACPI driver as part of the operating
system.
 On systems that have an ACPI BIOS, the HAL causes the
ACPI driver to be loaded during system start-up at the
base of the device tree, where the driver acts as the
interface between the operating system and the BIOS.
 The ACPI driver is transparent to other drivers.
 The ACPI driver's responsibilities include support for PnP
and power management.
 ACPI provides power management and PnP features to the
device stack by means of these device objects.

Power Manager
 The power manager is responsible for managing power usage for
the system.
 It administers the system-wide power policy and tracks the path
of power IRPs through the system.
 The power manager requests power operations by sending
IRP_MJ_POWER requests to drivers.
 A request can specify a new power state or can query whether a
change in power state is feasible.
 When sleep, hibernation, or shutdown is required, the power
manager requests the appropriate power action by sending an
IRP_MJ_POWER request to each leaf node in the device tree.
 The power manager considers the following in determining
whether the system should sleep, hibernate, or shut down:
◦ System activity level
◦ System battery level
◦ Shutdown, hibernate, or sleep requests from applications
◦ User actions, such as pressing the power button
◦ Control panel settings

Driver Role in Power
Management
 Drivers support power management in two ways:
◦ Drivers respond to system-wide power requests issued
by the power manager.
◦ Drivers manage power for their individual devices.
 Every driver must have a DispatchPower routine to handle
IRP_MJ_POWER requests.
 The DispatchPower routine must inspect each power IRP
and either handle it or pass it down to the next-lower
driver.
 For a device to participate in power management, every
driver in the device stack for the device must respond to
or pass power IRPs appropriately.
 Failure of a single driver to act correctly can cause power
management to be disabled across the entire system.
 Drivers might perform certain power tasks, such as
powering on a device at start-up or powering off a device
at removal, without receiving a power IRP.
Reporting Device Power Capabilities
 During enumeration, drivers report device-specific information in
response to a PnP IRP_MN_QUERY_CAPABILITIES request.
 Along with other such information, drivers report a device's power
management capabilities in the DEVICE_CAPABILITIES
structure.
 Typically, the bus driver fills in this structure.
 U LO N G   W a ke Fro m D 0 : 1 ;
typedef struct _DEVICE_CAPABILITIES {

  U LO N G   W a ke Fro m D 1 : 1 ;
  USHORT  Size;   U LO N G   W a ke Fro m D 2 : 1 ;
  USHORT  Version;   U LO N G   W a ke Fro m D 3 : 1 ;
  ULONG  DeviceD1:1;   U LO N G   H a rd w a re D isa b le d : 1 ;
  ULONG  DeviceD2:1;   U LO N G   N o n D yn a m ic : 1 ;
  ULONG  LockSupported:1;   U LO N G   W a rm E je ctS u p p o rte d : 1 ;
  ULONG  EjectSupported:1;   U LO N G   N o D isp la yIn U I: 1 ;
  ULONG  Removable:1;   U LO N G   R e se rve d : 1 4 ;
  ULONG  DockDevice:1;   U LO N G   A d d re ss;
  ULONG  UniqueID:1;   U LO N G   U IN u m b e r;
  ULONG  SilentInstall:1;   D E V IC E _PO W E R _S TA T E   D e vice S ta te [ Po w e rS
  ULONG  RawDeviceOK:1; yste m M a xim u m ] ;
  ULONG  SurpriseRemovalOK:1;   S Y S T E M _PO W E R _S TA T E   S yste m W a ke ;
    D E V IC E _PO W E R _S TA T E   D e vice W a ke ;
  U LO N G   D 1 La te n cy ;
  U LO N G   D 2 La te n cy ;
  U LO N G   D 3 La te n cy ;
}  DEVICE_CAPABILITIES ,  * PDEVICE_CAPABILITI
ES;
Reporting Device Power
Capabilities
 DeviceD1 and DeviceD2
◦ The DeviceD1 and DeviceD2 indicate whether the device hardware
supports these device power states.
◦ Each is a single bit, which is set if the device supports the state and is
clear if the device does not support the state.
◦ The operating system assumes that all devices support the D0 and D3
device power states.
 WakeFromD0, WakeFromD1, WakeFromD2, and
WakeFromD3
◦ Each of these DEVICE_CAPABILITIES structure members indicates
whether the device can awaken in response to an external signal that
arrives when the device is in the specified state.
◦ For a device that supports all four device power states (D0, D1, D2, D3)
but can awaken only from states D0 and D1, the WakeFromD0 and
WakeFromD1 bits are set, and the WakeFromD2 and WakeFromD3
bits are clear.
 DeviceState
◦ The DeviceState is an array of DEVICE_POWER_STATE values that are
indexed by SYSTEM_POWER_STATE values ranging from
PowerSystemWorking to PowerSystemShutdown.
◦ Each element of the array contains the maximum device power state
that the device can support for the system power state denoted by the
Reporting Device Power
Capabilities
 SystemWake
◦ The SystemWake contains the lowest system power state from
which the device can wake the system.
◦ The bus driver sets this value at when it enumerates the device.
◦ A higher-level driver can change the value to a higher-powered state
but cannot change it to a lower-powered state.
 DeviceWake
◦ The DeviceWake contains the lowest device power state from
which the device can signal a wake event, or
PowerDeviceUnspecified if the device cannot wake in response
to an external signal.
◦ The bus driver sets this value. A higher-level driver can change the
value to a higher-powered state.
 D1Latency, D2Latency, and D3Latency
◦ The D1Latency, D2Latency, and D3Latency contain the
approximate time, in 100-microsecond units, that the device
requires to return to the D0 state from each of the sleeping states.
◦ A driver should specify a latency time of zero for any device power
state that it does not support.


Handling Power IRPs
 Drivers handle power IRPs in a DispatchPower routine.
 All power management requests have the major IRP code
IRP_MJ_POWER and one of the following minor codes:
◦ IRP_MN_QUERY_POWER — Queries to determine
whether changing power state is feasible
◦ IRP_MN_SET_POWER — Requests a change from one
power state to another
◦ IRP_MN_WAIT_WAKE— Requests that a device be
enabled to wake itself or the system
◦ IRP_MN_POWER_SEQUENCE — Requests information to
optimize power restoration to a particular device





Device Power States
 A device power state describes the power state of a
particular device.
 Device power states are defined in terms of the
following criteria:
◦ Power consumption: How much power does the device
use?
◦ Device context: How much of its operational context does
the device retain in this state?
◦ Device driver behavior: What must the drivers for the
device do to restore the device to the fully operational
state?
◦ Restore time: How long does it take to restore the device
to the fully operational state?
◦ Wake-up capability: Can the device request wake-up from
this state? In general, if a device can request wake-up
from a given power state (D2, for example), it can also
request wake-up from any higher-powered state (D1).

Device Working State
D0
In the D0 state, the device is fully on
and operational.
◦ Power consumption Highest level of continuous
power consumption for the device.
◦ Device context All context retained.
◦ Device driver behavior Normal operation.
◦ Restore time Not applicable.
◦ Wake-up capability Not applicable.
Device Power State D1
 Device power state D1 is the highest-powered sleeping
state. It has the following characteristics:
◦ Power consumption Consumption is less than in the D0 state
but greater than or equal to that in the D2 state.
◦ Device context In general, device context is preserved by the
hardware and need not be restored by the driver.
◦ Device driver behavior Drivers must save and restore or
reinitialize any context lost by the hardware. Typically,
however, devices lose little context upon entering this state.
◦ Restore time In general, the time required to restore the device
to D0 from D1 should be less than restoration from D2 to D0.
◦ Wake-up capability A device in state D1 might be able to
request wake-up.
 To minimize the user's perception of delay, restoring a
device to state D0 from D1 should incur the least
possible delay. Minimizing delay in the state transition
is more important than reducing power consumption.
Device Power State D2
 State D2 is an intermediate sleeping state with the
following characteristics:
◦ Power consumption Consumption is less than or equal to that
in the D1 state.
◦ Device context In general, most device context is lost by the
hardware.
◦ Device driver behavior Device drivers must save and restore
or reinitialize any context lost by the hardware. A typical
device loses most context when it enters D2.
◦ Restore time Restoring the device from D2 to D0 takes at least
as long as restoring the device from D1 to D0.
◦ Wake-up capability A device in state D2 might be able to
request wake-up.
 In state D2, power consumption drops to the lowest
level from which drivers can recover in a reasonable
amount of time, that is, without a delay that most
users would find noticeably slow for a device of that
type.
 While the priority for state D1 is the user's perception of
Device Power State D3
 State D3 is the lowest-powered sleeping state. All
devices must support this state. It has the following
characteristics:
◦ Power consumption Power might have been fully removed
from the device and/or from the system.
◦ Device context The device driver is solely responsible for
restoring device context. The driver must preserve and then
restore device context or must reinitialize the device upon
transition to a different power state.
◦ Device driver behavior The device driver is solely responsible
for restoring device context, typically from the most recent
working configuration.
◦ Restore time Total restore time is the highest of any of the
device power states.
◦ Wake-up capability Devices in state D3 cannot wake a
sleeping system.
 In state D3, power has been completely removed from
the device or only minimal trickle current is available.
 Drivers and hardware must be prepared for the absence
of power.
Managing Device Power
Policy
 Just as the power manager maintains and
administers power policy for the system, one
driver in the device stack for each device
maintains and administers power policy for the
device.
 This driver is the device power policy owner for the
device.
 The device power policy owner is the driver that
has the most information about the device usage
and power state.
 It need not physically be able to set the device
registers to power the device on and off, but it
must be able to determine when the device is in
use, when it is idle, and when it should change
power state.
 Typically, the function driver for a device is its
Managing Device Power
Policy
 The device power policy owner is responsible
for the following:
◦ Setting the initial power state of the device to D0
by calling PoSetPowerState as it handles the
PnP manager's IRP_MN_START_DEVICE request.
◦ Sending a device power request in response to a
system power request by calling
PoRequestPowerIrp.
◦ Detecting when the device is idle and putting it to
sleep to conserve energy. Either the power
manager or the device policy owner can detect
an idle device and send a device power IRP to
change its state.
◦ Returning its device to the working state when
required. When an I/O request arrives for a
sleeping device, the device's drivers should
return it to the working state.
System Power States
 System power states describe the power
consumption of the system as a whole.
 The operating system supports six system
power states, referred to as S0 (fully on and
operational) through S5 (power off).
 Each state is characterized by the following:
◦ Power consumption: how much power does the
computer use?
◦ Software resumption: from what point does the
operating system restart?
◦ Hardware latency: how long does it take to return
the computer to the working state?
◦ System hardware context (such as the content of
volatile processor registers, memory caches, and
RAM): how much system hardware context is
retained? Must the operating system reboot to
System Power States
 State S0 is the working state.
 States S1, S2, S3, and S4 are sleeping states,
in which the computer appears off because
of reduced power consumption but retains
enough context to return to the working
state without restarting the operating
system.
 State S5 is the shutdown or off state.
 A system is waking when it is in transition from
the shutdown state (S5) or any sleeping
state (S1-S4) to the working state (S0), and it
is going to sleep when it is in transition from
the working state to any sleep state or the
shutdown state.
System Power States
 Possible System Power State Transitions
◦ As the previous figure shows, the system cannot enter
one sleep state directly from another; it must always
enter the working state before entering any sleep
state.
◦ For example, a system cannot transition from state S2 to
S4, nor from state S4 to S2.
◦ It must first return to S0, from which it can enter the next
sleep state.
◦ Because a system in an intermediate sleep state has
already lost some operating context, it must return to
the working state to restore that context before it can
make an additional state transition.
System Working State
 S0 power state S0, the system working state, has
System
the following characteristics:
 Power consumptionMaximum. However, the power
state of individual devices can change dynamically as
power conservation takes place on a per-device basis.
Unused devices can be powered down and powered
up as needed.
 Software resumption Not applicable.
 Hardware latency None.
 System hardware context All context is retained.
System Sleeping States
 States S1, S2, S3, and S4 are the sleeping states.
 A system in one of these states is not performing any computational
tasks and appears to be off.
 Unlike a system in the shutdown state (S5), however, a sleeping
system retains memory state, either in the hardware or on disk.
 The operating system need not be rebooted to return the computer to
the working state.
 Some devices can wake the system from a sleeping state when certain
events occur, such as an incoming call to a modem.
 In addition, on some computers, an external indicator tells the user
that the system is merely sleeping.
 With each successive sleep state, from S1 to S4, more of the computer
is shut down.
 All ACPI-compliant computers shut off their processor clocks at S1 and
lose system hardware context at S4 (unless a hibernate file is
written before shutdown), as listed in the sections below.
 Details of the intermediate sleep states can vary depending on how
the manufacturer has designed the machine. For example, on
some machines certain chips on the motherboard might lose power
at S3, while on others such chips retain power until S4.
Furthermore, some devices might be able to wake the system only
System Power State S1
 System power state S1 is a sleeping state with the
following characteristics:
 Power consumption Less consumption than in S0 and
greater than in the other sleep states. Processor clock
is off and bus clocks are stopped.
 Software resumption Control restarts where it left off.
 Hardware latency Typically no more than two seconds.
 System hardware context All context retained and
maintained by hardware.
System Power State S2
 System power state S2 is similar to S1 except that the CPU
context and contents of the system cache are lost
because the processor loses power. State S2 has the
following characteristics:
 Power consumption Less consumption than in state
S1 and greater than in S3. Processor is off. Bus clocks
are stopped; some buses might lose power.
 Software resumption After wake-up, control starts
from the processor's reset vector.
 Hardware latency Two seconds or more; greater than
or equal to the latency for S1.
 System hardware context CPU context and system
cache contents are lost.
System Power State S3
System power state S3 is a sleeping state with

the following characteristics:


 Power consumption Less consumption than
in state S2. Processor is off and some chips
on the motherboard also might be off.
 Software resumption After the wake-up
event, control starts from the processor's
reset vector.
 Hardware latency Almost indistinguishable
from S2.
 System hardware context Only system
memory is retained. CPU context, cache
contents, and chipset context are lost.
System Power State S4
To reduce power consumption to a minimum, the hardware
powers off all devices.
Operating system context, however, is maintained in a

hibernate file (an image of memory) that the system


writes to disk before entering the S4 state.
Upon restart, the loader reads this file and jumps to the

system's previous, prehibernation location.


If a computer in state S1, S2, or S3 loses all AC or battery

power, it loses system hardware context and therefore


must reboot to return to S0.
A computer in state S4, however, can restart from its

previous location even after it loses battery or AC power


because operating system context is retained in the
hibernate file.
A computer in the hibernate state uses no power (with the

possible exception of trickle current).


System Power State S4
 State S4 has the following characteristics:
 Power consumption Off, except for trickle current to the
power button and similar devices.
 Software resumption System restarts from the saved
hibernate file. If the hibernate file cannot be loaded,
rebooting is required. Reconfiguring the hardware while the
system is in the S4 state might result in changes that
prevent the hibernate file from loading correctly.
 Hardware latency Long and undefined. Only physical
interaction returns the system to the working state. Such
interaction might include the user pressing the ON switch
or, if the appropriate hardware is present and wake-up is
enabled, an incoming ring for the modem or activity on a
LAN. The machine can also awaken from a resume timer if
the hardware supports it.
 System hardware context None retained in hardware. The
system writes an image of memory in the hibernate file
before powering down. When the operating system is
loaded, it reads this file and jumps to its previous location.
System Power Policy
 In its role as system power policy manager, the power manager keeps
track of system activity, determines the appropriate system power
state, and sends IRP_MJ_POWER requests to query or change the
system power state.
 The power manager maintains two separate power policies — one for
AC (wall current) and one for DC (battery or UPS) — and
automatically switches between these two policies depending on
the current power source.
 Typically, AC power policy emphasizes performance over conservation,
while DC power policy emphasizes conservation over performance.
 Computers automatically switch from AC to battery power, and from
one battery to another, as each such power source goes off line.
 If the computer hardware allows the operating system to select the
power source, the power manager tracks which battery is the least
charged but still functional and selects it to power the computer.
 As soon as AC power becomes available, the computer hardware
automatically starts to charge a battery.
 If the hardware allows the operating system to select which battery to
charge, the power manager selects the least discharged battery for
recharging; this increases the chances that the system will have at
least one well-charged battery at all times.
Preventing System Power
State Changes
 Drivers cannot directly set system power policy, the power manager
provides three routines through which a driver can prevent system
transitions out of the working state:
◦ PoSetSystemState,
◦ PoRegisterSystemState,
◦ PoUnregisterSystemState.
 By calling PoRegisterSystemState or PoSetSystemState, a driver
can notify the power manager that a user is present or that the
driver requires use of the system or display.
 PoRegisterSystemState allows a driver to register a continuous
busy state.
 It returns a handle through which the driver can later change its
settings.
 As long as the state registration is in effect, the power manager does
not attempt to put the system to sleep.
 The driver cancels the state registration by calling
PoUnregisterSystemState.

Projects
Unit 6
Input/Output Techniques
Methods for Accessing Data
Buffers
 One of the primary responsibilities of driver stacks is
transferring data between user-mode applications and a
system's devices. The operating system provides the
following three methods for accessing data buffers:
◦ Buffered I/O The operating system creates a nonpaged system
buffer, equal in size to the application's buffer.
 For write operations, the I/O manager copies user data into the
system buffer before calling the driver stack.
 For read operations, the I/O manager copies data from the system
buffer into the application's buffer after the driver stack
completes the requested operation.
◦ Direct I/O The operating system locks the application's buffer in
memory.
 It then creates a memory descriptor list (MDL) that identifies the
locked memory pages, and passes the MDL to the driver stack.
 Drivers access the locked pages through the MDL.
◦ Neither Buffered Nor Direct I/O The operating system passes the
application buffer's virtual starting address and size to the
driver stack.
 The buffer is only accessible from drivers that execute in the
Using Buffered I/O
A driver that services an interactive or slow
device, or one that usually transfers relatively
small amounts of data at a time, should use
the buffered I/O transfer method.
 Using buffered I/O for small, interactive
transfers improves overall physical memory
usage, because the memory manager doesn't
need to lock down a full physical page for
each transfer, as it does for drivers that
request direct I/O.
 Generally, video, keyboard, mouse, serial, and
parallel drivers request buffered I/O.
Using Buffered I/O
Using Buffered I/O(day)
1. Some range of user-space virtual addresses represents the current
thread's buffer, and that buffer's contents might be stored
somewhere within a range of page-based physical addresses
(dark shading in the previous figure).
2. The I/O manager services the current thread's read request, for which
the thread passes a range of user-space virtual addresses
representing a buffer.
3. The I/O manager checks the user-supplied buffer for accessibility and
calls ExAllocatePoolWithTag to create a resident system-space
buffer (SystemBuffer) the size of the user-supplied buffer.
4. The I/O manager provides access to the newly allocated
SystemBuffer in the IRP it sends to the driver. If the figure
showed a write request, the I/O manager would copy data from
the user buffer into the system buffer before it sent the IRP to the
driver.
5. For the read request shown in the figure, the driver reads data from
the device into the system-space buffer. When the read request
has been satisfied, the driver calls IoCompleteRequest with the
IRP.
6. When the original thread is again active, the I/O manager copies the
read-in data from the system buffer into the user buffer. It also
calls ExFreePool to release the system buffer.
Using Direct I/O
 Drivers for devices that can transfer large amounts of
data at a time should use direct I/O for those transfers.
 Using direct I/O for large transfers improves a driver's
performance, both by reducing its interrupt overhead
and by eliminating the memory allocation and copying
operations inherent in buffered I/O.
 Generally, mass-storage device drivers request direct I/O
for transfer requests, including lowest-level drivers that
use direct memory access (DMA) or programmed I/O
(PIO), as well as any intermediate drivers chained
above them.
Using Direct I/O
Using Direct I/O
1. Some range of user-space virtual addresses represents the current thread's
buffer, and that buffer's contents might actually be stored on some number
of physically discontiguous pages (dark shading in the previous figure). The
I/O manager creates an MDL to describe this buffer. An MDL is an opaque
data structure, defined by the Memory manager, that maps a particular
virtual address range to one or more page-based physical address ranges.
2. The I/O manager services the current thread's read request, for which the thread
passes a range of user-space virtual addresses that represent a buffer.
3. The I/O manager or FSD checks the user-supplied buffer for accessibility and calls
MmProbeAndLockPages with the previously created MDL.
MmProbeAndLockPages also fills in the corresponding physical address
range in the MDL. As the previous figure shows, an MDL for a virtual range
can have several corresponding page-based physical address entries, and
the virtual range for a buffer might begin and end at some byte offset from
the start of the first and last pages described by an MDL.
4. The I/O manager provides a pointer to the MDL (MdlAddress) in an IRP that
requests a transfer operation. Until the I/O manager or file system calls
MmUnlockPages after the driver completes the IRP, the physical pages
described in the MDL remain locked down and assigned to the buffer.
However, the virtual addresses in such an MDL can become invisible (and
invalid), even before the IRP is sent to the device driver or to any
intermediate driver that might be layered above the device driver.
5. If the driver uses packet-based system or bus-master DMA, its AdapterControl
routine calls MmGetMdlVirtualAddress with the IRP's MdlAddress
pointer to get the base virtual address for the MDL's page-based entries.
Adapter Objects and DMA
 Any driver that uses direct I/O and DMA must create an
adapter object.
 The adapter object represents either a DMA controller channel
or port, or a bus-master device.
 Two kinds of lowest-level drivers must use adapter objects:
◦ Drivers for devices that use the system DMA controller.
Such devices are called slave devices and are said to
"use system (or slave) DMA."
◦ Drivers for devices that are bus-master adapters. Such
devices arbitrate with the system for use of the I/O bus,
and thus use bus-master DMA.
 Drivers provide storage, usually in a device extension, for a
pointer to the adapter object.
 To carry out DMA transfers, drivers of devices that use either
of these DMA methods usually have an AdapterControl
routine and call system-supplied support routines that
manipulate adapter objects.
Using System DMA

 Drivers of slave DMA devices use one of the


following types of system-provided DMA
support:
 Packet-based DMA, if the driver need not use a
system DMA controller's auto-initialize mode.
 Common-buffer DMA, if the driver does use the
auto-initialize mode.
Using Packet-Based System
DMA
Drivers of slave devices that use packet-based DMA call the following
general sequence of support routines as they process an IRP
requesting a DMA transfer:
 KeFlushIoBuffers just before attempting to allocate the system DMA
controller
 AllocateAdapterChannel when the driver is ready to program its
device for DMA and needs the system DMA controller
AllocateAdapterChannel, in turn, calls the driver's
AdapterControl routine.
 MmGetMdlVirtualAddress to get an index into the MDL, required as
an parameter in the initial call to MapTransfer
 MapTransfer to program the system DMA controller for the transfer
operation A driver might need to call MapTransfer
 FlushAdapterBuffers just after each DMA transfer operation to/from
the slave device If a driver must call MapTransfer more than once
to transfer all the requested data, it must call
FlushAdapterBuffers as many times as it calls MapTransfer.
 FreeAdapterChannel either as soon as all the requested data has
been transferred or if the driver fails the IRP because of a device I/O
error
Servicing Interrupts
Introduction to Interrupt
Objects
 Each driver of a physical device that generates
interrupts must register an InterruptService routine
(ISR) before it starts the device.
 When a driver registers an ISR, the system creates an
interrupt object.
 These system-defined objects are used to store the
following information:
◦ The system creates an interrupt object for each processor the
device is capable of interrupting. However, the system can
perform load balancing by restricting a particular device
interrupt to a subset of available processors.
◦ The system-assigned interrupt vectors for each device on each
I/O bus in the machine.
◦ For machines with more than one bus, the PnP manager maps
bus-relative interrupt vectors of the devices on each I/O bus to
a set of system-assigned interrupt vectors.
◦ The address of the InterruptService routine, which will be called
when the device interrupts.
◦ Additional information for internal use by the system.
Connecting to a Single
Interrupt Vector
 If the ISR handles a single device that uses a single interrupt vector, the driver
should specify the following parameters when calling IoConnectInterrupt:
◦ The address of a driver-allocated location that receives the interrupt object pointer
returned by IoConnectInterrupt.
◦ The ISR's entry point.
◦ A pointer to driver-supplied information the ISR will use when it is called
◦ A NULL spin lock pointer, which indicates that the driver will use an internal interrupt
spin lock provided by the system
◦ The device's interrupt vector, obtained from a CmResourceTypeInterrupt resource
in the CM_RESOURCE_LIST structure for translated resources, received in the
IRP_MN_START_DEVICE IRP.
◦ The device's DIRQL, obtained from a CmResourceTypeInterrupt resource in the
CM_RESOURCE_LIST structure for translated resources, received in the
IRP_MN_START_DEVICE IRP.
◦ The device's interrupt triggering mode obtained from the Flags member of a
CmResourceTypeInterrupt resource, in the CM_RESOURCE_LIST structure for
translated resources received in the IRP_MN_START_DEVICE IRP.
◦ A Boolean value indicating whether the device can share the vector, calculated by
examining the ShareDisposition member of a CmResourceTypeInterrupt
resource, in the CM_RESOURCE_LIST structure for translated resources received in
the IRP_MN_START_DEVICE IRP.
◦ A processor affinity mask value, indicating the set of processors the device can
interrupt on the machine, obtained from a CmResourceTypeInterrupt resource in
the CM_RESOURCE_LIST structure for translated resources, received in the
IRP_MN_START_DEVICE IRP.
◦ A value indicating whether the system should save floating-point registers when the
device interrupts (this must be FALSE for platform-independent drivers).
Connecting to Multiple
Interrupt Vectors
 If a driver must handle interrupts from more than one
device, each with a different interrupt vector, or if a
single device can interrupt through more than one
interrupt vector, the driver can have a single
multivector ISR, or it can have multiple ISRs.
 Such a driver must call IoConnectInterrupt for each
interrupt vector.
 It must also allocate a spin lock for each interrupt
vector.
 The following steps must be used:
◦ The driver must call KeInitializeSpinLock with a
pointer to driver-provided, resident storage for an
interrupt spin lock (in a device extension,
controller extension, or nonpaged pool allocated
by the driver).
◦ For each interrupt vector a driver's devices use, the
driver calls IoConnectInterrupt as described
Providing ISR Context
Information
 On entry, an ISR receives a pointer to whatever context
area the driver set up when it called
IoConnectInterrupt.
 Most drivers set the context pointer to the device object
that represents the physical device that generates
interrupts, or to that device object's device extension.
 In the device extension, the driver can store state
information for the driver's ISR and DpcForIsr routine,
the latter of which usually does almost all of the I/O
processing to satisfy each request that caused the
device to interrupt.
 Typically, drivers use the device extension to store
pointers to each of the device's interrupt objects
(returned from calls to IoConnectInterrupt).
 Drivers also typically store information in the device
extension that allows an ISR to determine if an
interrupt was issued by a device the ISR supports.
Writing an ISR
 Drivers for physical devices that generate interrupts must
have at least one InterruptService routine (ISR). The ISR
must do whatever is appropriate to the device to dismiss
the interrupt, possibly including stopping the device from
interrupting. Then, it should do only what is necessary to
save state and queue a DPC to finish the I/O operation at a
lower priority (IRQL) than that at which the ISR executes.
 A driver's ISR executes in an interrupt context, at some
system-assigned DIRQL, as specified by the SynchronizeIrql
parameter to IoConnectInterrupt.
 ISRs are interruptible. Another device with a higher system-
assigned DIRQL can interrupt, or a high-IRQL system
interrupt can occur, at any time.
 Before the system calls an ISR, it acquires the interrupt's spin
lock so the ISR cannot simultaneously execute on another
processor. After the ISR returns, the system releases the
spin lock.
 Because an ISR runs at a relatively high IRQL, which masks off
interrupts with an equivalent or lower IRQL on the current
processor, it should return control as quickly as possible.
Toaster Sample
Toaster
 Description
◦ The Toaster sample provides a starting point for
Microsoft Windows driver development. 
◦ This sample contains annotated code to illustrate
the functionality of a:
 bus driver
function driver
assorted class
Device driver
bus filter drivers
class installer
device-specific co-installer for a hypothetical
Toaster bus and its devices.
Toaster
 Theory of Operation
◦ Every device driver stack for a Plug and
Play (PnP) device on a Microsoft Windows
Server 2003, Windows XP, or Windows
2000 operating system typically consists
of a
 bus driver,
a function driver, and
zero or more filter drivers.
◦ These drivers must support PnP, power
management, and Windows Management
Instrumentation (WMI) to provide a better
user experience and greater satisfaction.
Toaster
 Theory of Operation
◦ Imagine a system with a new type of PnP I/O bus called a
toaster bus.
◦ A controller chip on the motherboard initializes and
manages the bus.
◦ The bus has a couple of ports that you can plug your
toasters into.
◦ To provide support for this bus on Windows NT 4.0, you
must modify the hardware abstraction layer (HAL) to
recognize and initialize the I/O bus during system
startup, and you must provide a set of HAL functions
for scanning the bus and accessing the configuration
space of the devices by other drivers.
◦ Next, you must write drivers for every type of toaster
device that loads along with the system, and then use
the exported HAL functions to scan the bus to detect
the device, read the I/O resource requirements, and
configure and initialize the device.
◦ These drivers are loaded regardless of whether or not a
Toaster
 Theory of Operation
◦ To support this bus and its devices under Windows,
however, you do not have to modify the HAL or export
a new set of functions.
◦ Instead, you need only to write a bus driver that has
knowledge of bus architecture, identifies (that is,
enumerates) devices on the bus, reads their resource
requirements, and configures them.
◦ This driver model also makes the operating system
independent of its I/O bus, so you do not need help
from Microsoft if you design a new I/O bus to modify
the HAL.
◦ Then, you write function drivers to control individual
devices that are connected to the bus.
◦ Later on, you can write one or more filter drivers to add
or modify the features that are supported by the bus, a
specific device, or class of devices.
◦ There can be any number of lower-level or upper-level
filter drivers for a bus, a device, or a class of devices.
Toaster
 Theory of Operation
◦ To make the sample code closer to a real-world
driver, the sample defines a new class of devices
called the TOASTER class and includes a bus
driver, function driver, and all possible class,
device, and bus filter drivers for this hypothetical
TOASTER bus and its devices. 
◦ There is also a sample coinstaller DLL to show how
you can parse a custom section from an INF file
and perform some special operations before and
after the installation of a device and how you can
create FriendlyName for a device.
◦ The function and bus driver also show how you can
provide power manager and WMI support.
Toaster
 Pre-compiled Module Information
Toaster
 Building the Sample
 bus
◦ Contains the source code of the toaster bus driver (Busenum.sys).
◦ This driver services the TOASTER bus controller, enumerate devices that are
plugged in, and performs bus-level power management.
◦ The bus driver supports D0 and D3 power states.
◦ It also has a WMI interface.
 func
◦ Contains subdirectories that contain the source code of the function driver
(Toaster.sys) for standard toaster devices.
◦ To be an illustrative and useful learning sample for beginners to driver
development, the sample has been built from almost nothing (skeletal) to
fully functional, adding useful features at each step.
◦ When the sample is built, all of the different versions produce Toaster.sys files in
the subdirectories of func.
◦ You can use the standard Toaster.inf or Toastco.inf to install and test.
◦ You can either manually install the driver (root-enumerations) or bus enumerate
the driver by using the toaster bus driver.
◦ They all share one common header file that is present in the shared directory.
◦ Assume that the function driver owns the power policy of the toaster device and
supports D0, D1, and D3 power states and also that the toaster device can
wake up the system from the D1 state.
Toaster
 Building the Sample
 inc

◦ Contains headers files that are shared among drivers and


applications.
 Disk

◦ The build target path.


◦ All of the toaster binaries are placed in the Disk directory
during build under the respective build
environment\target_OS subdirectories.
◦ For example, if you build under the Windows Server 2003
x86 checked build environment, the target path will be
disk\chk_wnet_x86\i386\.
◦ Because there is more than one version of Toaster.sys, it
is not placed in Disk directory to avoid overwriting
other versions.
◦ All of the various versions of Toaster.sys are built under
their respective source directory.
Toaster
 Building the Sample
 exe
◦ Contains three subdirectories, notify, enum, and toast, with files to produce Notify.exe,
Enum.exe, and Toast.exe (user-mode console applications):
◦ Enum.exe is a user-mode enumerator, a simple console application. Because the
toaster bus is not real, you need to have a mechanism to tell the bus driver when
you plug in, unplug, and eject devices from the system. The Enum.exe application
serves that purpose. Typically, it is written as a control panel applet for non-PnP
(legacy) devices (for example, Game.cpl).

 Usage: Enum [-
a SerialNo] - Plugs in a device.  SerialNo must be greater than zero.

            [-r SerialNo or 0] - Unplugs devices. Specify 0 to unplug all of
the devices that are enumerated so far.

            [-e SerialNo or 0] - Ejects devices. Specify 0 to eject all of
the devices that are enumerated so far.
  
 By design every toaster device will have a globally unique serial number.

◦ Toast.exe is a user-mode console application to control the toaster.


◦ Notify.exe is a GUI application that combines the functionality of Enum.exe and
Toast.exe and shows how to handle PnP notification in user mode. You should install
the coinstaller for the toaster device by using Toastco.inf to get a meaningful
display of the PnP notification. In Notify.exe, you can also specify some
other hardware ID (instead of the default toaster device ID) and cause other drivers
Toaster
 Building the Sample

filter
◦ Contains six different subdirectories
that each produce one of the
following drivers from a common
source file (Filter.c):
 Class upper filter (Clsupper.sys)
Class lower filter (Clslower.sys)
Device upper filter (Devupper.sys)
Device lower filter (Devlower.sys)
Bus FDO upper filter (Bfdoupr.sys)
Bus FDO lower filter (Bfdolwr.sys)
  
Toaster
 Building the Sample
 coinstaller
◦ Contains source code of the device-specific coinstaller
(Tostrco1.dll).
◦ The coinstaller demonstrates how to create a FriendlyName for a
device based on its unique instance ID.
◦ In this sample, during enumeration, the bus driver provides the
serial number in the UINumber field of the device capabilities.
◦ The FriendlyName is required to uniquely identify multiple
devices of the same interface class.
◦ The coinstaller also shows how to open an INF file and parse a
custom section.
 classinstaller
◦ Contains source code of the class-installer (Tostrcls.dll).
◦ This fake class installer is included to provide a class icon for all
of the TOASTER class devices. 
◦ This installer is copied to the system32 directory when the class
is installed for the first time in the system. 
Toaster(day)
 Building the Sample
 inf
◦ Contains three subdirectories (i386, amd64, and
ia64), and each subdirectory contains the
following files:
 Bus.inf installs Basenum.sys and sets up the registry.
 Simple.inf creates the Toaster class, installs Toaster.sys,
and sets up the registry.
 Toaster.inf is functionally similar to Simple.inf but also
installs the class installer. The class installer provides the
custom icon for the class and an advanced property page
to change the FriendlyName of the device in the device
manager.
 Toastco.inf is functionally similar to Toaster.inf but also
installs the coinstaller. The coinstaller is used to
dynamically create a unique FriendlyName of the device
based on the serial number.
 Busf.inf and Toasterf.inf are functionally similar to the
preceding INF files but also install all of the previously
mentioned filter drivers.
 Filter.inf installs a device upper filter for the toaster device.
Toaster
 Building the Sample
 toastmon

◦ Contains the source code of a root-enumerated driver


called Toastmon.sys.
◦ For more information about this driver, see the Toastmon
section under Operating System Concepts.
 toastpkg
◦ Contains the source code for an integrated device
installation solution that illustrates how to provide
support for the various user approaches to adding new
hardware, while providing optional value-added
software, and so on.
◦ For more information, see the Toastpkg.htm file in the
toastpkg directory.
Toaster
 Building the sample
◦ To build the Toaster sample drivers, you must first
set up the WDK environment on your host
computer .
◦ The “Installation and Release Notes” in the WDK
has a complete description on how to do this.
◦ The basic steps are as follows:
 Run the build –ceZ command in the Toaster
directory to build:
Busenum.sys,
Toaster.sys,
Enum.exe,
Toast.exe,
Tostrco1.dll,
Tostrcls.dll,
and the six filter drivers that were mentioned
previously.
Copy all of the .sys, .exe, and .dll files, a bus
Toaster
 Installation
◦ General
◦ First, install the bus driver. To install the bus driver
on Windows 2000:
1. Double-click Add or Remove Hardware in Control Panel.
2. In the Add or Remove Hardware wizard, click Next.
3. Select Add/Troubleshoot a device, and then click Next.
4. Select Add a new device, and then click Next.
5. Select No, I Want to Select the Hardware from a list,
and then click Next.
6. Select System Devices, and then click Next. Note that
this operation might take a few minutes.
7. Click Have Disk, make sure that drive A (or your disk drive)
is in the Copy manufacturer's files from box, and click
OK.
8. Click on the entry that you want, and then click Next.
9. On the Start Hardware Installation page, click Next.
10.On the Completing the Add/Remove Hardware Wizard
page, click Finish.
Toaster
 Installation
◦ General
 To install the bus driver on Windows XP and Windows Server
2003:  
 Double-click Add or Remove Hardware in Control Panel. 
 On the Welcome to the Add Hardware Wizard page,
click Next.
 Select Yes, I have already connected the hardware,
and then click Next.
 Select Add a new hardware device near the bottom of
the list, and then click Next.
 Select Install the hardware that I manually select
from a list (Advanced), and then click Next.
 Select System devices, and then click Next.
 Click Have Disk, make sure that drive A (or your disk drive)
is in the Copy manufacturer's files from box, and click
OK.
 Click on the entry that you want, and then click Next.
 On the The wizard is ready to install your hardware
page, click Next.
Toaster
 Installation
◦ The system copies the Busenum.sys file to the %Systemroot
%\system32\drivers directory and sets up the following
registry keys to represent the bus driver to the PnP manager:
◦ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\
{4D36E97D-E325-11CE-BFC1-08002BE10318}\nnnn
In this key, \nnnn is the instance number of this System Class
driver on the system.
◦ The system copies the INF file as OEM.n.INF, where n is a zero-
based number, to the system INF directory. It also creates the
following standard Services keys to load the driver:
◦ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\buse
num.
◦ After the driver is installed, the system creates device registry
keys (Hardware keys) under:
◦ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\SY
STEM\nnnn 
In this key, nnnn is the instance number of this System Class
driver on the system.
Toaster
Alternate Installation
◦ You can also quickly install the bus driver
without going through so many mouse
clicks by using the Installer sample
application in the
ntddk\src\general\devcon directory of the
WDK.
◦ This sample enables you to root-
enumerate a driver with one simple
command.
◦ Please read the help file that is included in
the sample to learn how to build and use
the application to install this driver.
◦ To install the bus driver by using
Toaster
Testing
◦ After the Toaster bus driver is installed and started by the
PnP manager, you can run the Enum.exe or Notify.exe
application from a command prompt to simulate plug
in, unplug, or ejection of toaster devices on the system.
◦ Both of these applications send an I/O control (IOCTL) to
the bus driver with the user-provided globally unique
serial number and hardware ID of the device and
trigger the entire enumeration process.
◦ The PnP manager takes the ID information that the bus
driver provides and searches the system INF directory
to find a matching INF file. If the PnP manager does not
find a suitable INF file (for example, when you install
for the first time), it prompts the user to specify an INF
file.
◦ At this point, you can pick one of the three INF files
(Toaster.inf, Toastco.inf, or Toasterf.inf) to be the device
INF file. If you are testing this sample for the first time,
you should choose Toastco.inf.
Toaster
Testing
◦ You can remove or eject a single device by giving
its serial number or remove or eject all of the
devices by specifying 0 (zero) as the serial
number of the device.
◦ To plug in a device
 At a command prompt, run enum -p 1.
◦ To unplug a device
 At a command prompt, run enum -u 1.
◦ To eject a device
 At a command prompt, run enum -e 1.
Toaster
Testing
◦ To test a plugged in device, you can use the Toast.exe
application. This application basically enumerates all of the
toaster class devices, displays its properties (such as
FriendlyName and InstanceId), and opens the last enumerated
device to perform a read operation and send DeviceIoControl
to the device, depending on the user command-line option.
◦ If you call Toast.exe without any option, it opens the last
enumerated interface and prompts you to initiate a read
operation in a loop. You press any key to continue the read
loop or press Q to break out of the loop. If you use the –h
option, Toast.exe opens the last enumerated interface and
sends DeviceIoControl to hide the device from the Device
Manager before performing the read operation.  
◦ Usage: Toast <–h> {-h option causes the device to hide from
the Device Manager user interface}
◦ Both Toast.exe and Enum.exe use the SetupDi functions to
enumerate and open the device interfaces. These functions
are documented in the WDK documentation.
Toaster
 Installing Toaster.sys as a root-enumerated driver 
◦ The preceding section describes how to install the Toaster.sys driver for a
toaster bus-enumerated device.
◦ You can also manually install the function driver (root-enumeration) by
using the Add Hardware wizard.
◦ Depending on which INF file you want to install, you will need a different
set of files:
◦ If you use Toaster.inf, you need any one version of Toaster.sys and
Tostrcls.dll.
◦ Copy those files to a floppy disk or to a directory on the target computer
and follow the install instructions that follow this list.
◦ If you use Toastco.inf, you also need Tostrco1.dll.
◦ If you use Toasterf.inf, you also need Devupper.sys, Devlower.sys,
Clasuppr.sys, and Classlwr.sys filter drivers and Toaster.sys and
Tostrcls.dll.
◦ You must make sure that the toaster class has not already been installed
on that computer.
◦ Otherwise, the computer will not install the class filter drivers.
◦ For testing purposes, if the toaster class is already installed, uninstall all
of the devices, and then manually delete the class registry
(HKLM\System\CurrentControlSet\Control\Class\{B85B7C50-6A01-11d2-
B841-00C04FAD5171}) before you install the driver with Toasterf.inf.
Toaster
 Installing Toaster.sys as a root-enumerated driver 
◦ To install the Toaster.sys driver on Windows Server 2003 or
Windows XP:
◦ Double-click the Add Hardware wizard in Control Panel.
◦ On the Welcome to the Add Hardware Wizard page, click
Next.
◦ Select Yes, I have already connected the hardware, and
then click Next.
◦ Select Add a new hardware device near the bottom of the list,
and then click Next.
◦ Select Install the hardware that I manually select from a
list (Advanced), and then click Next.
◦ Select System devices, and then click Next.
◦ Click Have Disk, make sure that drive A (or your disk drive) is in
the Copy manufacturer's files from box, and click OK.
◦ Click on the entry that you want, and then click Next.
◦ On the The wizard is ready to install your hardware page,
click Next.
◦ On the Completing the Add/Remove Hardware Wizard
page, click Finish.
Code
 Bus

NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,


 IN
PUNICODE_STRING RegistryPath )
 // Set entry points into the driver
 //
 DriverObject->MajorFunction [IRP_MJ_CREATE] =
 DriverObject->MajorFunction [IRP_MJ_CLOSE] = Bus_CreateClose;
 DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
 DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
 DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Bus_IoCtl;
 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
Bus_SystemControl;
 DriverObject->DriverUnload = Bus_DriverUnload;
 DriverObject->DriverExtension->AddDevice = Bus_AddDevice;
Code
Busenum.c

NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject,


 IN
PUNICODE_STRING RegistryPath )
 // Set entry points into the driver
 //
 DriverObject->MajorFunction [IRP_MJ_CREATE] =
 DriverObject->MajorFunction [IRP_MJ_CLOSE] = Bus_CreateClose;
 DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
 DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
 DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Bus_IoCtl;
 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
Bus_SystemControl;
 DriverObject->DriverUnload = Bus_DriverUnload;
 DriverObject->DriverExtension->AddDevice = Bus_AddDevice;
Bus_CreateClose
NTSTATUS

Bus_CreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp


 )
{

 PIO_STACK_LOCATION irpStack;
 NTSTATUS status;
 PFDO_DEVICE_DATA fdoData;
 PCOMMON_DEVICE_DATA commonData;
 PAGED_CODE ();
 commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
 //
 // We only allow create/close requests for the FDO.
 // That is the bus itself.
 //
 if (!commonData->IsFDO) {
 Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
 IoCompleteRequest (Irp, IO_NO_INCREMENT);
 return status;
 }
 fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
 Bus_IncIoCount (fdoData);

Bus_CreateClose
 // Check to see whether the bus is removed
 // if (fdoData->DevicePnPState == Deleted) {
 Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
 IoCompleteRequest (Irp, IO_NO_INCREMENT);
 return status;
 }
 irpStack = IoGetCurrentIrpStackLocation (Irp);
 switch (irpStack->MajorFunction) {
 case IRP_MJ_CREATE:
 Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Create \n"));
 status = STATUS_SUCCESS;
 break;
 case IRP_MJ_CLOSE:
 Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Close \n"));
 status = STATUS_SUCCESS;
 break;
 default:
 status = STATUS_INVALID_DEVICE_REQUEST;
 break;
 }
 Irp->IoStatus.Information = 0;
 Irp->IoStatus.Status = status;
 IoCompleteRequest (Irp, IO_NO_INCREMENT);
 Bus_DecIoCount (fdoData);
 return status;
}

Bus_IoCtl
NTSTATUS Bus_IoCtl(
 IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{

 PIO_STACK_LOCATION irpStack;
 NTSTATUS status;
 ULONG inlen;
 PFDO_DEVICE_DATA fdoData;
 PVOID buffer;
 PCOMMON_DEVICE_DATA commonData;
 PAGED_CODE ();
 commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
 //
 // We only allow create/close requests for the FDO.
 // That is the bus itself.
 //
 if (!commonData->IsFDO) {
 Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
 IoCompleteRequest (Irp, IO_NO_INCREMENT);
 return status;
 }
 fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
 Bus_IncIoCount (fdoData);
Bus_IoCtl
// Check to see whether the bus is removed

 //
 if (fdoData->DevicePnPState == Deleted) {
 status = STATUS_NO_SUCH_DEVICE;
 goto END;
 }
 irpStack = IoGetCurrentIrpStackLocation (Irp);
 buffer = Irp->AssociatedIrp.SystemBuffer;
 inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
 status = STATUS_INVALID_PARAMETER;
 switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
 case IOCTL_BUSENUM_PLUGIN_HARDWARE:
 if (
 //
 // Make sure it has at least two nulls and the size
 // field is set to the declared size of the struct
 //
 ((sizeof (BUSENUM_PLUGIN_HARDWARE) + sizeof(UNICODE_NULL) * 2) <=
 inlen) &&
 //
 // The size field should be set to the sizeof the struct as declared
 // and *not* the size of the struct plus the multi_sz
 //
Bus_IoCtl
 (sizeof (BUSENUM_PLUGIN_HARDWARE) ==
 ((PBUSENUM_PLUGIN_HARDWARE) buffer)->Size)) {
 Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));
 status= Bus_PlugInDevice((PBUSENUM_PLUGIN_HARDWARE)buffer,
 inlen, fdoData);
 }
 break;
 case IOCTL_BUSENUM_UNPLUG_HARDWARE
 if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) &&
 (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) {
 Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n"));
 status= Bus_UnPlugDevice(
 (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData);
 }
 break;
 case IOCTL_BUSENUM_EJECT_HARDWARE:
 if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) &&
 (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) {
 Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n"));
 status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer,
fdoData);
 } Irp->IoStatus.Information = 0;
 break; END:
Irp->IoStatus.Status = status;
 default: IoCompleteRequest (Irp, IO_NO_INCREMENT);
 break; // default status is STATUS_INVALID_PARAMETER Bus_DecIoCount (fdoData);
return status;
 } }
Bus_DriverUnload
 VOID Bus_DriverUnload( IN PDRIVER_OBJECT DriverObject )
{

 PAGED_CODE ();
 Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Unload\n"));
 //
 // All the device objects should be gone.
 //
 ASSERT (NULL == DriverObject->DeviceObject);
 //
 // Here we free all the resources allocated in the DriverEntry
 //
 if(Globals.RegistryPath.Buffer)
 ExFreePool(Globals.RegistryPath.Buffer);

 return;
}

Bus_IncIoCount
VOID Bus_IncIoCount(
 IN PFDO_DEVICE_DATA FdoData )
{

 LONG result;
 result = InterlockedIncrement(&FdoData->OutstandingIO);
 ASSERT(result > 0);
 //
 // Need to clear StopEvent (when OutstandingIO bumps from 1 to 2)
 //
 if (result == 2) {
 //
 // We need to clear the event
 //
 KeClearEvent(&FdoData->StopEvent);
 }
 return;
}

Bus_DecIoCoun
VOID Bus_DecIoCount(
 IN PFDO_DEVICE_DATA FdoData )
{

 LONG result;
 result = InterlockedDecrement(&FdoData->OutstandingIO);
 ASSERT(result >= 0);
 if (result == 1) {
 // Set the stop event. Note that when this happens
 // (i.e. a transition from 2 to 1), the type of requests we
 // want to be processed are already held instead of being
 // passed away, so that we can't "miss" a request that
 // will appear between the decrement and the moment when
 // the value is actually used.
 KeSetEvent (&FdoData->StopEvent, IO_NO_INCREMENT, FALSE);
 }
 if (result == 0) {
 // The count is 1-biased, so it can be zero only if an
 // extra decrement is done when a remove Irp is received
 ASSERT(FdoData->DevicePnPState == Deleted);
 // Set the remove event, so the device object can be deleted
 KeSetEvent (&FdoData->RemoveEvent, IO_NO_INCREMENT, FALSE);
 }
 return;
}

Buspdo.c Bus_PDO_Pn
NTSTATUS Bus_PDO_PnP(
 IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PIO_STACK_LOCATION
IrpStack, IN PPDO_DEVICE_DATA DeviceData )
{
 NTSTATUS status;
 PAGED_CODE ();
 // NB: Because we are a bus enumerator, we have no one to whom we could
 // defer these irps. Therefore we do not pass them down but merely
 // return them.
 switch (IrpStack->MinorFunction) {
 case IRP_MN_START_DEVICE:
// Here we do what ever initialization and ``turning on'' that is

 // required to allow others to access this device.


 // Power up the device.
DeviceData->DevicePowerState = PowerDeviceD0;

 SET_NEW_PNP_STATE(DeviceData, Started);
 status = STATUS_SUCCESS;
 break;
 case IRP_MN_STOP_DEVICE:
// Here we shut down the device and give up and unmap any resources

 // we acquired for the device.


SET_NEW_PNP_STATE(DeviceData, Stopped);

 status = STATUS_SUCCESS;
 break;
 case IRP_MN_QUERY_STOP_DEVICE:
Buspdo.c Bus_PDO_Pn
// No reason here why we can't stop the device.

 // If there were a reason we should speak now, because answering success


 // here may result in a stop device irp.
 SET_NEW_PNP_STATE(DeviceData, StopPending);
 status = STATUS_SUCCESS;
 break;
 case IRP_MN_CANCEL_STOP_DEVICE:
// The stop was canceled. Whatever state we set, or resources we put

 // on hold in anticipation of the forthcoming STOP device IRP should be


 // put back to normal. Someone, in the long list of concerned parties,
 // has failed the stop device query.
// First check to see whether you have received cancel-stop

 // without first receiving a query-stop. This could happen if someone


 // above us fails a query-stop and passes down the subsequent
 // cancel-stop.
if(StopPending == DeviceData->DevicePnPState)

 {
// We did receive a query-stop, so restore.

RESTORE_PREVIOUS_PNP_STATE(DeviceData);

 }
 status = STATUS_SUCCESS;// We must not fail this IRP.
 break;
 case IRP_MN_QUERY_REMOVE_DEVICE:
// Check to see whether the device can be removed safely.

 // If not fail this request. This is the last opportunity


 // to do so.
Buspdo.c Bus_PDO_Pn
if(DeviceData->ToasterInterfaceRefCount){

// Somebody is still using our interface.


 // We must fail remove.


status = STATUS_UNSUCCESSFUL;

 break;
 }
 SET_NEW_PNP_STATE(DeviceData, RemovePending);
 status = STATUS_SUCCESS;
 break;
case IRP_MN_CANCEL_REMOVE_DEVICE:

// Clean up a remove that did not go through.


// First check to see whether you have received cancel-remove


 // without first receiving a query-remove. This could happen if


 // someone above us fails a query-remove and passes down the
 // subsequent cancel-remove.
if(RemovePending == DeviceData->DevicePnPState)

 {
// We did receive a query-remove, so restore.

RESTORE_PREVIOUS_PNP_STATE(DeviceData);

 }
 status = STATUS_SUCCESS; // We must not fail this IRP.
 break;
 case IRP_MN_SURPRISE_REMOVAL:
Buspdo.c Bus_PDO_Pn
// We should stop all access to the device and relinquish all the

 // resources. Let's just mark that it happened and we will do


 // the cleanup later in IRP_MN_REMOVE_DEVICE.
 SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
 status = STATUS_SUCCESS;
 break;
 case IRP_MN_REMOVE_DEVICE:
// Present is set to true when the pdo is exposed via PlugIn IOCTL.

 // It is set to FALSE when a UnPlug IOCTL is received.


 // We will delete the PDO only after we have reported to the
 // Plug and Play manager that it's missing.
if (DeviceData->ReportedMissing) {

 PFDO_DEVICE_DATA fdoData;
 SET_NEW_PNP_STATE(DeviceData, Deleted);
// Remove the PDO from the list and decrement the count of PDO.

 // Don't forget to synchronize access to the FDO data.


 // If the parent FDO is deleted before child PDOs, the ParentFdo
 // pointer will be NULL. This could happen if the child PDO
 // is in a SurpriseRemovePending state when the parent FDO
 // is removed.
if(DeviceData->ParentFdo) {

 fdoData = FDO_FROM_PDO(DeviceData);
 ExAcquireFastMutex (&fdoData->Mutex);
 RemoveEntryList (&DeviceData->Link);
 fdoData->NumPDOs--;
 ExReleaseFastMutex (&fdoData->Mutex);
 }
Buspdo.c Bus_PDO_Pn
// Free up resources associated with PDO and delete it.

status = Bus_DestroyPdo(DeviceObject, DeviceData);


 break;
 }
 if (DeviceData->Present) {
 // When the device is disabled, the PDO transitions from
 // RemovePending to NotStarted. We shouldn't delete
 // the PDO because a) the device is still present on the bus,
 // b) we haven't reported missing to the PnP manager.
SET_NEW_PNP_STATE(DeviceData, NotStarted);

 status = STATUS_SUCCESS;
 } else {
 ASSERT(DeviceData->Present);
 status = STATUS_SUCCESS;
 }
 break;
 case IRP_MN_QUERY_CAPABILITIES:
// Return the capabilities of a device, such as whether the device

 // can be locked or ejected..etc


 status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp)
 break;
 case IRP_MN_QUERY_ID:
 // Query the IDs of the device
 Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
 ("\tQueryId Type: %s\n",
 DbgDeviceIDString(IrpStack->Parameters.QueryId.IdType)));

Buspdo.c Bus_PDO_Pn
 status = Bus_PDO_QueryDeviceId(DeviceData, Irp);
 break;
 case IRP_MN_QUERY_DEVICE_RELATIONS:
 Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
 ("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
 IrpStack->Parameters.QueryDeviceRelations.Type)));
 status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);
 break;
 case IRP_MN_QUERY_DEVICE_TEXT:
 status = Bus_PDO_QueryDeviceText(DeviceData, Irp);
 break;
 case IRP_MN_QUERY_RESOURCES:
 status = Bus_PDO_QueryResources(DeviceData, Irp);
 break
 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
 status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);
break;

case IRP_MN_QUERY_BUS_INFORMATION:

status = Bus_PDO_QueryBusInformation(DeviceData, Irp);


break;

case IRP_MN_DEVICE_USAGE_NOTIFICATION:

// OPTIONAL for bus drivers.


 // This bus drivers any of the bus's descendants


 // (child device, child of a child device, etc.) do not
 // contain a memory file namely paging file, dump file,
 // or hibernation file. So we fail this Irp.
Buspdo.c Bus_PDO_Pn
status = STATUS_UNSUCCESSFUL;

 break;
case IRP_MN_EJECT:

// For the device to be ejected, the device must be in the D3


 // device power state (off) and must be unlocked


 // (if the device supports locking). Any driver that returns success
 // for this IRP must wait until the device has been ejected before
 // completing the IRP.
DeviceData->Present = FALSE;

status = STATUS_SUCCESS;

 break;
case IRP_MN_QUERY_INTERFACE:

// This request enables a driver to export a direct-call


 // interface to other drivers. A bus driver that exports


 // an interface must handle this request for its child
 // devices (child PDOs).
status = Bus_PDO_QueryInterface(DeviceData, Irp);

 break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:

// OPTIONAL for bus drivers.


 // The PnP Manager sends this IRP to a device


 // stack so filter and function drivers can adjust the
 // resources required by the device, if appropriate.
//break;

Functional Driver Object
Toaster.c DriverEntry
DriverObject->DriverExtension->AddDevice
 = ToasterAddDevice;
 DriverObject->DriverUnload = ToasterUnload;
 DriverObject->MajorFunction[IRP_MJ_PNP] = ToasterDispatchPnp;
 DriverObject->MajorFunction[IRP_MJ_POWER] = ToasterDispatchPower;
 DriverObject->MajorFunction[IRP_MJ_CREATE] = ToasterCreate;
 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ToasterClose;
 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ToasterCleanup;
 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
ToasterDispatchIO;
 DriverObject->MajorFunction[IRP_MJ_READ] = ToasterDispatchIO;
 DriverObject->MajorFunction[IRP_MJ_WRITE] = ToasterDispatchIO;
 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
ToasterSystemControl;
Toaster.c
ToasterAddDevice

To a ste rC a n R e m o ve D e vice
ToasterDispatchPnp

To a ste rR e tu rn R e so u rce s
ToasterDispatchPnpComplete

To a ste rS e n d Irp S yn ch ro n o u sly
ToasterReadWrite

To a ste rG e tS ta n d a rd In te rfa ce
ToasterCreate

To a ste rG e tD e vice C a p a b ilitie s
ToasterClose

To a ste rIo In cre m e n t
ToasterDispatchIoctl

To a ste rIo D e cre m e n t
ToasterDispatchIO

Pn P M in o rFu n ctio n S trin g
ToasterStartDevice

ToasterCleanup

ToasterUnload

ToasterQueueRequest

ToasterProcessQueuedRequests

ToasterCancelQueued

ToasterCanStopDevice

Power.c
ToasterDispatchPower

ToasterDispatchPowerDefault
 To a ste rPo w e rB e g in Q u e u in g Irp s
ToasterDispatchSetPowerState
 To a ste rC a llb a ckH a n d le D e vice S e tPo w e r
ToasterDispatchQueryPowerState
 To a ste rG e tPo w e rPo licie sD e vice S ta te
ToasterDispatchSystemPowerIrp
 To a ste rC a n S u sp e n d D e vice
ToasterCompletionSystemPowerUp
 D b g Po w e rM in o rFu n ctio n S trin g
ToasterQueueCorrespondingDeviceIrp
 D b g S yste m Po w e rS trin g
ToasterCompletionOnFinalizedDeviceIrp D b g D e vice Po w e rS trin g

ToasterDispatchDeviceQueryPower

ToasterDispatchDeviceSetPower

ToasterCompletionDevicePowerUp

ToasterFinalizeDevicePowerIrp

ToasterQueuePassiveLevelPowerCallback

ToasterCallbackHandleDeviceQueryPower

ToasterQueuePassiveLevelPowerCallbackWor

ker
Wake.c
ToasterDispatchWaitWake

ToasterArmForWake

ToasterWaitWakeIoCompletionRoutine

ToasterDisarmWake

ToasterWaitWakePoCompletionRoutine

ToasterQueuePassiveLevelCallback

ToasterPassiveLevelReArmCallbackWorker

ToasterPassiveLevelClearWaitWakeEnableSta

te
ToasterAdjustCapabilities

ToasterSetWaitWakeEnableState

ToasterGetWaitWakeEnableState

Wmi.c
ToasterWmiRegistration

ToasterWmiDeRegistration

ToasterSystemControl

ToasterSetWmiDataItem

ToasterSetWmiDataBlock

ToasterQueryWmiDataBlock

ToasterFunctionControl

ToasterFireArrivalEvent

ToasterQueryWmiRegInfo

GetDeviceFriendlyName

WMIMinorFunctionString

Vous aimerez peut-être aussi