WindowsXP-SP1/admin/dsutils/displayspecifierupgrade/analisys.cpp
2020-09-30 16:53:49 +02:00

1751 lines
45 KiB
C++

#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;
}