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(®))
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;
}