windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/stdprov/cpropset.cpp
2020-09-26 16:20:57 +08:00

1308 lines
27 KiB
C++

/*++
Copyright (C) 1997-2001 Microsoft Corporation
Module Name:
CPROPSET.CPP
Abstract:
Implements the CProp and CPropSet classes.
History:
a-davj 04-Mar-97 Created.
--*/
#include "precomp.h"
#include "stdafx.h"
#include <wbemidl.h>
#include "cpropset.h"
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CProp::CProp()
{
m_dwPropID = 0;
m_dwSize = 0;
m_dwType = VT_EMPTY;
m_pValue = NULL; // must init to NULL
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CProp::~CProp()
{
FreeValue();
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CProp::Set(DWORD dwID, const LPVOID pValue, DWORD dwType, DWORD dwSize)
{
if (m_pValue != NULL)
FreeValue();
m_dwPropID = dwID;
m_dwSize = dwSize;
m_dwType = dwType;
m_pValue = NULL; // set later on if there is data
if(pValue == NULL || m_dwType == 0)
return TRUE;
if (NULL == AllocValue(dwSize))
{
TRACE0("CProp::AllocValue failed");
return FALSE;
}
memcpy(m_pValue, pValue, dwSize);
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
LPVOID CProp::Get()
{ return m_pValue; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
DWORD CProp::GetType()
{ return m_dwType; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
DWORD CProp::GetID()
{ return m_dwPropID; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CProp::WriteToStream(IStream* pIStream)
{
DWORD cb;
// write the type
pIStream->Write((LPVOID)&m_dwType, sizeof(m_dwType), &cb);
if (cb != sizeof(m_dwType))
return FALSE; //todo
// Write the value
if(m_dwSize > 0)
pIStream->Write(m_pValue, m_dwSize, &cb);
if (cb != m_dwSize)
return FALSE ; //todo
// make sure it ends up on a 32 bit boundry
int iLeftover = m_dwSize % 4;
DWORD dwTemp = 0;
if(iLeftover)
pIStream->Write((LPVOID)&dwTemp, iLeftover, &cb);
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CProp::ReadFromStream(IStream* pIStream, DWORD dwSize)
{
DWORD cb;
// All properties are made up of a type/value pair.
// The obvious first thing to do is to get the type...
pIStream->Read((LPVOID)&m_dwType, sizeof(m_dwType), &cb);
if (cb != sizeof(m_dwType))
return FALSE;
if (m_pValue != NULL)
FreeValue();
m_dwSize = dwSize;
m_pValue = NULL;
if(dwSize > 0) {
if (NULL == AllocValue(dwSize))
{
TRACE0("CProp::AllocValue failed");
return FALSE;
}
pIStream->Read((LPVOID)m_pValue, dwSize, &cb); //?? does size need to be passed?
if (cb != dwSize)
return FALSE;
}
// Done!
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
LPVOID CProp::AllocValue(ULONG cb)
{
return m_pValue = malloc((int)cb);
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CProp::FreeValue()
{
if (m_pValue != NULL)
{
free(m_pValue);
m_pValue = NULL;
}
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSection::CPropSection()
{
m_FormatID = GUID_NULL;
m_SH.cbSection = 0;
m_SH.cProperties = 0;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSection::CPropSection( CLSID FormatID)
{
m_FormatID = FormatID;
m_SH.cbSection = 0;
m_SH.cProperties = 0;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSection::~CPropSection()
{
RemoveAll();
return;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSection::SetFormatID(CLSID FormatID)
{ m_FormatID = FormatID; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSection::RemoveAll()
{
POSITION pos = m_PropList.GetHeadPosition();
while (pos != NULL)
delete (CProp*)m_PropList.GetNext(pos);
m_PropList.RemoveAll();
m_SH.cProperties = 0;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CProp* CPropSection::GetProperty(DWORD dwPropID)
{
POSITION pos = m_PropList.GetHeadPosition();
CProp* pProp;
while (pos != NULL)
{
pProp= (CProp*)m_PropList.GetNext(pos);
if (pProp->m_dwPropID == dwPropID)
return pProp;
}
return NULL;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSection::AddProperty(CProp* pProp)
{
m_PropList.AddTail(pProp);
m_SH.cProperties++;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
DWORD CPropSection::GetSize()
{ return m_SH.cbSection; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
DWORD CPropSection::GetCount()
{ return m_PropList.GetCount(); }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CObList* CPropSection::GetList()
{ return &m_PropList; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CPropSection::WriteToStream(IStream* pIStream)
{
// Create a dummy property entry for the name dictionary (ID == 0).
ULONG cb;
ULARGE_INTEGER ulSeekOld;
ULARGE_INTEGER ulSeek;
LPSTREAM pIStrPIDO;
PROPERTYIDOFFSET pido;
LARGE_INTEGER li;
// The Section header contains the number of bytes in the
// section. Thus we need to go back to where we should
// write the count of bytes
// after we write all the property sets..
// We accomplish this by saving the seek pointer to where
// the size should be written in ulSeekOld
m_SH.cbSection = 0;
m_SH.cProperties = m_PropList.GetCount();
LISet32(li, 0);
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeekOld);
pIStream->Write((LPVOID)&m_SH, sizeof(m_SH), &cb);
if (sizeof(m_SH) != cb)
{
TRACE0("Write of section header failed (1).\n");
return FALSE;
}
if (m_PropList.IsEmpty())
{
TRACE0("Warning: Wrote empty property section.\n");
return TRUE;
}
// After the section header is the list of property ID/Offset pairs
// Since there is an ID/Offset pair for each property and we
// need to write the ID/Offset pair as we write each property
// we clone the stream and use the clone to access the
// table of ID/offset pairs (PIDO)...
//
pIStream->Clone(&pIStrPIDO);
// Now seek pIStream past the PIDO list
//
LISet32(li, m_SH.cProperties * sizeof(PROPERTYIDOFFSET));
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
// Now write each section to pIStream.
CProp* pProp = NULL;
POSITION pos = m_PropList.GetHeadPosition();
while (pos != NULL)
{
// Get next element (note cast)
pProp = (CProp*)m_PropList.GetNext(pos);
// Write it
if (!pProp->WriteToStream(pIStream))
{
pIStrPIDO->Release();
return FALSE;
}
// Using our cloned stream write the Format ID / Offset pair
// The offset to this property is the current seek pointer
// minus the pointer to the beginning of the section
pido.dwOffset = ulSeek.LowPart - ulSeekOld.LowPart;
pido.propertyID = pProp->m_dwPropID;
pIStrPIDO->Write((LPVOID)&pido, sizeof(pido), &cb);
if (sizeof(pido) != cb)
{
TRACE0("Write of 'pido' failed\n");
pIStrPIDO->Release();
return FALSE;
}
// Get the seek offset after the write
LISet32(li, 0);
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
}
pIStrPIDO->Release();
// Now go back to ulSeekOld and write the section header.
// Size of section is current seek point minus old seek point
//
m_SH.cbSection = ulSeek.LowPart - ulSeekOld.LowPart;
// Seek to beginning of this section and write the section header.
LISet32(li, ulSeekOld.LowPart);
pIStream->Seek(li, STREAM_SEEK_SET, NULL);
pIStream->Write((LPVOID)&m_SH, sizeof(m_SH), &cb);
if (sizeof(m_SH) != cb)
{
TRACE0("Write of section header failed (2).\n");
return FALSE;
}
// Set pointer to where it was after last write
LISet32(li, ulSeek.LowPart);
pIStream->Seek(li, STREAM_SEEK_SET, NULL);
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CPropSection::ReadFromStream(IStream* pIStream,
LARGE_INTEGER liPropSet)
{
ULONG cb;
LPSTREAM pIStrPIDO;
ULARGE_INTEGER ulSectionStart;
LARGE_INTEGER li;
CProp* pProp;
if (m_SH.cProperties || !m_PropList.IsEmpty())
RemoveAll();
// pIStream is pointing to the beginning of the section we
// are to read. First there is a DWORD that is the count
// of bytes in this section, then there is a count
// of properties, followed by a list of propertyID/offset pairs,
// followed by type/value pairs.
//
LISet32(li, 0);
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSectionStart);
pIStream->Read((LPVOID)&m_SH, sizeof(m_SH), &cb);
if (cb != sizeof(m_SH))
return FALSE;
// Now we're pointing at the first of the PropID/Offset pairs
// (PIDOs). To get to each property we use a cloned stream
// to stay back and point at the PIDOs (pIStrPIDO). We seek
// pIStream to each of the Type/Value pairs, creating CProperites
// and so forth as we go...
//
pIStream->Clone(&pIStrPIDO);
// Read the propid /offset structures first
DWORD dwCnt;
PROPERTYIDOFFSET * pArray = new PROPERTYIDOFFSET[m_SH.cProperties];
if(pArray == NULL)
return FALSE; //TODO
for(dwCnt = 0; dwCnt < m_SH.cProperties; dwCnt++) {
pIStrPIDO->Read((LPVOID)&pArray[dwCnt], sizeof(PROPERTYIDOFFSET), &cb);
if (cb != sizeof(PROPERTYIDOFFSET))
{
pIStrPIDO->Release();
delete pArray;
return FALSE;
}
}
pIStrPIDO->Release();
// Now read in the actual properties
for(dwCnt = 0; dwCnt < m_SH.cProperties; dwCnt++)
{
DWORD dwSize;
// Do a seek from the beginning of the property set.
LISet32(li, ulSectionStart.LowPart + pArray[dwCnt].dwOffset);
pIStream->Seek(liPropSet, STREAM_SEEK_SET, NULL);
pIStream->Seek(li, STREAM_SEEK_CUR, NULL);
// Now pIStream is at the type/value pair
pProp = new CProp(); //todo, error checking???
pProp->Set(pArray[dwCnt].propertyID, NULL, 0,0);
if(dwCnt < m_SH.cProperties-1)
dwSize = pArray[dwCnt+1].dwOffset - pArray[dwCnt].dwOffset -
sizeof(DWORD);
else
dwSize = /*ulSectionStart.LowPart +*/ m_SH.cbSection -
pArray[dwCnt].dwOffset - sizeof(DWORD);
ASSERT(dwSize < 1000);
pProp->ReadFromStream(pIStream,dwSize);
m_PropList.AddTail(pProp);
}
delete pArray;
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CPropSection::SetSectionName(LPCTSTR pszName)
{
m_strSectionName = pszName;
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
LPCTSTR CPropSection::GetSectionName()
{
return (LPCTSTR)m_strSectionName;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSet::CPropSet()
{
m_PH.wByteOrder = 0xFFFE;
m_PH.wFormat = 0;
m_PH.dwOSVer = (DWORD)MAKELONG(LOWORD(GetVersion()), 2);
m_PH.clsID = GUID_NULL;
m_PH.cSections = 0;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSet::~CPropSet()
{ RemoveAll(); }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSet::RemoveAll()
{
POSITION pos = m_SectionList.GetHeadPosition();
while (pos != NULL)
{
delete (CPropSection*)m_SectionList.GetNext(pos);
}
m_SectionList.RemoveAll();
m_PH.cSections = 0;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSection* CPropSet::GetSection(CLSID FormatID)
{
POSITION pos = m_SectionList.GetHeadPosition();
CPropSection* pSect;
while (pos != NULL)
{
pSect = (CPropSection*)m_SectionList.GetNext(pos);
if (IsEqualCLSID(pSect->m_FormatID, FormatID))
return pSect;
}
return NULL;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CPropSection* CPropSet::AddSection(CLSID FormatID)
{
CPropSection* pSect = GetSection(FormatID);
if (pSect)
return pSect;
pSect = new CPropSection(FormatID);
if (pSect)
AddSection(pSect);
return pSect;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSet::AddSection(CPropSection* pSect)
{
m_SectionList.AddTail(pSect);
m_PH.cSections++;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CProp* CPropSet::GetProperty(CLSID FormatID, DWORD dwPropID)
{
CPropSection* pSect = GetSection(FormatID);
if (pSect)
return pSect->GetProperty(dwPropID);
else
return NULL;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSet::AddProperty(CLSID FormatID, CProp* pProp)
{
CPropSection* pSect = GetSection(FormatID);
if(pSect == NULL)
pSect = AddSection(FormatID);
if (pSect)
pSect->AddProperty(pProp);
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
WORD CPropSet::GetByteOrder()
{ return m_PH.wByteOrder; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
WORD CPropSet::GetFormatVersion()
{ return m_PH.wFormat; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSet::SetFormatVersion(WORD wFmtVersion)
{ m_PH.wFormat = wFmtVersion; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
DWORD CPropSet::GetOSVersion()
{ return m_PH.dwOSVer; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSet::SetOSVersion(DWORD dwOSVer)
{ m_PH.dwOSVer = dwOSVer; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CLSID CPropSet::GetClassID()
{ return m_PH.clsID; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CPropSet::SetClassID(CLSID clsID)
{ m_PH.clsID = clsID; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
DWORD CPropSet::GetCount()
{ return m_SectionList.GetCount(); }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CObList* CPropSet::GetList()
{ return &m_SectionList; }
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CPropSet::WriteToStream(IStream* pIStream)
{
LPSTREAM pIStrFIDO;
FORMATIDOFFSET fido;
ULONG cb;
ULARGE_INTEGER ulSeek;
LARGE_INTEGER li;
LISet32(li, 0);
pIStream->Seek(li,STREAM_SEEK_SET,NULL);
// Write the Property List Header
m_PH.cSections = m_SectionList.GetCount();
pIStream->Write((LPVOID)&m_PH, sizeof(m_PH), &cb);
if (sizeof(m_PH) != cb)
{
TRACE0("Write of Property Set Header failed.\n");
return FALSE;
}
if (m_SectionList.IsEmpty())
{
TRACE0("Warning: Wrote empty property set.\n");
return TRUE;
}
// After the header is the list of Format ID/Offset pairs
// Since there is an ID/Offset pair for each section and we
// need to write the ID/Offset pair as we write each section
// we clone the stream and use the clone to access the
// table of ID/offset pairs (FIDO)...
//
pIStream->Clone(&pIStrFIDO);
// Now seek pIStream past the FIDO list
//
LISet32(li, m_PH.cSections * sizeof(FORMATIDOFFSET));
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
// Write each section.
CPropSection* pSect = NULL;
POSITION pos = m_SectionList.GetHeadPosition();
while (pos != NULL)
{
// Get next element (note cast)
pSect = (CPropSection*)m_SectionList.GetNext(pos);
// Write it
if (!pSect->WriteToStream(pIStream))
{
pIStrFIDO->Release();
return FALSE;
}
// Using our cloned stream write the Format ID / Offset pair
fido.formatID = pSect->m_FormatID;
fido.dwOffset = ulSeek.LowPart;
pIStrFIDO->Write((LPVOID)&fido, sizeof(fido), &cb);
if (sizeof(fido) != cb)
{
TRACE0("Write of 'fido' failed.\n");
pIStrFIDO->Release();
return FALSE;
}
// Get the seek offset (for pIStream) after the write
LISet32(li, 0);
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
}
pIStrFIDO->Release();
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
BOOL CPropSet::ReadFromStream(IStream* pIStream)
{
ULONG cb;
FORMATIDOFFSET fido;
ULONG cSections;
LPSTREAM pIStrFIDO;
CPropSection* pSect;
LARGE_INTEGER li;
LARGE_INTEGER liPropSet;
LISet32(li, 0);
pIStream->Seek(li,STREAM_SEEK_SET,NULL);
// Save the stream position at which the property set starts.
LARGE_INTEGER liZero = {0,0};
pIStream->Seek(liZero, STREAM_SEEK_CUR, (ULARGE_INTEGER*)&liPropSet);
if (m_PH.cSections || !m_SectionList.IsEmpty())
RemoveAll();
// The stream starts like this:
// wByteOrder wFmtVer dwOSVer clsID cSections
// Which is nice, because our PROPHEADER is the same!
pIStream->Read((LPVOID)&m_PH, sizeof(m_PH), &cb);
if (cb != sizeof(m_PH))
return FALSE;
// Now we're pointing at the first of the FormatID/Offset pairs
// (FIDOs). To get to each section we use a cloned stream
// to stay back and point at the FIDOs (pIStrFIDO). We seek
// pIStream to each of the sections, creating CProperitySection
// and so forth as we go...
//
pIStream->Clone(&pIStrFIDO);
cSections = m_PH.cSections;
while (cSections--)
{
pIStrFIDO->Read((LPVOID)&fido, sizeof(fido), &cb);
if (cb != sizeof(fido))
{
pIStrFIDO->Release();
return FALSE;
}
// Do a seek from the beginning of the property set.
LISet32(li, fido.dwOffset);
pIStream->Seek(liPropSet, STREAM_SEEK_SET, NULL);
pIStream->Seek(li, STREAM_SEEK_CUR, NULL);
// Now pIStream is at the type/value pair
pSect = new CPropSection;
pSect->SetFormatID(fido.formatID);
pSect->ReadFromStream(pIStream, liPropSet);
m_SectionList.AddTail(pSect);
}
pIStrFIDO->Release();
return TRUE;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CBuff::CBuff( void )
{
bAllocError = FALSE;
pBuff = NULL;
dwSize = 0;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
CBuff::~CBuff()
{
if(pBuff)
CoTaskMemFree(pBuff);
pBuff = NULL;
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CBuff::Add(void * pSrc, DWORD dwAddSize)
{
char * pDest;
if(pBuff == NULL) {
pBuff = CoTaskMemAlloc(dwAddSize);
if(pBuff == NULL) {
bAllocError = TRUE;
return;
}
pDest = (char *)pBuff;
dwSize = dwAddSize;
}
else {
void * pNew;
pNew = CoTaskMemRealloc(pBuff,dwSize+dwAddSize);
if(pNew == NULL) {
bAllocError = TRUE;
return;
}
pBuff = pNew;
pDest = (char *)pBuff + dwSize;
dwSize += dwAddSize;
}
memcpy(pDest,pSrc,dwAddSize);
}
//***************************************************************************
//
//
// DESCRIPTION:
//
//
// PARAMETERS:
//
//
// RETURN VALUE:
//
//***************************************************************************
void CBuff::RoundOff(void)
{
DWORD dwLeftOver = dwSize % 4;
if(dwLeftOver) {
DWORD dwAdd = 4 - dwLeftOver;
DWORD dwZero = 0;
Add((void *)&dwZero,dwAdd);
}
}
/////////////////////////////////////////////////////////////////////////////
// Force any extra compiler-generated code into AFX_INIT_SEG
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif