321 lines
8.3 KiB
C++
321 lines
8.3 KiB
C++
|
/**********************************************************************/
|
||
|
/** Microsoft Windows/NT **/
|
||
|
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
|
||
|
/**********************************************************************/
|
||
|
|
||
|
/*
|
||
|
memmngr.cpp
|
||
|
memory manager for the WINS db object
|
||
|
|
||
|
FILE HISTORY:
|
||
|
Oct 13 1997 EricDav Modifed
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "wins.h"
|
||
|
#include "memmngr.h"
|
||
|
|
||
|
CMemoryManager::CMemoryManager()
|
||
|
{
|
||
|
m_hHeap = NULL;
|
||
|
}
|
||
|
|
||
|
CMemoryManager::~CMemoryManager()
|
||
|
{
|
||
|
Reset();
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::Initialize
|
||
|
Initializes the memory manager to free up and existing blocks
|
||
|
and pre-allocate one block
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT
|
||
|
CMemoryManager::Initialize()
|
||
|
{
|
||
|
HRESULT hr = hrOK;
|
||
|
|
||
|
CORg (Reset());
|
||
|
CORg (Allocate());
|
||
|
|
||
|
// create a heap for allocation of the multiple IP address blocks
|
||
|
m_hHeap = HeapCreate(0, 4096, 0);
|
||
|
if (m_hHeap == NULL)
|
||
|
{
|
||
|
Trace1("CMemoryManager::Initialize - HeapCreate failed! %d\n", GetLastError());
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
Error:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::Reset
|
||
|
Free's up all memory
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT
|
||
|
CMemoryManager::Reset()
|
||
|
{
|
||
|
// free the memory allocated
|
||
|
for (int i = 0; i< m_BlockArray.GetSize(); i++)
|
||
|
{
|
||
|
::GlobalFree(m_BlockArray.GetAt(i));
|
||
|
}
|
||
|
|
||
|
m_BlockArray.RemoveAll();
|
||
|
|
||
|
if (m_hHeap)
|
||
|
{
|
||
|
HeapDestroy(m_hHeap);
|
||
|
m_hHeap = NULL;
|
||
|
}
|
||
|
|
||
|
return hrOK;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::Allocate
|
||
|
Allocates one memory block
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT
|
||
|
CMemoryManager::Allocate()
|
||
|
{
|
||
|
HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, BLOCK_SIZE);
|
||
|
|
||
|
if (hMem != NULL)
|
||
|
{
|
||
|
m_hrowCurrent = (LPWINSDBRECORD) hMem;
|
||
|
m_BlockArray.Add(hMem);
|
||
|
|
||
|
return hrOK;
|
||
|
}
|
||
|
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::IsvalidHRow
|
||
|
Verifies that the given HROW is valid
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
BOOL
|
||
|
CMemoryManager::IsValidHRow(HROW hrow)
|
||
|
{
|
||
|
// check to see thet this HROW lies between the
|
||
|
// limits, i.e b/n hMem and hMem + INIT_SIZE
|
||
|
for (int i = 0; i < m_BlockArray.GetSize(); i++)
|
||
|
{
|
||
|
if (hrow >= (HROW)(m_BlockArray.GetAt(i)) && (hrow < (HROW)(m_BlockArray.GetAt(i)) + BLOCK_SIZE))
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::AddData
|
||
|
Copies a record into our internal store
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT
|
||
|
CMemoryManager::AddData(const WinsRecord & wRecord, LPHROW phrow)
|
||
|
{
|
||
|
HRESULT hr = hrOK;
|
||
|
|
||
|
CSingleLock cLock(&m_cs);
|
||
|
cLock.Lock();
|
||
|
|
||
|
Assert((BYTE) wRecord.szRecordName[15] == (BYTE) wRecord.dwType);
|
||
|
|
||
|
// check if for the validity fo the current
|
||
|
// m_hrowCurrent
|
||
|
if (!IsValidHRow((HROW) m_hrowCurrent))
|
||
|
{
|
||
|
Allocate();
|
||
|
m_hrowCurrent = (LPWINSDBRECORD) (m_BlockArray.GetAt(m_BlockArray.GetSize() - 1));
|
||
|
}
|
||
|
|
||
|
WinsRecordToWinsDbRecord(m_hHeap, wRecord, m_hrowCurrent);
|
||
|
|
||
|
if (phrow)
|
||
|
*phrow = (HROW) m_hrowCurrent;
|
||
|
|
||
|
// move our pointer to the next record
|
||
|
m_hrowCurrent++;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::GetData
|
||
|
Copies a record into our internal store
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT
|
||
|
CMemoryManager::GetData(HROW hrow, LPWINSRECORD pWinsRecord)
|
||
|
{
|
||
|
HRESULT hr = hrOK;
|
||
|
LPWINSDBRECORD pDbRec = (LPWINSDBRECORD) hrow;
|
||
|
|
||
|
CSingleLock cLock(&m_cs);
|
||
|
cLock.Lock();
|
||
|
|
||
|
// check if for the validity fo the current
|
||
|
// m_hrowCurrent
|
||
|
if (!IsValidHRow(hrow))
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
WinsDbRecordToWinsRecord(pDbRec, pWinsRecord);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
CMemoryManager::Delete
|
||
|
Marks a record as deleted
|
||
|
Author: EricDav, v-shubk
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT
|
||
|
CMemoryManager::Delete(HROW hrow)
|
||
|
{
|
||
|
HRESULT hr = hrOK;
|
||
|
|
||
|
CSingleLock cLock(&m_cs);
|
||
|
cLock.Lock();
|
||
|
|
||
|
LPWINSDBRECORD pRec = (LPWINSDBRECORD) hrow;
|
||
|
|
||
|
pRec->szRecordName[17] |= WINSDB_INTERNAL_DELETED;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WinsRecordToWinsDbRecord(HANDLE hHeap, const WinsRecord & wRecord, const LPWINSDBRECORD pRec)
|
||
|
{
|
||
|
ZeroMemory(pRec, sizeof(WinsDBRecord));
|
||
|
|
||
|
// fill in our internal struct, first the name
|
||
|
if (IS_WINREC_LONGNAME(&wRecord))
|
||
|
{
|
||
|
// name is too long for our internal struct, allocate space off of our heap
|
||
|
// this shouldn't happen very often. Only for scoped names.
|
||
|
pRec->szRecordName[17] |= WINSDB_INTERNAL_LONG_NAME;
|
||
|
char * pName = (char *) ::HeapAlloc(hHeap, HEAP_ZERO_MEMORY, (wRecord.dwNameLen + 1));
|
||
|
if (pName)
|
||
|
{
|
||
|
memcpy(pName, &wRecord.szRecordName[0], wRecord.dwNameLen);
|
||
|
memcpy(&pRec->szRecordName[0], &pName, sizeof(char *));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(&pRec->szRecordName[0], &wRecord.szRecordName[0], 16);
|
||
|
}
|
||
|
|
||
|
pRec->dwExpiration = (DWORD) wRecord.dwExpiration;
|
||
|
pRec->liVersion.QuadPart = wRecord.liVersion.QuadPart;
|
||
|
pRec->dwOwner = wRecord.dwOwner;
|
||
|
|
||
|
// max length is 255, so this is OK
|
||
|
pRec->szRecordName[19] = LOBYTE(LOWORD(wRecord.dwNameLen));
|
||
|
|
||
|
BYTE bTest = HIBYTE(LOWORD(wRecord.dwState));
|
||
|
|
||
|
pRec->szRecordName[20] = HIBYTE(LOWORD(wRecord.dwState));
|
||
|
|
||
|
// only the low byte of the dwState field is used
|
||
|
pRec->szRecordName[18] = (BYTE) wRecord.dwState;
|
||
|
pRec->szRecordName[17] |= HIWORD (wRecord.dwType);
|
||
|
|
||
|
// now figure out how many IP addrs there are
|
||
|
if (wRecord.dwNoOfAddrs > 1)
|
||
|
{
|
||
|
Assert(hHeap);
|
||
|
LPDWORD pdwIpAddrs = (LPDWORD) ::HeapAlloc(hHeap, HEAP_ZERO_MEMORY, (wRecord.dwNoOfAddrs + 1) * sizeof(DWORD));
|
||
|
|
||
|
if (pdwIpAddrs)
|
||
|
{
|
||
|
// first DWORD contains the # of addrs
|
||
|
pdwIpAddrs[0] = wRecord.dwNoOfAddrs;
|
||
|
for (UINT i = 0; i < wRecord.dwNoOfAddrs; i++)
|
||
|
pdwIpAddrs[i+1] = wRecord.dwIpAdd[i];
|
||
|
|
||
|
// now store our pointer off
|
||
|
pRec->dwIpAdd = (DWORD_PTR) pdwIpAddrs;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pRec->dwIpAdd = wRecord.dwIpAdd[0];
|
||
|
}
|
||
|
|
||
|
Assert((BYTE) pRec->szRecordName[16] == NULL);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WinsDbRecordToWinsRecord(const LPWINSDBRECORD pDbRec, LPWINSRECORD pWRec)
|
||
|
{
|
||
|
Assert((BYTE) pDbRec->szRecordName[16] == NULL);
|
||
|
|
||
|
ZeroMemory(pWRec, sizeof(WinsRecord));
|
||
|
DWORD dwType = 0;
|
||
|
|
||
|
size_t length = pDbRec->szRecordName[19] & 0x000000FF;
|
||
|
|
||
|
// fill in our internal struct, name first
|
||
|
if (IS_DBREC_LONGNAME(pDbRec))
|
||
|
{
|
||
|
char * pName = *((char **) pDbRec->szRecordName);
|
||
|
|
||
|
memcpy(&pWRec->szRecordName[0], pName, length);
|
||
|
dwType = (DWORD) pName[15];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(&pWRec->szRecordName[0], &pDbRec->szRecordName[0], 16);
|
||
|
dwType = (DWORD) pWRec->szRecordName[15];
|
||
|
}
|
||
|
|
||
|
pWRec->dwExpiration = pDbRec->dwExpiration;
|
||
|
pWRec->liVersion.QuadPart = pDbRec->liVersion.QuadPart;
|
||
|
pWRec->dwOwner = pDbRec->dwOwner;
|
||
|
pWRec->dwNameLen = length;
|
||
|
|
||
|
WORD wState = MAKEWORD(pDbRec->szRecordName[18], pDbRec->szRecordName[20]);
|
||
|
pWRec->dwState = wState;
|
||
|
|
||
|
//pWRec->dwState = pDbRec->szRecordName[18];
|
||
|
|
||
|
pWRec->dwType = pDbRec->szRecordName[17] & 0x03;
|
||
|
pWRec->dwType = pWRec->dwType << 16;
|
||
|
|
||
|
pWRec->dwType |= dwType;
|
||
|
|
||
|
// now the ip address(es)
|
||
|
if (pWRec->dwState & (BYTE) WINSDB_REC_MULT_ADDRS)
|
||
|
{
|
||
|
LPDWORD pdwIpAddrs = (LPDWORD) pDbRec->dwIpAdd;
|
||
|
|
||
|
// the first DWORD is the count
|
||
|
int nCount = pdwIpAddrs[0];
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
pWRec->dwIpAdd[i] = pdwIpAddrs[i+1];
|
||
|
|
||
|
pWRec->dwNoOfAddrs = (DWORD) nCount;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pWRec->dwIpAdd[0] = (DWORD) pDbRec->dwIpAdd;
|
||
|
pWRec->dwNoOfAddrs = 1;
|
||
|
}
|
||
|
|
||
|
}
|