Source code of Windows XP (NT5)
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.

208 lines
4.3 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // domain controller promotion wizard helper
  4. //
  5. // 8-13-99 sburns
  6. #include "headers.hxx"
  7. HINSTANCE hResourceModuleHandle = 0;
  8. const wchar_t* HELPFILE_NAME = 0;
  9. const wchar_t* RUNTIME_NAME = L"dcpromohelp";
  10. DWORD DEFAULT_LOGGING_OPTIONS =
  11. Log::OUTPUT_TO_FILE
  12. | Log::OUTPUT_FUNCCALLS
  13. | Log::OUTPUT_LOGS
  14. | Log::OUTPUT_ERRORS
  15. | Log::OUTPUT_HEADER;
  16. // Template function that actually calls ADsGetObject.
  17. //
  18. // Interface - The IADsXXX interface of the object to be bound.
  19. //
  20. // path - The ADSI path of the object to be bound.
  21. //
  22. // ptr - A null smart pointer to be bound to the interface of the object.
  23. template <class Interface>
  24. static
  25. HRESULT
  26. TemplateGetObject(
  27. const String& path,
  28. SmartInterface<Interface>& ptr)
  29. {
  30. LOG_FUNCTION2(TemplateGetObject, path);
  31. ASSERT(!path.empty());
  32. Interface* p = 0;
  33. HRESULT hr =
  34. ::ADsGetObject(
  35. path.c_str(),
  36. __uuidof(Interface),
  37. reinterpret_cast<void**>(&p));
  38. if (SUCCEEDED(hr))
  39. {
  40. ptr.Acquire(p);
  41. }
  42. return hr;
  43. }
  44. // Start csvde.exe with appropriate parameters, running without a window
  45. //
  46. // domainDn - full DN of the domain into which the display specifiers are
  47. // to be imported. e.g. DC=foo,DC=bar,DC=com
  48. HRESULT
  49. StartCsvde(const String& domainDn)
  50. {
  51. LOG_FUNCTION2(StartCsvde, domainDn);
  52. ASSERT(!domainDn.empty());
  53. String windir = Win::GetSystemWindowsDirectory();
  54. String logPath = windir + L"\\debug";
  55. String sys32dir = Win::GetSystemDirectory();
  56. String csvPath = sys32dir + L"\\mui\\dispspec\\dcpromo.csv";
  57. String exePath = sys32dir + L"\\csvde.exe";
  58. String commandLine =
  59. String::format(
  60. L" -i -f %1 -c DOMAINPLACEHOLDER %2 -j %3",
  61. csvPath.c_str(),
  62. domainDn.c_str(),
  63. logPath.c_str());
  64. STARTUPINFO startupInfo;
  65. memset(&startupInfo, 0, sizeof(startupInfo));
  66. startupInfo.cb = sizeof(startupInfo);
  67. PROCESS_INFORMATION procInfo;
  68. memset(&procInfo, 0, sizeof(procInfo));
  69. LOG(L"Calling CreateProcess");
  70. LOG(exePath);
  71. LOG(commandLine);
  72. HRESULT hr = S_OK;
  73. size_t len = commandLine.length();
  74. WCHAR* tempCommandLine = new WCHAR[len + 1];
  75. memset(tempCommandLine, 0, sizeof(WCHAR) * (len + 1));
  76. commandLine.copy(tempCommandLine, len);
  77. BOOL result =
  78. ::CreateProcessW(
  79. exePath.c_str(),
  80. tempCommandLine,
  81. 0,
  82. 0,
  83. FALSE,
  84. CREATE_NO_WINDOW,
  85. 0,
  86. 0,
  87. &startupInfo,
  88. &procInfo);
  89. if (!result)
  90. {
  91. hr = Win::GetLastErrorAsHresult();
  92. }
  93. LOG_HRESULT(hr);
  94. delete[] tempCommandLine;
  95. return hr;
  96. }
  97. HRESULT
  98. DoIt()
  99. {
  100. LOG_FUNCTION(DoIt);
  101. HRESULT hr = S_OK;
  102. do
  103. {
  104. hr = ::CoInitialize(0);
  105. BREAK_ON_FAILED_HRESULT2(hr, L"CoInitialize failed");
  106. // make sure the DS is running. If it is, then this implies that the
  107. // local machine is a DC, the local machine is not in safe boot mode,
  108. // and the local machine is at least version >= 5
  109. if (!IsDSRunning())
  110. {
  111. LOG(L"Active Directory is not running -- unable to proceed");
  112. hr = E_FAIL;
  113. break;
  114. }
  115. // bind to the RootDse on the local machine
  116. SmartInterface<IADs> iads(0);
  117. hr = TemplateGetObject<IADs>(L"LDAP://RootDse", iads);
  118. BREAK_ON_FAILED_HRESULT2(hr, L"bind to rootdse failed");
  119. // read the default naming context. This is the DN of the domain for
  120. // which the machine is a domain controller.
  121. _variant_t variant;
  122. hr = iads->Get(AutoBstr(L"defaultNamingContext"), &variant);
  123. BREAK_ON_FAILED_HRESULT2(hr, L"bind to default naming context failed");
  124. String domainDn = V_BSTR(&variant);
  125. LOG(domainDn);
  126. ASSERT(!domainDn.empty());
  127. hr = StartCsvde(domainDn);
  128. BREAK_ON_FAILED_HRESULT(hr);
  129. }
  130. while (0);
  131. return hr;
  132. }
  133. int
  134. _cdecl
  135. main(int, char **)
  136. {
  137. LOG_FUNCTION(main);
  138. int exitCode = 0;
  139. HANDLE mutex = 0;
  140. HRESULT hr = Win::CreateMutex(0, true, RUNTIME_NAME, mutex);
  141. if (hr == Win32ToHresult(ERROR_ALREADY_EXISTS))
  142. {
  143. LOG(L"already running. That's weird.");
  144. exitCode = 1;
  145. }
  146. else
  147. {
  148. HRESULT hr = DoIt();
  149. if (FAILED(hr))
  150. {
  151. LOG(GetErrorMessage(hr));
  152. exitCode = 2;
  153. }
  154. }
  155. return exitCode;
  156. }