mirror of https://github.com/lianthony/NT4.0
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.
550 lines
15 KiB
550 lines
15 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// File: cache.cxx
|
|
//
|
|
// Copyright (c) 1996-1996, Microsoft Corp. All rights reserved.
|
|
//
|
|
// Description: This file contains the implementation of the
|
|
// CEffectivePermsCache class. The cache is implemented as a hash
|
|
// without any fancy mechanism to handle collisions. If a
|
|
// collision occur, the old entry is simply overwritten.
|
|
//
|
|
// Classes: CEffectivePermsCache
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <ole2.h>
|
|
#include "Cache.h"
|
|
#define BIG_PRIME 48271
|
|
#define SMALL_PRIME 2683
|
|
|
|
#include "acext.h"
|
|
|
|
// constructor
|
|
|
|
#ifdef _CHICAGO_
|
|
CEffectivePermsCache::CEffectivePermsCache(void)
|
|
#else
|
|
CEffPermsCacheString::CEffPermsCacheString(void)
|
|
#endif
|
|
{
|
|
// Set the whole cache to null
|
|
memset(m_cache, 0 , CACHE_SIZE * sizeof(CACHE_ENTRY));
|
|
// Create an instance of the critical section object.
|
|
InitializeCriticalSection(&m_CacheLock);
|
|
|
|
}
|
|
|
|
// destructor
|
|
#ifdef _CHICAGO_
|
|
CEffectivePermsCache::~CEffectivePermsCache(void)
|
|
#else
|
|
CEffPermsCacheString::~CEffPermsCacheString(void)
|
|
#endif
|
|
{
|
|
// Flush the cache to free memory allocated for strings
|
|
FlushCache();
|
|
// Destroy critical section object
|
|
DeleteCriticalSection(&m_CacheLock);
|
|
}
|
|
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffectivePermsCache::Hash, private
|
|
//
|
|
// Summary: This function returns a hash value for a Unicode string
|
|
//
|
|
// Args: LPWSTR pwszString [in]- Pointer to a null terminated Unicode string.
|
|
//
|
|
// Modifies: Nothing
|
|
//
|
|
// Return: DWORD - The hash value of the string.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
#ifdef _CHICAGO_
|
|
DWORD CEffectivePermsCache::Hash
|
|
#else
|
|
DWORD CEffPermsCacheString::Hash
|
|
#endif
|
|
(
|
|
LPWSTR pwszString
|
|
)
|
|
{
|
|
DWORD dwHashValue = 0;
|
|
LPWSTR pwszWCHAR = pwszString;
|
|
WCHAR wc;
|
|
ULONG ulStrLen = lstrlenW(pwszString);
|
|
|
|
for (USHORT i = 0; i < ulStrLen; i++, pwszWCHAR++)
|
|
{
|
|
wc = *pwszWCHAR;
|
|
// Make the hash function case insensitive
|
|
wc = toupper(wc);
|
|
|
|
dwHashValue = ((dwHashValue + wc) * SMALL_PRIME) % BIG_PRIME;
|
|
} // for
|
|
|
|
return (dwHashValue % CACHE_SIZE);
|
|
|
|
} // Hash
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffectivePermsCache::LookUpEntry
|
|
//
|
|
// Summary: This function search for the effective permission of a trustee
|
|
// given the trustee name in Unicode.
|
|
//
|
|
// Args: LPWSTR pName [in] - The name of the trustee in unicode.
|
|
//
|
|
// Modifies: Nothing.
|
|
//
|
|
// Return: TRUE - If the the trustee's effective permission is found in
|
|
// the cache.
|
|
// FALSE - Otherwise.
|
|
//
|
|
// Actions: 1) Computes the hash value of the input string, k.
|
|
// 2) Compares the name in the kth entry of the cache with the
|
|
// trustee's name.
|
|
// 3) If the trustee's name matches, sets *pdwEffectivePermissions to the
|
|
// effective permissions in the cache entry and returns TRUE.
|
|
// 4) Returns FALSE otherwise.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
#ifdef _CHICAGO_
|
|
BOOL CEffectivePermsCache::LookUpEntry
|
|
#else
|
|
BOOL CEffPermsCacheString::LookUpEntry
|
|
#endif
|
|
(
|
|
LPWSTR pName,
|
|
DWORD *pdwEffectivePermissions
|
|
)
|
|
{
|
|
CACHE_ENTRY *pCacheEntry = m_cache + Hash(pName);
|
|
|
|
EnterCriticalSection(&m_CacheLock);
|
|
#ifdef _CHICAGO_
|
|
if (FoolstrcmpiW(pName, pCacheEntry->pName) == 0)
|
|
#else
|
|
if ((pCacheEntry->pName != NULL) && (lstrcmpiW(pName, pCacheEntry->pName) == 0))
|
|
#endif
|
|
{
|
|
*pdwEffectivePermissions = pCacheEntry->dwEffectivePermissions;
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return TRUE;
|
|
} // if
|
|
else
|
|
{
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return FALSE;
|
|
|
|
} // else
|
|
} // LookUpEntry
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffectivePermsCache::DeleteEntry
|
|
//
|
|
// Summary: This function search for the effective permission of a
|
|
//
|
|
// Args: LPWSTR pName [in] - The name of the trustee in unicode.
|
|
//
|
|
// Modifies: Nothing.
|
|
//
|
|
// Return: TRUE - If the the trustee's effective permission is found in
|
|
// the cache.
|
|
// FALSE - Otherwise.
|
|
//
|
|
// Actions: 1) Computes the hash value of the input string, k.
|
|
// 2) Compares the name in the kth entry of the cache with the
|
|
// trustee's name.
|
|
// 3) If the trustee's name matches, frees memory allocated for
|
|
// *pCacheEntry->pName, sets *pCacheEntry->pName to
|
|
// NULL and returns TRUE.
|
|
// 4) Returns FALSE otherwise.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
#ifdef _CHICAGO_
|
|
BOOL CEffectivePermsCache::DeleteEntry
|
|
#else
|
|
BOOL CEffPermsCacheString::DeleteEntry
|
|
#endif
|
|
(
|
|
LPWSTR pName
|
|
)
|
|
{
|
|
CACHE_ENTRY *pCacheEntry = m_cache + Hash(pName);
|
|
LPWSTR pCacheName;
|
|
|
|
EnterCriticalSection(&m_CacheLock);
|
|
pCacheName = pCacheEntry->pName;
|
|
#ifdef _CHICAGO_
|
|
if (FoolstrcmpiW(pName, pCacheName) == 0)
|
|
#else
|
|
if ((pCacheName != NULL) && (lstrcmpiW(pName, pCacheName) == 0))
|
|
#endif
|
|
{
|
|
LocalMemFree(pCacheName);
|
|
pCacheEntry->pName = NULL;
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return TRUE;
|
|
} // if
|
|
else
|
|
{
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return FALSE;
|
|
|
|
} // else
|
|
} // DeleteEntry
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffectivePermsCache::WriteEntry
|
|
//
|
|
// Summary: This function writes a new entry to the cache. In case of a hash
|
|
// collision the old entry is overwritten.
|
|
//
|
|
// Args: LPWSTR pName [in] - Name of the trustee in the form of a NULL
|
|
// terminated unicode string.
|
|
// DWORD dwEffectivePermissions [in] - The set of effective
|
|
// permissions that belong to the
|
|
// trustee.
|
|
//
|
|
// Modifies: m_cache - The object's private hash table.
|
|
//
|
|
// Return: TRUE - If the operation is successful.
|
|
// FALSE - If there is not enough memory to allocate the new string.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
#ifdef _CHICAGO_
|
|
BOOL CEffectivePermsCache::WriteEntry
|
|
#else
|
|
BOOL CEffPermsCacheString::WriteEntry
|
|
#endif
|
|
(
|
|
LPWSTR pName,
|
|
DWORD dwEffectivePermissions
|
|
)
|
|
{
|
|
CACHE_ENTRY *pCacheEntry = m_cache + Hash(pName);
|
|
ULONG ulcStringLength;
|
|
|
|
// See if the name is already in the cache
|
|
// and avoid reallocating a new string if possible.
|
|
EnterCriticalSection(&m_CacheLock);
|
|
#ifdef _CHICAGO_
|
|
if (FoolstrcmpiW(pName, pCacheEntry->pName) != 0)
|
|
#else
|
|
if ((pCacheEntry->pName == NULL) || (lstrcmpiW(pName, pCacheEntry->pName) != 0))
|
|
#endif
|
|
{
|
|
if (pCacheEntry->pName != NULL)
|
|
{
|
|
// Free the old list if there was an old entry
|
|
// in the slot
|
|
LocalMemFree(pCacheEntry->pName);
|
|
} // if
|
|
ulcStringLength = lstrlenW(pName) + 1;
|
|
pCacheEntry->pName = (LPWSTR)LocalMemAlloc(ulcStringLength * sizeof(WCHAR));
|
|
if (pCacheEntry->pName == NULL)
|
|
{
|
|
// Out of memory error
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return FALSE;
|
|
} // if
|
|
|
|
memcpy(pCacheEntry->pName, pName, sizeof(WCHAR) * ulcStringLength);
|
|
} // if
|
|
|
|
pCacheEntry->dwEffectivePermissions = dwEffectivePermissions;
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return TRUE;
|
|
} // WriteEntry
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffectivePermsCache::FlushCache
|
|
//
|
|
// Summary: This function empties the cache
|
|
//
|
|
// Args: void
|
|
//
|
|
// Modifies: m_cache - The object's private hash table
|
|
//
|
|
// Return: void
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
#ifdef _CHICAGO_
|
|
void CEffectivePermsCache::FlushCache
|
|
#else
|
|
void CEffPermsCacheString::FlushCache
|
|
#endif
|
|
(
|
|
void
|
|
)
|
|
{
|
|
LPWSTR pString;
|
|
USHORT i = 0;
|
|
CACHE_ENTRY *pCache;
|
|
|
|
EnterCriticalSection(&m_CacheLock);
|
|
for ( i = 0, pCache = m_cache
|
|
; i < CACHE_SIZE
|
|
; i++, pCache++)
|
|
{
|
|
if ((pString = pCache->pName) != NULL)
|
|
{
|
|
LocalMemFree(pString);
|
|
pCache->pName = NULL;
|
|
} // if
|
|
|
|
} // for
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return;
|
|
} // FlushCache
|
|
|
|
#ifndef _CHICAGO_
|
|
CEffPermsCacheSID::CEffPermsCacheSID(void)
|
|
{
|
|
// Set the whole cache to null
|
|
memset(m_cache, 0 , CACHE_SIZE * sizeof(CACHE_ENTRY));
|
|
// Create an instance of the critical section object.
|
|
InitializeCriticalSection(&m_CacheLock);
|
|
|
|
}
|
|
|
|
// destructor
|
|
CEffPermsCacheSID::~CEffPermsCacheSID(void)
|
|
{
|
|
// Flush the cache to free memory allocated for strings
|
|
FlushCache();
|
|
// Destroy critical section object
|
|
DeleteCriticalSection(&m_CacheLock);
|
|
}
|
|
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffPermsCacheSID::Hash, private
|
|
//
|
|
// Summary: This function returns a hash value for a security identifier.
|
|
//
|
|
// Args: PSID pSID [in] - Pointer to a security identifier.
|
|
//
|
|
// Modifies: Nothing
|
|
//
|
|
// Return: DWORD - The hash value of the SID.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
DWORD CEffPermsCacheSID::Hash
|
|
(
|
|
PSID pSID
|
|
)
|
|
{
|
|
DWORD dwHashValue = 0;
|
|
CHAR *pSIDBuff = (CHAR *)pSID;
|
|
DWORD dwSIDLen;
|
|
|
|
dwSIDLen = GetLengthSid(pSID);
|
|
|
|
for (USHORT i = 0; i < dwSIDLen; i++, pSIDBuff++)
|
|
{
|
|
// I have the feeling that the first line works better than the second line..
|
|
dwHashValue = ((dwHashValue + *pSIDBuff) * SMALL_PRIME) % BIG_PRIME;
|
|
} // for
|
|
|
|
return (dwHashValue % CACHE_SIZE);
|
|
|
|
} // Hash
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffPermsCacheSID::LookUpEntry
|
|
//
|
|
// Summary: This function search for the effective permission of a trustee
|
|
// given the trustee's security identifier.
|
|
//
|
|
// Args: PSID pSID [in] - Security identifier of the trustee.
|
|
//
|
|
// Modifies: Nothing.
|
|
//
|
|
// Return: TRUE - If the the trustee's effective permission is found in
|
|
// the cache.
|
|
// FALSE - Otherwise.
|
|
//
|
|
// Actions: 1) Computes the hash value of the input SID, k.
|
|
// 2) Compares the SID in the kth entry of the cache with the
|
|
// trustee's SID.
|
|
// 3) If the trustee's SID matches, sets *pdwEffectivePermissions to the
|
|
// effective permissions in the cache entry and return TRUE.
|
|
// 4) Returns FALSE otherwise.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
BOOL CEffPermsCacheSID::LookUpEntry
|
|
(
|
|
PSID pSID,
|
|
DWORD *pdwEffectivePermissions
|
|
)
|
|
{
|
|
CACHE_ENTRY *pCacheEntry = m_cache + Hash(pSID);
|
|
|
|
EnterCriticalSection(&m_CacheLock);
|
|
if ((pCacheEntry->pSID != NULL) && (EqualSid(pSID, pCacheEntry->pSID) == TRUE))
|
|
{
|
|
*pdwEffectivePermissions = pCacheEntry->dwEffectivePermissions;
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return TRUE;
|
|
} // if
|
|
else
|
|
{
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return FALSE;
|
|
|
|
} // else
|
|
} // LookUpEntry
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffPermsCacheSID::DeleteEntry
|
|
//
|
|
// Summary: This function search for the effective permission of a
|
|
//
|
|
// Args: PSID pSID [in] - Security identifier of the trustee.
|
|
//
|
|
// Modifies: Nothing.
|
|
//
|
|
// Return: TRUE - If the the trustee's effective permission is found in
|
|
// the cache.
|
|
// FALSE - Otherwise.
|
|
//
|
|
// Actions: 1) Computes the hash value of the input SID, k.
|
|
// 2) Compares the SID in the kth entry of the cache with the
|
|
// trustee's SID.
|
|
// 3) If the trustee's SID matches, frees memory allocated for
|
|
// *pCacheEntry->pSID, sets *pCacheEntry->pSID to
|
|
// NULL and returns TRUE.
|
|
// 4) Returns FALSE otherwise.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
BOOL CEffPermsCacheSID::DeleteEntry
|
|
(
|
|
PSID pSID
|
|
)
|
|
{
|
|
CACHE_ENTRY *pCacheEntry = m_cache + Hash(pSID);
|
|
PSID pCacheSID;
|
|
|
|
EnterCriticalSection(&m_CacheLock);
|
|
pCacheSID = pCacheEntry->pSID;
|
|
if ((pCacheSID != NULL) && (EqualSid(pSID, pCacheSID) == TRUE))
|
|
{
|
|
LocalMemFree(pCacheSID);
|
|
pCacheEntry->pSID = NULL;
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return TRUE;
|
|
} // if
|
|
else
|
|
{
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return FALSE;
|
|
|
|
} // else
|
|
} // DeleteEntry
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffPermsCacheSID::WriteEntry
|
|
//
|
|
// Summary: This function writes a new entry to the cache. In case of a hash
|
|
// collision the old entry is overwritten.
|
|
//
|
|
// Args: PSID pSID [in] - Security identifier of the trustee.
|
|
// DWORD dwEffectivePermissions [in] - The set of effective
|
|
// permissions that belong to the
|
|
// trustee.
|
|
//
|
|
// Modifies: m_cache - The object's private hash table.
|
|
//
|
|
// Return: TRUE - If the operation is successful.
|
|
// FALSE - If there is not enough memory to allocate the new string.
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
BOOL CEffPermsCacheSID::WriteEntry
|
|
(
|
|
PSID pSID,
|
|
DWORD dwEffectivePermissions
|
|
)
|
|
{
|
|
CACHE_ENTRY *pCacheEntry = m_cache + Hash(pSID);
|
|
ULONG ulSIDSize;
|
|
|
|
// See if the name is already in the cache
|
|
// and avoid reallocating a new string if possible.
|
|
EnterCriticalSection(&m_CacheLock);
|
|
if ((pCacheEntry->pSID == NULL) || (EqualSid(pSID, pCacheEntry->pSID) == FALSE))
|
|
{
|
|
if (pCacheEntry->pSID != NULL)
|
|
{
|
|
// Free the old list if there was an old entry
|
|
// in the slot
|
|
LocalMemFree(pCacheEntry->pSID);
|
|
} // if
|
|
ulSIDSize = GetLengthSid(pSID);
|
|
pCacheEntry->pSID = (PSID)LocalMemAlloc(ulSIDSize);
|
|
if (pCacheEntry->pSID == NULL)
|
|
{
|
|
// Out of memory error
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return FALSE;
|
|
} // if
|
|
|
|
CopySid(ulSIDSize, pCacheEntry->pSID, pSID);
|
|
} // if
|
|
|
|
pCacheEntry->dwEffectivePermissions = dwEffectivePermissions;
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return TRUE;
|
|
} // WriteEntry
|
|
|
|
//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
|
|
// Method: CEffPermsCacheSID::FlushCache
|
|
//
|
|
// Summary: This function empties the cache
|
|
//
|
|
// Args: void
|
|
//
|
|
// Modifies: m_cache - The object's private hash table
|
|
//
|
|
// Return: void
|
|
//
|
|
//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
|
|
|
|
void CEffPermsCacheSID::FlushCache
|
|
(
|
|
void
|
|
)
|
|
{
|
|
PSID pSID;
|
|
USHORT i = 0;
|
|
CACHE_ENTRY *pCache;
|
|
|
|
EnterCriticalSection(&m_CacheLock);
|
|
for ( i = 0, pCache = m_cache
|
|
; i < CACHE_SIZE
|
|
; i++, pCache++)
|
|
{
|
|
if ((pSID = pCache->pSID) != NULL)
|
|
{
|
|
LocalMemFree(pSID);
|
|
pCache->pSID = NULL;
|
|
} // if
|
|
|
|
} // for
|
|
LeaveCriticalSection(&m_CacheLock);
|
|
return;
|
|
} // FlushCache
|
|
|
|
#endif
|