#include <windows.h>
#include <memory.h>
#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"
//
struct SectorInfo
{
BYTE bDrive;
WORD wCylinder;
BYTE bHead;
BYTE bSector;
BYTE bCount;
};
typedef SectorInfo far *LPSectorInfo;
/*
Data structure used for EI13 functions
*/
struct BlockInfo
{
BYTE drive;
DWORD blockAddressLo;
DWORD blockAddressHi;
WORD count;
};
typedef BlockInfo far *LPBlockInfo;
struct DiskAddressPacket
{
BYTE size;
BYTE reserved;
WORD count;
DWORD buffer;
DWORD startLo;
DWORD startHi;
};
struct DriveParameters
{
WORD size;
WORD flags;
DWORD cylinders;
DWORD heads;
DWORD sectors;
DWORD sectorsLo;
DWORD sectorsHi;
WORD bytesPerSector;
//---v2.0+ ---
DWORD EDDptr;
//---v3.0 ---
WORD signature;
BYTE v3size;
BYTE reserved[3];
BYTE bus[4];
BYTE interface[8];
BYTE interfacePath[8];
BYTE devicePath[8];
BYTE reserved2;
BYTE checksum;
};
struct ExtDriveInfo
{
BYTE drive;
DWORD cylinders;
DWORD heads;
DWORD sectors;
DWORD sectorsLo;
DWORD sectorsHi;
WORD bytesPerSector;
};
void QTRACE(char* pszFormat, ... )
{
static BOOL bFirst = TRUE;
FILE* fp = fopen("trace.log",bFirst ? "w" : "a");
if( fp != 0 )
{
bFirst = FALSE;
va_list args;
va_start( args, pszFormat );
vfprintf( fp, pszFormat, args );
fclose(fp);
}
}
/*
End new types
*/
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
DWORD FAR PASCAL __export ResetDisk(LPSectorInfo s);
DWORD FAR PASCAL __export ReadPhysicalSector (LPSectorInfo s, LPBYTE lpBuffer, DWORD cbBuffSize);
DWORD FAR PASCAL __export WritePhysicalSector (LPSectorInfo s, LPBYTE lpBuffer, DWORD cbBuffSize);
DWORD FAR PASCAL __export ReadDiskGeometry (LPSectorInfo s);
/*
Extended Int 13 Functions
*/
DWORD FAR PASCAL __export EI13GetDriveParameters(ExtDriveInfo* b);
DWORD FAR PASCAL __export EI13ReadSector (LPBlockInfo b, LPBYTE lpBuffer, DWORD bufferSize);
DWORD FAR PASCAL __export EI13WriteSector(LPBlockInfo b, LPBYTE lpBuffer, DWORD bufferSize);
/*
End new functions
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
//--------------------------------------------------------------------
// 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.
--------------------------------------------------------------------*/
DWORD FAR PASCAL __export ResetDisk(LPSectorInfo s)
{
BOOL fResult;
RMCS callStruct;
/*
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
*/
/*
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 = MAKEWORD(0x00, 0x00); // BIOS Reset disk system
callStruct.edx = MAKEWORD(s->bDrive, 0x00); // Head 0, Drive #
/*
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.
*/
fResult = SimulateRM_Int (0x13, &callStruct);
return fResult;
}
DWORD FAR PASCAL __export ReadPhysicalSector (LPSectorInfo s,
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
BYTE CylinderLo;
BYTE CylinderHi;
/*
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 < (DWORD)(SECTOR_SIZE * s->bCount))
return FALSE;
/*
Alelocate the buffer that the Int 13h function will put th 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);
//
// John's code
//
CylinderLo = (BYTE) (s->wCylinder & 0xFF);
CylinderHi = (BYTE) ((s->wCylinder >> 8) & 0xFF);
// bits 6 and 7 of sector are the high bits of cylinder
s->bSector = (s->bSector & 0x3F) | ((CylinderHi << 6) & 0xC0);
callStruct.eax = MAKEWORD(s->bCount, 0x02); // BIOS read, 1 sector
callStruct.ecx = MAKEWORD(s->bSector, CylinderLo); // Sector 1, Cylinder 0
callStruct.edx = MAKEWORD(s->bDrive, s->bHead); // 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.
*/
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
// try again?
// do a disk reset
ResetDisk(s);
fResult = SimulateRM_Int (0x13, &callStruct); // call int
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
fResult = FALSE;
}
}
}
}
if(fResult)
{
// copy the data back into the buffer
_fmemcpy(lpBuffer, PMlpBuffer, (size_t)cbBuffSize);
}
// Free the sector data buffer this function allocated
GlobalDosFree (LOWORD(gdaBuffer));
return fResult;
}
DWORD FAR PASCAL __export WritePhysicalSector (LPSectorInfo s,
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
BYTE CylinderLo;
BYTE CylinderHi;
/*
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 < (DWORD)(SECTOR_SIZE * s->bCount))
return FALSE;
/*
Alelocate the buffer that the Int 13h function will put th 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);
//
// John's code
//
CylinderLo = (BYTE)(s->wCylinder & 0xFF);
CylinderHi = (BYTE)((s->wCylinder >> 8) & 0xFF);
// bits 6 and 7 of sector are the high bits of cylinder
s->bSector = (s->bSector & 0x3F) | ((CylinderHi << 6) & 0xC0);
callStruct.eax = MAKEWORD(s->bCount, 0x03); // BIOS write, 1 sector
callStruct.ecx = MAKEWORD(s->bSector, CylinderLo); // Sector 1, Cylinder 0
callStruct.edx = MAKEWORD(s->bDrive, s->bHead); // 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.
*/
// copy the data into the buffer
_fmemcpy(PMlpBuffer, lpBuffer, (size_t)cbBuffSize);
// call the interrupt
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
// try again?
// do a disk reset
ResetDisk(s);
fResult = SimulateRM_Int (0x13, &callStruct); // call int
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
fResult = FALSE;
}
}
}
}
// Free the sector data buffer this function allocated
GlobalDosFree (LOWORD(gdaBuffer));
return fResult;
}
DWORD FAR PASCAL __export ReadDiskGeometry (LPSectorInfo s)
{
BOOL fResult;
RMCS callStruct;
BYTE CylinderLo;
BYTE CylinderHi;
/*
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
*/
/*
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 = MAKEWORD(0x00, 0x08); // BIOS read, 1 sector
callStruct.ecx = MAKEWORD(0x00, 0x00); // Sector 1, Cylinder 0
callStruct.edx = MAKEWORD(s->bDrive, 0x00); // Head 0, Drive #
callStruct.ebx = 0;//LOWORD(RMlpBuffer); // Offset of sector buffer
callStruct.es = 0;//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.
*/
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult)
{
if(callStruct.wFlags & CARRY_FLAG)
{
ResetDisk(s);
// try again
fResult = SimulateRM_Int (0x13, &callStruct);
if (fResult)
{
if(callStruct.wFlags & CARRY_FLAG)
{
fResult = FALSE;
}
}
}
}
if(fResult)
{
// copy the data into the structure
s->bHead = HIBYTE(callStruct.edx);
CylinderLo = HIBYTE(callStruct.ecx);
CylinderHi = LOBYTE(callStruct.ecx) >> 6;
s->wCylinder = MAKEWORD(CylinderLo, CylinderHi);
s->bSector = (LOBYTE(callStruct.ecx) & 0x3F);
}
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));
}
/*
This is the implementation of the Extended Int 0x13 functions
Written by John Newbigin
*/
DWORD FAR PASCAL __export EI13GetDriveParameters(ExtDriveInfo* b)
{
BOOL fResult;
RMCS callStruct;
DWORD dpBuffer; // Return value of GlobalDosAlloc().
LPBYTE RMlpdpBuffer; // Real-mode buffer pointer
LPBYTE PMlpdpBuffer; // Protected-mode buffer pointer
DriveParameters *dpptr;
BuildRMCS (&callStruct);
callStruct.eax = MAKEWORD(0, 0x41); // IBM/MS INT 13 Extensions - INSTALLATION CHECK
callStruct.ebx = 0x55AA;
callStruct.edx = MAKEWORD(b->drive, 0);
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
fResult = FALSE;
}
if(LOWORD(callStruct.ebx) != 0xAA55)
{
fResult = FALSE;
}
}
if(fResult)
{
// get the version info
// version = HIBYTE(LOWORD(callStruct.eax));
// query the specified drive
dpBuffer = GlobalDosAlloc (sizeof(DriveParameters));
if (!dpBuffer)
{
return FALSE;
}
RMlpdpBuffer = (LPBYTE)MAKELONG(0, HIWORD(dpBuffer));
PMlpdpBuffer = (LPBYTE)MAKELONG(0, LOWORD(dpBuffer));
dpptr=(DriveParameters *)PMlpdpBuffer;
dpptr->size = sizeof(DriveParameters);
BuildRMCS (&callStruct);
callStruct.eax = MAKEWORD(0, 0x48); // GET DRIVE PARAMETERS
callStruct.edx = MAKEWORD(b->drive, 0);
callStruct.ds = HIWORD(RMlpdpBuffer);
callStruct.esi = LOWORD(RMlpdpBuffer);
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
fResult = FALSE;
}
}
if(fResult)
{
b->cylinders = dpptr->cylinders;
b->heads = dpptr->heads;
b->sectors = dpptr->sectors;
b->sectorsLo = dpptr->sectorsLo;
b->sectorsHi = dpptr->sectorsHi;
b->bytesPerSector = dpptr->bytesPerSector;
QTRACE("cylinders=%ld\n", (long) dpptr->cylinders );
QTRACE("heads=%ld\n", (long) dpptr->heads );
QTRACE("sectors=%ld\n", (long) dpptr->sectors );
QTRACE("sectorsLo=%ld\n", (long) dpptr->sectorsLo );
QTRACE("sectorsHi=%ld\n", (long) dpptr->sectorsHi );
QTRACE("bytesPerSector=%ld\n", (long)dpptr->bytesPerSector );
}
GlobalDosFree (LOWORD(dpBuffer));
}
return fResult;
}
DWORD FAR PASCAL __export EI13ReadSector (LPBlockInfo b, LPBYTE lpBuffer, DWORD bufferSize)
{
BOOL fResult;
RMCS callStruct;
DWORD gdaBuffer; // Return value of GlobalDosAlloc().
LPBYTE RMlpBuffer; // Real-mode buffer pointer
LPBYTE PMlpBuffer; // Protected-mode buffer pointer
DWORD dapBuffer; // Return value of GlobalDosAlloc().
LPBYTE RMlpdapBuffer; // Real-mode buffer pointer
LPBYTE PMlpdapBuffer; // Protected-mode buffer pointer
// struct DiskAddressPacket dap;
DiskAddressPacket FAR *lpdap;
if (lpBuffer == NULL || bufferSize < (SECTOR_SIZE * b->count))
{
return FALSE;
}
gdaBuffer = GlobalDosAlloc (bufferSize);
if (!gdaBuffer)
return FALSE;
RMlpBuffer = (LPBYTE)MAKELONG(0, HIWORD(gdaBuffer));
PMlpBuffer = (LPBYTE)MAKELONG(0, LOWORD(gdaBuffer));
dapBuffer = GlobalDosAlloc(sizeof(DiskAddressPacket));
if(!dapBuffer)
{
GlobalDosFree (LOWORD(gdaBuffer));
return FALSE;
}
RMlpdapBuffer = (LPBYTE)MAKELONG(0, HIWORD(dapBuffer));
PMlpdapBuffer = (LPBYTE)MAKELONG(0, LOWORD(dapBuffer));
/*
Initialize the real-mode call structure and set all values needed
to read the first sector of the specified physical drive.
*/
// fill in dap
lpdap = (DiskAddressPacket *)PMlpdapBuffer;
lpdap->size = sizeof(DiskAddressPacket);
lpdap->count = b->count;
lpdap->buffer = (DWORD)RMlpBuffer;
lpdap->startLo = b->blockAddressLo;
lpdap->startHi = b->blockAddressHi;
BuildRMCS (&callStruct);
callStruct.eax = MAKEWORD(0, 0x42); // BIOS read
callStruct.edx = MAKEWORD(b->drive, 0); // Drive #
callStruct.ds = HIWORD(RMlpdapBuffer);
callStruct.esi = LOWORD(RMlpdapBuffer);
/*
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.
*/
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
fResult = FALSE;
}
}
if(fResult)
{
// copy the data back into the buffer
_fmemcpy(lpBuffer, PMlpBuffer, (size_t)bufferSize);
}
// Free the sector data buffer this function allocated
GlobalDosFree (LOWORD(gdaBuffer));
GlobalDosFree (LOWORD(dapBuffer));
return fResult;
}
DWORD FAR PASCAL __export EI13WriteSector (LPBlockInfo b, LPBYTE lpBuffer, DWORD bufferSize)
{
BOOL fResult;
RMCS callStruct;
DWORD gdaBuffer; // Return value of GlobalDosAlloc().
LPBYTE RMlpBuffer; // Real-mode buffer pointer
LPBYTE PMlpBuffer; // Protected-mode buffer pointer
DWORD dapBuffer; // Return value of GlobalDosAlloc().
LPBYTE RMlpdapBuffer; // Real-mode buffer pointer
LPBYTE PMlpdapBuffer; // Protected-mode buffer pointer
DiskAddressPacket FAR *lpdap;
if (lpBuffer == NULL || bufferSize < (SECTOR_SIZE * b->count))
{
return FALSE;
}
gdaBuffer = GlobalDosAlloc (bufferSize);
if (!gdaBuffer)
return FALSE;
RMlpBuffer = (LPBYTE)MAKELONG(0, HIWORD(gdaBuffer));
PMlpBuffer = (LPBYTE)MAKELONG(0, LOWORD(gdaBuffer));
dapBuffer = GlobalDosAlloc(sizeof(DiskAddressPacket));
if(!dapBuffer)
{
GlobalDosFree (LOWORD(gdaBuffer));
return FALSE;
}
RMlpdapBuffer = (LPBYTE)MAKELONG(0, HIWORD(dapBuffer));
PMlpdapBuffer = (LPBYTE)MAKELONG(0, LOWORD(dapBuffer));
/*
Initialize the real-mode call structure and set all values needed
to read the first sector of the specified physical drive.
*/
// fill in dap
lpdap = (DiskAddressPacket *)PMlpdapBuffer;
lpdap->size = sizeof(DiskAddressPacket);
lpdap->count = b->count;
lpdap->buffer = (DWORD)RMlpBuffer;
lpdap->startLo = b->blockAddressLo;
lpdap->startHi = b->blockAddressHi;
// copy the buffer into rm buffer
_fmemcpy(PMlpBuffer, lpBuffer, (size_t)bufferSize);
BuildRMCS (&callStruct);
callStruct.eax = MAKEWORD(0, 0x43); // BIOS write, no verify
callStruct.edx = MAKEWORD(b->drive, 0); // Drive #
callStruct.ds = HIWORD(RMlpdapBuffer);
callStruct.esi = LOWORD(RMlpdapBuffer);
/*
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.
*/
fResult = SimulateRM_Int (0x13, &callStruct);
if(fResult) // DPMI success
{
if(callStruct.wFlags & CARRY_FLAG) // check carry flag for error
{
fResult = FALSE;
}
}
// Free the sector data buffer this function allocated
GlobalDosFree (LOWORD(gdaBuffer));
GlobalDosFree (LOWORD(dapBuffer));
return fResult;
}
// prototype for function in .obj file from the thunk script
extern "C" BOOL FAR PASCAL __export thk_ThunkConnect16(LPSTR lpDll16,
LPSTR lpDll32,
WORD hInst,
DWORD dwReason);
#include "stdio.h"
#include "stdlib.h"
extern "C" BOOL FAR PASCAL __export DllEntryPoint(DWORD dwReason,
WORD hInst,
WORD wDS,
WORD wHeapSize,
DWORD dwReserved1,
WORD wReserved2)
{
if (!thk_ThunkConnect16("RAWIO16.DLL",
"RAWIO32.DLL",
hInst,
dwReason))
{
return FALSE;
}
return TRUE;
}
syntax highlighted by Code2HTML, v. 0.9.1