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.
 
 
 
 
 
 

416 lines
10 KiB

/*****************************************************************************
* *
* DELAY.CPP *
* *
* Copyright (C) Microsoft Corporation 1990-1994 *
* All Rights reserved. *
* *
******************************************************************************
* *
* Module Intent *
* *
* This module handles delayed address processing. It is required because *
* physical addresses are not known until after a 16K block can be *
* processed with Zeck compression. Instead of writing addresses out *
* when they are encountered, the idfcp is recorded with a DelayExecution() *
* call. Then, after a block gets Zeck compressed and the addresses are *
* known, we go through this information and write out all the correct *
* addresses. *
*****************************************************************************/
#include "stdafx.h"
#pragma hdrstop
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*****************************************************************************
* *
* Defines *
* *
*****************************************************************************/
// Maximum value of an object offset
const int MAX_OBJRG = (1 << CBITS_OBJOFF);
/*****************************************************************************
* *
* Typedefs *
* *
*****************************************************************************/
// Delay Execution: Browse info
typedef struct {
PSTR szMajor, szMinor;
IDFCP idfcp;
} DEBROWSE, * QDEBROWSE;
// Delay Execution: Title info
typedef struct {
PSTR szTitle;
IDFCP idfcp;
} DETITLE, * LPDETITLE;
// Delay Execution: Context string info
typedef struct {
HASH hash;
IDFCP idfcp;
WORD wObjrg;
} DECONTEXT, * QDECONTEXT;
// Delay Execution: Keyword info
typedef struct {
CTable* ptbl;
KT chKey;
IDFCP idfcp;
WORD wObjrg;
} DEKEYWORD, * LPDEKEYWORD;
/*****************************************************************************
* *
* Static Variables *
* *
*****************************************************************************/
static CDrg* pdrgBrowse;
static CDrg* pdrgTitle;
static CDrg* pdrgContext;
static CDrg* pdrgKeyword;
static CDrg* pdrgWObjrg; // DRG of wObjrg in each FCP
static WORD wObjrgTotal;
static IDFCP _idfcpFirst; // id of first FCP in above DRG
/*****************************************************************************
* *
* Prototypes *
* *
*****************************************************************************/
void STDCALL FInitDelayExecution(void)
{
_idfcpFirst = FIRST_IDFCP; // REVIEW;
wObjrgTotal = 0;
pdrgTitle = new CDrg(sizeof(DETITLE), 100, 100);
pdrgContext = new CDrg(sizeof(DECONTEXT), 100, 100);
pdrgKeyword = new CDrg(sizeof(DEKEYWORD), 100, 100);
pdrgWObjrg = new CDrg(sizeof(WORD), 100, 100);
}
void STDCALL EndDelayExecution(void)
{
if (pdrgBrowse) {
delete pdrgBrowse;
pdrgBrowse = NULL;
}
// Use pdrgTitle to determine if any were created
if (pdrgTitle) {
delete pdrgWObjrg;
delete pdrgKeyword;
delete pdrgContext;
delete pdrgTitle;
pdrgTitle = NULL;
pdrgContext = NULL;
pdrgKeyword = NULL;
pdrgWObjrg = NULL;
}
}
/***************************************************************************
*
- Name: RcRegisterWObjrg
-
* Purpose:
* Used to register the number of object regions in every
* FCP, in order to calculate cumulative object offsets when
* determining physical addresses.
*
* Arguments:
* idfcp: id of FCP
* wObjrg: Number of object regions in FCP
*
* Returns:
* Return code:
* RC_Success: success
* RC_Failure: Current FCP overflows object region count. All
* FCPs up to but not including this one must be
* flushed.
* RC_TooBig: Current FCP overflows object region count all
* by itself. Paragraph contains too many objects
* and cannot be compiled.
* RC_OutOfMemory: Out of memory.
*
* Globals:
* Uses the global wObjrgTotal to accumulate current total of
* object offsets.
*
* +++
*
* Notes:
*
***************************************************************************/
RC_TYPE STDCALL RcRegisterWObjrg(IDFCP idfcp, UINT wObjrg)
{
Unreferenced(idfcp); // in non-debug build
// This assert happens in dolphin\crt.hpj -- but what does it mean?
// ASSERT(_idfcpFirst + pdrgWObjrg->Count() == idfcp);
/*
* REVIEW: This assert is valid because this condition is checked in
* RcOutputCommand, and outputting an end of text command is the last
* thing that ever happens to any FCP. However, the constants they check
* against are declared differently, although they currently evaluate to
* the same thing.
*/
ASSERT(wObjrg <= MAX_OBJRG);
pdrgWObjrg->Add(&wObjrg);
wObjrgTotal += wObjrg;
if (wObjrgTotal > MAX_OBJRG)
return RC_Failure;
return RC_Success;
}
/***************************************************************************
*
- Name: FKeepFlushing
-
* Purpose:
* This function is called to flush the zeck buffer until the
* total object region count is low enough to proceed.
*
* Arguments:
* none
*
* Returns:
* TRUE if the current object region total is still too large.
*
* Globals Used:
* wObjrgTotal
*
***************************************************************************/
BOOL STDCALL FKeepFlushing(void)
{
return (wObjrgTotal > MAX_OBJRG);
}
void STDCALL FDelayExecutionBrowse(PSTR szMajor, PSTR szMinor,
IDFCP idfcp)
{
DEBROWSE debrowse;
if (!pdrgBrowse)
pdrgBrowse = new CDrg(sizeof(DEBROWSE), 100, 100);
if (strlen(szMajor) >= 50) {
VReportError(HCERR_MAJOR_BROWSE_TOO_BIG, &errHpj, szMajor);
szMajor[50] = '\0';
}
if (strlen(szMinor) >= 50) {
VReportError(HCERR_MINOR_BROWSE_TOO_BIG, &errHpj, szMinor);
szMinor[50] = '\0';
}
debrowse.szMajor = lcStrDup(szMajor);
debrowse.szMinor = lcStrDup(szMinor);
debrowse.idfcp = idfcp;
pdrgBrowse->Add(&debrowse);
}
void STDCALL FDelayExecutionTitle(PCSTR szTitle, IDFCP idfcp)
{
DETITLE detitle;
detitle.szTitle = lcStrDup(szTitle);
detitle.idfcp = idfcp;
pdrgTitle->Add(&detitle);
}
void STDCALL FDelayExecutionContext(HASH hash, IDFCP idfcp, UINT wObjrg)
{
DECONTEXT decontext;
decontext.hash = hash;
decontext.idfcp = idfcp;
decontext.wObjrg = wObjrg;
pdrgContext->Add(&decontext);
}
void STDCALL FDelayExecutionKeyword(CTable* ptbl, KT chKey, IDFCP idfcp,
UINT wObjrg)
{
DEKEYWORD dekeyword;
dekeyword.ptbl = ptbl;
dekeyword.chKey = chKey;
dekeyword.idfcp = idfcp;
dekeyword.wObjrg = wObjrg;
pdrgKeyword->Add(&dekeyword);
}
RC_TYPE STDCALL RcExecuteDelayedExecution(DWORD ulBlknum, IDFCP idfcpFirst,
IDFCP idfcpLast, BROWSE_CALLBACK pfnBrowseCallback)
{
WORD * rgwOffset;
WORD iwOffset;
PA pa;
RC_TYPE rc;
LPDETITLE lpDeTitle;
ASSERT(_idfcpFirst == idfcpFirst);
// REVIEW ! ! REVIEW ! !
if (idfcpFirst > idfcpLast)
return RC_Success;
// First, set up addresses:
pa.blknum = ulBlknum;
ASSERT((idfcpLast - idfcpFirst + 1) * sizeof(WORD) < 63L * 1024L);
CMem gmem((idfcpLast - idfcpFirst + 1) * sizeof(WORD));
rgwOffset = (WORD *) gmem.pb;
ASSERT((IDFCP) pdrgWObjrg->Count() > idfcpLast - idfcpFirst);
rgwOffset[0] = 0;
for (iwOffset = 1; (IDFCP) iwOffset <= idfcpLast - idfcpFirst;
++iwOffset) {
rgwOffset[iwOffset] = rgwOffset[iwOffset - 1] +
*(WORD*) pdrgWObjrg->GetBasePtr();
// This call removes the iwOffset-1 element from pdrgWObjrg
pdrgWObjrg->RemoveFirst();
}
/*
* Subtract from wObjrgTotal all the registered object region counts we
* have removed.
*/
wObjrgTotal -= rgwOffset[idfcpLast - idfcpFirst];
// Now we remove the wObjrg of the last FCP in this block from pdrgWObjrg
wObjrgTotal -= *(WORD*) pdrgWObjrg->GetBasePtr();
pdrgWObjrg->RemoveFirst();
_idfcpFirst = idfcpLast + 1;
if (pdrgBrowse) {
ASSERT(ptblBrowse);
if (!fBrowseButtonSet)
VReportError(HCERR_NO_BROWSE_BUTTONS, &errHpj);
// REVIEW: This is not very efficient
QDEBROWSE lpDeBrowse;
while (pdrgBrowse->Count() > 0 &&
(lpDeBrowse = (QDEBROWSE) pdrgBrowse->GetBasePtr())->idfcp <=
idfcpLast) {
int iBitdex;
FCL fcl = (*pfnBrowseCallback) (lpDeBrowse->idfcp, &iBitdex);
pa.objoff = rgwOffset[lpDeBrowse->idfcp - idfcpFirst];
// Print prev/next codes into file:
// szMajor : szMinor : fcl fixup pos : Zeck compression bit dex : PA
char szBuf[200];
ASSERT(strlen(lpDeBrowse->szMajor) + strlen(lpDeBrowse->szMinor) < 170);
wsprintf(szBuf, "%s:%s:%8lX:%8lX:%8lX\n",
lpDeBrowse->szMajor,
lpDeBrowse->szMinor, fcl, iBitdex, *(int *) (&pa));
if (!ptblBrowse->AddString(szBuf))
OOM(); // does not return
lcFree(lpDeBrowse->szMajor);
lcFree(lpDeBrowse->szMinor);
pdrgBrowse->RemoveFirst();
}
}
while (pdrgTitle->Count() > 0 &&
(lpDeTitle = (LPDETITLE) pdrgTitle->GetBasePtr())->idfcp <= idfcpLast) {
pa.objoff = rgwOffset[lpDeTitle->idfcp - idfcpFirst];
#ifdef _DEBUG
{
// Verify that things are sorted correctly. If they aren't,
// RcFillHbt() will create a broken btree.
static ADDR addrLast = addrNil;
ASSERT(addrLast == addrNil || addrLast < *(ADDR *) &pa);
addrLast = *(ADDR *) &pa;
}
#endif // DEBUG
if ((rc = RcFillHbt(fmsg.qbthrTTL, (KEY) &pa, lpDeTitle->szTitle))
!= RC_Success)
return rc;
ASSERT(lpDeTitle->szTitle);
lcFree(lpDeTitle->szTitle);
pdrgTitle->RemoveFirst();
}
QDECONTEXT qdectx;
while (pdrgContext->Count() > 0 &&
(qdectx = (QDECONTEXT) pdrgContext->GetBasePtr())->idfcp <=
idfcpLast) {
pa.objoff = rgwOffset[qdectx->idfcp - idfcpFirst] + qdectx->wObjrg;
if ((rc = RcInsertHbt(fmsg.qbthrCtx, (KEY) &qdectx->hash,
(LPVOID) &pa)) != RC_Success && rc != RC_Exists)
return rc;
pdrgContext->RemoveFirst();
}
LPDEKEYWORD pDeKeyword;
while (pdrgKeyword->Count() > 0 &&
(pDeKeyword = (LPDEKEYWORD) pdrgKeyword->GetBasePtr())->idfcp <=
idfcpLast) {
KWD kwd;
pa.objoff = rgwOffset[pDeKeyword->idfcp - idfcpFirst] +
pDeKeyword->wObjrg;
kwd.addr = *(ADDR *)&pa;
for (int iszKey = 1; iszKey <= pDeKeyword->ptbl->CountStrings();
++iszKey) {
kwd.szKey = pDeKeyword->ptbl->GetPointer(iszKey);
RcWritePkwd(&kwd, pDeKeyword->chKey);
}
delete pDeKeyword->ptbl;
pdrgKeyword->RemoveFirst();
}
return RC_Success;
}