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.

370 lines
9.4 KiB

  1. // Copyright (c) 1997-2001 Microsoft Corporation
  2. //
  3. // File: ADInstallationUnit.cpp
  4. //
  5. // Synopsis: Defines a ADInstallationUnit
  6. // This object has the knowledge for installing
  7. // Active Directory
  8. //
  9. // History: 02/08/2001 JeffJon Created
  10. #include "pch.h"
  11. #include "resource.h"
  12. #include "InstallationUnitProvider.h"
  13. #include "state.h"
  14. #define CYS_DCPROMO_COMMAND_LINE L"dcpromo.exe"
  15. // Exit codes borrowed from DCPromo.cpp
  16. enum DCPromoExitCodes
  17. {
  18. // the operation failed.
  19. EXIT_CODE_UNSUCCESSFUL = 0,
  20. // the operation succeeded
  21. EXIT_CODE_SUCCESSFUL = 1,
  22. // the operation succeeded, and the user opted not to have the wizard
  23. // restart the machine, either manually or by specifying
  24. // RebootOnSuccess=NoAndNoPromptEither in the answerfile
  25. EXIT_CODE_SUCCESSFUL_NO_REBOOT = 2,
  26. // the operation failed, but the machine needs to be rebooted anyway
  27. EXIT_CODE_UNSUCCESSFUL_NEEDS_REBOOT = 3
  28. };
  29. // Finish page help
  30. static PCWSTR CYS_AD_FINISH_PAGE_HELP = L"cys.chm::/cys_configuring_domain_controller.htm";
  31. ADInstallationUnit::ADInstallationUnit() :
  32. isExpressPathInstall(false),
  33. InstallationUnit(
  34. IDS_DOMAIN_CONTROLLER_TYPE,
  35. IDS_DOMAIN_CONTROLLER_DESCRIPTION,
  36. CYS_AD_FINISH_PAGE_HELP,
  37. DC_INSTALL)
  38. {
  39. LOG_CTOR(ADInstallationUnit);
  40. }
  41. ADInstallationUnit::~ADInstallationUnit()
  42. {
  43. LOG_DTOR(ADInstallationUnit);
  44. }
  45. InstallationReturnType
  46. ADInstallationUnit::InstallService(HANDLE logfileHandle, HWND hwnd)
  47. {
  48. LOG_FUNCTION(ADInstallationUnit::InstallService);
  49. InstallationReturnType result = INSTALL_SUCCESS_REBOOT;
  50. do
  51. {
  52. // Set the rerun state to false since DCPromo requires a reboot
  53. State::GetInstance().SetRerunWizard(false);
  54. if (IsExpressPathInstall())
  55. {
  56. result = InstallServiceExpressPath(logfileHandle, hwnd);
  57. break;
  58. }
  59. // Set the home regkey so that we go through post boot operations
  60. bool regkeyResult = SetRegKeyValue(
  61. CYS_HOME_REGKEY,
  62. CYS_HOME_VALUE,
  63. CYS_HOME_REGKEY_DCPROMO_VALUE,
  64. HKEY_LOCAL_MACHINE,
  65. true);
  66. ASSERT(regkeyResult);
  67. // Run dcpromo.exe
  68. String commandline(CYS_DCPROMO_COMMAND_LINE);
  69. DWORD exitCode = 0;
  70. HRESULT hr = CreateAndWaitForProcess(commandline, exitCode);
  71. if (FAILED(hr) ||
  72. exitCode == EXIT_CODE_UNSUCCESSFUL ||
  73. exitCode == EXIT_CODE_UNSUCCESSFUL_NEEDS_REBOOT)
  74. {
  75. CYS_APPEND_LOG(String::load(IDS_LOG_DOMAIN_CONTROLLER_HEADING));
  76. CYS_APPEND_LOG(String::load(IDS_LOG_DOMAIN_CONTROLLER_INSTALL));
  77. CYS_APPEND_LOG(String::load(IDS_LOG_WIZARD_CANCELLED));
  78. result = INSTALL_FAILURE;
  79. break;
  80. }
  81. } while (false);
  82. LOG_INSTALL_RETURN(result);
  83. return result;
  84. }
  85. InstallationReturnType
  86. ADInstallationUnit::InstallServiceExpressPath(HANDLE /*logfileHandle*/, HWND /*hwnd*/)
  87. {
  88. LOG_FUNCTION(ADInstallationUnit::InstallServiceExpressPath);
  89. InstallationReturnType result = INSTALL_SUCCESS_REBOOT;
  90. // All these regkeys need to be set before we launch DCPromo because DCPromo
  91. // will reboot the machine
  92. // First set the home regkey to FirstServer so that we finish up the installation
  93. // after reboot
  94. bool regkeyResult = SetRegKeyValue(
  95. CYS_HOME_REGKEY,
  96. CYS_HOME_VALUE,
  97. CYS_HOME_REGKEY_FIRST_SERVER_VALUE,
  98. HKEY_LOCAL_MACHINE,
  99. true);
  100. ASSERT(regkeyResult);
  101. // Set the the first DC regkey
  102. regkeyResult = SetRegKeyValue(
  103. CYS_HOME_REGKEY,
  104. CYS_FIRST_DC_VALUE,
  105. CYS_FIRST_DC_VALUE_SET,
  106. HKEY_LOCAL_MACHINE,
  107. true);
  108. ASSERT(regkeyResult);
  109. // Set the key so CYS runs again
  110. String emptyString;
  111. regkeyResult = SetRegKeyValue(
  112. CYS_HOME_REGKEY,
  113. emptyString,
  114. CYS_HOME_RUN_KEY_RUN_AGAIN,
  115. HKEY_CURRENT_USER,
  116. true);
  117. ASSERT(regkeyResult);
  118. // set the key so CYS has to run again
  119. regkeyResult = SetRegKeyValue(
  120. CYS_HOME_REGKEY,
  121. CYS_HOME_REGKEY_MUST_RUN,
  122. CYS_HOME_RUN_KEY_RUN_AGAIN,
  123. HKEY_LOCAL_MACHINE,
  124. true);
  125. ASSERT(regkeyResult);
  126. // set the key to let the reboot know what the domain DNS name is
  127. regkeyResult = SetRegKeyValue(
  128. CYS_HOME_REGKEY,
  129. CYS_HOME_REGKEY_DOMAINDNS,
  130. GetNewDomainDNSName(),
  131. HKEY_LOCAL_MACHINE,
  132. true);
  133. ASSERT(regkeyResult);
  134. // set the key to let the reboot know what the IP address is
  135. regkeyResult = SetRegKeyValue(
  136. CYS_HOME_REGKEY,
  137. CYS_HOME_REGKEY_DOMAINIP,
  138. InstallationUnitProvider::GetInstance().GetDNSInstallationUnit().GetStaticIPAddressString(),
  139. HKEY_LOCAL_MACHINE,
  140. true);
  141. ASSERT(regkeyResult);
  142. do
  143. {
  144. // Create answer file for DCPromo
  145. String answerFilePath;
  146. bool answerFileResult = CreateAnswerFileForDCPromo(answerFilePath);
  147. if (!answerFileResult)
  148. {
  149. ASSERT(answerFileResult);
  150. result = INSTALL_FAILURE;
  151. break;
  152. }
  153. String commandline = String::format(
  154. L"dcpromo /answer:%1",
  155. answerFilePath.c_str());
  156. DWORD exitCode = 0;
  157. HRESULT hr = CreateAndWaitForProcess(commandline, exitCode);
  158. if (FAILED(hr))
  159. {
  160. LOG(String::format(
  161. L"Failed to launch DCPromo: hr = %1!x!",
  162. hr));
  163. result = INSTALL_FAILURE;
  164. break;
  165. }
  166. // We can't do anything else here because DCPromo will reboot
  167. } while (false);
  168. LOG_INSTALL_RETURN(result);
  169. return result;
  170. }
  171. bool
  172. ADInstallationUnit::CreateAnswerFileForDCPromo(String& answerFilePath)
  173. {
  174. LOG_FUNCTION(ADInstallationUnit::CreateAnswerFileForDCPromo);
  175. bool result = true;
  176. String answerFileText = L"[DCInstall]\r\n";
  177. answerFileText += L"ReplicaOrNewDomain=Domain\r\n";
  178. answerFileText += L"TreeOrChild=Tree\r\n";
  179. answerFileText += L"CreateOrJoin=Create\r\n";
  180. answerFileText += L"DomainNetbiosName=";
  181. answerFileText += GetNewDomainNetbiosName();
  182. answerFileText += L"\r\n";
  183. answerFileText += L"NewDomainDNSName=";
  184. answerFileText += GetNewDomainDNSName();
  185. answerFileText += L"\r\n";
  186. answerFileText += L"DNSOnNetwork=No\r\n";
  187. answerFileText += L"DatabasePath=%systemroot%\\tds\r\n";
  188. answerFileText += L"LogPath=%systemroot%\\tds\r\n";
  189. answerFileText += L"SYSVOLPath=%systemroot%\\sysvol\r\n";
  190. answerFileText += L"SiteName=Default-First-Site\r\n";
  191. answerFileText += L"RebootOnSuccess=Yes\r\n";
  192. answerFileText += L"AutoConfigDNS=Yes\r\n";
  193. answerFileText += L"AllowAnonymousAccess=Yes\r\n";
  194. answerFileText += L"SafeModeAdminPassword=";
  195. answerFileText += GetSafeModeAdminPassword();
  196. answerFileText += L"\r\n";
  197. String sysFolder = Win::GetSystemDirectory();
  198. answerFilePath = sysFolder + L"\\dcpromo.inf";
  199. // create the answer file for DCPromo
  200. LOG(String::format(
  201. L"Creating answer file at: %1",
  202. answerFilePath.c_str()));
  203. HRESULT hr = CreateTempFile(answerFilePath, answerFileText);
  204. if (FAILED(hr))
  205. {
  206. LOG(String::format(
  207. L"Failed to create answer file for DCPromo: hr = %1!x!",
  208. hr));
  209. result = false;
  210. }
  211. LOG_BOOL(result);
  212. return result;
  213. }
  214. bool
  215. ADInstallationUnit::IsServiceInstalled()
  216. {
  217. LOG_FUNCTION(ADInstallationUnit::IsServiceInstalled);
  218. bool result = State::GetInstance().IsDC();
  219. LOG_BOOL(result);
  220. return result;
  221. }
  222. String
  223. ADInstallationUnit::GetServiceDescription()
  224. {
  225. LOG_FUNCTION(ADInstallationUnit::GetServiceDescription);
  226. unsigned int resourceID = static_cast<unsigned int>(-1);
  227. if (IsServiceInstalled())
  228. {
  229. resourceID = IDS_DOMAIN_CONTROLLER_DESCRIPTION_INSTALLED;
  230. }
  231. else
  232. {
  233. resourceID = descriptionID;
  234. }
  235. ASSERT(resourceID != static_cast<unsigned int>(-1));
  236. return String::load(resourceID);
  237. }
  238. bool
  239. ADInstallationUnit::GetFinishText(String& message)
  240. {
  241. LOG_FUNCTION(ADInstallationUnit::GetFinishText);
  242. message = String::load(IDS_DC_FINISH_TEXT);
  243. LOG_BOOL(true);
  244. return true;
  245. }
  246. void
  247. ADInstallationUnit::SetExpressPathInstall(bool isExpressPath)
  248. {
  249. LOG_FUNCTION2(
  250. ADInstallationUnit::SetExpressPathInstall,
  251. (isExpressPath) ? L"true" : L"false");
  252. isExpressPathInstall = isExpressPath;
  253. }
  254. bool
  255. ADInstallationUnit::IsExpressPathInstall() const
  256. {
  257. LOG_FUNCTION(ADInstallationUnit::IsExpressPathInstall);
  258. return isExpressPathInstall;
  259. }
  260. void
  261. ADInstallationUnit::SetNewDomainDNSName(const String& newDomain)
  262. {
  263. LOG_FUNCTION2(
  264. ADInstallationUnit::SetNewDomainDNSName,
  265. newDomain);
  266. domain = newDomain;
  267. }
  268. void
  269. ADInstallationUnit::SetNewDomainNetbiosName(const String& newNetbios)
  270. {
  271. LOG_FUNCTION2(
  272. ADInstallationUnit::SetNewDomainNetbiosName,
  273. newNetbios);
  274. netbios = newNetbios;
  275. }
  276. void
  277. ADInstallationUnit::SetSafeModeAdminPassword(const String& newPassword)
  278. {
  279. LOG_FUNCTION(ADInstallationUnit::SetSafeModeAdminPassword);
  280. password = newPassword;
  281. }