|
|
#include "headers.hxx"
#include "global.hpp"
#include "Analisys.hpp"
#include "AnalisysResults.hpp"
#include "CSVDSReader.hpp"
#include "resource.h"
#include "AdsiHelpers.hpp"
#include "constants.hpp"
#include "dspecup.hpp"
Analisys::Analisys ( const CSVDSReader& csvReader409_, const CSVDSReader& csvReaderIntl_, const String& ldapPrefix_, const String& rootContainerDn_, AnalisysResults &res, const String &reportName_,//=L"",
void *caleeStruct_,//=NULL,
progressFunction stepIt_,//=NULL,
progressFunction totalSteps_//=NULL,
) : csvReader409(csvReader409_), csvReaderIntl(csvReaderIntl_), ldapPrefix(ldapPrefix_), rootContainerDn(rootContainerDn_), results(res), reportName(reportName_), caleeStruct(caleeStruct_), stepIt(stepIt_), totalSteps(totalSteps_) { LOG_CTOR(Analisys); ASSERT(!ldapPrefix.empty()); ASSERT(!rootContainerDn.empty());
};
// Analisys entry point
HRESULT Analisys::run() { LOG_FUNCTION(Analisys::run);
setReplaceW2KStrs();
HRESULT hr=S_OK; do { LongList locales; for(long t=0;LOCALEIDS[t]!=0;t++) { locales.push_back(LOCALEIDS[t]); } locales.push_back(LOCALE409[0]); if(totalSteps!=NULL) { // The cast bellow is for IA64 compilation since we know
// that locales.size() will fit in a long.
totalSteps(static_cast<long>(locales.size()),caleeStruct); }
BREAK_ON_FAILED_HRESULT(hr);
LongList::iterator begin=locales.begin(); LongList::iterator end=locales.end();
while(begin!=end) { long locale=*begin; bool isPresent;
hr=dealWithContainer(locale,isPresent); BREAK_ON_FAILED_HRESULT(hr);
if (isPresent) { hr=dealWithXPObjects(locale); BREAK_ON_FAILED_HRESULT(hr);
hr=dealWithW2KObjects(locale); BREAK_ON_FAILED_HRESULT(hr); }
if(stepIt!=NULL) { stepIt(1,caleeStruct); }
begin++; } BREAK_ON_FAILED_HRESULT(hr);
if(!reportName.empty()) { hr=createReport(reportName); BREAK_ON_FAILED_HRESULT(hr); } } while (0);
LOG_HRESULT(hr); return hr; }
// add entry to result.createContainers if container is not present
// also returns flag isPresent
HRESULT Analisys::dealWithContainer( const long locale, bool &isPresent) { LOG_FUNCTION(Analisys::dealWithContainer);
ASSERT(locale > 0); ASSERT(!rootContainerDn.empty());
HRESULT hr = S_OK;
do { String container = String::format(L"CN=%1!3x!,", locale); String childContainerDn =ldapPrefix + container + rootContainerDn;
// Attempt to bind to the container.
SmartInterface<IADs> iads(0); hr = AdsiOpenObject<IADs>(childContainerDn, iads); if (HRESULT_CODE(hr) == ERROR_DS_NO_SUCH_OBJECT) { // The container object does not exist. This is possible because
// the user has manually removed the container, or because it
// was never created due to an aboted post-dcpromo import of the
// display specifiers when the forest root dc was first promoted.
results.createContainers.push_back(locale);
isPresent=false;
hr = S_OK; break; } else if (FAILED(hr)) { error=String::format(IDS_ERROR_BINDING_TO_CONTAINER, childContainerDn.c_str()); break; }
// At this point, the bind succeeded, so the child container exists.
// So now we want to examine objects in that container.
isPresent=true; } while (0);
LOG_HRESULT(hr); return hr; }
// add entries to results.conflictingXPObjects or
// results.createXPObject as necessary
HRESULT Analisys::dealWithXPObjects(const long locale) { LOG_FUNCTION(Analisys::dealWithXPObjects);
ASSERT(locale > 0); ASSERT(!rootContainerDn.empty());
HRESULT hr = S_OK;
do { for ( int i = 0; *NEW_XP_OBJECTS[i]!=0; ++i ) { String objectName = NEW_XP_OBJECTS[i]; String objectPath = ldapPrefix + L"CN=" + objectName + L"," + String::format(L"CN=%1!3x!,", locale) + rootContainerDn;
SmartInterface<IADs> iads(0); hr = AdsiOpenObject<IADs>(objectPath, iads); if (HRESULT_CODE(hr) == ERROR_DS_NO_SUCH_OBJECT) { // The object does not exist. This is what we expect. We want
// to add the object in the repair phase.
ObjectId tempObj(locale,objectName); results.createXPObjects.push_back(tempObj); hr = S_OK; continue; } else if (SUCCEEDED(hr)) { // The object already exists. We have a conflict.
ObjectId tempObj(locale,objectName); results.conflictingXPObjects.push_back(tempObj); } else {
error=String::format( IDS_ERROR_BINDING_TO_OBJECT, objectName.c_str(), objectPath.c_str()); break; } } BREAK_ON_FAILED_HRESULT(hr); } while (0); LOG_HRESULT(hr); return hr;
}
// add entries to results.createW2KObjects
// and results.objectActions as necessary
HRESULT Analisys::dealWithW2KObjects(const long locale) { LOG_FUNCTION(Analisys::dealWithW2KObjects); ASSERT(locale >0); ASSERT(!rootContainerDn.empty());
HRESULT hr = S_OK;
do { for( long i = 0; *(CHANGE_LIST[i].object)!=0; ++i ) { String objectName = CHANGE_LIST[i].object; String objectPath = ldapPrefix + L"CN=" + objectName + L"," + String::format(L"CN=%1!3x!,", locale) + rootContainerDn;
SmartInterface<IADs> iads(0); hr = AdsiOpenObject<IADs>(objectPath, iads); if (HRESULT_CODE(hr) == ERROR_DS_NO_SUCH_OBJECT) { // The object does not exist.
ObjectId tempObj(locale,objectName); results.createW2KObjects.push_back(tempObj); hr = S_OK; continue; } else if (SUCCEEDED(hr)) { // At this point, the display specifier object exists. Determine if
// if has been touched since its creation.
SmartInterface<IDirectoryObject> iDirObj; hr=iDirObj.AcquireViaQueryInterface(iads); // hr = iads->QueryInterface(IID_IDirectoryObject,(void **)iDirObj);
BREAK_ON_FAILED_HRESULT(hr); hr = checkChanges(locale,CHANGE_LIST[i],iDirObj); BREAK_ON_FAILED_HRESULT(hr);
} else { error=String::format( IDS_ERROR_BINDING_TO_OBJECT, objectName.c_str(), objectPath.c_str());
break; } } BREAK_ON_FAILED_HRESULT(hr); } while (0); LOG_HRESULT(hr); return hr;
}
HRESULT Analisys::checkChanges( const long locale, const sChangeList& changes, IDirectoryObject *iDirObj) { LOG_FUNCTION(Analisys::checkChanges);
wchar_t *object=changes.object; HRESULT hr=S_OK; for( long i = 0; *(changes.changes[i].property)!=0; ++i) { struct sChange change=changes.changes[i]; switch(change.type) { case ADD_ALL_CSV_VALUES: hr = addAllCsvValues ( iDirObj, locale, object, change.property );
if(FAILED(hr)) { LOG_HRESULT(hr); return hr; } break;
case ADD_VALUE: hr = addValue ( iDirObj, locale, object, change.property, change.value ); if(FAILED(hr)) { LOG_HRESULT(hr); return hr; } break;
case REPLACE_W2K_MULTIPLE_VALUE:
hr = replaceW2KMultipleValue ( iDirObj, locale, object, change.property, change.value );
if(FAILED(hr)) { LOG_HRESULT(hr); return hr; } break;
case REPLACE_W2K_SINGLE_VALUE:
hr = replaceW2KSingleValue ( iDirObj, locale, object, change.property, change.value );
if(FAILED(hr)) { LOG_HRESULT(hr); return hr; } break;
case ADD_GUID:
hr = addGuid ( iDirObj, locale, object, change.property, change.value );
if(FAILED(hr)) { LOG_HRESULT(hr); return hr; } break;
case REMOVE_GUID:
hr = removeGuid ( iDirObj, locale, object, change.property, change.value );
if(FAILED(hr)) { LOG_HRESULT(hr); return hr; } break;
default: ASSERT(false); } } LOG_HRESULT(S_OK); return S_OK; }
// adds ordAndGuid to the property if Guid is not already there.
HRESULT Analisys::addGuid( IDirectoryObject *iDirObj, const int locale, const wchar_t *object, const wchar_t *property, const wchar_t *ordAndGuid) { LOG_FUNCTION(Analisys::addGuid);
HRESULT hr = S_OK;
String propertStr(property); String ordAndGuidStr(ordAndGuid); do { String guidFound; hr=getADGuid( iDirObj, propertStr, ordAndGuidStr, guidFound );
BREAK_ON_FAILED_HRESULT(hr); if (hr == S_FALSE) { ObjectId tempObj(locale,String(object)); ValueActions &act=results.objectActions[tempObj][property]; act.addValues.push_back(ordAndGuidStr); } } while (0);
LOG_HRESULT(hr); return hr; }
// adds all csv values still not on the property
HRESULT Analisys::addAllCsvValues( IDirectoryObject *iDirObj, const long locale, const wchar_t *object, const wchar_t *property) { LOG_FUNCTION(Analisys::addAllCsvValues); HRESULT hr = S_OK; const CSVDSReader &csvReader=(locale==0x409)?csvReader409:csvReaderIntl;
do { StringList values; hr=csvReader.getCsvValues(locale,object,property,values); BREAK_ON_FAILED_HRESULT(hr);
if (values.size()==0) { error=String::format(IDS_NO_CSV_VALUE,locale,object); hr=E_FAIL; break; } StringList::iterator begin=values.begin(); StringList::iterator end=values.end(); while(begin!=end) { hr=addValue(iDirObj,locale,object,property,begin->c_str()); BREAK_ON_FAILED_HRESULT(hr); begin++; } BREAK_ON_FAILED_HRESULT(hr); } while (0);
LOG_HRESULT(hr); return hr; }
// adds value to the property if it is not already there.
HRESULT Analisys::addValue( IDirectoryObject *iDirObj, const int locale, const wchar_t *object, const wchar_t *property, const wchar_t *value) { LOG_FUNCTION(Analisys::addValue);
HRESULT hr = S_OK;
String valueStr(value); String propertyStr(property); do { hr=isADValuePresent ( iDirObj, propertyStr, valueStr );
BREAK_ON_FAILED_HRESULT(hr); if (hr == S_FALSE) { ObjectId tempObj(locale,String(object)); ValueActions &act=results.objectActions[tempObj][property]; act.addValues.push_back(value); } } while (0);
LOG_HRESULT(hr); return hr; }
//Auxiliary function for replaceW2KSingleValue
// retrieves csvValue
HRESULT Analisys::getCsvSingleValue ( const int locale, const wchar_t *object, const wchar_t *property, String &csvValue ) { LOG_FUNCTION(Analisys::getCsvReplacementValue);
const CSVDSReader &csvReader=(locale==0x409)?csvReader409:csvReaderIntl;
HRESULT hr = S_OK; do {
StringList XPCsvValues; hr=csvReader.getCsvValues(locale,object,property,XPCsvValues); BREAK_ON_FAILED_HRESULT(hr);
// we should have only one value in the csv
// since we can't distinguish the
// value we want to replace from others as
// in REPLACE_W2K_MULTIPLE_VALE
if(XPCsvValues.size() != 1) { error=String::format ( IDS_NOT_ONE_CSV_VALUE, XPCsvValues.size(), csvReader.getFileName().c_str(), locale, object, property ); hr=E_FAIL; break; }
csvValue = *XPCsvValues.begin();
} while(0);
LOG_HRESULT(hr); return hr; }
// The idea of replaceW2KValue is replacing the W2K value
// for the Whistler. We also make sure we don't extraneous values.
HRESULT Analisys::replaceW2KSingleValue ( IDirectoryObject *iDirObj, const int locale, const wchar_t *object, const wchar_t *property, const wchar_t *value ) { LOG_FUNCTION(Analisys::replaceW2KValue);
long index = *value; String objectStr(object); String propertyStr(property);
HRESULT hr = S_OK; do { String XPCsvValue;
hr=getCsvSingleValue ( locale, object, property, XPCsvValue );
BREAK_ON_FAILED_HRESULT(hr);
// Retrieve W2KCsvValue from replaceW2KStrs
pair<long,long> tmpIndxLoc; tmpIndxLoc.first=index; tmpIndxLoc.second=locale; String &W2KCsvValue=replaceW2KStrs[tmpIndxLoc];
// There is nothing to do if the Whistler csv value
// is the same as it was in W2K
if (XPCsvValue.icompare(W2KCsvValue)==0) { break; }
// Now we might have a replacement to do since the value
// changed from W2K to Whistler
hr=isADValuePresent(iDirObj,propertyStr,XPCsvValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr == S_OK) // The Whistler value is already there
{ // We will remove any other value than the Whistler
hr=removeExtraneous(iDirObj,locale,objectStr,propertyStr,XPCsvValue); break; }
// Now we know that the Whistler value is not present
// and therefore we will add it if the W2K value is present
hr=isADValuePresent(iDirObj,propertyStr,W2KCsvValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr == S_OK) // The W2K value is there.
{ ObjectId tempObj(locale,String(object)); ValueActions &act=results.objectActions[tempObj][property]; act.addValues.push_back(XPCsvValue); act.delValues.push_back(W2KCsvValue);
// remove all but the W2K that we removed in the previous line
hr=removeExtraneous(iDirObj,locale,objectStr,propertyStr,W2KCsvValue); break; }
// Now we know that neither Whistler nor W2K values are present
// If we have a value we will log that it is a custom value
String ADValue; hr=getADFirstValue(iDirObj,propertyStr,ADValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr == S_OK) // We have a value
{ SingleValue tmpCustom(locale,objectStr,propertyStr,ADValue); results.customizedValues.push_back(tmpCustom);
// We will remove any other value than the one we found
hr=removeExtraneous(iDirObj,locale,objectStr,propertyStr,ADValue); break; } // Now we know that we don't have any values at all.
ObjectId tempObj(locale,String(object));
ValueActions &act=results.objectActions[tempObj][property]; act.addValues.push_back(XPCsvValue); } while(0);
LOG_HRESULT(hr); return hr; }
//Auxiliary function for replaceW2KMultipleValue
// retrieves csvValue and XPStart
HRESULT Analisys::getCsvMultipleValue ( const int locale, const wchar_t *object, const wchar_t *property, const wchar_t *value, String &csvValue, String &XPstart ) { LOG_FUNCTION(Analisys::getCsvReplacementValue);
const CSVDSReader &csvReader=(locale==0x409)?csvReader409:csvReaderIntl;
HRESULT hr = S_OK; do { String sW2KXP(value+2); // +2 for index and semicollon
StringList lW2KXP; size_t cnt=sW2KXP.tokenize(back_inserter(lW2KXP),L";"); XPstart=lW2KXP.back();
// We have the W2K and the XP start
ASSERT(cnt==2);
// Search the csv for the value starting with the XP string
hr=csvReader.getCsvValue( locale, object, property, XPstart.c_str(), csvValue );
BREAK_ON_FAILED_HRESULT(hr);
// We should always find a csv value
if(hr == S_FALSE) { error=String::format( IDS_VALUE_NOT_IN_CSV, XPstart.c_str(), locale, object, property, csvReader.getFileName().c_str() ); hr=E_FAIL; break; } } while(0);
LOG_HRESULT(hr); return hr; }
// The idea of replaceW2KValue is replacing the W2K value
// for the Whistler. We also make sure we don't extraneous values.
HRESULT Analisys::replaceW2KMultipleValue ( IDirectoryObject *iDirObj, const int locale, const wchar_t *object, const wchar_t *property, const wchar_t *value ) { LOG_FUNCTION(Analisys::replaceW2KValue);
long index = *value; String objectStr(object); String propertyStr(property);
HRESULT hr = S_OK; do { String XPCsvValue,XPStart;
// Get the Whistler csv value and the start of the Whistler value
hr=getCsvMultipleValue ( locale, object, property, value, XPCsvValue, XPStart );
BREAK_ON_FAILED_HRESULT(hr);
// Retrieve W2KCsvValue from replaceW2KStrs
pair<long,long> tmpIndxLoc; tmpIndxLoc.first=index; tmpIndxLoc.second=locale; String &W2KCsvValue=replaceW2KStrs[tmpIndxLoc];
// There is nothing to do if the Whistler csv value
// is the same as it was in W2K
if (XPCsvValue.icompare(W2KCsvValue)==0) { break; }
// Now we might have a replacement to do since the value
// changed from W2K to Whistler
// First we should get the beginning of the W2K string
// for use in removeExtraneous calls
size_t pos=W2KCsvValue.find(L','); String W2KStart; // We only need to assert since the W2KStrs tool would
// detect any REPLACE_W2K_MULTIPLE_VALUE without a comma
ASSERT(pos != String::npos); W2KStart=W2KCsvValue.substr(0,pos+1);
hr=isADValuePresent(iDirObj,propertyStr,XPCsvValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr == S_OK) // The Whistler value is already there
{ hr=removeExtraneous( iDirObj, locale, objectStr, propertyStr, XPCsvValue, XPStart, W2KStart ); BREAK_ON_FAILED_HRESULT(hr);
break; }
// Now we know that the Whistler value is not present
// and therefore we will add it if the W2K value is present
hr=isADValuePresent(iDirObj,propertyStr,W2KCsvValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr == S_OK) // The W2K value is there.
{ ObjectId tempObj(locale,String(object)); ValueActions &act=results.objectActions[tempObj][property]; act.addValues.push_back(XPCsvValue); act.delValues.push_back(W2KCsvValue);
// remove all but the W2K that we removed in the previous line
hr=removeExtraneous( iDirObj, locale, objectStr, propertyStr, W2KCsvValue, XPStart, W2KStart ); break; }
// Now we know that neither Whistler nor W2K values are present
// If we have a value starting like the W2K we will log that it
// is a custom value
String ADValue;
hr=isADStartValuePresent(iDirObj,propertyStr,W2KStart,ADValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr==S_OK) // Something starts like the W2K csv value
{ SingleValue tmpCustom(locale,objectStr,propertyStr,ADValue); results.customizedValues.push_back(tmpCustom);
// We will keep only the first custom value
hr=removeExtraneous( iDirObj, locale, objectStr, propertyStr, ADValue, XPStart, W2KStart ); break; }
// Now neither Whistler, W2K or W2KStart are present
if ( XPStart.icompare(W2KStart) != 0 ) { // We have to check the XPStart as well
hr=isADStartValuePresent(iDirObj,propertyStr,XPStart,ADValue); BREAK_ON_FAILED_HRESULT(hr);
if(hr == S_OK) // Something starts like the Whistler csv value
{ SingleValue tmpCustom(locale,objectStr,propertyStr,ADValue); results.customizedValues.push_back(tmpCustom);
// We will keep only the first custom value
hr=removeExtraneous( iDirObj, locale, objectStr, propertyStr, ADValue, XPStart, W2KStart ); break; } }
// Now we know that there are no values starting like
// the Whistler or W2K csv values so we have to add
// the Whistler value
ObjectId tempObj(locale,String(object));
ValueActions &act=results.objectActions[tempObj][property]; act.addValues.push_back(XPCsvValue); } while(0);
LOG_HRESULT(hr); return hr; }
// removes ordAndGuid from the property if Guid is there.
HRESULT Analisys::removeGuid( IDirectoryObject *iDirObj, const int locale, const wchar_t *object, const wchar_t *property, const wchar_t *ordAndGuid) {
LOG_FUNCTION(Analisys::removeGuid);
HRESULT hr = S_OK; String propertStr(property); String ordAndGuidStr(ordAndGuid); do { String guidFound; hr=getADGuid( iDirObj, propertStr, ordAndGuidStr, guidFound ); BREAK_ON_FAILED_HRESULT(hr); if (hr == S_OK) { ObjectId tempObj(locale,String(object)); ValueActions &act=results.objectActions[tempObj][property]; act.delValues.push_back(guidFound); } } while (0);
LOG_HRESULT(hr); return hr; }
//called from RwplaceW2KMultipleValue to remove all values
// starting with start1 or start2 other than keeper
HRESULT Analisys::removeExtraneous ( IDirectoryObject *iDirObj, const int locale, const String &object, const String &property, const String &keeper, const String &start1, const String &start2 ) { LOG_FUNCTION(Analisys::removeExtraneous);
DWORD dwReturn; ADS_ATTR_INFO *pAttrInfo =NULL; // GetObjectAttributes swears that pAttrName is an IN argument.
// It should have used a LPCWSTR but now we have to pay the
// casting price
LPWSTR pAttrName[] ={const_cast<LPWSTR>(property.c_str())}; HRESULT hr = S_OK;
do { hr = iDirObj->GetObjectAttributes( pAttrName, 1, &pAttrInfo, &dwReturn );
BREAK_ON_FAILED_HRESULT(hr);
if(pAttrInfo==NULL) { hr = S_FALSE; break;
}
for ( long val=0; val < pAttrInfo->dwNumValues; val++, pAttrInfo->pADsValues++ ) { wchar_t *valueAD = pAttrInfo->pADsValues->CaseIgnoreString;
if ( _wcsicmp(valueAD,keeper.c_str())!=0 && ( _wcsnicmp(valueAD,start1.c_str(),start1.size())==0 || _wcsnicmp(valueAD,start2.c_str(),start2.size())==0 ) ) { String value=pAttrInfo->pADsValues->CaseIgnoreString; ObjectId tempObj(locale,String(object));
ValueActions &act=results.extraneousValues[tempObj][property]; act.delValues.push_back(value); } } } while (0);
LOG_HRESULT(hr); return hr; }
// called from RwplaceW2KSingleValue to remove all values
// other than keeper
HRESULT Analisys::removeExtraneous ( IDirectoryObject *iDirObj, const int locale, const String &object, const String &property, const String &keeper ) { LOG_FUNCTION(Analisys::removeExtraneous);
DWORD dwReturn; ADS_ATTR_INFO *pAttrInfo =NULL; // GetObjectAttributes swears that pAttrName is an IN argument.
// It should have used a LPCWSTR but now we have to pay the
// casting price
LPWSTR pAttrName[] ={const_cast<LPWSTR>(property.c_str())}; HRESULT hr = S_OK;
do { hr = iDirObj->GetObjectAttributes( pAttrName, 1, &pAttrInfo, &dwReturn );
BREAK_ON_FAILED_HRESULT(hr);
if(pAttrInfo==NULL) { hr = S_FALSE; break;
}
for ( long val=0; val < pAttrInfo->dwNumValues; val++, pAttrInfo->pADsValues++ ) { wchar_t *valueAD = pAttrInfo->pADsValues->CaseIgnoreString;
if ( _wcsicmp(valueAD,keeper.c_str())!=0 ) { String value=pAttrInfo->pADsValues->CaseIgnoreString; ObjectId tempObj(locale,String(object));
ValueActions &act=results.extraneousValues[tempObj][property]; act.delValues.push_back(value); } } } while (0);
LOG_HRESULT(hr); return hr; }
// if any value exists in the AD with the same guid as guidValue
// it is returned in guidFound, otherwise S_FALSE is returned
HRESULT Analisys::getADGuid ( IDirectoryObject *iDirObj, const String &property, const String &guidValue, String &guidFound ) { LOG_FUNCTION(Analisys::getADGuid); DWORD dwReturn; ADS_ATTR_INFO *pAttrInfo =NULL; // GetObjectAttributes swears that pAttrName is an IN argument.
// It should have used a LPCWSTR but now we have to pay the
// casting price
LPWSTR pAttrName[] ={const_cast<LPWSTR>(property.c_str())};
size_t pos=guidValue.find(L','); ASSERT(pos!=String::npos);
String guid=guidValue.substr(pos+1);
HRESULT hr = S_OK;
do { hr = iDirObj->GetObjectAttributes( pAttrName, 1, &pAttrInfo, &dwReturn );
BREAK_ON_FAILED_HRESULT(hr);
// If there are no values we finish the search
hr=S_FALSE;
if(pAttrInfo==NULL) { break; }
for ( long val=0; val < pAttrInfo->dwNumValues; val++, pAttrInfo->pADsValues++ ) { wchar_t *guidAD=wcschr(pAttrInfo->pADsValues->CaseIgnoreString,L','); if(guidAD != NULL) { guidAD++;
if (_wcsicmp(guid.c_str(),guidAD)==0) { guidFound=pAttrInfo->pADsValues->CaseIgnoreString; hr=S_OK; break; } } }
} while (0);
LOG_HRESULT(hr); return hr; }
// returns S_OK if value is present or S_FALSE otherwise
HRESULT Analisys::isADValuePresent ( IDirectoryObject *iDirObj, const String &property, const String &value ) { LOG_FUNCTION(Analisys::isADValuePresent); DWORD dwReturn; ADS_ATTR_INFO *pAttrInfo =NULL; // GetObjectAttributes swears that pAttrName is an IN argument.
// It should have used a LPCWSTR but now we have to pay the
// casting price
LPWSTR pAttrName[] ={const_cast<LPWSTR>(property.c_str())}; HRESULT hr = S_OK;
do { hr = iDirObj->GetObjectAttributes( pAttrName, 1, &pAttrInfo, &dwReturn );
BREAK_ON_FAILED_HRESULT(hr);
hr=S_FALSE;
// If there are no values we finish the search
if(pAttrInfo==NULL) { break; }
for ( long val=0; val < pAttrInfo->dwNumValues; val++, pAttrInfo->pADsValues++ ) { wchar_t *valueAD=pAttrInfo->pADsValues->CaseIgnoreString; if (_wcsicmp(value.c_str(),valueAD)==0) { hr=S_OK; break; } }
} while (0);
LOG_HRESULT(hr); return hr; }
// retrieves the first value starting with valueStart
// from the Active Directory
// If no value is found S_FALSE is returned.
HRESULT Analisys::isADStartValuePresent ( IDirectoryObject *iDirObj, const String &property, const String &valueStart, String &value ) { LOG_FUNCTION(Analisys::isADStartValuePresent); DWORD dwReturn; ADS_ATTR_INFO *pAttrInfo =NULL; // GetObjectAttributes swears that pAttrName is an IN argument.
// It should have used a LPCWSTR but now we have to pay the
// casting price
LPWSTR pAttrName[] ={const_cast<LPWSTR>(property.c_str())}; HRESULT hr = S_OK;
do { hr = iDirObj->GetObjectAttributes( pAttrName, 1, &pAttrInfo, &dwReturn );
BREAK_ON_FAILED_HRESULT(hr); value.erase();
hr = S_FALSE;
// If there are no values we finish the search
if(pAttrInfo==NULL) { break;
}
for ( long val=0; (val < pAttrInfo->dwNumValues); val++, pAttrInfo->pADsValues++ ) { wchar_t *valueAD=pAttrInfo->pADsValues->CaseIgnoreString; if (_wcsnicmp(valueStart.c_str(),valueAD,valueStart.size())==0) { value=pAttrInfo->pADsValues->CaseIgnoreString; hr=S_OK; break; } }
} while (0);
LOG_HRESULT(hr); return hr; }
// retrieves the first value starting with valueStart
// from the Active Directory
// If no value is found S_FALSE is returned.
HRESULT Analisys::getADFirstValue ( IDirectoryObject *iDirObj, const String &property, String &value ) { LOG_FUNCTION(Analisys::getADFirstValue); DWORD dwReturn; ADS_ATTR_INFO *pAttrInfo =NULL; // GetObjectAttributes swears that pAttrName is an IN argument.
// It should have used a LPCWSTR but now we have to pay the
// casting price
LPWSTR pAttrName[] ={const_cast<LPWSTR>(property.c_str())}; HRESULT hr = S_OK;
do { hr = iDirObj->GetObjectAttributes( pAttrName, 1, &pAttrInfo, &dwReturn );
BREAK_ON_FAILED_HRESULT(hr);
// If there are no values we finish the search
if(pAttrInfo==NULL) { hr = S_FALSE; break; }
value=pAttrInfo->pADsValues->CaseIgnoreString;
} while (0);
LOG_HRESULT(hr); return hr; }
// auxiliary in the createReport to
// enumerate an ObjectIdList
HRESULT Analisys::reportObjects ( HANDLE file, const ObjectIdList &list, const String &header ) { LOG_FUNCTION(Analisys::reportObjects); HRESULT hr=S_OK;
do { if(list.size()==0) break; hr=FS::WriteLine(file,header); BREAK_ON_FAILED_HRESULT(hr);
ObjectIdList::const_iterator begin,end; begin=list.begin(); end=list.end(); while(begin!=end) {
hr=FS::WriteLine( file, String::format ( IDS_RPT_OBJECT_FORMAT, begin->object.c_str(), begin->locale ) ); BREAK_ON_FAILED_HRESULT(hr); begin++; } BREAK_ON_FAILED_HRESULT(hr); } while(0);
LOG_HRESULT(hr); return hr; }
// auxiliary in the createReport to
// enumerate a LongList
HRESULT Analisys::reportContainers ( HANDLE file, const LongList &list, const String &header ) { LOG_FUNCTION(Analisys::reportContainers); HRESULT hr=S_OK;
do { if(list.size()==0) break; hr=FS::WriteLine(file,header); BREAK_ON_FAILED_HRESULT(hr);
LongList::const_iterator begin,end; begin=list.begin(); end=list.end(); while(begin!=end) {
hr=FS::WriteLine( file, String::format ( IDS_RPT_CONTAINER_FORMAT, *begin ) ); BREAK_ON_FAILED_HRESULT(hr); begin++; } BREAK_ON_FAILED_HRESULT(hr); } while(0);
LOG_HRESULT(hr); return hr; }
// auxiliary in the createReport to
// enumerate a SingleValueList
HRESULT Analisys::reportValues ( HANDLE file, const SingleValueList &list, const String &header ) { LOG_FUNCTION(Analisys::reportContainers); HRESULT hr=S_OK;
do { if(list.size()==0) break; hr=FS::WriteLine(file,header); BREAK_ON_FAILED_HRESULT(hr);
SingleValueList::const_iterator begin,end; begin=list.begin(); end=list.end(); while(begin!=end) {
hr=FS::WriteLine( file, String::format ( IDS_RPT_VALUE_FORMAT, begin->value.c_str(), begin->locale, begin->object.c_str(), begin->property.c_str() ) ); BREAK_ON_FAILED_HRESULT(hr); begin++; } BREAK_ON_FAILED_HRESULT(hr); } while(0);
LOG_HRESULT(hr); return hr; }
// auxiliary in the createReport to
// enumerate ObjectActions
HRESULT Analisys::reportActions ( HANDLE file, const ObjectActions &list, const String &header ) { LOG_FUNCTION(Analisys::reportActions); HRESULT hr=S_OK;
do { if(list.size()==0) break; hr=FS::WriteLine(file,header); BREAK_ON_FAILED_HRESULT(hr);
ObjectActions::const_iterator beginObj=list.begin(); ObjectActions::const_iterator endObj=list.end();
while(beginObj!=endObj) {
hr=FS::WriteLine ( file, String::format ( IDS_RPT_OBJECT_FORMAT, beginObj->first.object.c_str(), beginObj->first.locale ) ); BREAK_ON_FAILED_HRESULT(hr); PropertyActions::iterator beginAct=beginObj->second.begin(); PropertyActions::iterator endAct=beginObj->second.end();
while(beginAct!=endAct) {
StringList::iterator beginDel = beginAct->second.delValues.begin(); StringList::iterator endDel = beginAct->second.delValues.end(); while(beginDel!=endDel) { hr=FS::WriteLine ( file, String::format ( IDS_RPT_DEL_VALUE_FORMAT, beginAct->first.c_str(), beginDel->c_str() ) ); BREAK_ON_FAILED_HRESULT(hr);
beginDel++; } BREAK_ON_FAILED_HRESULT(hr); // break on if internal while broke
StringList::iterator beginAdd = beginAct->second.addValues.begin(); StringList::iterator endAdd = beginAct->second.addValues.end(); while(beginAdd!=endAdd) { hr=FS::WriteLine ( file, String::format ( IDS_RPT_ADD_VALUE_FORMAT, beginAct->first.c_str(), beginAdd->c_str() ) ); BREAK_ON_FAILED_HRESULT(hr);
beginAdd++; } BREAK_ON_FAILED_HRESULT(hr); // break on if internal while broke
beginAct++; } // while(beginAct!=endAct)
BREAK_ON_FAILED_HRESULT(hr); // break on if internal while broke
beginObj++; } // while(beginObj!=endObj)
BREAK_ON_FAILED_HRESULT(hr);
} while(0);
LOG_HRESULT(hr); return hr; }
// Create the report from the AnalisysResults
HRESULT Analisys::createReport(const String& reportName) { LOG_FUNCTION(Analisys::createReport); HRESULT hr=S_OK; do { HANDLE file;
hr=FS::CreateFile(reportName, file, GENERIC_WRITE); if (FAILED(hr)) { error=String::format(IDS_COULD_NOT_CREATE_FILE,reportName.c_str()); break; }
do { hr=FS::WriteLine(file,String::load(IDS_RPT_HEADER)); BREAK_ON_FAILED_HRESULT(hr);
hr=reportActions ( file, results.extraneousValues, String::load(IDS_RPT_EXTRANEOUS) ); BREAK_ON_FAILED_HRESULT(hr);
hr=reportValues ( file, results.customizedValues, String::load(IDS_RPT_CUSTOMIZED) ); BREAK_ON_FAILED_HRESULT(hr);
hr=reportObjects ( file, results.conflictingXPObjects, String::load(IDS_RPT_CONFLICTINGXP) ); BREAK_ON_FAILED_HRESULT(hr);
hr=reportActions ( file, results.objectActions, String::load(IDS_RPT_ACTIONS) ); BREAK_ON_FAILED_HRESULT(hr); hr=reportObjects ( file, results.createW2KObjects, String::load(IDS_RPT_CREATEW2K) ); BREAK_ON_FAILED_HRESULT(hr);
hr=reportObjects ( file, results.createXPObjects, String::load(IDS_RPT_CREATEXP) ); BREAK_ON_FAILED_HRESULT(hr); hr=reportContainers( file, results.createContainers, String::load(IDS_RPT_CONTAINERS) ); BREAK_ON_FAILED_HRESULT(hr);
} while(0);
CloseHandle(file); BREAK_ON_FAILED_HRESULT(hr);
} while(0);
LOG_HRESULT(hr); return hr; }
|