home *** CD-ROM | disk | FTP | other *** search
- DOCUMENT:Q137176 09-JAN-1996 [win32sdk]
- TITLE :PRB: DeviceIoControl Int 13h Does Not Support Hard Disks
- PRODUCT :Microsoft Win32 Software Development Kit
- PROD/VER:4.00
- OPER/SYS:WINDOWS
- KEYWORDS:kbprg kbprb
-
- -------------------------------------------------------------------------
- The information in this article applies to:
-
- - Microsoft Win32 Application Programming Interface (API) included with:
-
- - Microsoft Windows 95 version 4.0
- -------------------------------------------------------------------------
-
- SYMPTOMS
- ========
-
- Win32-based 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 protected
- mode Windows- and Win32-based applications. The cause of this lack of
- support for hard disks is that BIOSXLAT.VXD does not translate BIOS
- requests 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-based applications must thunk to a
- Windows 16-bit 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-based 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 Windows 16-bit DLL. The relevant code for each DLL is labeled.
-
- Execution starts from a Win32-based application calling the Win32 DLL and
- proceeds as follows. The Win32 DLL function, CallReadPhysicalSector1, calls
- the 16-bit 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 reference words: 4.00 Windows 95 sector table physical
- KBCategory: kbprg kbprb
- KBSubcategory: BseFileio
-
- =============================================================================
-
- THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS
- PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS
- ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
- EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
- ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
- CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
- MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION
- OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES
- SO THE FOREGOING LIMITATION MAY NOT APPLY.
-
- Copyright Microsoft Corporation 1996.