Leaked source code of windows server 2003
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.
 
 
 
 
 
 

670 lines
17 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
cachglob.cxx
Abstract:
contains global variables and functions of urlcache
Author:
Madan Appiah (madana) 12-Dec-1994
Environment:
User Mode - Win32
Revision History:
--*/
#include <wininetp.h>
#include <cache.hxx>
// Typedef for GetFileAttributeEx function
typedef BOOL (WINAPI *PFNGETFILEATTREX)(LPCTSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
#ifdef unix
#include <flock.hxx>
#endif /* unix */
//
// global variables definition.
//
// from wininet\dll\globals.cxx
GLOBAL LONGLONG dwdwHttpDefaultExpiryDelta = 12 * 60 * 60 * (LONGLONG)10000000; // 12 hours in 100ns units
GLOBAL LONGLONG dwdwSessionStartTime; // initialized in InitGlob() in urlcache
GLOBAL LONGLONG dwdwSessionStartTimeDefaultDelta = 0;
// from wininet\dll\Dllentry.cxx
CRITICAL_SECTION GlobalCacheCritSect;
BOOL GlobalCacheInitialized = FALSE;
CConMgr *GlobalUrlContainers = NULL;
LONG GlobalScavengerRunning = -1;
DWORD GlobalRetrieveUrlCacheEntryFileCount = 0;
PFNGETFILEATTREX gpfnGetFileAttributesEx = 0;
char g_szFixup[sizeof(DWORD)];
HINSTANCE g_hFixup;
PFN_FIXUP g_pfnFixup;
MEMORY *CacheHeap = NULL;
HNDLMGR HandleMgr;
GLOBAL DWORD GlobalDiskUsageLowerBound = (4*1024*1024);
GLOBAL DWORD GlobalScavengeFileLifeTime = (10*60);
GLOBAL BOOL GlobalPleaseQuitWhatYouAreDoing = FALSE;
// Identity-related globals
GLOBAL DWORD GlobalIdentity = 0;
GLOBAL GUID GlobalIdentityGuid = { 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
GLOBAL BOOL GlobalSuppressCookiesPolicy = FALSE;
#ifdef WININET6
GLOBAL HKEY GlobalCacheHKey = HKEY_CURRENT_USER;
#endif
// shfolder.dll hmod handle
HMODULE g_HMODSHFolder = NULL;
// Shell32.dll hmod handle
HMODULE g_HMODShell32 = NULL;
// GLOBAL SECURITY_CACHE_LIST GlobalCertCache;
GLOBAL DWORD GlobalSettingsVersion=0; // crossprocess settings versionstamp
GLOBAL BOOL GlobalSettingsLoaded = FALSE;
GLOBAL const char vszDisableSslCaching[] = "DisableCachingOfSSLPages";
GLOBAL char vszCurrentUser[MAX_PATH];
GLOBAL DWORD vdwCurrentUserLen = 0;
// cookies info
GLOBAL BOOL vfPerUserCookies = TRUE;
const char vszAnyUserName[]="anyuser";
const char vszPerUserCookies[] = "PerUserCookies";
const char vszInvalidFilenameChars[] = "<>\\\"/:|?*";
#ifdef unix
/***********************
* ReadOnlyCache on Unix
* *********************
* When the cache resides on a file system which is shared over NFS
* and the user can access the same cache from different work-stations,
* it causes a problem. The fix is made so that, the first process has
* write access to the cache and any subsequent browser process which
* is started from a different host will receive a read-only version
* of the cache and will not be able to get cookies etc. A symbolic
* link is created in $HOME/.microsoft named ielock. Creation and
* deletion of this symbolic link should be atomic. The functions
* CreateAtomicCacheLockFile and DeleteAtomicCacheLockFile implement
* this behavior. When a readonly cache is used, cache deletion is
* not allowed (Scavenger thread need not be launched).
*
* g_ReadOnlyCaches denotes if a readonly cache is being used.
* gszLockingHost denotes the host that holds the cache lock.
*/
BOOL g_ReadOnlyCaches = FALSE;
char *gszLockingHost = 0;
extern "C" void unixGetWininetCacheLockStatus(BOOL *pBool, char **pszLockingHost)
{
if(pBool)
*pBool = g_ReadOnlyCaches;
if(pszLockingHost)
*pszLockingHost = gszLockingHost;
}
#endif /* unix */
#ifdef CHECKLOCK_PARANOID
// Code to enforce strict ordering on resources to prevent deadlock
// One cannot attempt to take the critical section for the first time
// if one holds a container lock
DWORD dwThreadLocked;
DWORD dwLockLevel;
void CheckEnterCritical(CRITICAL_SECTION *_cs)
{
EnterCriticalSection(_cs);
if (_cs == &GlobalCacheCritSect && dwLockLevel++ == 0)
{
dwThreadLocked = GetCurrentThreadId();
if (GlobalUrlContainers) GlobalUrlContainers->CheckNoLocks(dwThreadLocked);
}
}
void CheckLeaveCritical(CRITICAL_SECTION *_cs)
{
if (_cs == &GlobalCacheCritSect)
{
INET_ASSERT(dwLockLevel);
if (dwLockLevel == 1)
{
if (GlobalUrlContainers) GlobalUrlContainers->CheckNoLocks(dwThreadLocked);
dwThreadLocked = 0;
}
dwLockLevel--;
}
LeaveCriticalSection(_cs);
}
#endif
//
/*++
--*/
BOOL InitGlobals (void)
{
if (GlobalCacheInitialized)
return TRUE;
LOCK_CACHE();
if (GlobalCacheInitialized)
goto done;
GetWininetUserName();
// Read registry settings.
OpenInternetSettingsKey();
{ // Detect a fixup handler. Open scope to avoid compiler complaint.
REGISTRY_OBJ roCache (HKEY_LOCAL_MACHINE, OLD_CACHE_KEY);
if (ERROR_SUCCESS == roCache.GetStatus())
{
DWORD cbFixup = sizeof(g_szFixup);
if (ERROR_SUCCESS != roCache.GetValue
("FixupKey", (LPBYTE) g_szFixup, &cbFixup))
{
g_szFixup[0] = 0;
}
if (g_szFixup[0] != 'V' || g_szFixup[3] != 0)
{
g_szFixup[0] = 0;
}
}
}
/*
{
REGISTRY_OBJ roCache (HKEY_LOCAL_MACHINE, CACHE5_KEY);
if (ERROR_SUCCESS == roCache.GetStatus())
{
DWORD dwDefTime;
if (ERROR_SUCCESS == roCache.GetValue("SessionStartTimeDefaultDeltaSecs", &dwDefTime))
{
dwdwSessionStartTimeDefaultDelta = dwDefTime * (LONGLONG)10000000;
dwdwSessionStartTime -= dwdwSessionStartTimeDefaultDelta;
}
}
}
*/
// Seed the random number generator for random file name generation.
srand(GetTickCount());
GetCurrentGmtTime((LPFILETIME)&dwdwSessionStartTime);
GlobalUrlContainers = new CConMgr();
GlobalCacheInitialized =
GlobalUrlContainers && (GlobalUrlContainers->GetStatus() == ERROR_SUCCESS);
if( GlobalCacheInitialized )
{
DWORD dwError = GlobalUrlContainers->CreateDefaultGroups();
INET_ASSERT(dwError == ERROR_SUCCESS);
}
else
{
delete GlobalUrlContainers;
GlobalUrlContainers = NULL;
}
done:
UNLOCK_CACHE();
return GlobalCacheInitialized;
}
URLCACHEAPI
BOOL
WINAPI
DLLUrlCacheEntry(
IN DWORD Reason
)
/*++
Routine Description:
Performs global initialization and termination for all protocol modules.
This function only handles process attach and detach which are required for
global initialization and termination, respectively. We disable thread
attach and detach. New threads calling Wininet APIs will get an
INTERNET_THREAD_INFO structure created for them by the first API requiring
this structure
Arguments:
DllHandle - handle of this DLL. Unused
Reason - process attach/detach or thread attach/detach
Reserved - if DLL_PROCESS_ATTACH, NULL means DLL is being dynamically
loaded, else static. For DLL_PROCESS_DETACH, NULL means DLL
is being freed as a consequence of call to FreeLibrary()
else the DLL is being freed as part of process termination
Return Value:
BOOL
Success - TRUE
Failure - FALSE. Failed to initialize
--*/
{
HMODULE ModuleHandleKernel;
switch (Reason)
{
case DLL_PROCESS_ATTACH:
#ifdef CHECKLOCK_PARANOID
dwThreadLocked = 0;
dwLockLevel = 0;
#endif
ModuleHandleKernel = GetModuleHandle("KERNEL32");
if (ModuleHandleKernel)
{
gpfnGetFileAttributesEx = (PFNGETFILEATTREX)
GetProcAddress(ModuleHandleKernel, "GetFileAttributesExA");
}
InitializeCriticalSection (&GlobalCacheCritSect);
// RunOnceUrlCache (NULL, NULL, NULL, 0); // test stub
#ifdef unix
if(CreateAtomicCacheLockFile(&g_ReadOnlyCaches,&gszLockingHost) == FALSE)
return FALSE;
#endif /* unix */
break;
case DLL_PROCESS_DETACH:
// Clean up containers list.
if (GlobalUrlContainers != NULL)
{
delete GlobalUrlContainers;
GlobalUrlContainers = NULL;
}
// Unload fixup handler.
if (g_hFixup)
FreeLibrary (g_hFixup);
HandleMgr.Destroy();
#ifdef unix
DeleteAtomicCacheLockFile();
#endif /* unix */
DeleteCriticalSection (&GlobalCacheCritSect);
break;
}
return TRUE;
}
//
// proxy info
//
// GLOBAL PROXY_INFO_GLOBAL GlobalProxyInfo;
//
// DLL version info
//
/*
GLOBAL INTERNET_VERSION_INFO InternetVersionInfo = {
WININET_MAJOR_VERSION,
WININET_MINOR_VERSION
};
*/
//
// HTTP version info - default 1.0
//
// GLOBAL HTTP_VERSION_INFO HttpVersionInfo = {1, 0};
BOOL
PrintFileTimeInInternetFormat(
FILETIME *lpft,
LPSTR lpszBuff,
DWORD dwSize
)
{
SYSTEMTIME sSysTime;
if (dwSize < INTERNET_RFC1123_BUFSIZE) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (FALSE);
}
if (!FileTimeToSystemTime(((CONST FILETIME *)lpft), &sSysTime)) {
return (FALSE);
}
return (InternetTimeFromSystemTime( &sSysTime,
lpszBuff));
}
BOOL
GetWininetUserName(
VOID
)
{
BOOL fRet = FALSE;
DWORD dwT;
CHAR *ptr;
// Note this critsect could be blocked for a while if RPC gets involved...
// EnterCriticalSection(&GeneralInitCritSec);
if (vdwCurrentUserLen) {
fRet = TRUE;
goto Done;
}
dwT = sizeof(vszCurrentUser);
if (vfPerUserCookies) {
fRet = GetUserName(vszCurrentUser, &dwT);
if (!fRet) {
DEBUG_PRINT(HTTP,
ERROR,
("GetUsername returns %d\n",
GetLastError()
));
}
}
if (fRet == FALSE){
strcpy(vszCurrentUser, vszAnyUserName);
fRet = TRUE;
}
// Downcase the username.
ptr = vszCurrentUser;
while (*ptr)
{
*ptr = tolower(*ptr);
ptr++;
}
INET_ASSERT(fRet == TRUE);
vdwCurrentUserLen = (DWORD) (ptr - vszCurrentUser);
Done:
// LeaveCriticalSection(&GeneralInitCritSec);
return (fRet);
}
/***
*char *StrTokEx(pstring, control) - tokenize string with delimiter in control
*
*Purpose:
* StrTokEx considers the string to consist of a sequence of zero or more
* text tokens separated by spans of one or more control chars. the first
* call, with string specified, returns a pointer to the first char of the
* first token, and will write a null char into pstring immediately
* following the returned token. when no tokens remain
* in pstring a NULL pointer is returned. remember the control chars with a
* bit map, one bit per ascii char. the null char is always a control char.
*
*Entry:
* char **pstring - ptr to ptr to string to tokenize
* char *control - string of characters to use as delimiters
*
*Exit:
* returns pointer to first token in string,
* returns NULL when no more tokens remain.
* pstring points to the beginning of the next token.
*
*WARNING!!!
* upon exit, the first delimiter in the input string will be replaced with '\0'
*
*******************************************************************************/
char * StrTokExA (char ** pstring, const char * control)
{
unsigned char *str;
const unsigned char *ctrl = (const unsigned char *)control;
unsigned char map[32];
int count;
char *tokenstr;
if(*pstring == NULL)
return NULL;
/* Clear control map */
for (count = 0; count < 32; count++)
map[count] = 0;
/* Set bits in delimiter table */
do
{
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
} while (*ctrl++);
/* Initialize str. */
str = (unsigned char *)*pstring;
/* Find beginning of token (skip over leading delimiters). Note that
* there is no token if this loop sets str to point to the terminal
* null (*str == '\0') */
while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
str++;
tokenstr = (char *)str;
/* Find the end of the token. If it is not the end of the string,
* put a null there. */
for ( ; *str ; str++ )
{
if ( map[*str >> 3] & (1 << (*str & 7)) )
{
*str++ = '\0';
break;
}
}
/* string now points to beginning of next token */
*pstring = (char *)str;
/* Determine if a token has been found. */
if ( tokenstr == (char *)str )
return NULL;
else
return tokenstr;
}
const char vszUserNameHeader[4] = "~U:";
// ---- from wininet\http\httptime.cxx
//
// external prototypes
//
/********************* Local data *******************************************/
/******************** HTTP date format strings ******************************/
// Month
static const char cszJan[]="Jan";
static const char cszFeb[]="Feb";
static const char cszMar[]="Mar";
static const char cszApr[]="Apr";
static const char cszMay[]="May";
static const char cszJun[]="Jun";
static const char cszJul[]="Jul";
static const char cszAug[]="Aug";
static const char cszSep[]="Sep";
static const char cszOct[]="Oct";
static const char cszNov[]="Nov";
static const char cszDec[]="Dec";
// DayOfWeek in rfc1123 or asctime format
static const char cszSun[]="Sun";
static const char cszMon[]="Mon";
static const char cszTue[]="Tue";
static const char cszWed[]="Wed";
static const char cszThu[]="Thu";
static const char cszFri[]="Fri";
static const char cszSat[]="Sat";
// List of weekdays for rfc1123 or asctime style date
static const char *rgszWkDay[7] =
{
cszSun,cszMon,cszTue,cszWed,cszThu,cszFri,cszSat
};
// list of month strings for all date formats
static const char *rgszMon[12] =
{
cszJan,cszFeb,cszMar,cszApr,cszMay,cszJun,
cszJul,cszAug,cszSep,cszOct,cszNov,cszDec
};
/******************** HTTP date format strings ******************************/
/* Http date format: Sat, 29 Oct 1994 19:43:00 GMT */
const char cszHttpDateFmt[]="%s, %02i %s %02i %02i:%02i:%02i GMT";
/****************************************************************************/
INTERNETAPI
BOOL
WINAPI
InternetTimeFromSystemTimeA(
IN CONST SYSTEMTIME *pst, // input GMT time
IN DWORD dwRFC, // RFC format: must be FORMAT_RFC1123
OUT LPSTR lpszTime, // output string buffer
IN DWORD cbTime // output buffer size
)
/*++
Routine Description:
Converts system time to a time string fromatted in the specified RFC format
Arguments:
pst: points to the SYSTEMTIME to be converted
dwRFC: RFC number of the format in which the result string should be returned
lpszTime: buffer to return the string in
cbTime: size of lpszTime buffer
Return Value:
BOOL
TRUE - string converted
FALSE - couldn't convert string, GetLastError returns windows error code
--*/
{
DEBUG_ENTER_API((DBG_API,
Handle,
"InternetTimeFromSystemTimeA",
"%#x, %d, %#x, %d",
pst,
dwRFC,
lpszTime,
cbTime
));
DWORD dwErr;
BOOL fResult = FALSE;
FILETIME ft;
if ( dwRFC != INTERNET_RFC1123_FORMAT
|| IsBadReadPtr (pst, sizeof(*pst))
|| IsBadWritePtr (lpszTime, cbTime)
|| !SystemTimeToFileTime(pst, &ft)
)
{
dwErr = ERROR_INVALID_PARAMETER;
}
else if (cbTime < INTERNET_RFC1123_BUFSIZE)
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
}
else
{
SYSTEMTIME st;
if ((pst->wDay < 0)
|| (pst->wDay > 6))
{
// ST2FT ignores the week of the day; so if we round trip back,
// it should place the correct week of the day.
FileTimeToSystemTime(&ft, &st);
pst = &st;
}
wsprintf (lpszTime, cszHttpDateFmt,
rgszWkDay[pst->wDayOfWeek],
pst->wDay,
rgszMon[pst->wMonth-1],
pst->wYear,
pst->wHour,
pst->wMinute,
pst->wSecond);
fResult = TRUE;
}
if (!fResult)
{
SetLastError(dwErr);
DEBUG_ERROR(INET, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}