windows-nt/Source/XPSP1/NT/net/mmc/mprsnap/infobase.cpp
2020-09-26 16:20:57 +08:00

1654 lines
39 KiB
C++

//============================================================================
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: infobase.cpp
//
// History:
// Abolade Gbadegesin Feb. 10, 1996 Created.
//
// V. Raman Nov. 1, 1996
// Fixed alignment code in
// CInfoBase::BlockListToArray
//
// Kenn Takara June 3, 1997
// Wrapped code with a COM object wrapper.
//
// This file contains code for the CInfoBase class as well as
// the Router registry-parsing classes.
//============================================================================
#include "stdafx.h"
#include "globals.h" // holds the various string constants
extern "C" {
#include <rtinfo.h>
}
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//----------------------------------------------------------------------------
// Class: CInfoBase
//
// This function handles loading and saving of multi-block structures
// stored in the registry by the router managers.
//
// The data are saved as REG_BINARY values, and are manipulated using
// the RTR_INFO_BLOCK_HEADER structure as a template.
//----------------------------------------------------------------------------
class CInfoBase : public CObject {
protected:
IfDebug(DECLARE_DYNAMIC(CInfoBase))
public:
CInfoBase();
~CInfoBase();
//--------------------------------------------------------------------
// Registry-access methods
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Function: Load
//
// Loads value named 'pszValue' from subkey 'pszKey' of 'hkey'
//--------------------------------------------------------------------
HRESULT
Load(
IN HKEY hkey,
IN LPCTSTR pszKey,
IN LPCTSTR pszValue );
//--------------------------------------------------------------------
// Function: Save
//
// saves value named 'pszValue' to subkey 'pszKey' of 'hkey';
// 'pszKey' cannot be a path
//--------------------------------------------------------------------
HRESULT
Save(
IN HKEY hkey,
IN LPCTSTR pszKey,
IN LPCTSTR pszValue );
//--------------------------------------------------------------------
// Function: Unload
//
// unloads current infobase contents
//--------------------------------------------------------------------
HRESULT
Unload( );
//--------------------------------------------------------------------
// Function: CopyFrom
//
// copies contents of infobase 'src'
//--------------------------------------------------------------------
HRESULT
CopyFrom(
IN IInfoBase *pSrc);
//--------------------------------------------------------------------
// Function: LoadFrom
//
// loads from byte-array 'pBase'
//--------------------------------------------------------------------
HRESULT
LoadFrom(
IN PBYTE pBase,
IN DWORD dwSize = 0 )
{ Unload(); return ArrayToBlockList(pBase, dwSize); }
//--------------------------------------------------------------------
// Function: WriteTo
//
// sets 'pBase' to point to allocated memory into which
// opaque info is written; saves size of '*pBase' in 'dwSize'
//--------------------------------------------------------------------
HRESULT
WriteTo(
OUT PBYTE& pBase,
OUT DWORD& dwSize )
{
return BlockListToArray(pBase, dwSize);
}
//--------------------------------------------------------------------
// Structure manipulation methods
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Function: GetBlock
//
// retrieves 'dwNth' block of type 'dwType' from the list of blocks
//--------------------------------------------------------------------
HRESULT
GetBlock(
IN DWORD dwType,
OUT InfoBlock*& pBlock,
IN DWORD dwNth = 0 );
//--------------------------------------------------------------------
// Function: SetBlock
//
// Replaces 'dwNth' block of type 'dwType' with a copy of 'pBlock'.
// Note that this copies the data for the block from 'pBlock->pData'.
//--------------------------------------------------------------------
HRESULT
SetBlock(
IN DWORD dwType,
IN InfoBlock* pBlock,
IN DWORD dwNth = 0 );
//--------------------------------------------------------------------
// Function: AddBlock
//
// Add's a new block of type 'dwType' to the list of blocks
//--------------------------------------------------------------------
HRESULT
AddBlock(
IN DWORD dwType,
IN DWORD dwSize,
IN PBYTE pData,
IN DWORD dwCount = 1,
IN BOOL bRemoveFirst = FALSE );
//--------------------------------------------------------------------
// Function: GetData
//
// Retrieves the data for the 'dwNth' block of type 'dwType'.
//--------------------------------------------------------------------
PBYTE
GetData(
IN DWORD dwType,
IN DWORD dwNth = 0 );
//--------------------------------------------------------------------
// Function: SetData
//
// Replaces the data for the 'dwNth' block of type 'dwType'.
// Note that this does not copy 'pData'; the block is changed
// to point to 'pData', and thus 'pData' should not be a pointer
// to data on the stack, and it should not be deleted.
// Furthermore, it must have been allocated using 'new'.
//--------------------------------------------------------------------
HRESULT
SetData(
IN DWORD dwType,
IN DWORD dwSize,
IN PBYTE pData,
IN DWORD dwCount = 1,
IN DWORD dwNth = 0 );
//--------------------------------------------------------------------
// Function: RemoveBlock
//
// Removes the 'dwNth' block of type 'dwType' from the list of blocks.
//--------------------------------------------------------------------
HRESULT
RemoveBlock(
IN DWORD dwType,
IN DWORD dwNth = 0 );
//--------------------------------------------------------------------
// Function: BlockExists
//
// Returns TRUE is a block of the specified type is in the block-list,
// FALSE otherwise
//--------------------------------------------------------------------
BOOL
BlockExists(
IN DWORD dwType
) {
InfoBlock *pblock;
return (GetBlock(dwType, pblock) == NO_ERROR);
}
//--------------------------------------------------------------------
// Function: ProtocolExists
//
// Returns TRUE if the given routing-protocol exists in the info-base;
// this is so if the block is present and non-empty.
//--------------------------------------------------------------------
BOOL
ProtocolExists(
IN DWORD dwProtocol
) {
InfoBlock *pblock;
return (!GetBlock(dwProtocol, pblock) && pblock->dwSize);
}
//--------------------------------------------------------------------
// Function: RemoveAllBlocks
//
// Removes all blocks from the list of blocks.
//--------------------------------------------------------------------
HRESULT
RemoveAllBlocks( ) { return Unload(); }
//--------------------------------------------------------------------
// Function: QueryBlockList
//
// Returns a reference to the list of blocks;
// the returned list contains items of type 'InfoBlock',
// and the list must not be modified.
//--------------------------------------------------------------------
CPtrList&
QueryBlockList( ) { return m_lBlocks; }
//--------------------------------------------------------------------
// Function: GetInfo
//
// Returns information about the infobase. This is useful for
// determining if this is a new infobase or not.
//
// Returns the size (in bytes) of the InfoBase as well as the
// number of blocks.
//--------------------------------------------------------------------
HRESULT
GetInfo(DWORD *pcSize, int *pcBlocks);
protected:
PBYTE m_pBase; // opaque block of bytes loaded
DWORD m_dwSize; // size of m_pBase
CPtrList m_lBlocks; // list of blocks of type InfoBlock
//--------------------------------------------------------------------
// Functions: BlockListToArray
// ArrayToBlockList
//
// These functions handle parsing opaque data into block-lists
// and combining blocks into opaque data.
//--------------------------------------------------------------------
HRESULT
BlockListToArray(
IN PBYTE& pBase,
IN DWORD& dwSize );
HRESULT
ArrayToBlockList(
IN PBYTE pBase,
IN DWORD dwSize );
#ifdef _DEBUG
BOOL m_fLoaded; // TRUE if data was loaded
#endif
};
//---------------------------------------------------------------------------
// Class: CInfoBase
//---------------------------------------------------------------------------
IfDebug(IMPLEMENT_DYNAMIC(CInfoBase, CObject));
//---------------------------------------------------------------------------
// Function: CInfoBase::CInfoBase
//
// minimal contructor
//---------------------------------------------------------------------------
CInfoBase::CInfoBase()
: m_pBase(NULL), m_dwSize(0)
#ifdef _DEBUG
, m_fLoaded(FALSE)
#endif
{ }
//---------------------------------------------------------------------------
// Function: CInfoBase::CInfoBase
//
// destructor.
//---------------------------------------------------------------------------
CInfoBase::~CInfoBase() { Unload(); }
//---------------------------------------------------------------------------
// Function: CInfoBase::CopyFrom
//
// Copies the contents of the given CInfoBase
//---------------------------------------------------------------------------
HRESULT
CInfoBase::CopyFrom(
IN IInfoBase *pSrc
) {
SPIEnumInfoBlock spEnumInfoBlock;
InfoBlock * pbsrc = NULL;
InfoBlock * pbdst = NULL;
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
// Unload the current information, if any
Unload();
// go through the source's blocks copying each one
pSrc->QueryBlockList(&spEnumInfoBlock);
if (spEnumInfoBlock == NULL)
goto Error;
spEnumInfoBlock->Reset();
while (hrOK == spEnumInfoBlock->Next(1, &pbsrc, NULL))
{
// allocate space for the copy
pbdst = new InfoBlock;
Assert(pbdst);
// copy the fields from the source
pbdst->dwType = pbsrc->dwType;
pbdst->dwSize = pbsrc->dwSize;
pbdst->dwCount = pbsrc->dwCount;
// allocate space for a copy of the data
pbdst->pData = NULL;
pbdst->pData = new BYTE[pbsrc->dwSize * pbsrc->dwCount];
Assert(pbdst->pData);
// copy the data
::CopyMemory(pbdst->pData, pbsrc->pData,
pbsrc->dwSize * pbsrc->dwCount);
// add the copy to our list of blocks
m_lBlocks.AddTail(pbdst);
pbdst = NULL;
}
COM_PROTECT_ERROR_LABEL;
}
COM_PROTECT_CATCH;
// if something went wrong, make certain we're unloaded
if (!FHrSucceeded(hr))
{
if (pbdst)
delete pbdst->pData;
delete pbdst;
Unload();
}
#ifdef _DEBUG
if (FHrSucceeded(hr))
m_fLoaded = TRUE;
#endif
return hr;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::Load
//
// Loads the infobase from the specified registry path.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::Load(
IN HKEY hkey,
IN LPCTSTR pszSubKey,
IN LPCTSTR pszValue
) {
PBYTE pBase = NULL;
DWORD dwErr, dwSize, dwType;
RegKey regsubkey; // hold subkey that has to be freed
RegKey regkey; // holds key, must NOT be closed
HRESULT hr = hrOK;
if (pszSubKey && StrLen(pszSubKey))
{
HKEY hkTemp = hkey;
dwErr = regsubkey.Open(hkTemp, pszSubKey, KEY_READ);
if (dwErr != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(dwErr);
// We use this as THE key. However, since this key is attached
// to a RegKey, it will get cleaned up on exit/thrown exception.
hkey = (HKEY) regsubkey;
}
COM_PROTECT_TRY
{
do {
// This regkey is used to utilize the class. Do NOT
// close this regkey (it may be the key that was passed into us).
regkey.Attach(hkey);
// query the value specified for its size and type
dwSize = 0;
dwType = 0;
dwErr = regkey.QueryTypeAndSize(pszValue, &dwType, &dwSize);
if (dwErr != ERROR_SUCCESS)
break;
//$ Review: kennt, if the key is not the correct type
// what error code do we want to return?
if (dwErr != ERROR_SUCCESS || dwType != REG_BINARY)
break;
pBase = new BYTE[dwSize];
Assert(pBase);
// get the actual data
dwErr = regkey.QueryValue(pszValue, (LPVOID) pBase, dwSize);
if (dwErr != ERROR_SUCCESS)
break;
// convert the infobase into a list of blocks
dwErr = ArrayToBlockList(pBase, dwSize);
} while(FALSE);
hr = HRESULT_FROM_WIN32(dwErr);
}
COM_PROTECT_CATCH;
// free the memory allocated for the block
delete [] pBase;
// we do NOT want this key closed
regkey.Detach();
return hr;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::Unload
//
// frees resources used by infoblocks.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::Unload(
) {
//
// go through the list of blocks, deleting each one
//
while (!m_lBlocks.IsEmpty()) {
InfoBlock *pBlock = (InfoBlock *)m_lBlocks.RemoveHead();
if (pBlock->pData) { delete [] pBlock->pData; }
delete pBlock;
}
//
// if we have a copy of the opaque data, free that too
//
if (m_pBase) { delete [] m_pBase; m_pBase = NULL; m_dwSize = 0; }
return HRESULT_FROM_WIN32(NO_ERROR);
}
//---------------------------------------------------------------------------
// Function: CInfoBase::Save
//
// Saves the list of blocks as an infobase in the registry.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::Save(
IN HKEY hkey,
IN LPCTSTR pszSubKey,
IN LPCTSTR pszValue
) {
PBYTE pBase = NULL;
DWORD dwErr, dwSize;
RegKey regsubkey; // hold subkey that has to be freed
RegKey regkey; // holds key, must NOT be closed
HRESULT hr = hrOK;
// create/open the key specified
if (pszSubKey && lstrlen(pszSubKey))
{
dwErr = regsubkey.Create(hkey, pszSubKey,
REG_OPTION_NON_VOLATILE, KEY_WRITE);
if (dwErr != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(dwErr);
// This subkey will get closed by the regsubkey destructor
hkey = (HKEY) regsubkey;
}
COM_PROTECT_TRY
{
do {
regkey.Attach(hkey);
// convert our list of blocks into one block of data
dwErr = BlockListToArray(pBase, dwSize);
if (dwErr != NO_ERROR) { pBase = NULL; break; }
if (!pBase || !dwSize) { break; }
// attempt to set the value
dwErr = regkey.SetValue(pszValue, (LPVOID) pBase, dwSize);
if (dwErr != ERROR_SUCCESS) { break; }
} while(FALSE);
hr = HRESULT_FROM_WIN32(dwErr);
}
COM_PROTECT_CATCH;
regkey.Detach();
delete [] pBase;
return hr;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::GetBlock
//
// Retrieves a block of data of the specified type
// from the currently loaded infobase.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::GetBlock(
IN DWORD dwType,
OUT InfoBlock*& pBlock,
IN DWORD dwNth
) {
POSITION pos;
InfoBlock *pib;
// start at the head of the list, and look for the block requested
pos = m_lBlocks.GetHeadPosition();
while (pos)
{
// retrieve the next block
pib = (InfoBlock *)m_lBlocks.GetNext(pos);
if (pib->dwType != dwType) { continue; }
if (dwNth-- != 0) { continue; }
// this is the block requested
pBlock = pib;
return HRESULT_FROM_WIN32(NO_ERROR);
}
pBlock = NULL;
return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
}
//---------------------------------------------------------------------------
// Function: CInfoBase::SetBlock
//
// Sets a block of data of the specified type to a copy of the given data
// in the currently loaded infobase.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::SetBlock(
IN DWORD dwType,
IN InfoBlock* pBlock,
IN DWORD dwNth
) {
DWORD dwErr;
HRESULT hr;
PBYTE pData;
InfoBlock *pib;
// retrieve the block to be modified
hr = GetBlock(dwType, pib, dwNth);
if (!FHrSucceeded(hr))
return hr;
// modify the contents
if (pBlock->dwSize == 0) { pData = NULL; }
else
{
// allocate space for the new data
pData = new BYTE[pBlock->dwSize * pBlock->dwCount];
Assert(pData);
::CopyMemory(pData, pBlock->pData, pBlock->dwSize * pBlock->dwCount);
}
// if any space was allocated before, free it now
if (pib->pData) { delete [] pib->pData; }
// set the blocks new contents
*pib = *pBlock;
pib->pData = pData;
return HRESULT_FROM_WIN32(NO_ERROR);
}
//--------------------------------------------------------------------
// Function: GetData
//
// Retrieves the data for the 'dwNth' block of type 'dwType'.
//--------------------------------------------------------------------
PBYTE
CInfoBase::GetData(
IN DWORD dwType,
IN DWORD dwNth
) {
InfoBlock* pblock;
if (!FHrSucceeded(GetBlock(dwType, pblock, dwNth)))
return NULL;
return pblock->pData;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::SetData
//
// Sets the data for an existing block.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::SetData(
IN DWORD dwType,
IN DWORD dwSize,
IN PBYTE pData,
IN DWORD dwCount,
IN DWORD dwNth
) {
DWORD dwErr;
InfoBlock *pib;
HRESULT hr;
//
// retrieve the block to be modified
//
hr = GetBlock(dwType, pib, dwNth);
if (!FHrSucceeded(hr)) { return hr; }
//
// modify the data
//
if (pib->pData) { delete [] pib->pData; }
pib->dwSize = dwSize;
pib->dwCount = dwCount;
pib->pData = pData;
return HRESULT_FROM_WIN32(NO_ERROR);
}
//---------------------------------------------------------------------------
// Function: CInfoBase::AddBlock
//
// Adds a block with the given values to the end of the block list.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::AddBlock(
IN DWORD dwType,
IN DWORD dwSize,
IN PBYTE pData,
IN DWORD dwCount,
IN BOOL bRemoveFirst
) {
InfoBlock *pBlock = NULL;
HRESULT hr = hrOK;
if (bRemoveFirst) { RemoveBlock(dwType); }
COM_PROTECT_TRY
{
// allocate space for the block
pBlock = new InfoBlock;
Assert(pBlock);
// initialize member fields with values passed in
pBlock->dwType = dwType;
pBlock->dwSize = dwSize;
pBlock->dwCount = dwCount;
// initialize the data field, copying the data passed in
if (dwSize == 0 || dwCount == 0)
pBlock->pData = NULL;
else
{
pBlock->pData = NULL;
pBlock->pData = new BYTE[dwSize * dwCount];
Assert(pBlock->pData);
::CopyMemory(pBlock->pData, pData, dwSize * dwCount);
}
// add the new block to the end of the list
m_lBlocks.AddTail(pBlock);
}
COM_PROTECT_CATCH;
if (!FHrSucceeded(hr))
{
if (pBlock)
delete pBlock->pData;
delete pBlock;
}
return hr;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::RemoveBlock
//
// Removes a block of the gievn type from the list
//---------------------------------------------------------------------------
HRESULT
CInfoBase::RemoveBlock(
IN DWORD dwType,
IN DWORD dwNth
) {
POSITION pos;
InfoBlock *pBlock;
//
// find the block
//
pos = m_lBlocks.GetHeadPosition();
while (pos) {
POSITION postemp = pos;
pBlock = (InfoBlock *)m_lBlocks.GetNext(pos);
if (pBlock->dwType != dwType) { continue; }
if (dwNth-- != 0) { continue; }
//
// this is the block, remove it from the list
//
m_lBlocks.RemoveAt(postemp);
//
// free the block's memory as well
//
if (pBlock->pData) { delete [] pBlock->pData; }
delete pBlock;
return HRESULT_FROM_WIN32(NO_ERROR);
}
//
// the block wasn't found
//
return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
}
HRESULT CInfoBase::GetInfo(DWORD *pdwSize, int *pcBlocks)
{
if (pdwSize)
*pdwSize = m_dwSize;
if (pcBlocks)
*pcBlocks = (int) m_lBlocks.GetCount();
return hrOK;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::BlockListToArray
//
// Converts a list of blocks into an array.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::BlockListToArray(
OUT PBYTE& pBase,
OUT DWORD& dwSize
) {
PBYTE pdata;
DWORD dwCount;
POSITION pos;
RTR_INFO_BLOCK_HEADER *prtrbase;
RTR_TOC_ENTRY *prtrblock;
InfoBlock *pblock;
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
// Compute the total size occupied by the infobase's blocks
// base structure
dwCount = 0;
dwSize = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry);
// Table Of Contents Entries
pos = m_lBlocks.GetHeadPosition();
while (pos) {
pblock = (InfoBlock *)m_lBlocks.GetNext(pos);
dwSize += sizeof(RTR_TOC_ENTRY);
++dwCount;
}
// information blocks
pos = m_lBlocks.GetHeadPosition();
while (pos) {
pblock = (InfoBlock *)m_lBlocks.GetNext(pos);
dwSize += ALIGN_SHIFT;
dwSize &= ALIGN_MASK;
dwSize += pblock->dwSize * pblock->dwCount;
}
//
// Allocate enough memory to hold the converted infobase
//
pBase = new BYTE[dwSize];
Assert(pBase);
ZeroMemory(pBase, dwSize);
//
// Initialize the header
//
prtrbase = (RTR_INFO_BLOCK_HEADER *)pBase;
prtrbase->Size = dwSize;
prtrbase->Version = RTR_INFO_BLOCK_VERSION;
prtrbase->TocEntriesCount = dwCount;
//
// Now walk the list again, this time copying blocks over
// along with their data
//
prtrblock = prtrbase->TocEntry;
pdata = pBase + FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry) +
dwCount * sizeof(RTR_TOC_ENTRY);
pos = m_lBlocks.GetHeadPosition();
while (pos) {
pdata += ALIGN_SHIFT;
pdata = (PBYTE)((LONG_PTR)pdata & ALIGN_MASK);
pblock = (InfoBlock *)m_lBlocks.GetNext(pos);
prtrblock->InfoType = pblock->dwType;
prtrblock->Count = pblock->dwCount;
prtrblock->InfoSize = pblock->dwSize;
prtrblock->Offset = (ULONG)(pdata - pBase);
if (pblock->pData) {
::CopyMemory(pdata, pblock->pData, pblock->dwSize * pblock->dwCount);
}
pdata += pblock->dwSize * pblock->dwCount;
++prtrblock;
}
}
COM_PROTECT_CATCH;
return hr;
}
//---------------------------------------------------------------------------
// Function: CInfoBase::ArrayToBlockList
//
// This functions converts an array to a list of InfoBlock structures.
//---------------------------------------------------------------------------
HRESULT
CInfoBase::ArrayToBlockList(
IN PBYTE pBase,
IN DWORD dwSize
) {
PBYTE pdata;
DWORD dwCount, dwErr;
RTR_TOC_ENTRY *prtrblock;
RTR_INFO_BLOCK_HEADER *prtrbase;
HRESULT hr = hrOK;
if (!pBase) { return HRESULT_FROM_WIN32(NO_ERROR); }
//
// Walk the infobase converting each block to an InfoBlock
//
prtrbase = (RTR_INFO_BLOCK_HEADER *)pBase;
dwCount = prtrbase->TocEntriesCount;
prtrblock = prtrbase->TocEntry;
for ( ; dwCount > 0; dwCount--) {
//
// Get the next entry in the array
//
pdata = pBase + prtrblock->Offset;
//
// Add the array-entry to the list of blocks
//
hr = AddBlock(
prtrblock->InfoType, prtrblock->InfoSize,
pdata, prtrblock->Count
);
if (!FHrSucceeded(hr))
{
Unload();
return hr;
}
++prtrblock;
}
return HRESULT_FROM_WIN32(NO_ERROR);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// This section is for the actual implementation of the various
// COM objects, which wrap the previous C++ implementation.
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/*---------------------------------------------------------------------------
Class: InfoBase
This is an interface wrapper around the CInfoBase class.
---------------------------------------------------------------------------*/
class InfoBase :
public IInfoBase
{
public:
DeclareIUnknownMembers(IMPL)
DeclareIInfoBaseMembers(IMPL)
InfoBase();
~InfoBase();
protected:
CInfoBase m_cinfobase;
LONG m_cRef;
};
/*---------------------------------------------------------------------------
Class: InfoBlockEnumerator
---------------------------------------------------------------------------*/
class InfoBlockEnumerator :
public IEnumInfoBlock
{
public:
DeclareIUnknownMembers(IMPL)
DeclareIEnumInfoBlockMembers(IMPL)
InfoBlockEnumerator(IInfoBase *pInfoBase, CPtrList* pPtrList);
~InfoBlockEnumerator();
protected:
SPIInfoBase m_spInfoBase;
CPtrList * m_pPtrList;
POSITION m_pos;
LONG m_cRef;
};
/*---------------------------------------------------------------------------
InfoBase implementation
---------------------------------------------------------------------------*/
DEBUG_DECLARE_INSTANCE_COUNTER(InfoBase)
InfoBase::InfoBase()
: m_cRef(1)
{
DEBUG_INCREMENT_INSTANCE_COUNTER(InfoBase);
}
InfoBase::~InfoBase()
{
Unload();
DEBUG_DECREMENT_INSTANCE_COUNTER(InfoBase);
}
IMPLEMENT_ADDREF_RELEASE(InfoBase);
HRESULT InfoBase::QueryInterface(REFIID riid, LPVOID *ppv)
{
// Is the pointer bad?
if (ppv == NULL)
return E_INVALIDARG;
// Place NULL in *ppv in case of failure
*ppv = NULL;
// This is the non-delegating IUnknown implementation
if (riid == IID_IUnknown)
*ppv = (LPVOID) this;
else if (riid == IID_IInfoBase)
*ppv = (IInfoBase *) this;
// If we're going to return an interface, AddRef it first
if (*ppv)
{
((LPUNKNOWN) *ppv)->AddRef();
return hrOK;
}
else
return E_NOINTERFACE;
}
/*!--------------------------------------------------------------------------
InfoBase::Load
Implementation of IInfoBase::Load
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::Load(HKEY hKey,
LPCOLESTR pszKey,
LPCOLESTR pszValue)
{
HRESULT hr;
COM_PROTECT_TRY
{
hr = m_cinfobase.Load(hKey, OLE2CT(pszKey), OLE2CT(pszValue));
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::Save
Implementation of IInfoBase::Save
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::Save(HKEY hKey,
LPCOLESTR pszKey,
LPCOLESTR pszValue)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.Save(hKey, OLE2CT(pszKey), OLE2CT(pszValue));
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::Unload
Implementation of IInfoBase::Unload
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::Unload()
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.Unload();
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::CopyFrom
Implementation of IInfoBase::CopyFrom
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::CopyFrom(IInfoBase * pSrc)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.CopyFrom(pSrc);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::LoadFrom
Implementation of IInfoBase::LoadFrom
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::LoadFrom(DWORD dwSize, PBYTE pBase)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.LoadFrom(pBase, dwSize);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::WriteTo
Implementation of IInfoBase::WriteTo
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::WriteTo(PBYTE *ppBase,
DWORD *pdwSize)
{
HRESULT hr = hrOK;
PBYTE pBaseT = NULL;
DWORD dwSizeT;
Assert(ppBase);
Assert(pdwSize);
COM_PROTECT_TRY
{
hr = m_cinfobase.WriteTo(pBaseT, dwSizeT);
if (FHrSucceeded(hr))
{
*ppBase = (PBYTE) CoTaskMemAlloc(dwSizeT);
if (*ppBase == NULL)
hr = E_OUTOFMEMORY;
else
{
::CopyMemory(*ppBase, pBaseT, dwSizeT);
*pdwSize = dwSizeT;
delete pBaseT;
}
}
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::GetBlock
Implementation of IInfoBase::GetBlock
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::GetBlock(DWORD dwType,
InfoBlock **ppBlock,
DWORD dwNth)
{
HRESULT hr = hrOK;
Assert(ppBlock);
COM_PROTECT_TRY
{
hr = m_cinfobase.GetBlock(dwType, *ppBlock, dwNth);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::SetBlock
Implementation of IInfoBase::SetBlock
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::SetBlock(DWORD dwType,
InfoBlock *pBlock,
DWORD dwNth)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.SetBlock(dwType, pBlock, dwNth);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::AddBlock
Implementation of IInfoBase::AddBlock
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::AddBlock(DWORD dwType,
DWORD dwSize,
PBYTE pData,
DWORD dwCount,
BOOL bRemoveFirst)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.AddBlock(dwType, dwSize, pData, dwCount, bRemoveFirst);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::GetData
Implementation of IInfoBase::GetData
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::GetData(DWORD dwType,
DWORD dwNth,
PBYTE * ppData)
{
HRESULT hr = hrOK;
PBYTE pb = NULL;
Assert(ppData);
COM_PROTECT_TRY
{
pb = m_cinfobase.GetData(dwType, dwNth);
*ppData = pb;
}
COM_PROTECT_CATCH;
return *ppData ? hr : E_INVALIDARG;
}
/*!--------------------------------------------------------------------------
InfoBase::SetData
Implementation of IInfoBase::SetData
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::SetData(DWORD dwType,
DWORD dwSize,
PBYTE pData,
DWORD dwCount,
DWORD dwNth)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.SetData(dwType, dwSize, pData, dwCount, dwNth);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::RemoveBlock
Implementation of IInfoBase::RemoveBlock
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::RemoveBlock(DWORD dwType,
DWORD dwNth)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.RemoveBlock(dwType, dwNth);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::BlockExists
Implementation of IInfoBase::BlockExists
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::BlockExists(DWORD dwType )
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.BlockExists(dwType) ? hrOK : hrFalse;
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::ProtocolExists
Implementation of IInfoBase::ProtocolExists
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::ProtocolExists(DWORD dwProtocol )
{
HRESULT hr = hrOK;
BOOL bResult;
COM_PROTECT_TRY
{
bResult = m_cinfobase.ProtocolExists(dwProtocol);
hr = (bResult ? S_OK : S_FALSE);
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::RemoveAllBlocks
Implementation of IInfoBase::RemoveAllBlocks
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::RemoveAllBlocks()
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
hr = m_cinfobase.RemoveAllBlocks();
}
COM_PROTECT_CATCH;
return hr;
}
/*!--------------------------------------------------------------------------
InfoBase::QueryBlockList
Implementation of IInfoBase::QueryBlockList
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBase::QueryBlockList(IEnumInfoBlock **ppBlockEnum)
{
HRESULT hr = hrOK;
InfoBlockEnumerator *pIBEnum = NULL;
COM_PROTECT_TRY
{
pIBEnum = new InfoBlockEnumerator(this, &m_cinfobase.QueryBlockList());
Assert(pIBEnum);
}
COM_PROTECT_CATCH;
*ppBlockEnum = static_cast<IEnumInfoBlock *>(pIBEnum);
return hr;
}
STDMETHODIMP InfoBase::GetInfo(DWORD *pdwSize, int *pcBlocks)
{
return m_cinfobase.GetInfo(pdwSize, pcBlocks);
return hrOK;
}
/*!--------------------------------------------------------------------------
CreateInfoBase
Creates an IInfoBase object.
Author: KennT
---------------------------------------------------------------------------*/
TFSCORE_API(HRESULT) CreateInfoBase(IInfoBase **ppInfoBase)
{
HRESULT hr = hrOK;
InfoBase * pinfobase = NULL;
Assert(ppInfoBase);
COM_PROTECT_TRY
{
pinfobase = new InfoBase;
*ppInfoBase = static_cast<IInfoBase *>(pinfobase);
}
COM_PROTECT_CATCH;
return hr;
}
/*---------------------------------------------------------------------------
InfoBlockEnumerator implementation
---------------------------------------------------------------------------*/
DEBUG_DECLARE_INSTANCE_COUNTER(InfoBlockEnumerator);
InfoBlockEnumerator::InfoBlockEnumerator(IInfoBase *pInfoBase, CPtrList *pPtrList)
: m_cRef(1)
{
m_spInfoBase.Set(pInfoBase);
m_pPtrList = pPtrList;
DEBUG_INCREMENT_INSTANCE_COUNTER(InfoBlockEnumerator);
}
InfoBlockEnumerator::~InfoBlockEnumerator()
{
DEBUG_DECREMENT_INSTANCE_COUNTER(InfoBlockEnumerator);
}
IMPLEMENT_ADDREF_RELEASE(InfoBlockEnumerator);
HRESULT InfoBlockEnumerator::QueryInterface(REFIID riid, LPVOID *ppv)
{
// Is the pointer bad?
if (ppv == NULL)
return E_INVALIDARG;
// Place NULL in *ppv in case of failure
*ppv = NULL;
// This is the non-delegating IUnknown implementation
if (riid == IID_IUnknown)
*ppv = (LPVOID) this;
else if (riid == IID_IEnumInfoBlock)
*ppv = (IEnumInfoBlock *) this;
// If we're going to return an interface, AddRef it first
if (*ppv)
{
((LPUNKNOWN) *ppv)->AddRef();
return hrOK;
}
else
return E_NOINTERFACE;
}
/*!--------------------------------------------------------------------------
InfoBlockEnumerator::Next
Implementation of IEnumInfoBlock::Next
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBlockEnumerator::Next(ULONG uNum, InfoBlock **ppBlock,
ULONG *pNumReturned)
{
Assert(uNum == 1);
Assert(m_pPtrList);
Assert(ppBlock);
if (ppBlock)
*ppBlock = NULL;
if (!m_pos)
{
if (pNumReturned)
*pNumReturned = 0;
return S_FALSE;
}
*ppBlock = (InfoBlock *) m_pPtrList->GetNext(m_pos);
if (pNumReturned)
*pNumReturned = 1;
return hrOK;
}
/*!--------------------------------------------------------------------------
InfoBlockEnumerator::Skip
Implementation of IEnumInfoBlock::Skip
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBlockEnumerator::Skip(ULONG uNum)
{
Assert(uNum == 1);
Assert(m_pPtrList);
if (!m_pos)
return S_FALSE;
m_pPtrList->GetNext(m_pos);
return hrOK;
}
/*!--------------------------------------------------------------------------
InfoBlockEnumerator::Reset
Implementation of IEnumInfoBlock::Reset
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBlockEnumerator::Reset()
{
Assert(m_pPtrList);
m_pos = m_pPtrList->GetHeadPosition();
return hrOK;
}
/*!--------------------------------------------------------------------------
InfoBlockEnumerator::Clone
Implementation of IEnumInfoBlock::Clone
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP InfoBlockEnumerator::Clone(IEnumInfoBlock **ppBlockEnum)
{
return E_NOTIMPL;
}