IO Subsystem

The Windows I/O Subsystem provides the core infrastructure that enables applications and drivers to communicate with hardware and the file system. It abstracts device interactions, manages I/O request packets (IRPs), and ensures synchronization, security, and performance across the system.

Overview

The I/O Subsystem consists of several components:

Architecture

A typical I/O request flow follows these stages:

Application → Win32 API → I/O Manager → Driver Stack → Device → Completion → Callback

The diagram below illustrates the logical layers:

IO Subsystem Architecture

I/O Manager

The I/O Manager is responsible for:

Typical entry points in a driver:

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
NTSTATUS MyAddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS MyDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyDispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyUnload(PDRIVER_OBJECT DriverObject);

File System Drivers

File system drivers implement the IRP_MJ_CREATE, IRP_MJ_READ, IRP_MJ_WRITE, and other I/O operations for persistent storage. Examples include:

Device Drivers

Device drivers handle communication with hardware. The driver model includes:

I/O Request Packet (IRP)

An IRP encapsulates all information needed for an I/O operation. Key fields include:

typedef struct _IRP {
    CSHORT Type;
    USHORT Size;
    PMDL MdlAddress;
    PVOID UserIosb;
    PIO_STATUS_BLOCK IoStatus;
    PCHAR StackLocation[1];
    // ...
} IRP, *PIRP;

Drivers retrieve their specific stack location via IoGetCurrentIrpStackLocation.

Sample Code

Below is a minimal skeleton for a driver that handles read and write requests.

#include <ntddk.h>

NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    UNREFERENCED_PARAMETER(RegistryPath);
    DriverObject->DriverUnload = DriverUnload;
    DriverObject->MajorFunction[IRP_MJ_READ] = DriverRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = DriverWrite;
    return STATUS_SUCCESS;
}

VOID
DriverUnload(PDRIVER_OBJECT DriverObject)
{
    UNREFERENCED_PARAMETER(DriverObject);
    DbgPrint("MyDriver unloaded\n");
}

NTSTATUS
DriverRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);
    // Complete with dummy data
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS
DriverWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);
    // Accept data and complete
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = Irp->RequestorMode == KernelMode ?
        Irp->IoStatus.Information : 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

For a full walkthrough, see the Sample Code section.