Source code of Windows XP (NT5)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*
* LZEXP.C * * Routines used in Lempel-Ziv expansion. * */
#include "kernel.h"
#if ROM //--------------------------------------------------------------
#define API _far _pascal _loadds
#define RING_BUF_LEN 4096 // size of ring buffer
#define MAX_RING_BUF_LEN 4224 // size of ring buffer - from LZFile
// struct declaration in lzexpand.h
#define BUF_CLEAR_BYTE ((BYTE) ' ') // rgbyteRingBuf[] initializer
#define MAX_LITERAL_LEN 2 // encode string into position and
// length if match length greater than
// this value (== # of bytes required
// to encode position and length)
#define LZ_MAX_MATCH_LEN (0x10 + MAX_LITERAL_LEN)
// upper limit for match length
// (n.b., assume length field implies
// length += 3)
#define END_OF_INPUT 500 // EOF flag for input file
#define FOREVER for(;;)
#define ReadByte(byte) ((byte = (BYTE)(cbSrc ? *pSrc++ : 0)), \
(cbSrc ? (cbSrc--, TRUE) : END_OF_INPUT)) #define WriteByte(byte) ((*pDst++ = byte), cblOutSize++)
typedef struct COMPHEAD _far * LPCOMPHEAD;
struct COMPHEAD { // Compressed segment/resource header
BYTE Sig; // signature
BYTE Method; // compression method
DWORD cbSize; // # compressed bytes following
};
#define CMP_SIG ('C')
#define CMP_LZ ('L')
/*
* LZDecode * * Parameters: * selDst Selector pointing to destination buffer * selSrc Selector pointing to compressed data * lpBuf Pointer to optional ring buffer * * Returns: * count (in bytes) of uncompressed data written to selDst buffer * * Note: This routine does not use any static or external data. * This allows it to be used to uncompress Kernel's own * data segment. */
DWORD FAR API LZDecode(WORD selDst, WORD selSrc, LPSTR lpBuf) {
int i, cb, // number of bytes to unpack
f; // holds ReadByte() return values
int oStart; // buffer offset for unpacking
BYTE byte1, byte2; // input byte holders
unsigned uFlags; // LZ decoding description byte
int iCurRingBufPos; // ring buffer offset
int cbMaxMatchLen; LPSTR rgbyteRingBuf; HANDLE hRingBuf; LPCOMPHEAD lpHead; DWORD cblOutSize, cbSrc; char _based((_segment)selDst) *pDst = NULL; char _based((_segment)selSrc) *pSrc = NULL; struct COMPHEAD _based((_segment)selSrc) *pHead = NULL;
pSrc += sizeof(struct COMPHEAD);
cblOutSize = 0; cbSrc = pHead->cbSize; cbMaxMatchLen = LZ_MAX_MATCH_LEN;
// Make sure we know how to expand this object
if (pHead->Sig != CMP_SIG || pHead->Method != CMP_LZ) return(0);
// Set up a fresh buffer state.
if (lpBuf) { hRingBuf = NULL; rgbyteRingBuf = lpBuf; } else { if (!(hRingBuf = GlobalAlloc(GMEM_MOVEABLE,MAX_RING_BUF_LEN))) return(0); rgbyteRingBuf = GlobalLock(hRingBuf); }
// Initialize ring buffer.
for (i = 0; i < RING_BUF_LEN - cbMaxMatchLen; i++) rgbyteRingBuf[i] = BUF_CLEAR_BYTE;
// Initialize decoding globals.
uFlags = 0U; iCurRingBufPos = RING_BUF_LEN - cbMaxMatchLen;
f = ReadByte(byte1);
// Decode one encoded unit at a time.
FOREVER { if (f == END_OF_INPUT) // EOF reached
break;
// High order byte counts the number of bits used in the low order
// byte.
if (((uFlags >>= 1) & 0x100) == 0) { // Set bit mask describing the next 8 bytes.
uFlags = ((unsigned)byte1) | 0xff00;
if ((f = ReadByte(byte1)) != TRUE) break; }
if (uFlags & 1) { // Just store the literal byte in the buffer.
WriteByte(byte1);
rgbyteRingBuf[iCurRingBufPos++] = byte1; iCurRingBufPos &= RING_BUF_LEN - 1; } else { // Extract the offset and count to copy from the ring buffer.
if ((f = ReadByte(byte2)) != TRUE) break;
cb = (int)byte2; oStart = (cb & 0xf0) << 4 | (int)byte1; cb = (cb & 0x0f) + MAX_LITERAL_LEN;
for (i = 0; i <= cb; i++) { byte1 = rgbyteRingBuf[(oStart + i) & (RING_BUF_LEN - 1)];
WriteByte(byte1);
rgbyteRingBuf[iCurRingBufPos++] = byte1; iCurRingBufPos &= RING_BUF_LEN - 1; } }
f = ReadByte(byte1); }
if (hRingBuf) { GlobalUnlock(hRingBuf); GlobalFree(hRingBuf); }
return(cblOutSize); }
#endif //ROM -------------------------------------------------------
|