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.
 
 
 
 
 
 

672 lines
17 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
fcache.cxx
Abstract:
This module supports functions for file caching for servers
Author:
Murali R. Krishnan ( MuraliK ) 11-Oct-1995
Environment:
Win32 Apps
Project:
Internet Services Common DLL
Functions Exported:
Revision History:
Obtained from old inetsvcs.dll
--*/
/************************************************************
* Include Headers
************************************************************/
# include <tcpdllp.hxx>
# include <tssched.hxx>
# include "tsunami.hxx"
# include "tsvcinfo.hxx"
#ifdef JAPAN
#include <festrcnv.h>
#endif
# include "inetreg.h"
//
// Prototypes
//
VOID
CacheScavenger(
VOID * pContext
);
//
// Globals
//
//
// The TTL to scavenge the cache and the id of the scheduled work item of the
// next scheduled scavenge
//
DWORD g_cmsecObjectCacheTTL = (INETA_DEF_OBJECT_CACHE_TTL * 1000);
DWORD g_dwObjectCacheCookie = 0;
/************************************************************
* Functions
************************************************************/
#define FILE_DEMUX 42
BOOL
CheckOutCachedFile(
IN const CHAR * pchFile,
IN TSVC_CACHE * pTsvcCache,
IN HANDLE hToken,
OUT BYTE * * ppbData,
OUT DWORD * pcbData,
IN BOOL fIsAnonymous,
#ifdef JAPAN
OUT PCACHE_FILE_INFO pCacheFileInfo,
IN int nCharset
#else
OUT PCACHE_FILE_INFO pCacheFileInfo
#endif
)
/*++
Description:
Attempts to retrieve the passed file from the cache. If it's not
cached, then we read the file and add it to the cache.
Arguments:
pchFile - Fully qualified file to retrieve
pTsvcCache - Cache object to charge memory against
hToken - Impersonation token to open the file with
pcbData - Receives pointer to first byte of data, used as handle to
free data
pcbSize - Size of output buffer
pCacheFileInfo - File cache information
#ifdef JAPAN
nCharset - Charset (if this isn't SJIS, we convert it to SJIS
before Check-In)
#endif
Returns:
TRUE if successful, FALSE otherwise
Notes:
The file is extended by two bytes and is appended with two zero bytes,
thus callers are guaranteed of a zero terminated text file.
--*/
{
TS_OPEN_FILE_INFO * pFile = NULL;
DWORD cbLow, cbHigh;
BYTE * pbData = NULL;
OVERLAPPED Overlapped;
BOOL fCached = fIsAnonymous; // Non-anon will never be cached
#ifdef JAPAN
BYTE * pbBuff = NULL;
int cbSJISSize;
#endif
//
// Is the file already in the cache?
//
if ( !fIsAnonymous ||
!TsCheckOutCachedBlob( *pTsvcCache,
pchFile,
FILE_DEMUX,
(VOID **) &pbData,
pcbData ))
{
//
// The file isn't in the cache so open the file and get its size
//
fCached = FALSE;
if ( !(pFile = TsCreateFile( *pTsvcCache,
pchFile,
hToken,
(fIsAnonymous ? TS_CACHING_DESIRED :
0) )) ||
!pFile->QuerySize( &cbLow, &cbHigh ))
{
goto ErrorExit;
}
//
// Limit the file size to 128k
//
if ( cbHigh || cbLow > 131092L )
{
SetLastError( ERROR_NOT_SUPPORTED );
goto ErrorExit;
}
#ifdef JAPAN
if ( CODE_JPN_JIS == nCharset || CODE_JPN_EUC == nCharset )
{
if ( !( pbBuff = pbData = (BYTE *)LocalAlloc( LPTR, cbLow ) ) )
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY);
goto ErrorExit;
}
}
else
#endif // JAPAN
if ( !TsAllocate( *pTsvcCache,
cbLow + sizeof(WCHAR),
(VOID **) &pbData ))
{
goto ErrorExit;
}
#ifndef CHICAGO
//
// Read the file data
//
Overlapped.Offset = 0;
Overlapped.OffsetHigh = 0;
Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( !Overlapped.hEvent )
goto ErrorExit;
if ( !ReadFile( pFile->QueryFileHandle(),
pbData,
cbLow,
pcbData,
&Overlapped ))
{
if ( GetLastError() != ERROR_IO_PENDING )
{
CloseHandle( Overlapped.hEvent );
goto ErrorExit;
}
}
if ( !GetOverlappedResult( pFile->QueryFileHandle(),
&Overlapped,
pcbData,
TRUE ))
{
CloseHandle( Overlapped.hEvent );
goto ErrorExit;
}
CloseHandle( Overlapped.hEvent );
#else
//
// No async file i/o for win95
//
if ( !ReadFile( pFile->QueryFileHandle(),
pbData,
cbLow,
pcbData,
NULL ))
{
goto ErrorExit;
}
#endif
#ifdef JAPAN
if ( CODE_JPN_JIS == nCharset || CODE_JPN_EUC == nCharset )
{
pbData = NULL;
//
// get the length after conversion
//
cbSJISSize = UNIX_to_PC( 932,
nCharset,
pbBuff,
*pcbData,
NULL,
0 );
DBG_ASSERT( cbSJISSize <= (int)cbLow );
if ( !TsAllocate( *pTsvcCache,
cbSJISSize + sizeof(WCHAR),
(VOID **) &pbData ))
{
goto ErrorExit;
}
//
// conversion
//
UNIX_to_PC( 932,
nCharset,
pbBuff,
*pcbData,
pbData,
cbSJISSize );
*pcbData = cbLow = cbSJISSize;
}
#endif // JAPAN
DBG_REQUIRE( TsCloseHandle( *pTsvcCache,
pFile ));
pFile = NULL;
DBG_ASSERT( *pcbData <= cbLow );
//
// Zero terminate the file for both ANSI and Unicode files
//
*((WCHAR UNALIGNED *)(pbData + cbLow)) = L'\0';
*pcbData += sizeof(WCHAR);
//
// Add this blob to the cache manager and check it out, if it fails,
// we just free it below
//
if ( fIsAnonymous &&
TsCacheDirectoryBlob( *pTsvcCache,
pchFile,
FILE_DEMUX,
pbData,
*pcbData,
TRUE ) )
{
fCached = TRUE;
}
}
pCacheFileInfo->pbData = *ppbData = pbData;
pCacheFileInfo->dwCacheFlags = fCached;
#ifdef JAPAN
if ( pbBuff )
{
LocalFree( pbBuff );
}
#endif
return TRUE;
ErrorExit:
if ( pFile )
{
DBG_REQUIRE( TsCloseHandle( *pTsvcCache,
pFile ));
}
#ifdef JAPAN
if ( pbBuff )
{
if ( pbBuff == pbData )
{
pbData = NULL;
}
LocalFree( pbBuff );
}
#endif
if ( pbData )
{
if ( fCached )
{
DBG_REQUIRE( TsCheckInCachedBlob( *pTsvcCache,
pbData ));
}
else
{
DBG_REQUIRE( TsFree( *pTsvcCache,
pbData ));
}
}
return FALSE;
}
BOOL
CheckInCachedFile(
IN TSVC_CACHE * pTsvcCache,
IN PCACHE_FILE_INFO pCacheFileInfo
)
/*++
Description:
Checks in or frees a cached file
Arguments:
pTsvcCache - Cache object to charge memory against
pCacheFileInfo - Pointer to file cache information
Returns:
TRUE if successful, FALSE otherwise
Notes:
--*/
{
BOOL fRet;
DBG_ASSERT( (pCacheFileInfo->dwCacheFlags == FALSE) || (
pCacheFileInfo->dwCacheFlags == TRUE) );
//
// If we cached the item, check it back in to the cache, otherwise
// free the associated memory
//
if ( pCacheFileInfo->dwCacheFlags )
{
DBG_REQUIRE( fRet = TsCheckInCachedBlob( *pTsvcCache,
pCacheFileInfo->pbData ));
}
else
{
DBG_REQUIRE( fRet = TsFree( *pTsvcCache,
pCacheFileInfo->pbData ));
}
return fRet;
}
BOOL
InitializeCacheScavenger(
VOID
)
/*++
Description:
This function kicks off the scheduled tsunami object cache scavenger
--*/
{
HKEY hkey;
//
// Schedule a scavenger to close all of the objects that haven't been
// referenced in the last ttl
//
if ( !RegOpenKeyEx( HKEY_LOCAL_MACHINE,
INETA_PARAMETERS_KEY,
0,
KEY_READ,
&hkey ))
{
g_cmsecObjectCacheTTL = ReadRegistryDword(
hkey,
INETA_OBJECT_CACHE_TTL,
0 );
//
// Don't schedule anything if the scavenger should be disabled
//
if ( g_cmsecObjectCacheTTL == 0xffffffff )
{
RegCloseKey( hkey );
return TRUE;
}
//
// The registry setting is in seconds, convert to milliseconds
//
g_cmsecObjectCacheTTL *= 1000;
//
// Supply the default if no value was specified
//
if ( !g_cmsecObjectCacheTTL )
{
g_cmsecObjectCacheTTL = INETA_DEF_OBJECT_CACHE_TTL * 1000;
}
RegCloseKey( hkey );
}
//
// Require a minimum of thirty seconds
//
g_cmsecObjectCacheTTL = max( g_cmsecObjectCacheTTL, 30 * 1000 );
g_dwObjectCacheCookie = ScheduleWorkItem(
(PFN_SCHED_CALLBACK) CacheScavenger,
NULL,
g_cmsecObjectCacheTTL );
if ( !g_dwObjectCacheCookie )
{
return FALSE;
}
return TRUE;
}
VOID
TerminateCacheScavenger(
VOID
)
{
if ( g_dwObjectCacheCookie )
{
RemoveWorkItem( g_dwObjectCacheCookie );
g_dwObjectCacheCookie = 0;
}
}
VOID
CacheScavenger(
VOID * pContext
)
{
g_dwObjectCacheCookie = 0;
//
// Tell tsunami to decrement the TTL on the cache items and remove
// anything that has timed out
//
TsFlushTimedOutCacheObjects();
//
// Schedule ourselves again at the next TTL
//
g_dwObjectCacheCookie = ScheduleWorkItem(
(PFN_SCHED_CALLBACK) CacheScavenger,
NULL,
g_cmsecObjectCacheTTL );
if ( !g_dwObjectCacheCookie )
{
DBGPRINTF(( DBG_CONTEXT,
"[CacheScavenger] ScheduleWorkItem failed, error %d, scavenging disabled\n",
GetLastError() ));
}
}
//
// Taken from NCSA HTTP and wwwlib.
//
// NOTE: These conform to RFC1113, which is slightly different then the Unix
// uuencode and uudecode!
//
const int _pr2six[256]={
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64
};
char _six2pr[64] = {
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/'
};
const int _pr2six64[256]={
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,64,64,64,64,64
};
char _six2pr64[64] = {
'`','!','"','#','$','%','&','\'','(',')','*','+',',',
'-','.','/','0','1','2','3','4','5','6','7','8','9',
':',';','<','=','>','?','@','A','B','C','D','E','F',
'G','H','I','J','K','L','M','N','O','P','Q','R','S',
'T','U','V','W','X','Y','Z','[','\\',']','^','_'
};
BOOL uudecode(char * bufcoded,
BUFFER * pbuffdecoded,
DWORD * pcbDecoded,
BOOL fBase64
)
{
int nbytesdecoded;
char *bufin = bufcoded;
unsigned char *bufout;
int nprbytes;
int *pr2six = (int*)(fBase64 ? _pr2six64 : _pr2six);
/* Strip leading whitespace. */
while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
/* Figure out how many characters are in the input buffer.
* If this would decode into more bytes than would fit into
* the output buffer, adjust the number of input bytes downwards.
*/
bufin = bufcoded;
while(pr2six[*(bufin++)] <= 63);
nprbytes = bufin - bufcoded - 1;
nbytesdecoded = ((nprbytes+3)/4) * 3;
if ( !pbuffdecoded->Resize( nbytesdecoded + 4 ))
return FALSE;
if ( pcbDecoded )
*pcbDecoded = nbytesdecoded;
bufout = (unsigned char *) pbuffdecoded->QueryPtr();
bufin = bufcoded;
while (nprbytes > 0) {
*(bufout++) =
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) =
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) =
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
if(nprbytes & 03) {
if(pr2six[bufin[-2]] > 63)
nbytesdecoded -= 2;
else
nbytesdecoded -= 1;
}
((CHAR *)pbuffdecoded->QueryPtr())[nbytesdecoded] = '\0';
return TRUE;
}
BOOL uuencode( BYTE * bufin,
DWORD nbytes,
BUFFER * pbuffEncoded,
BOOL fBase64 )
{
unsigned char *outptr;
unsigned int i;
char *six2pr = fBase64 ? _six2pr64 : _six2pr;
//
// Resize the buffer to 133% of the incoming data
//
if ( !pbuffEncoded->Resize( nbytes + ((nbytes + 3) / 3) + 4))
return FALSE;
outptr = (unsigned char *) pbuffEncoded->QueryPtr();
for (i=0; i<nbytes; i += 3) {
*(outptr++) = six2pr[*bufin >> 2]; /* c1 */
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; /*c2*/
*(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];/*c3*/
*(outptr++) = six2pr[bufin[2] & 077]; /* c4 */
bufin += 3;
}
/* If nbytes was not a multiple of 3, then we have encoded too
* many characters. Adjust appropriately.
*/
if(i == nbytes+1) {
/* There were only 2 bytes in that last group */
outptr[-1] = '=';
} else if(i == nbytes+2) {
/* There was only 1 byte in that last group */
outptr[-1] = '=';
outptr[-2] = '=';
}
*outptr = '\0';
return TRUE;
}
/************************ End of File ***********************/