VxD
A virtual device driver (VxD) is a kernel-mode software module in early Microsoft Windows operating systems that runs at ring 0 privilege level within the Windows 386 Virtual Machine Manager (VMM) to simulate hardware devices, manage resource contention, and enable multitasking across multiple virtual machines (VMs) in protected and real modes.[1] Introduced in Windows/386 2.x in 1987 and significantly enhanced for Windows 3.1's 386 Enhanced Mode in 1992, VxDs formed the core of the modular driver architecture for handling hardware virtualization in 32-bit flat memory models.[1] They remained the standard driver model throughout the Windows 9x series, including Windows 95 (1995), Windows 98 (1998), and Windows Me (2000), supporting a hybrid 16/32-bit environment that ran legacy MS-DOS applications alongside protected-mode programs.[1] Key functionalities of VxDs include trapping I/O port accesses for virtualization, hooking and simulating interrupts (including IRQs and DMA channels), allocating and locking memory pages for VMs, and providing APIs for interprocess communication and system events like VM creation, suspension, and termination.[1] These features allowed efficient sharing of physical hardware—such as COM ports, video adapters, and timers—among concurrent VMs, improving system stability and performance in preemptive multitasking scenarios without direct hardware access by user-mode applications.[1] VxDs were event-driven, supporting both synchronous and asynchronous service calls through mechanisms like global event lists and nested execution, and included debugging tools for development.[1] However, with the transition to the Windows NT kernel in Windows 2000, VxD architecture was not supported, as the new Windows Driver Model (WDM) provided a unified, more secure framework for device drivers across consumer and enterprise editions. Today, VxDs are legacy components, incompatible with modern Windows versions and preserved mainly for compatibility in emulated environments.Naming and Fundamentals
Definition and Purpose
A VxD, short for virtual device driver (also known as virtual xxx driver, where "xxx" indicates the specific device class, such as virtual joystick driver for input devices), is a type of kernel-mode device driver used in legacy Microsoft Windows operating systems, particularly Windows 3.x and Windows 9x. VxDs operate as 32-bit protected mode components within the Windows kernel, providing low-level interaction with hardware and system resources.[2][3] The primary purpose of a VxD is to deliver hardware abstraction and support multitasking by executing in ring 0, the highest privilege level of the CPU, where it can intercept and virtualize hardware calls originating from DOS applications running in virtual machines. This ring 0 operation grants unrestricted access to hardware, memory, and interrupts, allowing VxDs to manage device operations efficiently without the overhead of privilege level transitions. By virtualizing hardware interfaces, VxDs prevent direct conflicts and ensure safe resource sharing among applications.[1][3] A key concept of VxDs is their role in enabling Windows to oversee multiple DOS sessions concurrently within virtual machines, avoiding hardware conflicts through centralized control. This virtualization supports 32-bit protected mode execution on Intel 386 and later processors, allowing the system to simulate isolated environments for legacy applications while maintaining overall stability. In Windows 3.x, VxDs integrate with the Virtual Machine Manager to handle these virtual machines, facilitating seamless multitasking.[1][3] VxDs were designed to overcome the limitations of MS-DOS by unifying the handling of I/O operations, memory management, and interrupt processing in a single kernel environment, thereby extending the capabilities of early Windows for more robust hardware support. This approach provided a foundational layer for device management, ensuring compatibility and performance in pre-NT Windows architectures.[1][2]File Formats and Conventions
Virtual device drivers (VxDs) for Windows 3.x utilize the .386 file extension and are structured in the Linear Executable (LE) format, which supports a hybrid of 16-bit and 32-bit code segments to accommodate the 386 Enhanced mode environment.[1] This format includes real-mode initialization code for early boot phases and protected-mode execution for runtime operations, with the LE signature identifiable at the file offset to distinguish Windows-specific executables.[1] In contrast, VxDs developed for Windows 9x employ the .vxd extension and adhere to the Linear Executable (LE) format, enabling pure 32-bit or hybrid code in a flat memory model that enhances compatibility with the evolved Virtual Machine Manager (VMM).[1] Naming conventions for VxDs follow a standardized pattern beginning with the prefix "v" (lowercase in filenames), followed by an abbreviation descriptive of the virtualized device or function, and ending with the suffix "d" to denote the driver nature.[1] For instance, vjoyd.386 represents the joystick virtual device driver, while vmm.386 designates the core virtual memory manager.[1] These filenames are placed in the Windows SYSTEM directory and directly reflect the hardware or system component being virtualized, facilitating identification during development and loading.[1] Regarding compatibility, .386 files from Windows 3.x can be loaded and executed in Windows 9x environments, as the later system maintains backward support for the LE format through its VMM, though some services may require updates for full functionality.[1] However, .vxd files from Windows 9x, reliant on the LE format, are incompatible with Windows 3.x due to the latter's inability to process the advanced linear executable structure.[1] VxDs are loaded dynamically by the VMM kernel component during system initialization, with the filename serving as a key identifier for the specific device virtualization task.[1]Technical Architecture
Execution Environment
VxDs execute in ring 0 kernel mode, granting them unrestricted access to hardware resources and enabling direct management of interrupts, I/O ports, and memory, which circumvents the limitations inherent in the protected modes of DOS applications.[3] This privileged execution level allows VxDs to operate within a 32-bit flat memory model, utilizing the full 4 GB address space provided by the x86 architecture without the segmentation constraints of real-mode environments.[4] The Virtual Machine Manager (VMM), implemented as WIN386.EXE, serves as the core kernel component that loads and integrates VxDs into the system, facilitating the creation and control of virtual machines (VMs) to run DOS applications in a virtualized V86 mode.[3] VxDs collaborate with VMM to handle page faults on hooked memory pages—either by mapping physical memory or terminating the offending VM—and to emulate devices, simulating hardware behavior for compatibility while buffering requests to manage shared resources across VMs.[4] This integration ensures that DOS applications perceive a dedicated hardware environment, even as VMM orchestrates the underlying virtualization to prevent direct conflicts. To support multitasking, VxDs enable concurrent hardware access by serializing calls through the VxD layer, utilizing mechanisms such as critical sections to enforce mutual exclusion and avoid reentrant code execution that could lead to hardware contention.[3] VMM's scheduling employs primary priority-based and secondary time-slice algorithms, allowing VxDs to boost VM priorities dynamically and coordinate device focus, thereby maintaining system stability during simultaneous operations from multiple VMs.[4] VxDs rely on callbacks and control messages dispatched by VMM to respond to key system events, including initialization via Sys_Critical_Init and Device_Init, device open and close operations through services like Set_Device_Focus, and system shutdown with System_Exit or Sys_Critical_Exit.[3] These mechanisms, often handled through control procedures in the VxD's Device Descriptor Block (DDB), enable event-driven processing and VM-specific notifications, such as VM_Init for startup or VM_Terminate for cleanup, ensuring orderly lifecycle management within the kernel.[4]Programming Model and APIs
VxDs employ a message-based programming model, operating at ring 0 in a 32-bit flat memory model provided by the Virtual Machine Manager (VMM) to manage hardware virtualization and virtual machines (VMs) within the Windows 9x environment. Developers implement VxDs to respond to control messages dispatched by the VMM, such as Device_Init for initialization and Sys_Critical_Init for early system setup, through a central dispatch mechanism that processes events asynchronously or synchronously based on priority. This model enables VxDs to handle interrupts and VM states while maintaining isolation between VMs.[5][4] The core entry point for message handling is the DriverProc (or ControlProc), a procedure exported via the Device Descriptor Block (DDB) that receives messages in the EAX register, with VM handles in EBX or EDI, and processes them using dispatch tables or macros like Control_Dispatch. VxDs support dynamic loading and unloading without system reboot, facilitated by messages such as SYS_DYNAMIC_DEVICE_INIT for runtime attachment, enabling modular extension of system functionality. For inter-VxD communication, services like PostMessage queue events, ensuring orderly processing across global and VM-specific event lists. VxDs run with kernel-mode privileges, granting direct access to hardware resources.[5][4] Access to VMM services occurs primarily through the _VMMCall macro, which invokes over 200 functions via interrupt 20h for tasks like memory allocation (_HeapAllocate for small blocks, _PageAllocate for DMA buffers), interrupt simulation (Simulate_Int), and device I/O trapping (_Install_IO_Handler for port monitoring). These services pass parameters in registers (e.g., EAX for service ID, EBX for VM handle) and return results via flags or EAX, with no reliance on standard C/C++ libraries; instead, developers use custom wrappers like those in the DDK's VXDWRAPS.LIB or VToolsD for stack-based calls from C code. VxDs also export protected-mode (PM) and virtual-86 (V86) APIs via DDB fields, accessible from applications through DeviceIoControl or INT 2Fh, supporting Win32 and Win16 interactions.[5][4] Development of VxDs typically involves assembly language (e.g., MASM 6.1) for low-level control and performance-critical sections, or C with inline assembly and thunking for higher-level logic, compiled using 16/32-bit tools from Microsoft's Device Driver Kit (DDK). The DDK provides include files (e.g., VMM.INC), partial libraries, and utilities like the Thunk Compiler for bridging C callbacks to VMM services, while debuggers such as SoftICE facilitate ring 0 testing. Pagelocked segments (_LTEXT, _LDATA) ensure interrupt-safe execution, with per-VM data allocated via _Allocate_Device_CB_Area to maintain state isolation.[5][4]Historical Context
Origins in Early Windows
VxDs first appeared with Windows/386 2.01, released in September 1987 as an extension of Windows 2.0 tailored for Intel 80386 processors to enable enhanced mode operation.[6] This version introduced a 32-bit protected-mode kernel that supported preemptive multitasking, marking Microsoft's initial foray into leveraging the 386's advanced features for a more robust DOS environment.[7] The primary purpose of VxDs in this early implementation was to facilitate the concurrent execution of multiple DOS applications within isolated virtual machines, preventing interference and enabling efficient resource sharing.[8] Central to this capability was the Virtual Machine Manager (VMM), the core VxD that handled memory allocation, task switching, and emulation of expanded memory standards like EMS across these virtual environments.[6] Earlier Windows versions, constrained to real mode on pre-386 hardware, encountered frequent crashes from direct hardware access conflicts when running multiple DOS sessions; Windows/386 resolved these issues through virtual device emulation, where VxDs intercepted and mediated hardware interactions to support stable, crash-free multitasking of DOS boxes.[7] While limited to 386-compatible CPUs and initially bundled with select OEM systems like Compaq's, the VxD model achieved broad popularity with Windows 3.0's release in May 1990, which incorporated standard .386 VxDs for key system components including serial ports, timers, and disk controllers, thereby democratizing protected-mode features for mainstream users.[9][6]Evolution in Windows 9x
With the release of Windows 95 in 1995, VxDs underwent a major shift to the .vxd file format, emphasizing 32-bit protected-mode execution for improved performance and stability over the .386 drivers of earlier versions.[5] This evolution enabled dynamic loading via the registry or standard paths, replacing static loading from SYSTEM.INI files in Windows 3.x, and supported a flat 32-bit memory model addressing up to 4 GB.[5] The hybrid kernel architecture of Windows 95, blending real-mode and protected-mode elements, positioned VxDs at Ring 0 under the Virtual Machine Manager (VMM) to handle multiple execution environments, including Win32 applications indirectly through preemptive threading and services like _MapPhysToLinear for memory-mapped devices.[5] VxDs became integral to Windows 95's Plug and Play (PnP) framework, with the Configuration Manager VxD enabling dynamic hardware enumeration, resource arbitration (e.g., I/O ports, IRQs), and support for emerging standards like basic USB in OSR2 releases via dedicated VxDs such as usb.vxd.[5] This marked a departure from Windows 3.x's pure virtual machine focus, where VxDs primarily virtualized hardware for DOS and Win16 sessions, to a more integrated model allowing VxDs to manage Win32 workloads through enhanced VMM services like 1 ms timer resolution and appy-time callbacks.[5] Windows 98, released in 1998, built on this foundation with refinements to VxD stability, including improved error handling in the VMM and better fault isolation to reduce system crashes from faulty drivers.[10] It introduced partial compatibility with the Windows Driver Model (WDM), allowing hybrid setups where VxDs coexisted with WDM kernel-streaming components for audio and USB, facilitating smoother transitions for developers while maintaining backward compatibility for existing 32-bit VxDs.[10] The 2000 release of Windows Me finalized VxD evolution in the 9x series, incorporating multimedia optimizations such as enhanced DirectX integration and kernel-level streaming for better video and audio performance, often leveraging VxDs for low-latency hardware access.[10] Despite increasing reliance on user-mode components for newer features like System Restore and universal plug-and-play, VxDs remained essential for legacy hardware support, ensuring compatibility with older peripherals through the hybrid real/protected-mode environment.[10]Practical Usage
Built-in System VxDs
Built-in system VxDs form the foundational layer of hardware abstraction and system management in Windows 95 and 98, providing essential services for virtualization, resource allocation, and device control. These Microsoft-supplied drivers, typically numbering around 26 in a standard installation, are bundled into the monolithic VMM32.VXD file located in the \Windows\System\VMM32 directory to optimize boot performance and memory usage by loading only necessary components during startup. They operate at ring 0 privilege level, enabling protected-mode execution while emulating real-mode environments for compatibility with MS-DOS applications.[11] The Virtual Machine Manager (VMM.386 or VMM.VXD) serves as the core orchestrator among built-in VxDs, responsible for creating and managing virtual machines (VMs), handling memory paging through dynamic page allocation, and facilitating task switching via its integrated scheduler. It traps processor exceptions, vectors interrupts to other VxDs like VPICD, and provides timing services with 1 ms resolution, ensuring multitasking across Win32, Win16, and DOS sessions. During the boot process, VMM initializes the system VM and coordinates the loading of other static VxDs from VMM32.VXD, replacing real-mode MS-DOS drivers with protected-mode equivalents for enhanced stability.[5][11] Other critical built-in VxDs handle specific hardware virtualization and system services. For instance, VPICD.386 (Virtual Programmable Interrupt Controller) manages IRQ allocation and reflection to VMs, supporting Plug and Play resource arbitration by virtualizing the 8259/8259A interrupt controllers and issuing end-of-interrupt (EOI) commands. VTD.VXD (Virtual Timer Device) controls the 8254 programmable interval timer, generating system ticks at 18.2 Hz for the foreground VM while preventing direct hardware reprogramming, and offers services for DOS idle detection. VJOYD.386 virtualizes joystick inputs, trapping relevant I/O ports to enable game device support without conflicts in multi-VM environments. These VxDs are essential for device initialization during boot, ensuring seamless hardware detection and configuration via the integrated Configuration Manager.[5][11] For storage and I/O, VCD.386 (Virtual COMM Device) emulates serial (COM) and parallel (LPT) ports, buffering data and reflecting interrupts to maintain VM isolation during suspend/resume operations. MMSYS.386 (Multimedia System) provides runtime services for audio, MIDI, and video devices, integrating with the multimedia architecture to support timing callbacks (e.g., timeSetEvent) and DMA contexts for sound output. Additional examples include VMOUSE.386 for mouse input polling, VKD.386 for keyboard handling, and VNETSUP.386 for basic network stack support, contributing to runtime functionalities like power management through idle detection and coordinated shutdown sequences. Collectively, these VxDs—covering ports, disks, interrupts, and peripherals—enable the core boot process, hardware abstraction, and ongoing system services in Windows 9x without relying on user intervention.[5][11]| VxD Name | Primary Role | Key Functionality |
|---|---|---|
| VMM.VXD | Virtual Machine Management | VM creation, memory paging, task switching, exception handling |
| VPICD.386 | Interrupt Control | IRQ virtualization, EOI processing, Plug and Play arbitration |
| VTD.VXD | Timer Management | 8254 timer trapping, system ticks, idle detection |
| VJOYD.386 | Joystick Input | Game port virtualization, input reflection to VMs |
| VCD.386 | Communications | Serial/parallel port emulation, buffering and interrupt reflection |
| MMSYS.386 | Multimedia Services | Audio/MIDI support, timing callbacks, DMA integration |