Windows2003-3790/inetsrv/iis/svcs/smtp/server/shash.hxx
2020-09-30 16:53:55 +02:00

337 lines
8.2 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name :
shash.hxx
Abstract:
This file contains type definitions hash table support
Author:
Revision History:
Rohan Phillips (RohanP) MARCH-08-1997 - modified for SMTP
--*/
#ifndef _SHASH_H_
#define _SHASH_H_
#include <limits.h>
#define TURN_DATA_SIGNATURE_VALID 'TDSV'
#define TURN_DATA_SIGNATURE_FREE 'TDSF'
#define LAST_SMTP_ACTION ((DOMAIN_ROUTE_ACTION_TYPE)BitFlag(1)|BitFlag(2) | BitFlag(3))
class CSMTP_HASH_TABLE;
class CTurnData;
class CHASH_ENTRY
{
protected:
DWORD m_Signature;
LONG m_RefCount;
BOOL m_InList;
CSMTP_HASH_TABLE * m_MyTable;
private:
DWORD m_NumAccess;
BOOL m_fWildCard;
public:
LIST_ENTRY m_ListEntry;
CHASH_ENTRY(DWORD Signature)
{
m_Signature = Signature;
m_RefCount = 0;
m_InList = FALSE;
m_NumAccess = 0;
m_MyTable = NULL;
m_fWildCard = FALSE;
}
void SetWildCard(void) { m_fWildCard = TRUE; }
void ClearWildCard(void) { m_fWildCard = FALSE; }
BOOL IsWildCard(void) {return m_fWildCard;}
LIST_ENTRY & QueryListEntry(void) {return ( m_ListEntry);}
void SetTableEntry(CSMTP_HASH_TABLE * ThisTable) { m_MyTable = ThisTable;}
void SetInList(void) { m_InList = TRUE;}
void ClearInList(void) { m_InList = FALSE;}
BOOL GetInList(void) { return m_InList;}
LONG QueryRefCount(void){return m_RefCount;}
virtual LONG IncRefCount(void){return InterlockedIncrement(&m_RefCount);}
virtual void DecRefCount(void)
{
if(InterlockedDecrement(&m_RefCount) == 0)
{
//we should not be in the list if the ref
//count is zero
_ASSERT(m_InList == FALSE);
delete this;
}
}
void IncAccessCount(void)
{
InterlockedIncrement((LPLONG) &m_NumAccess);
}
BOOL IncAndCheckMaxAccess(DWORD MaxConnectionCount)
{
LONG OldAccessValue;
BOOL fRet = TRUE;
TraceFunctEnterEx((LPARAM)this, "CHASH_ENTRY::IsMaxAccessReached");
OldAccessValue = InterlockedExchangeAdd((LPLONG) &m_NumAccess, 1);
if((MaxConnectionCount > 0) && (OldAccessValue >= (LONG) MaxConnectionCount))
{
fRet = FALSE;
}
TraceFunctLeaveEx((LPARAM)this);
return fRet;
}
void DecAccessCount(void)
{
InterlockedDecrement((LPLONG) &m_NumAccess);
}
DWORD GetAccessCount(void)
{
return m_NumAccess;
}
virtual char * GetData(void) = 0;
virtual ~CHASH_ENTRY(){}
};
typedef struct HASH_BUCKET_ENTRY
{
DWORD m_NumEntries;
LONG m_RefNum;
LIST_ENTRY m_ListHead;
CShareLockNH m_Lock;
HASH_BUCKET_ENTRY (void)
{
InitializeListHead(&m_ListHead);
m_NumEntries = 0;
m_RefNum = 0;
}
}BUCKET_ENTRY, *PBUCKET_ENTRY;
#define BITS_IN_int (sizeof(int) * CHAR_BIT)
#define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4))
#define ONE_EIGHTH ((int) (BITS_IN_int / 8))
#define HIGH_BITS (~((unsigned int)(~0) >> ONE_EIGHTH))
#define TABLE_SIZE 241
class CSMTP_HASH_TABLE
{
protected:
DWORD m_Signature;
LONG m_TotalEntries;
DWORD m_CacheHits;
DWORD m_CacheMisses;
BOOL m_fWildCard;
BOOL m_fDupesAllowed;
HASH_BUCKET_ENTRY m_HashTable[TABLE_SIZE];
public:
CSMTP_HASH_TABLE::CSMTP_HASH_TABLE()
{
m_TotalEntries = 0;
m_CacheHits = 0;
m_CacheMisses = 0;
m_fWildCard = FALSE;
m_fDupesAllowed = FALSE;
}
virtual ~CSMTP_HASH_TABLE();
virtual DWORD PrimaryCompareFunction(const char * SearchData, CHASH_ENTRY * pExistingEntry)
{
DWORD Result = 0;
Result = lstrcmpi(SearchData, pExistingEntry->GetData());
return Result;
}
virtual DWORD SecondaryCompareFunction(const char * SearchData, CHASH_ENTRY * pExistingEntry)
{
return 0;
}
virtual void MultiszFunction(CHASH_ENTRY * pExistingEntry, MULTISZ* pMsz)
{
}
void RemoveAllEntries(void);
void RemoveThisEntry(CHASH_ENTRY * pHashEntry, DWORD BucketNum);
virtual void PrintAllEntries(void);
virtual BOOL RemoveFromTable(const char * SearchData);
virtual BOOL RemoveFromTableNoDecRef(const char * SearchData);
virtual BOOL InsertIntoTable (CHASH_ENTRY * pHashEntry);
virtual BOOL InsertIntoTableEx (CHASH_ENTRY * pHashEntry, char * szDefaultDomain);
CHASH_ENTRY * FindHashData(const char * SearchData, BOOL fUseShareLock = TRUE, MULTISZ* pmsz = NULL);
CHASH_ENTRY * UnSafeFindHashData(const char * SearchData);
CHASH_ENTRY * WildCardFindHashData(const char * DomainName);
void SetDupesAllowed(void){m_fDupesAllowed = TRUE;}
void SetWildCard(void){m_fWildCard = TRUE;}
void ClearWildCard(void) {m_fWildCard = FALSE;}
BOOL IsWildCard(void) {return m_fWildCard;}
BOOL IsDupesAllowed(void) {return m_fDupesAllowed;}
BOOL IsTableEmpty(void) const {return (m_TotalEntries == 0);}
//An adaptation of Peter Weinberger's (PJW) generic
//hashing algorithm based on Allen Holub's version.
//Code from Practical Algorithms for Programmers
//by Andrew Binstock
unsigned int HashFunction (const char * String)
{
unsigned int HashValue = 0;
unsigned int i = 0;
_ASSERT(String != NULL);
for (HashValue = 0; String && *String; ++String)
{
HashValue = (HashValue << ONE_EIGHTH) + * String;
if((i = HashValue & HIGH_BITS) != 0)
{
HashValue = (HashValue ^ (i >> THREE_QUARTERS)) & ~ HIGH_BITS;
}
}
HashValue %= TABLE_SIZE;
return HashValue;
}
LIST_ENTRY & GetBucketHead(DWORD BucketNum)
{
return m_HashTable[BucketNum].m_ListHead;
}
//this must be called with a lock if you
//want it to be accurate!!!!!!!
DWORD GetBucketRefNum(DWORD BucketNum)
{
DWORD RefNum;
RefNum = m_HashTable[BucketNum].m_RefNum;
return RefNum;
}
void ShareLockBucket(DWORD BucketNumber)
{
m_HashTable[BucketNumber].m_Lock.ShareLock();
}
void ShareUnLockBucket(DWORD BucketNumber)
{
m_HashTable[BucketNumber].m_Lock.ShareUnlock();
}
};
class CTurnData : public CHASH_ENTRY
{
private:
char m_UserName[MAX_INTERNET_NAME + 1];
char m_DomainName[AB_MAX_DOMAIN + 1];
public:
virtual char * GetData(void)
{
return m_UserName;
}
CTurnData()
:CHASH_ENTRY (TURN_DATA_SIGNATURE_VALID)
{
m_UserName[0] = '\0';
m_DomainName[0] = '\0';
}
CTurnData(const char * szUserName, char * szDomainName)
:CHASH_ENTRY (TURN_DATA_SIGNATURE_VALID)
{
lstrcpyn(m_UserName, szUserName, MAX_INTERNET_NAME);
CharLowerBuff(m_UserName, lstrlen(m_UserName));
lstrcpyn(m_DomainName, szDomainName, AB_MAX_DOMAIN);
CharLowerBuff(m_DomainName, lstrlen(m_DomainName));
}
virtual ~CTurnData()
{
m_Signature = TURN_DATA_SIGNATURE_FREE;
}
char * GetRouteDomainName(void)
{
return m_DomainName;
}
};
class CTURN_ACCESS_TABLE : public CSMTP_HASH_TABLE
{
public:
CTURN_ACCESS_TABLE()
{
}
virtual DWORD SecondaryCompareFunction(char * SearchData, CHASH_ENTRY * pExistingEntry)
{
DWORD Result = 0;
CTurnData * pTurnData = (CTurnData *)pExistingEntry;
if(pExistingEntry == NULL)
{
return 1;
}
if(SearchData == NULL)
{
return 1;
}
Result = lstrcmpi(SearchData, pTurnData->GetRouteDomainName());
return Result;
}
virtual void MultiszFunction(CHASH_ENTRY * pExistingEntry, MULTISZ* pMsz)
{
CTurnData * pTurnData = (CTurnData *)pExistingEntry;
pMsz->Append(pTurnData->GetRouteDomainName());
}
~CTURN_ACCESS_TABLE(){}
};
#endif