You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
4.6 KiB
205 lines
4.6 KiB
// Copyright (c) 1997-1999 Microsoft Corporation
|
|
//
|
|
// domain controller promotion wizard helper
|
|
//
|
|
// 8-13-99 sburns
|
|
|
|
|
|
|
|
#include "headers.hxx"
|
|
|
|
|
|
|
|
HINSTANCE hResourceModuleHandle = 0;
|
|
const wchar_t* HELPFILE_NAME = 0;
|
|
const wchar_t* RUNTIME_NAME = L"dcpromohelp";
|
|
|
|
DWORD DEFAULT_LOGGING_OPTIONS =
|
|
Log::OUTPUT_TO_FILE
|
|
| Log::OUTPUT_FUNCCALLS
|
|
| Log::OUTPUT_LOGS
|
|
| Log::OUTPUT_ERRORS
|
|
| Log::OUTPUT_HEADER;
|
|
|
|
|
|
|
|
// Template function that actually calls ADsGetObject.
|
|
//
|
|
// Interface - The IADsXXX interface of the object to be bound.
|
|
//
|
|
// path - The ADSI path of the object to be bound.
|
|
//
|
|
// ptr - A null smart pointer to be bound to the interface of the object.
|
|
|
|
template <class Interface>
|
|
static
|
|
HRESULT
|
|
TemplateGetObject(
|
|
const String& path,
|
|
SmartInterface<Interface>& ptr)
|
|
{
|
|
LOG_FUNCTION2(TemplateGetObject, path);
|
|
ASSERT(!path.empty());
|
|
|
|
Interface* p = 0;
|
|
HRESULT hr =
|
|
::ADsGetObject(
|
|
path.c_str(),
|
|
__uuidof(Interface),
|
|
reinterpret_cast<void**>(&p));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ptr.Acquire(p);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
// Start csvde.exe with appropriate parameters, running without a window
|
|
//
|
|
// domainDn - full DN of the domain into which the display specifiers are
|
|
// to be imported. e.g. DC=foo,DC=bar,DC=com
|
|
|
|
HRESULT
|
|
StartCsvde(const String& domainDn)
|
|
{
|
|
LOG_FUNCTION2(StartCsvde, domainDn);
|
|
ASSERT(!domainDn.empty());
|
|
|
|
// REVIEWED-2002/02/27-sburns we're passing full paths
|
|
|
|
String windir = Win::GetSystemWindowsDirectory();
|
|
String logPath = windir + L"\\debug";
|
|
|
|
String sys32dir = Win::GetSystemDirectory();
|
|
String csvPath = sys32dir + L"\\mui\\dispspec\\dcpromo.csv";
|
|
String exePath = sys32dir + L"\\csvde.exe";
|
|
|
|
String commandLine =
|
|
String::format(
|
|
L" -i -f %1 -c DOMAINPLACEHOLDER %2 -j %3",
|
|
csvPath.c_str(),
|
|
domainDn.c_str(),
|
|
logPath.c_str());
|
|
|
|
STARTUPINFO startupInfo;
|
|
|
|
// REVIEWED-2002/02/27-sburns correct byte count passed
|
|
|
|
::ZeroMemory(&startupInfo, sizeof startupInfo);
|
|
|
|
startupInfo.cb = sizeof(startupInfo);
|
|
|
|
PROCESS_INFORMATION procInfo;
|
|
|
|
// REVIEWED-2002/02/27-sburns correct byte count passed
|
|
|
|
::ZeroMemory(&procInfo, sizeof procInfo);
|
|
|
|
LOG(L"Calling CreateProcess");
|
|
LOG(exePath);
|
|
LOG(commandLine);
|
|
|
|
HRESULT hr =
|
|
Win::CreateProcess(
|
|
exePath,
|
|
commandLine,
|
|
CREATE_NO_WINDOW,
|
|
String(),
|
|
startupInfo,
|
|
procInfo);
|
|
LOG_HRESULT(hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
DoIt()
|
|
{
|
|
LOG_FUNCTION(DoIt);
|
|
|
|
HRESULT hr = S_OK;
|
|
do
|
|
{
|
|
AutoCoInitialize coInit;
|
|
hr = coInit.Result();
|
|
BREAK_ON_FAILED_HRESULT2(hr, L"CoInitialize failed");
|
|
|
|
// make sure the DS is running. If it is, then this implies that the
|
|
// local machine is a DC, the local machine is not in safe boot mode,
|
|
// and the local machine is at least version >= 5
|
|
|
|
if (!IsDSRunning())
|
|
{
|
|
LOG(L"Active Directory is not running -- unable to proceed");
|
|
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
// bind to the RootDse on the local machine
|
|
|
|
SmartInterface<IADs> iads(0);
|
|
hr = TemplateGetObject<IADs>(L"LDAP://RootDse", iads);
|
|
BREAK_ON_FAILED_HRESULT2(hr, L"bind to rootdse failed");
|
|
|
|
// read the default naming context. This is the DN of the domain for
|
|
// which the machine is a domain controller.
|
|
|
|
_variant_t variant;
|
|
hr = iads->Get(AutoBstr(L"defaultNamingContext"), &variant);
|
|
BREAK_ON_FAILED_HRESULT2(hr, L"bind to default naming context failed");
|
|
|
|
String domainDn = V_BSTR(&variant);
|
|
|
|
LOG(domainDn);
|
|
ASSERT(!domainDn.empty());
|
|
|
|
hr = StartCsvde(domainDn);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
}
|
|
while (0);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
_cdecl
|
|
main(int, char **)
|
|
{
|
|
LOG_FUNCTION(main);
|
|
|
|
int exitCode = 0;
|
|
|
|
HANDLE mutex = 0;
|
|
|
|
// REVIEWED-2002/02/27-sburns This is a global named object, and subject to
|
|
// squatting, but the consquenences of that are administrative annoyance
|
|
// (the admin will have to manually import the display specifiers).
|
|
|
|
HRESULT hr = Win::CreateMutex(0, true, RUNTIME_NAME, mutex);
|
|
if (hr == Win32ToHresult(ERROR_ALREADY_EXISTS))
|
|
{
|
|
LOG(L"already running. That's weird.");
|
|
exitCode = 1;
|
|
}
|
|
else
|
|
{
|
|
hr = DoIt();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(GetErrorMessage(hr));
|
|
|
|
exitCode = 2;
|
|
}
|
|
}
|
|
|
|
return exitCode;
|
|
}
|