windows-nt/Source/XPSP1/NT/ds/adsi/nwnds/ndscache.cxx
2020-09-26 16:20:57 +08:00

225 lines
4.7 KiB
C++

#include "nds.hxx"
#pragma hdrstop
NDS_CONTEXT BindCache ;
DWORD BindCacheCount = 0 ;
//
// Initializes a cache entry
//
HRESULT BindCacheAllocEntry(NDS_CONTEXT **ppCacheEntry)
{
NDS_CONTEXT *pCacheEntry ;
*ppCacheEntry = NULL ;
if (!(pCacheEntry = (PNDS_CONTEXT)AllocADsMem(sizeof(NDS_CONTEXT)))) {
RRETURN(E_OUTOFMEMORY);
}
pCacheEntry->RefCount = 0;
pCacheEntry->Flags = 0;
pCacheEntry->List.Flink = NULL ;
pCacheEntry->List.Blink = NULL ;
*ppCacheEntry = pCacheEntry ;
RRETURN(S_OK);
}
//
// Invalidates a cache entry so it will not be used.
//
VOID BindCacheInvalidateEntry(NDS_CONTEXT *pCacheEntry)
{
pCacheEntry->Flags |= NDS_CACHE_INVALID ;
}
//
// Lookup an entry in the cache. Does not take into account timeouts.
// Increments ref count if found.
//
PNDS_CONTEXT
BindCacheLookup(
LPWSTR pszNDSTreeName,
CCredentials& Credentials
)
{
DWORD i ;
PNDS_CONTEXT pEntry = (PNDS_CONTEXT) BindCache.List.Flink ;
//
// Loop thru looking for match. A match is defined as:
// tree name and credentials, and it is NOT invalid.
//
while (pEntry != &BindCache) {
if (!(pEntry->Flags & NDS_CACHE_INVALID) &&
(((pszNDSTreeName != NULL) && (pEntry->pszNDSTreeName != NULL) &&
(wcscmp(pEntry->pszNDSTreeName, pszNDSTreeName) == 0)) ||
(pEntry->pszNDSTreeName == NULL && pszNDSTreeName == NULL)) &&
(*(pEntry->pCredentials) == Credentials)) {
++pEntry->RefCount ;
return(pEntry) ;
}
pEntry = (PNDS_CONTEXT)pEntry->List.Flink ;
}
return NULL ;
}
//
// Add entry to cache
//
HRESULT
BindCacheAdd(
LPWSTR pszNDSTreeName,
CCredentials& Credentials,
BOOL fLoggedIn,
PNDS_CONTEXT pCacheEntry)
{
if (BindCacheCount > MAX_BIND_CACHE_SIZE) {
//
// If exceed limit, just dont put in cache. Since we leave the
// RefCount & the Links unset, the deref will simply note that
// this entry is not in cache and allow it to be freed.
//
// We limit cache so that if someone leaks handles we dont over
// time end up traversing this huge linked list.
//
RRETURN(S_OK) ;
}
LPWSTR pszTreeName = (LPWSTR) AllocADsMem(
(wcslen(pszNDSTreeName)+1)*sizeof(WCHAR)) ;
if (!pszTreeName) {
RRETURN(E_OUTOFMEMORY);
}
CCredentials * pCredentials = new CCredentials(Credentials);
if (!pCredentials) {
FreeADsMem(pszTreeName);
RRETURN(E_OUTOFMEMORY);
}
//
// setup the data
//
wcscpy(pszTreeName,pszNDSTreeName) ;
pCacheEntry->pszNDSTreeName = pszTreeName;
pCacheEntry->pCredentials = pCredentials;
pCacheEntry->RefCount = 1 ;
pCacheEntry->fLoggedIn = fLoggedIn;
//
// insert into list
//
InsertHeadList(&BindCache.List, &pCacheEntry->List) ;
++BindCacheCount ;
RRETURN(S_OK);
}
//
// Dereference an entry in the cache. Removes if ref count is zero.
// Returns the final ref count or zero if not there. If zero, caller
// should close the handle.
//
DWORD BindCacheDeref(NDS_CONTEXT *pCacheEntry)
{
DWORD i=0;
ENTER_BIND_CRITSECT() ;
if ((pCacheEntry->List.Flink == NULL) &&
(pCacheEntry->List.Blink == NULL) &&
(pCacheEntry->RefCount == NULL)) {
//
// this is one of the entries that never got into the cache.
//
LEAVE_BIND_CRITSECT() ;
return(0) ;
}
ADsAssert(pCacheEntry->List.Flink) ;
ADsAssert(pCacheEntry->RefCount > 0) ;
//
// Dereference by one. If result is non zero, just return.
//
--pCacheEntry->RefCount ;
if (pCacheEntry->RefCount) {
LEAVE_BIND_CRITSECT() ;
return(pCacheEntry->RefCount) ;
}
//
// This entry can be cleaned up.
//
--BindCacheCount ;
(void) FreeADsMem(pCacheEntry->pszNDSTreeName) ;
pCacheEntry->pszNDSTreeName = NULL ;
delete pCacheEntry->pCredentials;
pCacheEntry->pCredentials = NULL;
RemoveEntryList(&pCacheEntry->List) ;
LEAVE_BIND_CRITSECT() ;
return 0 ;
}
VOID
BindCacheInit(
VOID
)
{
InitializeCriticalSection(&BindCacheCritSect) ;
InitializeListHead(&BindCache.List) ;
}
VOID
BindCacheCleanup(
VOID
)
{
PNDS_CONTEXT pEntry = (PNDS_CONTEXT) BindCache.List.Flink ;
while (pEntry != &BindCache) {
PNDS_CONTEXT pNext = (PNDS_CONTEXT) pEntry->List.Flink;
(void) FreeADsMem(pEntry->pszNDSTreeName) ;
pEntry->pszNDSTreeName = NULL ;
RemoveEntryList(&pEntry->List) ;
pEntry = pNext;
}
DeleteCriticalSection(&BindCacheCritSect);
}