Calling DeviceIoControl on Windows 95

A Win32-based application running on Windows 95 and Windows 98 can use the DeviceIoControl function to send control codes directly to a virtual device driver (VxD). Any VxD can support any number of control codes, or none at all.

The system VxD, VWIN32.VXD, supports the input and output control (IOCTL) functions originally provided by MS-DOS Interrupt 21h. The following example shows how to call Get Media ID (Interrupt 21h Function 440Dh Minor Code 66h) from a Win32-based application:

#define VWIN32_DIOC_DOS_IOCTL 1 
 
typedef struct _DEVIOCTL_REGISTERS 
{ 
    DWORD reg_EBX; 
    DWORD reg_EDX; 
    DWORD reg_ECX; 
    DWORD reg_EAX; 
    DWORD reg_EDI; 
    DWORD reg_ESI; 
    DWORD reg_Flags; 
} DEVIOCTL_REGISTERS, *PDEVIOCTL_REGISTERS; 
 
typedef struct _MID 
{ 
    WORD  midInfoLevel; 
    DWORD midSerialNum; 
    BYTE  midVolLabel[11]; 
    BYTE  midFileSysType[8]; 
} MID, *PMID; 
 
BOOL GetMediaID(PMID pmid, UINT nDrive) 
{ 
    DEVIOCTL_REGISTERS reg; 
 
    reg.reg_EAX = 0x440D;       // IOCTL for block devices 
    reg.reg_EBX = nDrive;       // zero-based drive ID 
    reg.reg_ECX = 0x0866;       // Get Media ID command 
    reg.reg_EDX = (DWORD) pmid; // receives media ID info 
 
    if (!DoIOCTL(&reg)) 
        return FALSE; 
 
    if (reg.reg_Flags & 0x8000) // error if carry flag set 
        return FALSE; 
 
    return TRUE; 
} 
 
BOOL DoIOCTL(PDEVIOCTL_REGISTERS preg) 
{ 
    HANDLE hDevice; 
 
    BOOL fResult; 
    DWORD cb; 
 
    preg->reg_Flags = 0x8000; // assume error (carry flag set) 
 
    hDevice = CreateFile("\\\\.\\vwin32", 
        GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
        (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); 
 
    if (hDevice == (HANDLE) INVALID_HANDLE_VALUE) 
        return FALSE; 
    else 
    { 
        fResult = DeviceIoControl(hDevice, VWIN32_DIOC_DOS_IOCTL, 
            preg, sizeof(*preg), preg, sizeof(*preg), &cb, 0); 
 
        if (!fResult) 
            return FALSE; 
    } 
 
    CloseHandle(hDevice); 
 
    return TRUE; 
}