263 lines
6.7 KiB
C++
263 lines
6.7 KiB
C++
// Active Directory Display Specifier Upgrade Tool
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// class Repairer
|
|
//
|
|
// keeps a list of the localeIds to be extracted from the dcpromo.csv file,
|
|
// and a list of operations to be represented in an LDIF file.
|
|
//
|
|
// 7 Mar 2001 sburns
|
|
|
|
|
|
|
|
#include "headers.hxx"
|
|
#include "Repairer.hpp"
|
|
|
|
|
|
|
|
// // // make sure that the ldif operations are executed in advance of the csv
|
|
// // // operations. this is so the object creates will not conflict with object
|
|
// // // deletes
|
|
|
|
|
|
|
|
|
|
Repairer::Repairer(
|
|
const String& dcpromoCsvFilePath_)
|
|
:
|
|
dcpromoCsvFilePath(dcpromoCsvFilePath_)
|
|
{
|
|
LOG_CTOR(Repairer);
|
|
ASSERT(!dcpromoCsvFilePath.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
Repairer::IsLocaleInObjectsToCreateTable(int localeId) const
|
|
{
|
|
LOG_FUNCTION2(
|
|
Repairer::IsLocaleInObjectsToCreateTable,
|
|
String::format(L"%1!d!", localeId));
|
|
ASSERT(localeId);
|
|
|
|
bool result = false;
|
|
|
|
for (
|
|
LocaleIdObjectNamePairList::iterator i = objectsToCreate.begin();
|
|
i != objectsToCreate.end();
|
|
++i)
|
|
{
|
|
if (i->first == localeId)
|
|
{
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
Repairer::AddCreateContainerWorkItem(int localeId)
|
|
{
|
|
LOG_FUNCTION2(
|
|
Repairer::AddCreateContainerWorkItem,
|
|
String::format(L"%1!d!", localeId));
|
|
ASSERT(localeId);
|
|
|
|
do
|
|
{
|
|
LocaleIdList::iterator i =
|
|
std::find(
|
|
containersToCreate.begin(),
|
|
containersToCreate.end(),
|
|
localeId);
|
|
|
|
if (i != containersToCreate.end())
|
|
{
|
|
// The locale should not already be in the list, since each locale
|
|
// container is evaluated only once.
|
|
|
|
LOG(L"locale already in list");
|
|
ASSERT(false);
|
|
break;
|
|
}
|
|
|
|
if (IsLocaleInObjectsToCreateTable(localeId))
|
|
{
|
|
// We don't expect any entries for this locale to be present in the
|
|
// objects-to-create list, because the containers are evaluated first.
|
|
|
|
LOG(L"objects for locale already in object list");
|
|
ASSERT(false);
|
|
|
|
// CODEWORK: we should handle this situation anyway, just for
|
|
// robustness' sake. To deal with it, all entires in the objects-
|
|
// to-create list for this locale id should be removed.
|
|
|
|
break;
|
|
}
|
|
|
|
containersToCreate.push_back(localeId);
|
|
}
|
|
while (0);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
Repairer::AddCreateObjectWorkItem(
|
|
int localeId,
|
|
const String& displaySpecifierObjectName)
|
|
{
|
|
LOG_FUNCTION2(
|
|
Repairer::AddCreateObjectWorkItem,
|
|
String::format(
|
|
L"%1!d! %2", localeId, displaySpecifierObjectName.c_str()));
|
|
ASSERT(localeId);
|
|
ASSERT(!displaySpecifierObjectName.empty());
|
|
|
|
do
|
|
{
|
|
LocaleIdList::iterator i =
|
|
std::find(
|
|
containersToCreate.begin(),
|
|
containersToCreate.end(),
|
|
localeId);
|
|
|
|
if (i != containersToCreate.end())
|
|
{
|
|
// The locale is already in the containers-to-create list, which
|
|
// we don't expect, since if the container does not exist, we should
|
|
// not be evaluating which objects should be created in that container.
|
|
|
|
ASSERT(false);
|
|
|
|
// do nothing, as the object will be created as part of the container
|
|
// creation.
|
|
|
|
break;
|
|
}
|
|
|
|
LocaleIdObjectNamePair p(localeId, displaySpecifierObjectName);
|
|
LocaleIdObjectNamePairList::iterator j =
|
|
std::find(
|
|
objectsToCreate.begin(),
|
|
objectsToCreate.end(),
|
|
p);
|
|
|
|
if (j != objectsToCreate.end())
|
|
{
|
|
// The object is already in the list. We don't expect this, since
|
|
// each object should be evaluated only once per locale.
|
|
|
|
ASSERT(false);
|
|
|
|
// do nothing, if the object is already present, then fine.
|
|
|
|
break;
|
|
}
|
|
|
|
objectsToCreate.push_back(p);
|
|
}
|
|
while (0);
|
|
}
|
|
|
|
void
|
|
Repairer::AddDeleteObjectWorkItem(
|
|
int localeId,
|
|
const String& displaySpecifierObjectName)
|
|
{
|
|
//CODEWORK:
|
|
//lucios: Inserted to remove link error
|
|
localeId++;
|
|
String x=displaySpecifierObjectName;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
Repairer::BuildRepairFiles()
|
|
{
|
|
LOG_FUNCTION(Repairer::BuildRepairFiles);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// CODEWORK
|
|
// csv file:
|
|
//
|
|
// create a (temp) file
|
|
// copy out the first line of the dcpromo.csv file (the column labels)
|
|
// for each localeid in the list
|
|
// copy out all of the lines in the dcpromo.csv file for that locale
|
|
// for each <localeid, objectname> entry
|
|
// copy out that line from the dcpromo.csv file
|
|
//
|
|
// ldif file:
|
|
|
|
LOG_HRESULT(hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
Repairer::ApplyRepairs()
|
|
{
|
|
LOG_FUNCTION(Repairer::ApplyRepairs);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// CODEWORK: needs finishing
|
|
|
|
LOG_HRESULT(hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
// could have gone with a architecture like:
|
|
//
|
|
// repairer.workQueue.Add(new CreateContainerWorkItem(localeId));
|
|
//
|
|
// but while that certainly seems more OO, more "extensible" because new work
|
|
// item types could be derived. Upon further thought, it seems like a worse
|
|
// solution to me, since there are them lots of trivial classes involved, and
|
|
// the coordination of those classes becomes a real nuisance. Once all the
|
|
// work items are collected, who's responsible for translating them into the
|
|
// csv/ldif files? It would have to be an additional manager class. The
|
|
// extensibility turns out to be an illusion, since adding a new work item
|
|
// type requires modifying the manager class. So the added complexity buys
|
|
// nothing.
|
|
//
|
|
// The other design choice was whether to make the Repairer a "static class"
|
|
// -- my name for a class that is really a namespace, which instead of members
|
|
// uses static data that is hidden in a single translation unit as though it
|
|
// were private class data. This is a technique that makes the private data
|
|
// truly secret, as there is no mention of the data in the header declaration
|
|
// for the class at all. It also is a nice way to implement the Singleton
|
|
// pattern: there are no instances, and therefore no need to worry about
|
|
// constructors, destructors, assignment, stack or heap allocation, no
|
|
// "GetInstance" methods, and no lifetime issues.
|
|
//
|
|
// The technique gives a slightly nicer syntax as:
|
|
//
|
|
// Repairer::AddCreateContainerWorkItem(localeId)
|
|
//
|
|
// as opposed to
|
|
//
|
|
// Repairer::GetInstance()->AddCreateContainerWorkItem(localeId);
|
|
//
|
|
// I decided to go with a real, fully-contained object implementation, instead
|
|
// of a singleton, thinking that maybe someday multiple instances could be
|
|
// repairing multiple forests at once. Not likely, but why not?
|