Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

430 lines
10 KiB

/*****************************************************************************
* *
* EXPAND.C *
* *
* Copyright (C) Microsoft Corporation 1989. *
* All Rights reserved. *
* *
******************************************************************************
* *
* Module Intent *
* This code compresses and decompresses bitmap bits, as well as the code *
* to expand Help 3.0 format bitmaps from disk image to the memory structure.*
* *
*****************************************************************************/
#include "stdafx.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "skip.h"
#define fRLEBit 0x80
const int MAX_RUN = 127;
static int STDCALL LcbUncompressHb(PBYTE pbSrc, PBYTE pbDest, int cbSrc);
/***************************************************************************
*
- Name HbmhExpandQv
-
* Purpose
* This function decompresses the bitmap from its disk format to an
* in memory bitmap header, including bitmap and hotspot data.
*
* Arguments
* A pointer to a buffer containing the bitmap data as read off disk.
*
* Returns
* A handle to the bitmap header. Returns hbmhOOM on out of memory.
* Note that this is the same as NULL. Also returns hbmhInvalid on
* invalid format. This handle is non-discardable, but the code that
* deals with qbmi->hbmh can deal with discardable blocks, so after
* initialization this can be made discardable.
*
* +++
*
* Notes
*
***************************************************************************/
HBMH STDCALL HbmhExpandQv(void* qv)
{
PBMH qbmh;
BMH bmh;
int cbBits, cbUncompressedBits;
PBYTE pDst;
PBYTE pBase = (PBYTE) qv;
bmh.bmFormat = *((PBYTE) qv);
qv = QFromQCb(qv, sizeof(BYTE));
bmh.fCompressed = *((PBYTE) qv);
qv = QFromQCb(qv, sizeof(BYTE));
switch(bmh.bmFormat) {
case bmWbitmap:
case bmDIB:
qv = QVSkipQGB(qv, (&bmh.w.dib.biXPelsPerMeter));
qv = QVSkipQGB(qv, (&bmh.w.dib.biYPelsPerMeter));
qv = QVSkipQGA(qv, (&bmh.w.dib.biPlanes));
qv = QVSkipQGA(qv, (&bmh.w.dib.biBitCount));
qv = QVSkipQGB(qv, (&bmh.w.dib.biWidth));
qv = QVSkipQGB(qv, (&bmh.w.dib.biHeight));
qv = QVSkipQGB(qv, (&bmh.w.dib.biClrUsed));
qv = QVSkipQGB(qv, (&bmh.w.dib.biClrImportant));
qv = QVSkipQGB(qv, (&bmh.cbSizeBits));
qv = QVSkipQGB(qv, (&bmh.cbSizeExtra));
bmh.cbOffsetBits = *((DWORD *) qv);
qv = (PBYTE) qv + sizeof(DWORD);
bmh.cbOffsetExtra = *((DWORD *) qv);
qv = (PBYTE) qv + sizeof(DWORD);
// Fix up constant fields in DIB structure:
bmh.w.dib.biSize = sizeof(BITMAPINFOHEADER);
bmh.w.dib.biCompression = 0L;
bmh.w.dib.biSizeImage = 0L;
// Determine size of bitmap header plus all data
if (bmh.fCompressed)
cbBits = LAlignLong (bmh.w.dib.biWidth * bmh.w.dib.biBitCount) *
bmh.w.dib.biHeight;
else
cbBits = bmh.cbSizeBits;
qbmh = (BMH*) lcCalloc(LcbSizeQbmh(&bmh) + cbBits
+ bmh.cbSizeExtra);
// Copy header and color table:
memmove(qbmh, &bmh, sizeof(BMH) - 2 * sizeof(RGBQUAD));
memmove(qbmh->rgrgb, qv, sizeof(RGBQUAD) * (int) bmh.w.dib.biClrUsed);
// Copy bits, decompressing if necessary:
qbmh->cbOffsetBits = LcbSizeQbmh(qbmh);
if (bmh.fCompressed == BMH_COMPRESS_30) {
qbmh->cbSizeBits = LcbUncompressHb(pBase + bmh.cbOffsetBits,
(PBYTE) QFromQCb(qbmh, qbmh->cbOffsetBits), bmh.cbSizeBits);
ASSERT(qbmh->cbSizeBits <= cbBits);
}
else if (bmh.fCompressed == BMH_COMPRESS_ZECK) {
qbmh->cbSizeBits = LcbUncompressZeck(
pBase + bmh.cbOffsetBits,
(PBYTE) qbmh + qbmh->cbOffsetBits, bmh.cbSizeBits);
ASSERT(qbmh->cbSizeBits <= cbBits);
}
else
memmove(QFromQCb(qbmh, qbmh->cbOffsetBits),
pBase + bmh.cbOffsetBits,
bmh.cbSizeBits);
qbmh->fCompressed = BMH_COMPRESS_NONE; // bits are no longer compressed
// Copy extra info:
qbmh->cbOffsetExtra = qbmh->cbOffsetBits + qbmh->cbSizeBits;
if (bmh.cbSizeExtra)
memmove((PBYTE) qbmh + qbmh->cbOffsetExtra,
pBase + bmh.cbOffsetExtra, bmh.cbSizeExtra);
break;
case bmWmetafile:
qv = QVSkipQGA(qv, (&bmh.w.mf.mm));
bmh.w.mf.xExt = *(INT16 *) qv;
qv = (PBYTE) qv + sizeof(INT16);
bmh.w.mf.yExt = *(INT16 *) qv;
qv = (PBYTE) qv + sizeof(INT16);
qv = QVSkipQGB(qv, &cbUncompressedBits);
qv = QVSkipQGB(qv, (&bmh.cbSizeBits));
qv = QVSkipQGB(qv, (&bmh.cbSizeExtra));
bmh.cbOffsetBits = *((DWORD *) qv);
qv = (PBYTE) qv + sizeof(DWORD);
bmh.cbOffsetExtra = *((DWORD *) qv);
qv = (PBYTE) qv + sizeof(DWORD);
qbmh = (BMH*) lcCalloc(sizeof(BMH) + bmh.cbSizeExtra);
*qbmh = bmh;
qbmh->cbOffsetExtra = sizeof(BMH);
memmove((PBYTE) qbmh + qbmh->cbOffsetExtra,
pBase + bmh.cbOffsetExtra, bmh.cbSizeExtra);
qbmh->w.mf.hMF =
(HMETAFILE) lcMalloc(cbUncompressedBits);
if (qbmh->w.mf.hMF == NULL) {
lcFree(qbmh);
return hbmhOOM;
}
// REVIEW: 18-Sep-1993 [ralphw] -- Don't lock!
pDst = (PBYTE) qbmh->w.mf.hMF;
switch (bmh.fCompressed) {
case BMH_COMPRESS_NONE:
memmove(pDst, pBase + bmh.cbOffsetBits, bmh.cbSizeBits);
break;
case BMH_COMPRESS_30:
LcbUncompressHb(pBase + bmh.cbOffsetBits, pDst, bmh.cbSizeBits);
break;
case BMH_COMPRESS_ZECK:
LcbUncompressZeck(pBase + bmh.cbOffsetBits,
pDst, bmh.cbSizeBits);
break;
default:
ASSERT(FALSE);
}
// Invalidate this field, as the bits are in a separate handle:
qbmh->cbOffsetBits = 0L;
qbmh->cbSizeBits = cbUncompressedBits;
qbmh->fCompressed = BMH_COMPRESS_NONE;
break;
default:
return hbmhInvalid;
}
return (HBMH) qbmh;
}
/***************************************************************************
*
- Name: FreeHbmh
-
* Purpose:
* This function frees a bitmap handle, whether it was created in
* FWritePbitmap() or HbmhExpandQv(). In the first case, metafile
* bits will be stored at the end of the bitmap handle, while in
* the second case, they will be stored in a separate handle.
*
* Arguments:
* hbmh -- handle to a bitmap.
*
* Returns:
* nothing.
*
***************************************************************************/
void STDCALL FreeHbmh(PBMH qbmh)
{
if (qbmh && qbmh != hbmhInvalid) {
// The bmh has not been discarded.
if (qbmh->bmFormat == bmWmetafile && qbmh->cbOffsetBits == 0) {
// Get rid of the current description of the metafile.
if (qbmh->w.mf.hMF != NULL)
lcFree(qbmh->w.mf.hMF);
}
lcFree(qbmh);
}
}
/***************************************************************************
*
- Name RleCompress
-
* Purpose
* Compresses bitmap bits using RLE -- used when zeck compression is off
*
* Arguments
* pbSrc: pointer to source bits.
* pbDest: pointer to destination bits.
* cbSrc: Number of bytes in source.
*
* Returns
* Number of bytes in the destination. Guaranteed not to be
* more than 128/127 times cbSrc.
*
***************************************************************************/
#define GRIND_UPDATE 1024 // when to update grinder
int STDCALL RleCompress(PBYTE pbSrc, PBYTE pbDest, int cbSrc)
{
int cbRun, cb;
BYTE ch;
cGrind = 0;
PBYTE pbStart = pbDest;
while (cbSrc > 0) {
if (++cGrind == GRIND_UPDATE) {
cGrind = 0;
doGrind();
}
// Find next run of dissimilar bytes:
cbRun = 0;
if (cbSrc <= 2)
cbRun = cbSrc;
else {
while (pbSrc[cbRun] != pbSrc[cbRun + 1] ||
pbSrc[cbRun] != pbSrc[cbRun + 2])
if (++cbRun >= cbSrc - 2) {
cbRun = cbSrc;
break;
}
}
cbSrc -= cbRun;
// Output run of dissimilar bytes:
while (cbRun > 0) {
cb = MIN(cbRun, MAX_RUN);
*pbDest++ = ((BYTE) cb) | fRLEBit;
cbRun -= cb;
while (cb-- > 0)
*pbDest++ = *pbSrc++;
}
if (cbSrc == 0)
break;
// Find next run of identical bytes:
ch = *pbSrc;
cbRun = 1;
while (cbRun < cbSrc && ch == pbSrc[cbRun])
cbRun++;
cbSrc -= cbRun;
pbSrc += cbRun;
// Output run of identical bytes:
while (cbRun > 0) {
cb = MIN(cbRun, MAX_RUN);
*pbDest++ = (BYTE) cb;
*pbDest++ = ch;
cbRun -= cb;
}
}
return (int) (pbDest - pbStart);
}
/***************************************************************************
*
- Name LcbOldUncompressHb
-
* Purpose
* This function is used only to decompress Help 2.5 bitmaps.
*
* Arguments
* pbSrc: Huge pointer to source bits.
* pbDest: Huge pointer to beginning of destination buffer.
* cbSrc: Number of compressed bytes in source.
* cbDest: Size of destination buffer.
*
* Returns
* Actual number of bytes copied to destination buffer, or -1 if
* buffer is too small.
*
* +++
*
* Notes
*
***************************************************************************/
int pascal LcbOldUncompressHb(PBYTE pbSrc, PBYTE pbDest,
int cbSrc, int cbDest)
{
PBYTE pbStart;
WORD cbRun;
BYTE ch;
// Move pointers to the end of the buffers:
pbSrc += cbSrc;
pbDest += cbDest;
pbStart = pbDest;
while (cbSrc-- > 0) {
cbRun = *(--pbSrc);
cbDest -= (cbRun & ~fRLEBit);
if (cbDest < 0)
return -1;
if (cbRun & fRLEBit) {
cbRun -= fRLEBit;
cbSrc -= cbRun;
while (cbRun-- > 0)
*(--pbDest) = *(--pbSrc);
}
else {
ch = *(--pbSrc);
while (cbRun-- > 0)
*(--pbDest) = ch;
cbSrc--;
}
}
return (int) pbStart - (int) pbDest;
}
/***************************************************************************
*
- Name LcbUncompressHb
-
* Purpose
* Decompresses the bits in pbSrc.
*
* Arguments
* pbSrc: Huge pointer to compressed bits.
* pbDest: Buffer to copy decompressed bits to.
* cbSrc: Number of bytes in pbSrc.
*
* Returns
* Number of bytes copied to pbDest. This can only be used for
* real mode error checking, as the maximum size of pbDest must
* be determined before decompression.
*
* +++
*
* Notes
*
***************************************************************************/
static int STDCALL LcbUncompressHb(PBYTE pbSrc, PBYTE pbDest, int cbSrc)
{
PBYTE pbStart;
WORD cbRun;
BYTE ch;
pbStart = pbDest;
while (cbSrc-- > 0) {
cbRun = *pbSrc++;
if (cbRun & fRLEBit) {
cbRun -= fRLEBit;
cbSrc -= cbRun;
while (cbRun-- > 0)
*pbDest++ = *pbSrc++;
}
else {
ch = *pbSrc++;
while (cbRun-- > 0)
*pbDest++ = ch;
cbSrc--;
}
}
return (int) (pbDest - pbStart);
}