|
|
// Active Directory Display Specifier Upgrade Tool
//
// Copyright (c) 2001 Microsoft Corporation
//
// 1 Mar 2001 sburns
#include "headers.hxx"
#include "resource.h"
#include "AdsiHelpers.hpp"
#include "Repairer.hpp"
#include "Amanuensis.hpp"
#include "Analyst.hpp"
HINSTANCE hResourceModuleHandle = 0; const wchar_t* HELPFILE_NAME = 0; // no context help available
// don't change this: it is also the name of a mutex that the ui
// uses to determine if it is already running.
const wchar_t* RUNTIME_NAME = L"dspecup";
DWORD DEFAULT_LOGGING_OPTIONS = Log::OUTPUT_TO_FILE | Log::OUTPUT_FUNCCALLS | Log::OUTPUT_LOGS | Log::OUTPUT_ERRORS | Log::OUTPUT_HEADER;
Popup popup(IDS_APP_TITLE, false);
// this is the mutex that indicates the program is running.
HANDLE appRunningMutex = INVALID_HANDLE_VALUE;
// these are the valid exit codes returned as the process exit code
enum ExitCode { // the operation failed.
EXIT_CODE_UNSUCCESSFUL = 0,
// the operation succeeded
EXIT_CODE_SUCCESSFUL = 1, };
// returns true if the parameter was extracted. If so, it is removed from
// args
bool ExtractParameter( ArgMap& args, const String& parameterName, String& parameterValue) { LOG_FUNCTION2(ExtractParameter, parameterName); ASSERT(!parameterName.empty());
parameterValue.erase(); bool result = false; ArgMap::iterator itr = args.find(parameterName); if (itr != args.end()) { parameterValue = itr->second; args.erase(itr); result = true; }
LOG_BOOL(result); LOG(parameterValue);
return result; }
// Returns false if the command line is malformed.
bool ParseCommandLine( String& targetMachine, String& csvFilename) { LOG_FUNCTION(ParseCommandLine);
targetMachine.erase(); csvFilename.erase(); bool result = true; ArgMap args; MapCommandLineArgs(args); // check for target domain controller parameter
static const String TARGETDC(L"dc"); ExtractParameter(args, TARGETDC, targetMachine);
// check for csv filename parameter
static const String CSVFILE(L"csv"); ExtractParameter(args, CSVFILE, csvFilename);
// anything left over gets you command line help, (one arg will always
// remain: the name of the exe)
if (args.size() > 1) { LOG(L"Unrecognized command line options specified");
result = false; }
LOG_BOOL(result); LOG(targetMachine); LOG(csvFilename);
return result; }
HRESULT FindCsvFile(const String& targetPath, String& csvFilePath) { LOG_FUNCTION(CheckPreconditions);
csvFilePath.erase(); HRESULT hr = S_OK;
do { // look for dcpromo.csv file in system or current directory
if (targetPath.empty()) { // no preference given, so check the default of
// %windir%\system32\mui\dispspec\dcpromo.csv and
// .\dcpromo.csv
static const String csvname(L"dcpromo.csv"); String sys32dir = Win::GetSystemDirectory(); String csvPath = sys32dir + L"\\mui\\dispspec\\" + csvname;
if (FS::FileExists(csvPath)) { csvFilePath = csvPath; break; } csvPath = L".\\" + csvname; if (FS::FileExists(csvPath)) { csvFilePath = csvPath; break; } } else { if (FS::FileExists(targetPath)) { csvFilePath = targetPath; break; } }
// not found.
hr = S_FALSE; } while (0);
LOG_HRESULT(hr); LOG(csvFilePath); return hr; }
HRESULT Start() { LOG_FUNCTION(Start);
HRESULT hr = S_OK; do { //
// parse the command line options
//
String targetDomainControllerName; String csvFilename; ParseCommandLine( targetDomainControllerName, csvFilename);
//
// find the dcpromo.csv file to use
//
hr = FindCsvFile(csvFilename, csvFilename); if (FAILED(hr)) { // encountered an error looking for the csv file
popup.Error( Win::GetDesktopWindow(), hr, IDS_ERROR_LOOKING_FOR_CSV_FILE); break; } if (hr == S_FALSE) { // no error looking, just not found.
popup.Error( Win::GetDesktopWindow(), IDS_DCPROMO_CSV_FILE_MISSING); break; }
//
// Determine the target domain controller
//
if (targetDomainControllerName.empty()) { // no target specified, default to the current machine
targetDomainControllerName = Win::GetComputerNameEx(ComputerNameDnsFullyQualified); if (targetDomainControllerName.empty()) { // no DNS name? that's not right...
LOG(L"no default DNS computer name found. Using netbios name."); targetDomainControllerName = Win::GetComputerNameEx(ComputerNameNetBIOS); } }
//
// Analysis Phase
//
// First we need a Repairer object to keep track of the changes we
// will make during the Repair Phase.
Repairer repairer( csvFilename // might also need domain NC,
// might also need targetMachine full name
);
// Then we need a scribe to record the analysis.
Amanuensis amanuensis;
// Then we need an Analyst to figure out what's broken and how to
// fix it.
Analyst analyst(targetDomainControllerName, amanuensis, repairer); hr = analyst.AnalyzeDisplaySpecifiers(); BREAK_ON_FAILED_HRESULT(hr);
//
// Repair Phase
//
// CODEWORK: get user confirmation to apply repairs
hr = repairer.BuildRepairFiles(); BREAK_ON_FAILED_HRESULT(hr);
hr = repairer.ApplyRepairs(); BREAK_ON_FAILED_HRESULT(hr); } while (0);
LOG_HRESULT(hr);
return hr; }
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE /* hPrevInstance */ , PSTR /* lpszCmdLine */ , int /* nCmdShow */) { hResourceModuleHandle = hInstance;
ExitCode exitCode = EXIT_CODE_UNSUCCESSFUL;
HRESULT hr = Win::CreateMutex(0, true, RUNTIME_NAME, appRunningMutex); if (hr == Win32ToHresult(ERROR_ALREADY_EXISTS)) { // The application is already running
// CODEWORK: use FindWindowEx and BringWindowToTop,
// SetForegroundWindow to transfer focus
// to the other instance?
} else { hr = ::CoInitialize(0); ASSERT(SUCCEEDED(hr));
hr = Start(); if (SUCCEEDED(hr)) { exitCode = EXIT_CODE_SUCCESSFUL; } }
return static_cast<int>(exitCode); }
|