BUG: Int 21 Read/Write Track on Logical Drive Fails on OSR2
ID: Q174569
|
The information in this article applies to:
-
Microsoft Win32 Application Programming Interface (API), included with:
SYMPTOMS
On Windows 95 OEM Service Release2 (OSR2), Read Track on Logical Drive (Int
21h function 440Dh minor code 61h) and Write Track on Logical Drive (Int
21h function 440Dh minor code 41h), do not work when called through the
DeviceIoControl API. When these functions are called, both DeviceIoControl
and the Int 21h functions succeed, but the data is not read or written.
However, both functions work correctly when called from Win16-based and MS-
DOS based applications.
On the retail version of Windows 95, both functions work when called
through DeviceIOControl as well as Win16-based and MS-DOS based
applications.
CAUSE
Windows 95 OEM Service Release 2 has a bug that affects Int 21h function
440Dh minor codes 61h and 41h only when called through DeviceIoControl.
RESOLUTION
There are two ways to work around this bug:
- Use DeviceIoControl with VWIN32_DIOC_DOS_INT25 and
VWIN32_DIOC_DOS_INT26 to issue Absolute Disk Read (Int 25h) and
Absolute Disk Write (Int 26h) respectively. This method works
for FAT12 and FAT16 volumes. This method is compatible with the
retail release version of Windows 95, but will not work on
FAT32 volumes.
- Use DeviceIoControl with VWIN32_DIOC_DOS_DRIVEINFO to issue
Ext Absolute Disk Read & Write (Int 21h function 7305h). This
method works for FAT12, FAT16, and FAT32 volumes, but is not
backward compatible with the retail release version of
Windows 95.
STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article. We are researching this bug and will post
new information here in the Microsoft Knowledge Base as it becomes
available.
MORE INFORMATION
Win32 and console applications running on Windows 95 and its successors use
the DeviceIoControl() API to issue MS-DOS Interrupt 21h functions to
perform low-level disk I/O. Such applications usually are disk utilities
that must bypass the file system in order to perform activities such as
formatting and defragmenting disks.
Windows 95 and its successors provides several functions to access sectors
on a logical drive. These functions correspond to those available to MS-DOS
and Win16-based applications, including Int 21h function 440Dh functions,
Int 25h, and Int 26h. In addition, Windows 95 OEM Service Release 2 (OSR2)
includes a new function, Int 21h function 7305h.
If your application must be compatible with the retail release version of
Windows 95, but still support FAT32, then it should check the operating
system version. If Windows 95 OSR2 is running, your application can call
Int 21h function 7305h. If it is running on the retail release of Windows
95, it should use Int 25h and Int 26h. The following code demonstrates how
to call these functions.
Sample Code
#include <windows.h>
#define VWIN32_DIOC_DOS_INT25 2
#define VWIN32_DIOC_DOS_INT26 3
#define VWIN32_DIOC_DOS_DRIVEINFO 6
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;
#define CARRY_FLAG 1
#pragma pack(1)
typedef struct _DISKIO {
DWORD dwStartSector; // starting logical sector number
WORD wSectors; // number of sectors
DWORD dwBuffer; // address of read/write buffer
} DISKIO, * PDISKIO;
#pragma pack()
/*------------------------------------------------------------------
ReadLogicalSectors (hDev, bDrive, dwStartSector, wSectors, lpSectBuff)
Purpose:
Reads sectors from a logical drive. Uses Int 25h.
Parameters:
hDev
Handle of VWIN32
bDrive
The MS-DOS logical drive number. 1 = A, 2 = B, 3 = C, etc.
dwStartSector
The first logical sector to read
wSectors
The number of sectors to read
lpSectBuff
The caller-supplied buffer that will contain the sector data
Return Value:
Returns TRUE if successful, or FALSE if failure.
Comments:
This function does not validate its parameters.
------------------------------------------------------------------*/
BOOL ReadLogicalSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio = {0};
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = bDrive - 1; // Int 25h drive numbers are 0-based.
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = 0xFFFF; // use DISKIO struct
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT25,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the read succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult;
}
/*------------------------------------------------------------------
WriteLogicalSectors (hDev, bDrive, dwStartSector, wSectors, lpSectBuff)
Purpose:
Writes sectors to a logical drive. Uses Int 26h
Parameters:
hDev
Handle of VWIN32
bDrive
The MS-DOS logical drive number. 1 = A, 2 = B, 3 = C, etc.
dwStartSector
The first logical sector to write
wSectors
The number of sectors to write
lpSectBuff
The caller-supplied buffer that contains the sector data
Return Value:
Returns TRUE if successful, or FALSE if failure.
Comments:
This function does not validate its parameters.
------------------------------------------------------------------*/
BOOL WriteLogicalSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio = {0};
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = bDrive - 1; // Int 26h drive numbers are 0-based.
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = 0xFFFF; // use DISKIO struct
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT26,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult;
}
/*------------------------------------------------------------------
NewReadSectors(hDev, bDrive, dwStartSector, wSectors, lpSectBuff)
Purpose:
Reads the specified number of sectors into a caller-supplied
buffer. Uses Int 21h function 7305h
Parameters:
hDev
Handle of VWIN32
bDrive
The MS-DOS logical drive number. 0 = default, 1 = A, 2 = B,
3 = C, etc.
dwStartSector
The first sector to read.
wSectors
The number of sectors to read.
lpSectBuff
The caller-supplied buffer to read into.
Return Value:
Returns TRUE if successful, or FALSE if failure.
Comments:
This function does not validate its parameters. It assumes that
lpSectBuff is allocated by the caller and is large enough to
hold all of the data from all of the sectors being read.
------------------------------------------------------------------*/
BOOL NewReadSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio;
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.lpBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = -1;
reg.reg_EDX = bDrive; // Int 21h, fn 7305h drive numbers are 1-based
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the read succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult;
}
/*------------------------------------------------------------------
NewWriteSectors(hDev, bDrive, dwStartSector, wSectors, lpSectBuff)
Purpose:
Writes the specified number of sectors from a caller-supplied
buffer. Uses Int 21h function 7305h
Parameters:
hDev
Handle of VWIN32
bDrive
The MS-DOS logical drive number. 0 = default, 1 = A, 2 = B,
3 = C, etc.
dwStartSector
The first sector to write.
wSectors
The number of sectors to write.
lpSectBuff
The caller-supplied buffer from which to write.
Return Value:
Returns TRUE if successful, or FALSE if failure.
Comments:
This function does not validate its parameters. It assumes that
lpSectBuff is allocated by the caller and is large enough to
hold all of the data to be written.
------------------------------------------------------------------*/
BOOL NewWriteSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio;
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.lpBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = -1;
reg.reg_EDX = bDrive; // Int 21h, fn 7305h drive numbers are 1-based
reg.reg_ESI = 0x6001; // Normal file data (See function
// documentation for other values)
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult;
}
REFERENCES
"Microsoft MS-DOS Programmer's Reference", Version 6.0, pages 140-144, 313-
314, 321-322.
Online Documentation:
Microsoft Win32 SDK, Programming Tools and Guides; Programmer's Guide to
Windows 95; Windows 95 Reference; FAT32 API Reference; Functions; Int 21h
Function 7305h Ext_AbsDiskReadWrite (FAT32)
Additional query words:
format logical drive low level ioctl bios
Keywords : kbAPI kbKernBase kbGrpKernBase
Version : winnt:
Platform : winnt
Issue type : kbbug