WindowsXP/inetsrv/iis/svcs/infocomm/metadata/dll/mbcollectionwriter.cpp
2025-04-27 07:49:33 -04:00

661 lines
14 KiB
C++

#include "catalog.h"
#include "Catmeta.h"
#include "WriterGlobalHelper.h"
#include "Writer.h"
#include "WriterGlobals.h"
#include "MBPropertyWriter.h"
#include "MBCollectionWriter.h"
typedef CMBPropertyWriter* LP_CMBPropertyWriter;
//
// TODO: Determine an optimal number - set to max number of properties in an ADSI class?
//
#define MAX_PROPERTY 700
/***************************************************************************++
Routine Description:
Constructor for CMBCollectionWriter.
Arguments:
None.
Return Value:
None.
--***************************************************************************/
CMBCollectionWriter::CMBCollectionWriter():
m_pCWriter(NULL),
m_wszMBClass(NULL),
m_wszContainerClassList(NULL),
m_bContainer(FALSE),
m_apProperty(NULL),
m_cProperty(0),
m_iProperty(0),
m_aIndexToProperty(NULL),
m_dwLargestID(1)
{
} // CCollectionWriter
/***************************************************************************++
Routine Description:
Destructor for CMBCollectionWriter.
Arguments:
None.
Return Value:
None.
--***************************************************************************/
CMBCollectionWriter::~CMBCollectionWriter()
{
if(NULL != m_apProperty)
{
for(ULONG i=0; i<m_iProperty; i++)
{
if(NULL != m_apProperty[i])
{
delete m_apProperty[i];
m_apProperty[i] = NULL;
}
}
delete [] m_apProperty;
m_apProperty = NULL;
}
m_cProperty = 0;
m_iProperty = 0;
} // ~CCollectionWriter
/***************************************************************************++
Routine Description:
Initialize the collection writer object
Arguments:
[in] Name of the collection
[in] Optional - Is its a container class (for Non-IIsConfigObject
collections)
[in] Optional - Container class list (for Non-IIsConfigObject
collections)
[in] Writer object - Assume that it is valid for the lifetime of the
collection writer
Return Value:
None.
--***************************************************************************/
void CMBCollectionWriter::Initialize(LPCWSTR i_wszMBClass,
BOOL i_bContainer,
LPCWSTR i_wszContainerClassList,
CWriter* i_pcWriter)
{
m_wszMBClass = i_wszMBClass;
m_bContainer = i_bContainer;
m_wszContainerClassList = i_wszContainerClassList;
//
// Assumption: i_pcWriter will be valid for the
// lifetime of the schema writer object.
//
m_pCWriter = i_pcWriter;
} // CCatalogCollectionWriter::Initialize
/***************************************************************************++
Routine Description:
Creates a new property writer and adds it to its list.
Note: This is called only when you add a property to the IIsConfigObject
collection.
Arguments:
[in] Property ID.
[out] Property writer object.
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::GetMBPropertyWriter(DWORD i_dwID,
CMBPropertyWriter** o_pProperty)
{
HRESULT hr = S_OK;
if((NULL == m_aIndexToProperty) ||
(i_dwID > m_dwLargestID) ||
(NULL == m_aIndexToProperty[i_dwID])
)
{
//
// If index not created, then create a new property.
// If index does not have an object for this id, then create it.
// Note if the ID is greater than the largest id and the index
// has been created then GetNewMBPropertyWriter reallocates
// the index. GetNewMBPropertyWriter updates the index with
// the new property, if the index array has been created.
//
hr = GetNewMBPropertyWriter(i_dwID,
o_pProperty);
}
else
{
//
// If Index has a valid object, then return from index.
//
*o_pProperty = m_aIndexToProperty[i_dwID];
}
return hr;
} // CMBCollectionWriter::GetMBPropertyWriter
/***************************************************************************++
Routine Description:
Creates a new property writer and adds it to its list.
Note: This is called only when you add a property to the non-
IIsConfigObject collection.
Arguments:
[in] Name of the collection
[in] Is it a manditory property or not.
[out] Property writer object.
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::GetMBPropertyWriter(LPCWSTR i_wszName,
BOOL i_bMandatory,
CMBPropertyWriter** o_pProperty)
{
HRESULT hr = S_OK;
DWORD dwID = -1;
//
// TODO: Assert that the index is always NULL.
//
if(m_iProperty == m_cProperty)
{
hr = ReAllocate();
if(FAILED(hr))
{
return hr;
}
}
m_apProperty[m_iProperty++] = new CMBPropertyWriter();
if(NULL == m_apProperty[m_iProperty-1])
{
return E_OUTOFMEMORY;
}
m_apProperty[m_iProperty-1]->Initialize(dwID,
i_bMandatory,
this,
m_pCWriter);
m_apProperty[m_iProperty-1]->AddNameToProperty(i_wszName);
*o_pProperty = m_apProperty[m_iProperty-1];
return hr;
} // CMBCollectionWriter::GetMBPropertyWriter
/***************************************************************************++
Routine Description:
Helper function that creates a new property writer and adds it to its
list.
Arguments:
[in] Property ID
[out] Property writer object.
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::GetNewMBPropertyWriter(DWORD i_dwID,
CMBPropertyWriter** o_pProperty)
{
HRESULT hr = S_OK;
if(m_iProperty == m_cProperty)
{
hr = ReAllocate();
if(FAILED(hr))
{
return hr;
}
}
m_apProperty[m_iProperty++] = new CMBPropertyWriter();
if(NULL == m_apProperty[m_iProperty-1])
{
return E_OUTOFMEMORY;
}
m_apProperty[m_iProperty-1]->Initialize(i_dwID,
FALSE,
this,
m_pCWriter);
*o_pProperty = m_apProperty[m_iProperty-1];
if(NULL == m_aIndexToProperty)
{
hr = ReAllocateIndex(i_dwID);
if(FAILED(hr))
{
return hr;
}
}
if(i_dwID > m_dwLargestID)
{
//
// If the ID being added, is greater than the highest ID seen so far,
// then update the highest id saved, and if the index has been
// created, update it.
//
hr = ReAllocateIndex(i_dwID);
if(FAILED(hr))
{
return hr;
}
}
//
// If the index has been created, then updated it with the new property
//
m_aIndexToProperty[i_dwID] = *o_pProperty;
return hr;
} // CMBCollectionWriter::GetNewMBPropertyWriter
/***************************************************************************++
Routine Description:
Helper function grows the buffer that contains all property writers of
a collection.
Arguments:
None
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::ReAllocate()
{
CMBPropertyWriter** pSav = NULL;
pSav = new LP_CMBPropertyWriter[m_cProperty + MAX_PROPERTY];
if(NULL == pSav)
{
return E_OUTOFMEMORY;
}
memset(pSav, 0, (sizeof(LP_CMBPropertyWriter))*(m_cProperty + MAX_PROPERTY));
if(NULL != m_apProperty)
{
memcpy(pSav, m_apProperty, (sizeof(LP_CMBPropertyWriter))*(m_cProperty));
delete [] m_apProperty;
m_apProperty = NULL;
}
m_apProperty = pSav;
m_cProperty = m_cProperty + MAX_PROPERTY;
return S_OK;
} // CMBCollectionWriter::ReAllocate
/***************************************************************************++
Routine Description:
In order to provide fast access to locate the property writer of a given
property, we create an index to the property writer buffer based on the
property id. m_aIndexToProperty[PropertyID] will give you a pointer to the
property writer object for that property.
This function creates the index.
Arguments:
None
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::CreateIndex()
{
HRESULT hr = S_OK;
hr = ReAllocateIndex(m_dwLargestID);
if(FAILED(hr))
{
return hr;
}
for(ULONG i=0; i<m_iProperty; i++)
{
m_aIndexToProperty[m_apProperty[i]->ID()] = m_apProperty[i];
}
return hr;
} // CMBCollectionWriter::CreateIndex
/***************************************************************************++
Routine Description:
Helper function grows the property writer index buffer.
Arguments:
None
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::ReAllocateIndex(DWORD i_dwLargestID)
{
CMBPropertyWriter** pSav = NULL;
DWORD dwLargestID = 0;
//
// Always allocate one more that the largest ID because if the largest
// ID is say "i" we will store in m_aIndexToProperty[i] and hence need
// array of size i+1
//
// Since the index is being updated everytime a new property is added
// we allocate extra space so that we dont have to reallocate each time.
//
//
if(i_dwLargestID < 0xFFFFFFFF)
{
if(i_dwLargestID < 0xFFFFFFFF-(50+1))
{
dwLargestID = i_dwLargestID+50;
}
else
{
dwLargestID = i_dwLargestID;
}
}
else
{
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
}
pSav = new LP_CMBPropertyWriter[dwLargestID+1];
if(NULL == pSav)
{
return E_OUTOFMEMORY;
}
memset(pSav, 0, (sizeof(LP_CMBPropertyWriter))*(dwLargestID+1));
if(NULL != m_aIndexToProperty)
{
memcpy(pSav, m_aIndexToProperty, (sizeof(LP_CMBPropertyWriter))*(m_dwLargestID+1));
delete [] m_aIndexToProperty;
m_aIndexToProperty = NULL;
}
m_aIndexToProperty = pSav;
m_dwLargestID = dwLargestID;
return S_OK;
} // CMBCollectionWriter::ReAllocateIndex
/***************************************************************************++
Routine Description:
Function that writes the collection.
Arguments:
None
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::WriteCollection()
{
HRESULT hr = S_OK;
hr = BeginWriteCollection();
if(FAILED(hr))
{
return hr;
}
for(ULONG i=0; i<m_iProperty; i++)
{
hr = m_apProperty[i]->WriteProperty();
if(FAILED(hr))
{
return hr;
}
}
hr = EndWriteCollection();
if(FAILED(hr))
{
return hr;
}
return hr;
} // CMBCollectionWriter::WriteCollection
/***************************************************************************++
Routine Description:
Function that writes the begin collection tag
Arguments:
None
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::BeginWriteCollection()
{
HRESULT hr = S_OK;
LPWSTR wszEndBeginCollection = NULL;
ULONG cchEndBeginCollection = 0;
ULONG iColMetaFlagsEx = iTABLEMETA_SchemaGeneratorFlags;
LPWSTR wszContainer = NULL;
if(0 == _wcsicmp(m_wszMBClass, wszTABLE_IIsConfigObject))
{
wszEndBeginCollection = (LPWSTR)g_wszSchemaGen;
cchEndBeginCollection = g_cchSchemaGen;
}
else
{
wszEndBeginCollection = (LPWSTR)g_wszInheritsFrom;
cchEndBeginCollection = g_cchInheritsFrom;
}
if(m_bContainer)
{
hr = m_pCWriter->m_pCWriterGlobalHelper->FlagToString(fTABLEMETA_CONTAINERCLASS,
&wszContainer,
wszTABLE_TABLEMETA,
iColMetaFlagsEx);
if(FAILED(hr))
{
goto exit;
}
}
hr = m_pCWriter->WriteToFile((LPVOID)g_wszBeginCollection,
g_cchBeginCollection);
if(FAILED(hr))
{
goto exit;
}
hr = m_pCWriter->WriteToFile((LPVOID)m_wszMBClass,
wcslen(m_wszMBClass));
if(FAILED(hr))
{
goto exit;
}
if(m_bContainer)
{
hr = m_pCWriter->WriteToFile((LPVOID)g_wszMetaFlagsExEq,
g_cchMetaFlagsExEq);
if(FAILED(hr))
{
goto exit;
}
hr = m_pCWriter->WriteToFile((LPVOID)wszContainer,
wcslen(wszContainer));
if(FAILED(hr))
{
goto exit;
}
}
if(m_wszContainerClassList)
{
hr = m_pCWriter->WriteToFile((LPVOID)g_wszContainerClassListEq,
g_cchContainerClassListEq);
if(FAILED(hr))
{
goto exit;
}
hr = m_pCWriter->WriteToFile((LPVOID)m_wszContainerClassList,
wcslen(m_wszContainerClassList));
if(FAILED(hr))
{
goto exit;
}
}
hr = m_pCWriter->WriteToFile((LPVOID)wszEndBeginCollection,
wcslen(wszEndBeginCollection));
if(FAILED(hr))
{
goto exit;
}
exit:
if(NULL != wszContainer)
{
delete [] wszContainer;
wszContainer = NULL;
}
return hr;
} // CMBCollectionWriter::BeginWriteCollection
/***************************************************************************++
Routine Description:
Function that writes the end collection tag
Arguments:
None
Return Value:
HRESULT
--***************************************************************************/
HRESULT CMBCollectionWriter::EndWriteCollection()
{
return m_pCWriter->WriteToFile((LPVOID)g_wszEndCollection,
g_cchEndCollection);
} // CMBCollectionWriter::EndWriteCollection