In Windows NT / 2K / XP, open the name directly with "//./a:" with "//./a:", you can drive it with the device, and access the disk with the readFile / WriteFile. But Windows 9x does not support this simple method. This article describes a method of implementing a disk directly accessed in Windows 9x: Use the system's vwin32.vxd, complete the DOS INT21 7305H and 440DH functionality through DeviceIoControl. This call supports FAT12, FAT16, and FAT32 for Windows 95 SR2 and higher.
Let's take a look at the entrance parameters of the DOS INT21 7305H function:
AX - Function No. 7305H
DS: BX - Information structure for reading and writing sectors
CX - must be -1
DL - Drive Number: 1 = A:, 2 = B: 3 = C: ...
Si - read and write logo: lowest 0 = read, 1 = write
If you call success, clear the C flag; otherwise set the C flag.
DS: BX points to a structure, this structure is defined as follows:
Diskio Struc
DWSTARTSECTOR DD?; start sector
WSECTOR DW?;
LPBuffer DD?; Data buffer address
Diskio Ends
Under Write operation, you need to "lock" drives. The 4AH / 6AH feature of DOS INT21 440DH enables lock / unlocks of logical drives. The entrance parameters are:
AX - Function number 440DH
BH - lock level, 0-3, direct writing sectors 1
BL - Drive Number: 1 = A: 2 = B: 3 = C: ...
CH - 0x08
CL - 0x4a
DX - 0
AX - Function number 440DH
BL - Drive Number: 1 = A: 2 = B: 3 = C: ...
CH - 0x08
CL - 0x6A
The above two calls, if the success is successful, clear the C flag; otherwise set the C flag.
The above interrupt is called by IOCTL code VWIN32_DIOC_DOS_DRIVEINFO. The key code to achieve absolute disk read and write is as follows:
// int21 IOCTL code
#define vwin32_dioc_dos_iocTl 1
#define vwin32_dioc_dos_driveInfo 6
// Register group
Typedef struct _dioc_registers {
DWORD reg_ebx;
DWORD reg_edx;
DWORD reg_ecx;
DWORD reg_eax;
DWORD reg_edi;
DWord reg_esi;
DWORD reg_flags;
} DIOC_REGISTERS, * PDIOC_REGISTERS;
// IO parameters (pay attention to byte alignment)
#pragma pack (1)
Typedef struct _diskio {
DWORD DWSTARTSector; // Start sector
Word Wsectors; // Distance
Void * pBuffer; // buffer pointer
} DISKIO, * PDISKIO;
#pragma pack ()
Bool absdiskread
Byte ndisknumber, // disk number, 1 = A:, 2 = B:, 3 = C:, ...
DWORD DWSTARTSector, // Start sector
Word Wsectors, // Distance
VOID * PBUFFER) // Data buffer pointer {
Handle HDevice;
DIOC_REGISTERS Regs;
Diskio DIO;
DWORD DWOUTBYTES;
Bool Bresult;
// Open the device to get a VXD handle
HDevice = CREATEFILE (".// vwin32", // device path
Generic_read | generic_write, // Read and write
File_share_read | file_share_write, // shared method
NULL, / / Default security descriptor
Open_existing, // creation method
FILE_ATTRIBUTE_NORMAL, // File Properties
NULL); // Do not need to refer to the template file
IF (HDevice == Invalid_Handle_Value)
{
Return False;
}
// Fill the DISKIO parameter structure
Dio.dwstartsector = dwstartsector;
Dio.wsectors = WSECTORS;
Dio.pbuffer = pbuffer;
// Fill Register Group - Interrupt Portactor
MEMSET (& Regs, 0, SizeOf (Dioc_registers);
Regs.reg_eax = 0x7305; // AX = 0x7305
Regs.reg_ebx = (dword) & dio; // EBX = DS: bx = parameter pointer
Regs.reg_ecx = 0xfffff; // CX = -1
Regs.reg_edx = ndiskNumber; // DL = disk number
Regs.reg_esi = 0; // si = 0 - read operation
// Read the disk with vwin32_dioc_dos_driveinfo
DwoutBytes = 0;
BRESULT = Deviceiocontrol (HDevice, // Equipment handle
Vwin32_dioc_dos_driveinfo, // int21
& regs, sizeof (regs), // output data buffer and length
& regs, sizeof (regs), // output data buffer and length
& dwoutBytes, // Output data length
Null); // with synchronous I / O
/ / Determine that DeviceIocontrol and INT21 have no error
BRESULT = BRESULT &&! (regs.reg_flags & 1);
CloseHandle (HDEvice);
Return BRESULT;
}
Bool absdiskwrite
Byte ndisknumber, // disk number, 1 = A:, 2 = B:, 3 = C:, ...
DWORD DWSTARTSector, // Start sector
Word Wsectors, // Distance
VOID * PBUFFER) // Data buffer pointer {
Handle HDevice;
DIOC_REGISTERS Regs;
Diskio DIO;
DWORD DWOUTBYTES;
Bool Bresult;
// Open the device to get a VXD handle
HDevice = CREATEFILE (".// vwin32", // device path
Generic_read | generic_write, // Read and write
File_share_read | file_share_write, // shared method
NULL, / / Default security descriptor
Open_existing, // creation method
FILE_ATTRIBUTE_NORMAL, // File Properties
NULL); // Do not need to refer to the template file
IF (HDevice == Invalid_Handle_Value)
{
Return False;
}
// Fill the DISKIO parameter structure
Dio.dwstartsector = dwstartsector;
Dio.wsectors = WSECTORS;
Dio.pbuffer = pbuffer;
// Fill Register Group - Interrupt Portactor
MEMSET (& Regs, 0, SizeOf (Dioc_registers);
Regs.reg_eax = 0x7305; // AX = 0x7305
Regs.reg_ebx = (dword) & dio; // EBX = DS: bx = parameter pointer
Regs.reg_ecx = 0xfffff; // CX = -1
Regs.reg_edx = ndiskNumber; // DL = disk number
Regs.reg_esi = 0x6001; // si = 0x6001 - ordinary write operation
// Write disk with vwin32_dioc_dos_driveinfo
DwoutBytes = 0;
BRESULT = Deviceiocontrol (HDevice, // Equipment handle
Vwin32_dioc_dos_driveinfo, // int21
& regs, sizeof (regs), // output data buffer and length
& regs, sizeof (regs), // output data buffer and length
& dwoutBytes, // Output data length
Null); // with synchronous I / O
/ / Determine that DeviceIocontrol and INT21 have no error
BRESULT = BRESULT &&! (regs.reg_flags & 1);
CloseHandle (HDEvice);
Return BRESULT;
}
Bool LockVolume
Byte ndisknumber) / / disk number, 1 = A:, 2 = B:, 3 = C:, ...
{
Handle HDevice;
DIOC_REGISTERS Regs;
DWORD DWOUTBYTES;
Bool Bresult; // Open the device to get the VXD handle
HDevice = CREATEFILE (".// vwin32", // device path
Generic_read | generic_write, // Read and write
File_share_read | file_share_write, // shared method
NULL, / / Default security descriptor
Open_existing, // creation method
FILE_ATTRIBUTE_NORMAL, // File Properties
NULL); // Do not need to refer to the template file
IF (HDevice == Invalid_Handle_Value)
{
Return False;
}
// Fill Register Group - Interrupt Portactor
MEMSET (& Regs, 0, SizeOf (Dioc_registers);
Regs.reg_eax = 0x440d; // AX = 0x440d
Regs.reg_ebx = 0x0100 | ndisknumber; // BH = Lock level, BL = disk number
Regs.reg_ecx = 0x084a;
Regs.reg_edx = 0;
// Read the disk with vwin32_dioc_dos_driveinfo
DwoutBytes = 0;
BRESULT = Deviceiocontrol (HDevice, // Equipment handle
Vwin32_dioc_dos_iocTl, // int21
& regs, SIZEOF (Regs), // Enter data buffer and length
& regs, sizeof (regs), // output data buffer and length
& dwoutBytes, // Output data length
Null); // with synchronous I / O
/ / Determine that DeviceIocontrol and INT21 have no error
BRESULT = BRESULT &&! (regs.reg_flags & 1);
CloseHandle (HDEvice);
Return BRESULT;
}
Bool unlockvolume
Byte ndisknumber) / / disk number, 1 = A:, 2 = B:, 3 = C:, ...
{
Handle HDevice;
DIOC_REGISTERS Regs;
DWORD DWOUTBYTES;
Bool Bresult;
// Open the device to get a VXD handle
HDevice = CREATEFILE (".// vwin32", // device path
Generic_read | generic_write, // Read and write
File_share_read | file_share_write, // shared method
NULL, / / Default security descriptor
Open_existing, // creation method
File_attribute_normal, // file attribute null; // Do not need to reference template files
IF (HDevice == Invalid_Handle_Value)
{
Return False;
}
// Fill Register Group - Interrupt Portactor
MEMSET (& Regs, 0, SizeOf (Dioc_registers);
Regs.reg_eax = 0x440d; // AX = 0x440d
Regs.reg_ebx = ndisknumber; // BL = disk number
Regs.reg_ecx = 0x086a;
// Read the disk with vwin32_dioc_dos_driveinfo
DwoutBytes = 0;
BRESULT = Deviceiocontrol (HDevice, // Equipment handle
Vwin32_dioc_dos_iocTl, // int21
& regs, SIZEOF (Regs), // Enter data buffer and length
& regs, sizeof (regs), // output data buffer and length
& dwoutBytes, // Output data length
Null); // with synchronous I / O
/ / Determine that DeviceIocontrol and INT21 have no error
BRESULT = BRESULT &&! (regs.reg_flags & 1);
CloseHandle (HDEvice);
Return BRESULT;
}
The following example begins with the 0 sector of the A disk, read the data of 10 sectors, and saves in the file:
UNSIGNED Char BUF [512 * 10];
IF (Absdiskread (1, 0, 10, BUF))
{
FILE * fp = fopen ("a.dat", "w b");
FWRITE (BUF, 512, 10, FP);
Fclose (fp);
}
The following example reads the 8888 sector of the D drive, then write back:
UNSIGNED Char BUF [512]
LockVolume (4);
IF (Absdiskread (4, 8888, 1, buf))
{
...
IF (AbsdiskWrite (4, 8888, 1, buf))
{
...
}
}
UNLOCKVOLUME (4);
In a write mode, the bit 0 of the Si register is set to 1, and the bit 15-13 needs to have different values in different regions of the disk:
Bit 15bit 14bit 13description000other / unknown.001fat data.010directory data.011normal file data.100Reselved.
If you do not follow the above value, although it is possible to write success, the system cannot automatically complete the relevant functionality, it may cause problems with the FAT data backup, drive data compression.
[related resources]
BHW98 column: http://www.9cbs.net/develop/author/netauthor/bhw98/
First release: 2003-08-20 Last revision: 2003-09-12