/***************************************************************************** * * * FILEOFF.C * * * * Copyright (C) Microsoft Corporation 1995. * * All Rights reserved. * * * ****************************************************************************** * * * Module Intent * * * * File Offset data type to replace using LONG for file offsets to handle * * files larger than 4 gigs in size. * * WARNING: To support 68K retail version, some functions don't have the * Pascal keyword. MSVC 4.0 had a bug that caused structure parameter to * * destroyed * * * ****************************************************************************** * * * Current Owner: davej * *****************************************************************************/ /***************************************************************************** * * Created 07/28/95 - davej * 3/05/97 erinfox Change errors to HRESULTS * *****************************************************************************/ static char s_aszModule[] = __FILE__; /* For error report */ #include #include #include /***************************************************************************** * * * Globals * * * *****************************************************************************/ FILEOFFSET EXPORT_API foNil = {0L, 0L}; FILEOFFSET EXPORT_API foMax = {0xffffffffL,0x7ffffffeL}; FILEOFFSET EXPORT_API foMin = {0x00000000L,0x80000001L}; FILEOFFSET EXPORT_API foInvalid = {0xffffffffL, 0xffffffffL}; /***************************************************************************** * * * Defines * * * *****************************************************************************/ /***************************************************************************** * * * Prototypes * * * *****************************************************************************/ /*************************************************************************** * * * Private Functions * * * ***************************************************************************/ /*************************************************************************** * * @doc INTERNAL * * @func FILEOFFSET PASCAL FAR | MakeFo | * Make a file offset from two dwords * * @parm DWORD | dwLo | * Low order dword * * @parm DWORD | dwHi | * High order dword * * @rdesc Returns a double DWORD file offset struct * * @comm * Use this function to build file offsets that can be passed to other * functions that need them as input. * ***************************************************************************/ FILEOFFSET PASCAL FAR EXPORT_API MakeFo(DWORD dwLo, DWORD dwHi) { FILEOFFSET fo; fo.dwOffset=dwLo; fo.dwHigh=dwHi; return fo; } /*************************************************************************** * * @doc PRIVATE * * @func FILEOFFSET PASCAL FAR | FoFromSz | * Convert a variable byte value to a FILEOFFSET * * @parm LPBYTE | szBytes | * Byte array containing variable byte length * * @rdesc Returns a double DWORD file offset struct from data of the form: * If High Bit Set, more bits follow (up to 9 bytes for 64 bits). * max for: 1 byte = 127 * 2 bytes = 16384 * 3 bytes = 2 M * 4 bytes = 268 M * 5 bytes = 34 G * 6 bytes = 4 T * 7 bytes = 562 T * 8 bytes = 72 Q * 9 bytes = 9223 Q (virtually infinite) * * @comm * Only a maximum of 9 bytes will be read from szBytes in the worst * case (or likely if szBytes points to invalid data). Use * to get the length of a byte array for advancing to the next encoded * offset for example. * ***************************************************************************/ FILEOFFSET PASCAL FAR EXPORT_API FoFromSz(LPBYTE sz) { register DWORD offset; register FILEOFFSET fo; register DWORD high=0L; for (;;) { offset=*sz; // Insert Segment A if (!(*(sz++)&0x80)) break; offset&=0x7f; offset|=((DWORD)(*sz))<<7; // Insert Segment B if (!(*(sz++)&0x80)) break; offset&=0x3fff; offset|=((DWORD)(*sz))<<14; // Insert Segment C if (!(*(sz++)&0x80)) break; offset&=0x1fffff; offset|=(((DWORD)*sz))<<21; // Insert Segment D if (!(*(sz++)&0x80)) break; offset&=0xfffffff; offset|=((DWORD)(*sz))<<28; // Insert Segment E high|=(*sz)>>4; if (!(*(sz++)&0x80)) break; high&=0x7; high|=(((DWORD)*sz))<<3; // Insert Segment F; if (!(*(sz++)&0x80)) break; high&=0x3ff; high|=((DWORD)(*sz))<<10; // Insert Segment G if (!(*(sz++)&0x80)) break; high&=0x1ffff; high|=((DWORD)(*sz))<<17; // Insert Segment H if (!(*(sz++)&0x80)) break; high&=0xffffff; high|=((DWORD)(*sz))<<24; // Segment I break; } fo.dwOffset=offset; fo.dwHigh=high; return fo; } /*************************************************************************** * * @doc PRIVATE * * @func WORD PASCAL FAR | FoToSz | * Convert a file offset to a string * * @parm FILEOFFSET | fo | * File offset to convert to string representation * * @parm LPBYTE | szBytes | * Byte array to contain variable byte address * * @rdesc Returns number of bytes copied. * See for description of byte array format * * @comm * The byte array should contain at least 9 valid bytes should be allocated, * since at most the 9 bytes starting at

may be filled in. * ***************************************************************************/ WORD PASCAL FAR EXPORT_API FoToSz(FILEOFFSET fo, LPBYTE sz) { register DWORD offset = fo.dwOffset; register DWORD high = fo.dwHigh; WORD wSize=1; for (;;) { *sz=(BYTE)(offset&0x7f); // A byte offset>>=7; if (!(offset|high)) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(offset&0x7f); // B byte offset>>=7; if (!(offset|high)) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(offset&0x7f); // C byte offset>>=7; if (!(offset|high)) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(offset&0x7f); // D byte offset>>=7; if (!(offset|high)) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(offset&0x0f); // E byte *sz|=(BYTE)((high&0x07)<<4); high>>=3; if (!high) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(high&0x7f); // F Byte high>>=7; if (!high) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(high&0x7f); // G Byte high>>=7; if (!high) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)(high&0x7f); // H Byte high>>=7; if (!high) break; wSize++; *(sz++)|=0x80; *sz=(BYTE)high; // I byte break; } return wSize; } /*************************************************************************** * * @doc PRIVATE * * @func WORD PASCAL FAR | LenSzFo | * Find number of bytes comprising this byte-array address code * * @parm LPBYTE | szBytes | * Byte array containing variable byte address * * @rdesc Returns number of bytes in byte-array for this address * ***************************************************************************/ WORD PASCAL FAR EXPORT_API LenSzFo(LPBYTE sz) { register WORD wLen=1; while ((*(sz++))&0x80) wLen++; return wLen; } /*************************************************************************** * * @doc PRIVATE * * @func FILEOFFSET FAR | FoAddDw | * Add a dword to a file offset * * @parm FILEOFFSET | fo | * Byte array containing variable byte length * * @parm DWORD | dwAdd | * Add this amount to the file offset * * @rdesc Returns the sum of the file offset fo and dwAdd as a FILEOFFSET. * Since only a dword is added, the dwHigh dword will never increase * more than one. * * ***************************************************************************/ FILEOFFSET FAR EXPORT_API FoAddDw(FILEOFFSET fo, DWORD dwAdd) { register FILEOFFSET foSum = fo; foSum.dwOffset+=dwAdd; if (foSum.dwOffset fo2, 0 if fo1 == fo2, positive if * fo1 > fo2 * ***************************************************************************/ short int PASCAL FAR EXPORT_API FoCompare(FILEOFFSET foLeft, FILEOFFSET foRight) { if (foLeft.dwHigh==foRight.dwHigh) { if (foLeft.dwOffsetfoRight.dwOffset) return 1; else return 0; } else if ((long)foLeft.dwHigh<(long)foRight.dwHigh) return -1; else return 1; }