|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
Importer.cpp
Abstract:
IIS MetaBase subroutines to support Import
Author:
Mohit Srivastava 04-April-01
Revision History:
Notes:
--*/
#include "precomp.hxx"
const WCHAR CImporter::sm_wszInheritedPropertiesLocationPrefix[] = L"inherited:"; const ULONG CImporter::sm_cchInheritedPropertiesLocationPrefix = sizeof(sm_wszInheritedPropertiesLocationPrefix)/sizeof(WCHAR) - 1;
//
// public
//
CImporter::CImporter( LPCWSTR i_wszFileName, LPCSTR i_pszPassword) { m_bInitCalled = false;
m_wszFileName = i_wszFileName; m_pszPassword = i_pszPassword; }
CImporter::~CImporter() { }
HRESULT CImporter::Init() { MD_ASSERT(m_bInitCalled == false); m_bInitCalled = true; return InitIST(); }
HRESULT CImporter::ShowPathsInFile( LPCWSTR pszKeyType, DWORD dwMDBufferSize, LPWSTR pszBuffer, DWORD* pdwMDRequiredBufferSize) { HRESULT hr = S_OK;
//
// All of the stuff is read into pISTProperty.
// Now loop through and populate in-memory cache.
// Properties are sorted by location.
//
ULONG acbMBPropertyRow[cMBProperty_NumberOfColumns]; tMBPropertyRow MBPropertyRow; DWORD dwPreviousLocationID = (DWORD)-1; DWORD bufLoc = 0; DWORD dSize = 0;
for(ULONG i=0; ;i++) { hr = m_spISTProperty->GetColumnValues( i, cMBProperty_NumberOfColumns, 0, acbMBPropertyRow, (LPVOID*)&MBPropertyRow); if(E_ST_NOMOREROWS == hr) { hr = S_OK; break; } else if(FAILED(hr)) { DBGINFO((DBG_CONTEXT, "[ReadSomeDataFromXML] GetColumnValues failed with hr = 0x%x. Table:%ws. Read row index:%d.\n", \ hr, wszTABLE_MBProperty, i)); return hr; }
bool bNewLocation = false; if(dwPreviousLocationID != *MBPropertyRow.pLocationID) { dwPreviousLocationID = *MBPropertyRow.pLocationID; bNewLocation = true; }
if(*MBPropertyRow.pID == MD_KEY_TYPE || *MBPropertyRow.pID == MD_SERVER_COMMENT) { if (!wcscmp((LPCWSTR)MBPropertyRow.pValue, pszKeyType)) { // MBPropertyRow.pLocation
dSize = (DWORD)wcslen(MBPropertyRow.pLocation); if (bufLoc + dSize < dwMDBufferSize - 1) { wcscpy(&(pszBuffer[bufLoc]), MBPropertyRow.pLocation); pszBuffer[bufLoc + dSize] = 0; } bufLoc += dSize+1; } } }
if (bufLoc < dwMDBufferSize) { pszBuffer[bufLoc] = 0; } else { pszBuffer[dwMDBufferSize-1] = 0; pszBuffer[dwMDBufferSize-2] = 0; }
*pdwMDRequiredBufferSize = bufLoc; return hr; }
HRESULT CImporter::DoIt( LPWSTR i_wszSourcePath, LPCWSTR i_wszKeyType, DWORD i_dwMDFlags, CMDBaseObject** o_ppboNew) /*++
Synopsis:
Arguments: [i_wszSourcePath] - [i_wszKeyType] - [i_dwMDFlags] - [o_ppboNew] -
Return Value:
--*/ { MD_ASSERT(m_bInitCalled); MD_ASSERT(i_wszKeyType); MD_ASSERT(o_ppboNew); MD_ASSERT(*o_ppboNew == NULL);
HRESULT hr = S_OK; BOOL bSawSourcePath = false; LPWSTR pLocation = NULL;
//
// This is a pointer to some node in *o_ppboNew
// It is the current node we are reading to.
//
CMDBaseObject* pboRead = NULL;
//
// Used for decryption
//
IIS_CRYPTO_STORAGE* pStorage = NULL;
g_LockMasterResource.ReadLock(); hr = InitSessionKey(m_spISTProperty, &pStorage, (LPSTR)m_pszPassword); g_LockMasterResource.ReadUnlock(); if(FAILED(hr)) { goto exit; }
//
// Create the parent base object
//
*o_ppboNew = new CMDBaseObject(L"Thenamedoesntmatter", NULL); if (*o_ppboNew == NULL || !((*o_ppboNew)->IsValid()) ) { hr = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); delete *o_ppboNew; goto exit; }
//
// All of the stuff is read into pISTProperty.
// Now loop through and populate in-memory cache.
// Properties are sorted by location.
//
ULONG acbMBPropertyRow[cMBProperty_NumberOfColumns]; tMBPropertyRow MBPropertyRow; BOOL bSkipLocation = FALSE; DWORD dwPreviousLocationID = (DWORD)-1; Relation eRelation = eREL_NONE; for(ULONG i=0; ;i++) { BOOL bLocationWithProperty = TRUE; BOOL bNewLocation = FALSE;
hr = m_spISTProperty->GetColumnValues( i, cMBProperty_NumberOfColumns, 0, acbMBPropertyRow, (LPVOID*)&MBPropertyRow); if(E_ST_NOMOREROWS == hr) { hr = S_OK; break; } else if(FAILED(hr)) { DBGINFOW((DBG_CONTEXT, L"[ReadSomeDataFromXML] GetColumnValues failed with hr = 0x%x. Table:%s. Read row index:%d.\n", \ hr, wszTABLE_MBProperty, i));
goto exit; }
if(0 == wcscmp(MD_GLOBAL_LOCATIONW, MBPropertyRow.pLocation)) { //
// Ignore globals.
//
continue; }
if((*MBPropertyRow.pID == MD_LOCATION) && (*MBPropertyRow.pName == MD_CH_LOC_NO_PROPERTYW)) { bLocationWithProperty = FALSE; } if(dwPreviousLocationID != *MBPropertyRow.pLocationID) { bNewLocation = TRUE; bSkipLocation = FALSE; dwPreviousLocationID = *MBPropertyRow.pLocationID; pboRead = *o_ppboNew; pLocation = MBPropertyRow.pLocation;
if(*MBPropertyRow.pGroup == eMBProperty_IIsInheritedProperties) { if(_wcsnicmp( pLocation, sm_wszInheritedPropertiesLocationPrefix, sm_cchInheritedPropertiesLocationPrefix) == 0) { pLocation += sm_cchInheritedPropertiesLocationPrefix; } } } if(bSkipLocation) { continue; } #if DBG
if(bLocationWithProperty == false) { MD_ASSERT(bNewLocation); } #endif
if(bNewLocation) { //
// See if we're at a (grand*)child or self
//
eRelation = GetRelation(i_wszSourcePath, pLocation);
switch(eRelation) { case eREL_SELF: if(*MBPropertyRow.pGroup != eMBProperty_IIsInheritedProperties) { bSawSourcePath = true; } break; case eREL_PARENT: if(!(i_dwMDFlags & MD_IMPORT_INHERITED)) { bSkipLocation = TRUE; continue; } break; case eREL_CHILD: if(i_dwMDFlags & MD_IMPORT_NODE_ONLY) { bSkipLocation = TRUE; continue; } break; default: // eRelation == eREL_NONE
bSkipLocation = TRUE; continue; }
if(*MBPropertyRow.pGroup == eMBProperty_IIsInheritedProperties) { if(!(i_dwMDFlags & MD_IMPORT_INHERITED)) { bSkipLocation = TRUE; continue; } } }
//
// Some checks to see whether we skip just the current property, but not
// necessarily the entire location.
//
if(*MBPropertyRow.pGroup == eMBProperty_IIsInheritedProperties) { if( !(fMBProperty_INHERIT & *MBPropertyRow.pAttributes) ) { continue; } } else { //
// Check for keytype match
//
if( eRelation == eREL_SELF && *MBPropertyRow.pID == MD_KEY_TYPE && MBPropertyRow.pValue != NULL && i_wszKeyType[0] != L'\0' ) { if(_wcsicmp((LPWSTR)MBPropertyRow.pValue, i_wszKeyType) != 0) { hr = RETURNCODETOHRESULT(ERROR_NO_MATCH); goto exit; } } }
if(eRelation == eREL_PARENT) { if( !(fMBProperty_INHERIT & *MBPropertyRow.pAttributes) ) { continue; } }
if(bNewLocation && (eRelation != eREL_PARENT)) { //
// Create node in the metabase if it is not there yet.
// pboRead is pointer to this node.
//
hr = ReadMetaObject(i_wszSourcePath, *o_ppboNew, pLocation, &pboRead); if(FAILED(hr)) { goto exit; } }
if(bLocationWithProperty) { MD_ASSERT(pboRead != NULL); hr = ReadDataObject(pboRead, (LPVOID*)&MBPropertyRow, acbMBPropertyRow, pStorage, TRUE); if(FAILED(hr)) { goto exit; } }
}
if(!bSawSourcePath) { hr = RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND); goto exit; }
exit:
//
// Cleanup
//
if(FAILED(hr) && NULL != *o_ppboNew) { delete (*o_ppboNew); *o_ppboNew = NULL; }
delete pStorage; pStorage = NULL;
return hr; }
HRESULT CImporter::InitIST() /*++
Synopsis:
Return Value:
--*/ { HRESULT hr = S_OK; STQueryCell QueryCell[1];
//
// Get the property table.
//
QueryCell[0].pData = (LPVOID)m_wszFileName; QueryCell[0].eOperator = eST_OP_EQUAL; QueryCell[0].iCell = iST_CELL_FILE; QueryCell[0].dbType = DBTYPE_WSTR; QueryCell[0].cbSize = (lstrlenW(m_wszFileName)+1)*sizeof(WCHAR);
ULONG cCell = sizeof(QueryCell)/sizeof(STQueryCell);
//
// No need to initilize dispenser (InitializeSimpleTableDispenser()),
// because we now specify USE_CRT=1 in sources, which means that
// globals will be initialized.
//
hr = DllGetSimpleObjectByIDEx( eSERVERWIRINGMETA_TableDispenser, IID_ISimpleTableDispenser2, (VOID**)&m_spISTDisp, WSZ_PRODUCT_IIS ); if(FAILED(hr)) { DBGERROR(( DBG_CONTEXT, "[%s] DllGetSimpleObjectByIDEx failed with hr = 0x%x.\n",__FUNCTION__,hr)); return hr; }
hr = m_spISTDisp->GetTable( wszDATABASE_METABASE, wszTABLE_MBProperty, (LPVOID)QueryCell, (LPVOID)&cCell, eST_QUERYFORMAT_CELLS, fST_LOS_DETAILED_ERROR_TABLE | fST_LOS_NO_LOGGING, (LPVOID *)&m_spISTProperty);
//
// Log warnings/errors in getting the mb property table
// Do this BEFORE checking the return code of GetTable.
//
CComPtr<IErrorInfo> spErrorInfo; HRESULT hrErrorTable = GetErrorInfo(0, &spErrorInfo); if(hrErrorTable == S_OK) // GetErrorInfo returns S_FALSE when there is no error object
{ //
// Get the ICatalogErrorLogger interface to log the errors.
//
CComPtr<IAdvancedTableDispenser> spISTDispAdvanced; hrErrorTable = m_spISTDisp->QueryInterface( IID_IAdvancedTableDispenser, (LPVOID*)&spISTDispAdvanced); if(FAILED(hrErrorTable)) { DBGWARN(( DBG_CONTEXT, "[%s] Could not QI for Adv Dispenser, hr=0x%x\n", __FUNCTION__, hrErrorTable)); return hr; }
hrErrorTable = spISTDispAdvanced->GetCatalogErrorLogger(&m_spILogger); if(FAILED(hrErrorTable)) { DBGWARN(( DBG_CONTEXT, "[%s] Could not get ICatalogErrorLogger2, hr=0x%x\n", __FUNCTION__, hrErrorTable)); return hr; }
//
// Get the ISimpleTableRead2 interface to read the errors.
//
hrErrorTable = spErrorInfo->QueryInterface(IID_ISimpleTableRead2, (LPVOID*)&m_spISTError); if(FAILED(hrErrorTable)) { DBGWARN((DBG_CONTEXT, "[%s] Could not get ISTRead2 from IErrorInfo\n, __FUNCTION__")); return hr; }
for(ULONG iRow=0; ; iRow++) { tDETAILEDERRORSRow ErrorInfo; hrErrorTable = m_spISTError->GetColumnValues( iRow, cDETAILEDERRORS_NumberOfColumns, 0, 0, (LPVOID*)&ErrorInfo); if(hrErrorTable == E_ST_NOMOREROWS) { break; } if(FAILED(hrErrorTable)) { DBGWARN((DBG_CONTEXT, "[%s] Could not read an error row.\n", __FUNCTION__)); return hr; }
hrErrorTable = m_spILogger->ReportError( BaseVersion_DETAILEDERRORS, ExtendedVersion_DETAILEDERRORS, cDETAILEDERRORS_NumberOfColumns, 0, (LPVOID*)&ErrorInfo); if(FAILED(hrErrorTable)) { DBGWARN((DBG_CONTEXT, "[%s] Could not log error.\n", __FUNCTION__)); return hr; } hr = MD_ERROR_READ_METABASE_FILE; } // for(ULONG iRow=0; ; iRow++)
} // if(hrErrorTable == S_OK)
if(FAILED(hr)) { DBGERROR((DBG_CONTEXT, "[%s] GetTable failed with hr = 0x%x.\n",__FUNCTION__,hr)); return hr; }
return hr; }
//
// private
//
CImporter::Relation CImporter::GetRelation( LPCWSTR i_wszSourcePath, LPCWSTR i_wszCheck) /*++
Synopsis:
Arguments: [i_wszSourcePath] - [i_wszCheck] -
Return Value:
--*/ { Relation eRelation = eREL_NONE; BOOL bIsSourcePath = false; BOOL bIsChild = IsChild(i_wszSourcePath, i_wszCheck, &bIsSourcePath); if(bIsChild) { eRelation = (bIsSourcePath) ? eREL_SELF : eREL_CHILD; } else { BOOL bIsParent = IsChild(i_wszCheck, i_wszSourcePath, &bIsSourcePath); if(bIsParent) { MD_ASSERT(bIsSourcePath == false); eRelation = eREL_PARENT; } else { eRelation = eREL_NONE; } }
return eRelation; }
BOOL CImporter::IsChild( LPCWSTR i_wszParent, LPCWSTR i_wszCheck, BOOL *o_pbSamePerson) /*++
Synopsis:
Arguments: [i_wszParent] - Ex. /LM/w3svc/1/root [i_wszCheck] - Ex. /LM/w3svc/1 [o_pbSamePerson] - true if i_wszParent and i_wszCheck is same person
Return Value: true if i_wszCheck is child or same person
--*/ { MD_ASSERT(i_wszParent != NULL); MD_ASSERT(i_wszCheck != NULL); MD_ASSERT(o_pbSamePerson != NULL);
LPCWSTR pParent; LPCWSTR pCheck;
pParent = i_wszParent; pCheck = i_wszCheck;
SKIP_DELIMETER(pParent, MD_PATH_DELIMETERW); SKIP_DELIMETER(pCheck, MD_PATH_DELIMETERW);
if(*pParent == L'\0') { switch(*pCheck) { case L'\0': *o_pbSamePerson = TRUE; break; default: *o_pbSamePerson = FALSE; } return TRUE; }
while(*pParent != L'\0') { if(_wcsnicmp(pParent, pCheck, 1) == 0) { pParent++; pCheck++; } else if(*pParent == MD_PATH_DELIMETERW && pParent[1] == L'\0' && *pCheck == L'\0') { *o_pbSamePerson = TRUE; return TRUE; } else { return FALSE; } }
switch(*pCheck) { case L'\0': *o_pbSamePerson = TRUE; return TRUE; case MD_PATH_DELIMETERW: *o_pbSamePerson = (pCheck[1] == L'\0') ? TRUE : FALSE; return TRUE; default: return FALSE; } }
HRESULT CImporter::ReadMetaObject( IN LPCWSTR i_wszAbsParentPath, IN CMDBaseObject *i_pboParent, IN LPCWSTR i_wszAbsChildPath, OUT CMDBaseObject **o_ppboChild) /*++
Synopsis: Returns a pbo for the child. If it does not already exist, it is created.
Arguments: [i_wszAbsParentPath] - [i_pboParent] - pbo corresponding to i_wszAbsParentPath [i_wszAbsChildPath] - [o_ppboChild] - pbo corresponding to i_wszAbsChildPath
Return Value:
--*/ { MD_ASSERT(i_pboParent != NULL); MD_ASSERT(i_wszAbsParentPath != NULL); MD_ASSERT(i_wszAbsChildPath != NULL); MD_ASSERT(o_ppboChild != NULL);
HRESULT hr = ERROR_SUCCESS; HRESULT hrWarn = ERROR_SUCCESS;
int iLenParent = (int)wcslen(i_wszAbsParentPath); int iLenChild = (int)wcslen(i_wszAbsChildPath);
LPWSTR wszParent = NULL; LPWSTR wszChild = NULL;
wszParent = new wchar_t[iLenParent+1]; if(wszParent == NULL) { hr = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); goto exit; } wszChild = new wchar_t[iLenChild+1]; if(wszChild == NULL) { hr = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); goto exit; }
int idxParent = 0; int idxChild = 0;
BOOL bRetParent = FALSE; BOOL bRetChild = FALSE;
CMDBaseObject *pboNew = NULL; CMDBaseObject *pboLastParent = i_pboParent;
while(1) { bRetParent = EnumMDPath(i_wszAbsParentPath, wszParent, &idxParent); bRetChild = EnumMDPath(i_wszAbsChildPath, wszChild, &idxChild);
if(bRetParent == FALSE) { break; } }
while(bRetChild == TRUE) { //
// This is okay, since function that uses this takes an LPSTR
// and a bool saying whether or not the string is unicode.
//
LPSTR pszTemp = (LPSTR)wszChild;
pboNew = pboLastParent->GetChildObject(pszTemp, &hrWarn, TRUE); if(pboNew == NULL) { //
// Create it
//
pboNew = new CMDBaseObject(wszChild, NULL); if (pboNew == NULL) { hr = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); goto exit; } else if (!pboNew->IsValid()) { hr = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY); delete (pboNew); goto exit; } hr = pboLastParent->InsertChildObject(pboNew); if(FAILED(hr)) { delete pboNew; goto exit; } } pboLastParent = pboNew;
bRetChild = EnumMDPath(i_wszAbsChildPath, wszChild, &idxChild); }
//
// Set out params
//
*o_ppboChild = pboLastParent;
exit: delete [] wszParent; delete [] wszChild;
return hr; }
BOOL CImporter::EnumMDPath( LPCWSTR i_wszFullPath, LPWSTR io_wszPath, int* io_iStartIndex) /*++
Synopsis: Starting at io_iStartIndex, this function will find the next token. Eg. i_wszFullPath = /LM/w3svc/1 *io_iStartIndex = 3 io_wszPath => w3svc *io_iStartIndex = 9
Arguments: [i_wszFullPath] - Ex. /LM/w3svc/1 [io_wszPath] - Should be at least same size as i_wszFullPath [io_iStartIndex] - 0-based index to start looking from
Return Value: true if io_wszPath is set.
--*/ { MD_ASSERT(i_wszFullPath != NULL); MD_ASSERT(io_wszPath != NULL);
int idxEnd = *io_iStartIndex; int idxStart = *io_iStartIndex;
if(i_wszFullPath[idxStart] == MD_PATH_DELIMETERW) { idxStart++; idxEnd++; }
//
// If there is no more to enum, just exit and don't set out params
//
if(i_wszFullPath[idxStart] == L'\0') { return FALSE; }
for(; ; idxEnd++) { if(i_wszFullPath[idxEnd] == MD_PATH_DELIMETERW) { break; } if(i_wszFullPath[idxEnd] == L'\0') { break; } }
//
// Set out params
//
*io_iStartIndex = idxEnd; memcpy(io_wszPath, &i_wszFullPath[idxStart], sizeof(wchar_t) * (idxEnd-idxStart)); io_wszPath[idxEnd-idxStart] = L'\0';
return TRUE; }
|