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.
|
|
#include "precomp.h"
#pragma hdrstop
/*********************************************************************/ /***** Common Library Component - Context Handling Routines 1 ********/ /*********************************************************************/
//
// Global variables
//
PINFCONTEXT pContextTop = NULL; PINFCONTEXT pContextBottom = NULL; PINFPERMINFO pInfPermInfoHead = NULL; PINFPERMINFO pInfPermInfoTail = NULL; PPARSED_INF pParsedInfCache = NULL; INT ParsedInfCached = 0;
//
// Maximum number of parsed INFs that we keep in the cache
//
#define INF_CACHE_THRESHOLD 4
/*
** Purpose: ** Pushes INF context onto stack ** ** Arguments: ** Context to push ** ** Returns: ** True if pushed. ** ** **************************************************************************/ BOOL APIENTRY PushContext( PINFCONTEXT pContext ) {
SZ szHelpContext; BOOL fOkay = fTrue;
//
// Set the per-context information
//
if ( pContextTop ) {
if ( pContextTop->szHelpFile ) { while ((pContext->szHelpFile = SzDupl(pContextTop->szHelpFile )) == (SZ)NULL) { if (!FHandleOOM(hWndShell)) { pContext->szHelpFile = NULL; return fFalse; } } } else { pContext->szHelpFile = NULL; }
pContext->pseflHead = NULL; pContext->dwLowContext = pContextTop->dwLowContext; pContext->dwHighContext = pContextTop->dwHighContext; pContext->dwHelpIndex = pContextTop->dwHelpIndex; pContext->bHelpIsIndexed = pContextTop->bHelpIsIndexed; szHelpContext = SzFindSymbolValueInSymTab("HelpContext");
} else {
pContext->pseflHead = NULL; pContext->szHelpFile = NULL; pContext->dwLowContext = 0; pContext->dwHighContext = 0; pContext->dwHelpIndex = 0; pContext->bHelpIsIndexed = fFalse; szHelpContext = NULL; }
//
// Allocate the local symbol table
//
if ( !(pContext->SymTab = SymTabAlloc()) ) { if ( pContext->szHelpFile ) { SFree( pContext->szHelpFile ); pContext->szHelpFile = NULL; }
return fFalse; }
//
// Push context onto stack
//
pContext->pNext = pContextTop; pContextTop = pContext;
if ( !pContextBottom ) { pContextBottom = pContextTop; }
//
// Add to the symbol table any per-context values.
//
if ( szHelpContext ) { while (!FAddSymbolValueToSymTab("HelpContext", szHelpContext)) { if (!FHandleOOM(hWndShell)) { PopContext(); fOkay = fFalse; break; } } }
while (!FAddSymbolValueToSymTab("$ShellCode", "0")) { if (!FHandleOOM(hWndShell)) { PopContext(); fOkay = fFalse; break; } }
return fOkay; }
/*
** Purpose: ** Pops a context off the stack ** ** Arguments: ** none ** ** Returns: ** Popped context ** ** **************************************************************************/ PINFCONTEXT APIENTRY PopContext( VOID ) { PINFCONTEXT pContext = pContextTop;
pContextTop = pContext->pNext;
return pContext; }
/*
** Purpose: ** Frees memory of a context ** ** Arguments: ** Pointer to context ** ** Returns: ** nothing ** ** **************************************************************************/ VOID APIENTRY FreeContext( PINFCONTEXT pContext ) { //
// Free per-context information
//
if ( pContext->pseflHead ) {
PSEFL psefl = pContext->pseflHead; PSEFL pseflNext;
while ( psefl ) { pseflNext = psefl->pseflNext; FFreePsefl(psefl); psefl = pseflNext; } }
if ( pContext->szHelpFile ) { SFree( pContext->szHelpFile ); }
if ( pContext->szShlScriptSection ) { SFree( pContext->szShlScriptSection ); }
//
// Free local symbol table
//
FFreeSymTab( pContext->SymTab );
//
// Free context
//
SFree( pContext ); }
/*
** Purpose: ** Given an INF name, returns a pointer to the corresponding ** INF permanent information block. It creates a new permanent ** information block if none exists for the name provided. ** ** Arguments: ** INF name ** ** Returns: ** Pointer to INF permanent information block. ** ** **************************************************************************/ PINFPERMINFO APIENTRY NameToInfPermInfo( SZ szName , BOOL AllocIfNotPresent) { PINFPERMINFO pInfo;
if ( pInfPermInfoHead ) {
pInfo = pInfPermInfoHead;
while ( pInfo ) {
if (CrcStringCompare( szName, pInfo->szName ) == crcEqual) { return pInfo; } pInfo = pInfo->pNext; } }
if( AllocIfNotPresent ) { return AddInfPermInfo( szName ); } else { return (PINFPERMINFO)NULL; } }
/*
** Purpose: ** Adds a new INF permanent information block with the given INF ** name. ** ** Arguments: ** INF name ** ** Returns: ** Pointer to the INF permanent information block. ** ** **************************************************************************/ PINFPERMINFO APIENTRY AddInfPermInfo( SZ szName ) {
PINFPERMINFO pInfo; SZ szInfName;
if ( (pInfo = (PINFPERMINFO)SAlloc( sizeof( INFPERMINFO ) )) != NULL ) {
if ( (szInfName = (SZ)SAlloc( lstrlen( szName ) + 1 )) != NULL) {
strcpy( szInfName, szName );
pInfo->szName = szInfName; pInfo->psdleHead = NULL; pInfo->psdleCur = NULL; pInfo->pclnHead = NULL; pInfo->ppclnTail = &(pInfo->pclnHead); pInfo->pNext = NULL; pInfo->pstfHead = NULL;
if ( pInfPermInfoTail ) {
pInfo->InfId = pInfPermInfoTail->InfId+1; pInfPermInfoTail->pNext = pInfo; pInfPermInfoTail = pInfo;
} else {
pInfo->InfId = 0; pInfPermInfoHead = pInfPermInfoTail = pInfo; }
return pInfo; }
SFree( pInfo); }
return NULL; }
/*
** Purpose: ** Given the path of an INF file, obtains the INF name (i.e. the ** name of the file without extension. ** ** Arguments: ** Path to inf file ** Pointer to buffer where the INF name will be stored ** ** Returns: ** TRUE if name obtained. ** ** **************************************************************************/ BOOL APIENTRY PathToInfName( SZ szPath, SZ szName ) { PCHAR p,r,q;
p = r = szPath + strlen(szPath) - 1; while ( (p >= szPath) && (*p != '\\') && (*p != ':') ) { p--; } p++; q = p; while ( (q <= r) && (*q != '.') && (*q != '\0') ) { q++; } memcpy( szName, p, (size_t)(q-p) ); szName[q-p] = '\0'; SzStrUpper( szName );
return fTrue;
}
/*
** Purpose: ** Determines what symbol table to use for a given symbol ** ** Arguments: ** szSymbol: non-NULL, non-empty zero terminated string containing ** the value of the symbol to be searched for. ** ** ** ** Syntax: ** ** VarName := [![<Modifier>:]]Name ** ** Modifier := L | G | P | S ** ** ** L = Local (this context) ** G = Global (top context) ** P = Parent (parent context) ** S = Static (INF temp. info) ** ** ** ** Returns: ** Pointer to the context in which to look for the symbol ** ** **************************************************************************/ PSYMTAB APIENTRY PInfSymTabFind( SZ szSymbol, SZ *szRealSymbol ) {
SZ p; PSYMTAB pSymTab = NULL;
p = szSymbol;
if ( p && *p != '\0' ) {
if ( *p == '!' ) {
p++;
if ( (strlen(p) > 2) && (*(p+1) == ':') ) {
switch ( *p ) {
case 'G': case 'g': //
// Global
//
pSymTab = pGlobalContext()->SymTab; *szRealSymbol = p+2; break;
case 'L': case 'l': //
// Local
//
pSymTab = pLocalContext()->SymTab; *szRealSymbol = p+2; break;
case 'P': case 'p': //
// Parent
//
pSymTab = pLocalContext()->pNext->SymTab; *szRealSymbol = p+2; break;
case 'S': case 's': //
// Static
//
pSymTab = pLocalContext()->pInfTempInfo->SymTab; *szRealSymbol = p+2; break;
default: //
// Invalid
//
pSymTab = NULL; *szRealSymbol = NULL; break; }
} else {
//
// Global variable
//
pSymTab = pGlobalContext()->SymTab; *szRealSymbol = p;
}
} else {
//
// Local variable
//
pSymTab = pLocalContext()->SymTab; *szRealSymbol = p;
} }
return pSymTab; }
PPARSED_INF APIENTRY ParsedInfAlloc( PINFPERMINFO pInfPermInfo ) { PPARSED_INF pParsedInf = NULL;
//
// If the cache is not empty, see if this INF is already in
// the cache.
//
if ( ParsedInfCached > 0 ) {
pParsedInf = pParsedInfCache;
while ( pParsedInf ) {
if ( pParsedInf->pInfPermInfo == pInfPermInfo ) {
//
// Found the parsed INF in the cache.
// Take it out of the cache.
//
if (pParsedInf->pPrev) { (pParsedInf->pPrev)->pNext = pParsedInf->pNext; }
if (pParsedInf->pNext) { (pParsedInf->pNext)->pPrev = pParsedInf->pPrev; }
if ( pParsedInfCache == pParsedInf ) { pParsedInfCache = pParsedInf->pNext; }
pParsedInf->pPrev = NULL; pParsedInf->pNext = NULL;
ParsedInfCached--;
break; }
pParsedInf = pParsedInf->pNext; } }
//
// If the parsed INF was not in the cache, we allocate space for a
// new one.
//
if ( pParsedInf == NULL ) {
if ( pParsedInf = (PPARSED_INF)SAlloc( sizeof( PARSED_INF ) ) ) {
pParsedInf->pPrev = NULL; pParsedInf->pNext = NULL; pParsedInf->pInfPermInfo = pInfPermInfo; pParsedInf->MasterLineArray = NULL; pParsedInf->MasterLineCount = 0; pParsedInf->MasterFile = NULL; pParsedInf->MasterFileSize = 0; } }
return pParsedInf; }
extern BOOL APIENTRY FFreeParsedInf( PPARSED_INF pParsedInf ) { PPARSED_INF pInf;
//
// We will put this Parsed INF in the cache. If the number of cached
// INFs is above the threshold we will free the least recently used
// one.
//
if (pParsedInfCache) { pParsedInfCache->pPrev = pParsedInf; } pParsedInf->pNext = pParsedInfCache; pParsedInfCache = pParsedInf;
if ( ParsedInfCached++ >= INF_CACHE_THRESHOLD ) {
//
// There are too many INFs in the cache, look for the last one
// and free it.
//
pInf = pParsedInf;
while ( pInf->pNext ) { pInf = pInf->pNext; }
if (pInf->pPrev) { (pInf->pPrev)->pNext = pInf->pNext; }
if (pInf->pNext) { (pInf->pNext)->pPrev = pInf->pPrev; }
if ( pParsedInfCache == pInf ) { pParsedInfCache = pInf->pNext; }
pInf->pPrev = NULL; pInf->pNext = NULL;
ParsedInfCached--;
if ( pInf->MasterLineArray ) { SFree( pInf->MasterLineArray); }
if ( pInf->MasterFile ) { SFree( pInf->MasterFile ); }
SFree( pInf);
}
return TRUE; }
extern BOOL APIENTRY FFlushInfParsedInfo( SZ szInfName ) { CHAR szName[cchlFullPathMax]; PINFPERMINFO pPermInfo; PPARSED_INF pInf;
//
// Convert the inf path passed in to an inf name
//
PathToInfName( szInfName, szName );
//
// Find the perminfo for this inf. If none exists then return
//
if( !( pPermInfo = NameToInfPermInfo( szName , FALSE ) ) ) { return ( TRUE ); }
//
// Go through the parsed inf cache, see if inf exists in the cache.
// if it does, flush it.
//
if (pParsedInfCache) { pInf = pParsedInfCache; while ( pInf ) { if( pInf->pInfPermInfo == pPermInfo ) {
if (pInf->pPrev) { (pInf->pPrev)->pNext = pInf->pNext; }
if (pInf->pNext) { (pInf->pNext)->pPrev = pInf->pPrev; }
if ( pParsedInfCache == pInf ) { pParsedInfCache = pInf->pNext; }
pInf->pPrev = NULL; pInf->pNext = NULL;
ParsedInfCached--;
if ( pInf->MasterLineArray ) { SFree( pInf->MasterLineArray ); }
if ( pInf->MasterFile ) { SFree( pInf->MasterFile ); }
SFree( pInf ); break; }
pInf = pInf->pNext; }
} return ( TRUE ); }
|