home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1999 September
/
CHIPCD_9_99.iso
/
software
/
uaktualnienia
/
OptionPackPL
/
iis4_07.cab
/
CACHE.C
< prev
next >
Wrap
Text File
|
1998-04-27
|
8KB
|
390 lines
/*++
Copyright (c) 1996 Microsoft Corporation
This program is released into the public domain for any purpose.
Module Name:
cache.c
Abstract:
This module implements a simple user cache. The cached users are kept
in an LRU sorted list. If there will be a large number of simultaneous
users, then a sorted array would be more appropriate.
--*/
#include <windows.h>
#include <httpfilt.h>
#include "authfilt.h"
//
// Constants
//
//
// The maximum number of users we will cache. If there will be a large number
// of simultaneous users, bump this value
//
#define MAX_CACHED_USERS 100
//
// The position after which we'll move a cache entry to the front of the list
//
#define LIST_REORDER_THRESHOLD 6
//
// Cached user structure
//
typedef struct _USER_INFO
{
LIST_ENTRY ListEntry; // Double linked list entry
CHAR achUserName[SF_MAX_USERNAME]; // External username and password
CHAR achPassword[SF_MAX_PASSWORD];
CHAR achNTUserName[SF_MAX_USERNAME]; // NT account and password to map user to
CHAR achNTUserPassword[SF_MAX_PASSWORD];
} USER_INFO, *PUSER_INFO;
//
// Globals
//
//
// Circular double linked list of cached users
//
LIST_ENTRY CacheListHead;
//
// Critical section protects cache list
//
CRITICAL_SECTION csCacheLock;
//
// Indicates whether we are initialized
//
BOOL fCacheInitialized = FALSE;
//
// Number of items in the cache
//
DWORD cCacheItems = 0;
BOOL
InitializeCache(
VOID
)
/*++
Routine Description:
Initializes the cache module
Return Value:
TRUE if initialized successfully, FALSE on error
--*/
{
if ( fCacheInitialized )
return TRUE;
InitializeCriticalSection( &csCacheLock );
CacheListHead.Blink = CacheListHead.Flink = &CacheListHead;
fCacheInitialized = TRUE;
return TRUE;
}
BOOL
LookupUserInCache(
CHAR * pszUserName,
BOOL * pfFound,
CHAR * pszPassword,
CHAR * pszNTUser,
CHAR * pszNTUserPassword
)
/*++
Routine Description:
Checks to see if a user is in the cache and returns the user properties
if found
Arguments:
pszUserName - Case insensitive username to find
pfFound - Set to TRUE if the specified user was found
pszPassword - Receives password for specified user if found
pszNTUser - Receives the NT Username to map this user to
pszNTUserPassword - Receives the NT Password for pszNTUser
Note: pszPassword and pszNTUserPassword must be at least SF_MAX_PASSWORD
characters. pszNTUser must be at least SF_MAX_USERNAME characters.
Return Value:
TRUE if no errors occurred.
--*/
{
LIST_ENTRY * pEntry;
USER_INFO * pUser;
DWORD cPosition = 0;
//
// Search the cache for the specified user
//
EnterCriticalSection( &csCacheLock );
for ( pEntry = CacheListHead.Flink;
pEntry != &CacheListHead;
pEntry = pEntry->Flink )
{
pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
if ( !stricmp( pszUserName, pUser->achUserName ))
{
goto Found;
}
cPosition++;
}
LeaveCriticalSection( &csCacheLock );
//
// Not Found
//
*pfFound = FALSE;
return TRUE;
Found:
//
// Copy out the user properties
//
strcpy( pszPassword, pUser->achPassword );
strcpy( pszNTUser, pUser->achNTUserName );
strcpy( pszNTUserPassword, pUser->achNTUserPassword );
//
// Move this user entry to the front of the list as we're probably going
// to get subsequent requests for this user. Note we only move it
// if it's not already near the front
//
if ( cPosition > LIST_REORDER_THRESHOLD )
{
//
// Remove from the old position...
//
pEntry->Blink->Flink = pEntry->Flink;
pEntry->Flink->Blink = pEntry->Blink;
//
// ...and insert it at the beginning of the list
//
pEntry->Blink = &CacheListHead;
pEntry->Flink = CacheListHead.Flink;
CacheListHead.Flink->Blink = pEntry;
CacheListHead.Flink = pEntry;
}
LeaveCriticalSection( &csCacheLock );
*pfFound = TRUE;
return TRUE;
}
BOOL
AddUserToCache(
CHAR * pszUserName,
CHAR * pszPassword,
CHAR * pszNTUser,
CHAR * pszNTUserPassword
)
/*++
Routine Description:
Adds the specified user to the cache
Arguments:
pszUserName - Username to add
pszPassword - Contains the external password for this user
pszNTUser - Contains the NT user name to use for this user
pszNTUserPassword - Contains the password for NTUser
Return Value:
TRUE if no errors occurred.
--*/
{
LIST_ENTRY * pEntry;
USER_INFO * pUser;
//
// Check our parameters before adding them to the cache
//
if ( strlen( pszUserName ) > SF_MAX_USERNAME ||
strlen( pszPassword ) > SF_MAX_PASSWORD ||
strlen( pszNTUser ) > SF_MAX_USERNAME ||
strlen( pszNTUserPassword ) > SF_MAX_PASSWORD )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// Search the cache for the specified user to make sure there are no
// duplicates
//
EnterCriticalSection( &csCacheLock );
for ( pEntry = CacheListHead.Flink;
pEntry != &CacheListHead;
pEntry = pEntry->Flink )
{
pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
if ( !stricmp( pszUserName, pUser->achUserName ))
{
goto Found;
}
}
//
// Allocate a new cache item and put it at the head of the list
//
pUser = (USER_INFO *) LocalAlloc( LPTR, sizeof( USER_INFO ));
if ( !pUser )
{
LeaveCriticalSection( &csCacheLock );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
pUser->ListEntry.Flink = CacheListHead.Flink;
pUser->ListEntry.Blink = &CacheListHead;
CacheListHead.Flink->Blink = &pUser->ListEntry;
CacheListHead.Flink = &pUser->ListEntry;
Found:
//
// Set the various fields
//
strcpy( pUser->achUserName, pszUserName );
strcpy( pUser->achPassword, pszPassword );
strcpy( pUser->achNTUserName, pszNTUser );
strcpy( pUser->achNTUserPassword, pszNTUserPassword );
cCacheItems++;
//
// If there are too many cached users, remove the least recently
// used one now
//
if ( cCacheItems > MAX_CACHED_USERS )
{
pEntry = CacheListHead.Blink;
pEntry->Blink->Flink = &CacheListHead;
CacheListHead.Blink = pEntry->Blink;
LocalFree( CONTAINING_RECORD( pEntry, USER_INFO, ListEntry ));
cCacheItems--;
}
LeaveCriticalSection( &csCacheLock );
return TRUE;
}
VOID
TerminateCache(
VOID
)
/*++
Routine Description:
Terminates the cache module and frees any allocated memory
--*/
{
LIST_ENTRY * pEntry;
LIST_ENTRY * pEntryNext;
USER_INFO * pUser;
if ( !fCacheInitialized )
return;
EnterCriticalSection( &csCacheLock );
//
// Free all of the cache entries
//
for ( pEntry = CacheListHead.Flink;
pEntry != &CacheListHead;
pEntry = pEntryNext )
{
pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
pEntryNext = pEntry->Flink;
//
// Remove this entry from the list and free it
//
pEntry->Blink->Flink = pEntry->Flink;
pEntry->Flink->Blink = pEntry->Blink;
LocalFree( pUser );
}
cCacheItems = 0;
LeaveCriticalSection( &csCacheLock );
DeleteCriticalSection( &csCacheLock );
fCacheInitialized = FALSE;
}