How Windows 98 Managed Virtual Device Drivers
Microsoft Windows 98 managed hardware communication through a hybrid architecture relying heavily on Virtual Device Drivers (VxDs), while simultaneously introducing support for the newer Windows Driver Model (WDM). This article examines how Windows 98 loaded, executed, and coordinated VxDs at the privileged Ring 0 level, the role of the Virtual Machine Manager (VMM), how applications interfaced with these drivers, and how the operating system bridged the gap between legacy VxDs and modern driver architectures.
The Role and Privilege Level of VxDs
Virtual Device Drivers—commonly known by their file extension,
.VXD—were 32-bit modules designed to virtualize physical
hardware and manage direct device operations. In Windows 98, VxDs
executed at Ring 0, the CPU's most privileged execution level. This gave
them unrestricted access to the microprocessor's instruction set,
physical memory, and I/O ports. Because Windows 98 ran on a single flat
4 GB memory model where Ring 0 was shared across the operating system
kernel and drivers, any VxD had direct access to system memory, ensuring
high performance at the expense of memory protection and stability.
The Virtual Machine Manager (VMM32)
At the core of the Windows 98 driver subsystem was the Virtual
Machine Manager, bundled inside VMM32.VXD. The VMM acted as
the core operating system kernel responsible for:
- Hardware Virtualization: Allowing multiple Virtual 8086 Machines (used for MS-DOS sessions) and the Protected Mode environment to share hardware ports and interrupts safely.
- Interrupt Handling: Intercepting hardware interrupts (IRQs) through the Virtual Programmable Interrupt Controller (VPICD) driver and routing them to either the appropriate VxD, real-mode DOS handler, or Win32 process.
- Service Dispatch: Maintaining a central service
table. Each VxD declared a unique device ID and a set of callable
functions, which the VMM exposed to other kernel components via software
interrupts (such as
INT 20h).
Loading Mechanisms: Static vs. Dynamic VxDs
Windows 98 supported two primary methods for loading VxDs into system memory:
- Static Loading: Static drivers were loaded during
the boot process before the Win32 subsystem fully started. They were
specified either within the
SYSTEM.INIconfiguration file under the[386Enh]section or inside the Windows Registry underHKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD. Many static drivers were packaged directly into a monolithicVMM32.VXDcache to speed up boot times. - Dynamic Loading: Unlike Windows 3.1, Windows 98
fully supported loading and unloading VxDs dynamically at runtime.
Software applications or the operating system could load a dynamic VxD
on-demand using the Win32
CreateFileAPI function with the\\.\device naming convention. Once loaded, the VMM allocated kernel memory for the driver and integrated its exported services into the running system. Dynamic VxDs were terminated and unloaded when their handles were closed viaCloseHandle.
Application-to-Driver Communication
User-mode software running at Ring 3 (such as Win32 applications)
could not directly access Ring 0 hardware resources. To bridge this
divide, Windows 98 used the Virtual Win32 Driver
(VWIN32.VXD).
When an application called DeviceIoControl(), the
request was passed down to VWIN32.VXD, which translated the
request and dispatched a W32_DEVICEIOCONTROL control
message directly to the target VxD's control procedure. The VxD parsed
the control code, read user memory buffers directly, performed the
requested hardware operations, and returned status codes back across the
privilege boundary to the calling application.
The Transition to WDM via NTKERN
Windows 98 marked the beginning of the phase-out of the VxD architecture. To provide cross-compatibility with Windows NT, Windows 98 introduced the Windows Driver Model (WDM).
Rather than replacing VxDs entirely, Windows 98 managed WDM drivers
using a specialized wrapper VxD named NTKERN.VXD. When a
WDM driver was loaded, NTKERN.VXD acted as an adapter
layer, translating Windows NT-style I/O Request Packets (IRPs) into
operations that the Windows 98 VMM and hardware subsystem could execute.
This hybrid approach allowed Windows 98 to support newer USB, IEEE 1394,
and unified audio/video drivers while retaining full backward
compatibility with legacy Windows 95 and Windows 3.x VxD software.