#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_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; iID()] = 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; iWriteProperty(); 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