You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1653 lines
41 KiB
1653 lines
41 KiB
//============================================================================
|
|
// 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;
|
|
}
|
|
|