首页  编辑  

HD INT13

Tags: /超级猛料/Hardware.硬件相关/驱动器相关/硬盘/   Date Created:

Worldwide Support

PRB: DeviceIoControl Int 13h Does Not Support Hard Disks

The information in this article applies to:

Microsoft Win32 Application Programming Interface (API), included with:

Microsoft Windows 95

----------------------------------------------------------------------------

----

SYMPTOMS

Win32 applications running under Windows 95 use CreateFile to open VWIN32

and then use DeviceIoControl with the VWIN32_DIOC_DOS_INT13 flag to perform

low-level BIOS disk functions. The functions work on floppy disks but always

fail on hard disks.

CAUSE

Windows 95, like previous versions of Windows, does not support calling BIOS

disk functions to gain access to hard disks from Win16 and Win32

applications. The reason is that BIOSXLAT.VXD does not translate BIOS

requests to hard disks from protected-mode into V86 mode, and this causes

the ROM BIOS to be called with an invalid address.

RESOLUTION

To work around this problem, Win32 applications must thunk to a Win16 DLL

and have that DLL call the DOS Protected Mode Interface (DPMI) Simulate Real

Mode Interrupt function to call Int 13h BIOS disk functions on hard disks.

When you use DPMI to call Int 13h BIOS disk functions, you bypass

BIOSXLAT.VXD and call the real-mode BIOS. Note that you cannot call DPMI

from 32-bit code.

STATUS

This behavior is by design.

MORE INFORMATION

The following example code shows how a Win32 application running under

Windows 95 can read the first physical sector of a hard disk, which contains

the disk's partition tables. This code requires a flat thunk, so parts of it

must be placed in a Win32 DLL and other parts must be placed in a Win16 DLL.

The relevant code for each DLL is labeled.

Execution starts from a Win32 application calling the Win32 DLL and proceeds

as follows. The Win32 DLL function, CallReadPhysicalSector1, calls the Win16

DLL's ReadPhysicalSector1 function by way of a thunk. Then

ReadPhysicalSector1, which is exported by the 16-bit DLL, calls DPMI to call

the BIOS Read Track function to read the first sector of the specified hard

disk. After ReadPhysicalSector1 returns, the contents of the first sector of

the hard disk, including the hard disk's partition table and bootstrap

program, will be in the buffer pointed to by lpBuff.

Code Sample

// Code in the 32-bit DLL

// Prototype for function in 16-bit DLL.

BOOL FAR PASCAL ReadPhysicalSector1 (BYTE   bDrive,

                                    LPBYTE lpBuffer,

                                    DWORD  cbBuffSize);

/*--------------------------------------------------------------------

CallReadPhysicalSector1()

Reads the first sector of the first hard disk.

Return Value

   Returns TRUE if the first sector was read, and FALSE if it

   wasn't.

--------------------------------------------------------------------*/

__declspec(dllexport) BOOL WINAPI CallReadPhysicalSector1()

{

   char lpBuff[512];

   BOOL fResult;

   // Read the first sector of the first hard disk.

   fResult = ReadPhysicalSector1 (0x80, lpBuff, 512);

   if (fResult)

      {

       // lpBuff contains the sector data.  Use it here

      }

   return fResult;

}

// Thunk Script

enablemapdirect3216 = true;

typedef unsigned long   DWORD;

typedef unsigned char   BYTE, * LPBYTE;

typedef bool            BOOL;

BOOL ReadPhysicalSector1 (BYTE   bDrive,

                         LPBYTE lpBuffer,

                         DWORD  cbBuffSize)

{

  lpBuffer = inout;

}

// Code in the 16-bit DLL

// Converts two BYTEs into a WORD.  This is useful for working with

// a RMCS, but was not provided in WINDOWS.H.

#define MAKEWORD(low, high) \

          ((WORD)((((WORD)(high)) << 8) | ((BYTE)(low))))

#define SECTOR_SIZE 512       // Size, in bytes, of a disk sector

#define CARRY_FLAG  0x0001

typedef BYTE FAR *LPBYTE;

typedef struct tagRMCS

{

  DWORD edi, esi, ebp, RESERVED, ebx, edx, ecx, eax;

  WORD  wFlags, es, ds, fs, gs, ip, cs, sp, ss;

} RMCS, FAR* LPRMCS;

BOOL FAR PASCAL SimulateRM_Int (BYTE bIntNum, LPRMCS lpCallStruct);

void FAR PASCAL BuildRMCS (LPRMCS lpCallStruct);

BOOL FAR PASCAL __export ReadPhysicalSector1 (BYTE   bDrive,

                                             LPBYTE lpBuffer,

                                             DWORD  cbBuffSize);

/*--------------------------------------------------------------------

 ReadPhysicalSector1()

 Calls DPMI to call the BIOS Int 13h Read Track function to read the

 first physical sector of a physical drive. This function is used to

 read partition tables, for example.

 Parameters

    bDrive

       The Int 13h device unit,

          0x00 for floppy drive 0

          0x00 for floppy drive 1

          0x80 for physical hard disk 0

          0x81 for physical hard disk 1

          etc.

    lpBuffer

       Pointer to a buffer that receives the sector data.  The buffer

       must be at least SECTOR_SIZE bytes long.

    cbBuffSize

       Actual size of lpBuffer.

 Return Value

    Returns TRUE if the first sector was read into the buffer pointed

    to by lpBuffer, or FALSE otherwise.

 Assumptions

    Assumes that sectors are at least SECTOR_SIZE bytes long.

--------------------------------------------------------------------*/

BOOL FAR PASCAL __export ReadPhysicalSector1 (BYTE   bDrive,

                                             LPBYTE lpBuffer,

                                             DWORD  cbBuffSize)

{

  BOOL   fResult;

  RMCS   callStruct;

  DWORD  gdaBuffer;     // Return value of GlobalDosAlloc().

  LPBYTE RMlpBuffer;    // Real-mode buffer pointer

  LPBYTE PMlpBuffer;    // Protected-mode buffer pointer

  /*

    Validate params:

       bDrive should be int 13h device unit -- let the BIOS validate

          this parameter -- user could have a special controller with

          its own BIOS.

       lpBuffer must not be NULL

       cbBuffSize must be large enough to hold a single sector

  */

  if (lpBuffer == NULL || cbBuffSize < SECTOR_SIZE)

     return FALSE;

  /*

    Allocate the buffer that the Int 13h function will put the sector

    data into. As this function uses DPMI to call the real-mode BIOS, it

    must allocate the buffer below 1 MB, and must use a real-mode

    paragraph-segment address.

    After the memory has been allocated, create real-mode and

    protected-mode pointers to the buffer. The real-mode pointer

    will be used by the BIOS, and the protected-mode pointer will be

    used by this function because it resides in a Windows 16-bit DLL,

    which runs in protected mode.

  */

  gdaBuffer = GlobalDosAlloc (cbBuffSize);

  if (!gdaBuffer)

     return FALSE;

  RMlpBuffer = (LPBYTE)MAKELONG(0, HIWORD(gdaBuffer));

  PMlpBuffer = (LPBYTE)MAKELONG(0, LOWORD(gdaBuffer));

  /*

    Initialize the real-mode call structure and set all values needed

    to read the first sector of the specified physical drive.

  */

  BuildRMCS (&callStruct);

  callStruct.eax = 0x0201;                // BIOS read, 1 sector

  callStruct.ecx = 0x0001;                // Sector 1, Cylinder 0

  callStruct.edx = MAKEWORD(bDrive, 0);   // Head 0, Drive #

  callStruct.ebx = LOWORD(RMlpBuffer);    // Offset of sector buffer

  callStruct.es  = HIWORD(RMlpBuffer);    // Segment of sector buffer

  /*

     Call Int 13h BIOS Read Track and check both the DPMI call

     itself and the BIOS Read Track function result for success.  If

     successful, copy the sector data retrieved by the BIOS into the

     caller's buffer.

  */

  if (fResult = SimulateRM_Int (0x13, &callStruct))

     if (!(callStruct.wFlags & CARRY_FLAG))

        {

        _fmemcpy (lpBuffer, PMlpBuffer, (size_t)cbBuffSize);

        fResult = TRUE;

        }

     else

        fResult = FALSE;

  // Free the sector data buffer this function allocated

  GlobalDosFree (LOWORD(gdaBuffer));

  return fResult;

}

/*--------------------------------------------------------------------

 SimulateRM_Int()

 Allows protected mode software to execute real mode interrupts such

 as calls to DOS TSRs, DOS device drivers, etc.

 This function implements the "Simulate Real Mode Interrupt" function

 of the DPMI specification v0.9.

 Parameters

    bIntNum

       Number of the interrupt to simulate

    lpCallStruct

       Call structure that contains params (register values) for

       bIntNum.

 Return Value

    SimulateRM_Int returns TRUE if it succeeded or FALSE if it

    failed.

 Comments

    lpCallStruct is a protected-mode selector:offset address, not a

    real-mode segment:offset address.

--------------------------------------------------------------------*/

BOOL FAR PASCAL SimulateRM_Int (BYTE bIntNum, LPRMCS lpCallStruct)

  {

  BOOL fRetVal = FALSE;      // Assume failure

  _asm {

        push di

        mov  ax, 0300h         ; DPMI Simulate Real Mode Int

        mov  bl, bIntNum       ; Number of the interrupt to simulate

        mov  bh, 01h           ; Bit 0 = 1; all other bits must be 0

        xor  cx, cx            ; No words to copy

        les  di, lpCallStruct

        int  31h                   ; Call DPMI

        jc   END1                  ; CF set if error occurred

        mov  fRetVal, TRUE

     END1:

        pop di

       }

  return (fRetVal);

  }

/*--------------------------------------------------------------------

 BuildRMCS()

 Initializes a real mode call structure to contain zeros in all its

 members.

 Parameters:

    lpCallStruct

       Points to a real mode call structure

 Comments:

    lpCallStruct is a protected-mode selector:offset address, not a

    real-mode segment:offset address.

--------------------------------------------------------------------*/

void FAR PASCAL BuildRMCS (LPRMCS lpCallStruct)

  {

  _fmemset (lpCallStruct, 0, sizeof (RMCS));

  }

REFERENCES

Information on using DPMI may be found in the DOS Protected Mode Interface

(DPMI) Specification Version 0.9.

Flat thunks are documented in "The Microsoft Programmer's Guide To Windows

95" topic in the Win32 Software Development Kit online documentation.

Additional query words: Windows sector table physical

Keywords : kbAPI kbKernBase kbGrpKernBase

Version :

Platform : WINDOWS

Issue type :

Last Reviewed: March 7, 1999

? 2000 Microsoft Corporation. All rights reserved. Terms of Use.

Article ID: Q137176

Last Reviewed:

March 7, 1999

Provided by Microsoft Product Support Services.

----------------------------------------------------------------------------

----

     Did the information in this article help answer your question?

Yes

No

Did not apply

Please provide additional comments about this information. If you require a

response or technical support, please click Contact Us.

(255 character max)