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:

  1. Static Loading: Static drivers were loaded during the boot process before the Win32 subsystem fully started. They were specified either within the SYSTEM.INI configuration file under the [386Enh] section or inside the Windows Registry under HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD. Many static drivers were packaged directly into a monolithic VMM32.VXD cache to speed up boot times.
  2. 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 CreateFile API 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 via CloseHandle.

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.