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.

1778 lines
31 KiB

  1. // Copyright (C) 1997 Microsoft Corporation
  2. //
  3. // wizard state object
  4. //
  5. // 12-15-97 sburns
  6. #include "headers.hxx"
  7. #include "state.hpp"
  8. #include "resource.h"
  9. #include "ds.hpp"
  10. #include "common.hpp"
  11. static const String SECTION_NAME(L"DCInstall");
  12. const String State::OPTION_NEW_DOMAIN_NAME(L"NewDomainDNSName");
  13. const String State::OPTION_SITE_NAME(L"SiteName");
  14. const String State::OPTION_PARENT_DOMAIN_NAME(L"ParentDomainDNSName");
  15. const String State::OPTION_CHILD_NAME(L"ChildName");
  16. const String State::OPTION_DNS_ON_NET(L"DNSOnNetwork");
  17. const String State::OPTION_REPLICA_OR_NEW_DOMAIN(L"ReplicaOrNewDomain");
  18. const String State::VALUE_DOMAIN(L"Domain");
  19. const String State::OPTION_REPLICA_OR_MEMBER(L"ReplicaOrMember");
  20. const String State::VALUE_REPLICA(L"Replica");
  21. const String State::OPTION_NEW_DOMAIN(L"NewDomain");
  22. const String State::VALUE_CHILD(L"Child");
  23. const String State::VALUE_TREE(L"Tree");
  24. const String State::OPTION_NEW_DOMAIN_NETBIOS_NAME(L"DomainNetbiosName");
  25. const String State::OPTION_DATABASE_PATH(L"DatabasePath");
  26. const String State::OPTION_LOG_PATH(L"LogPath");
  27. const String State::OPTION_SYSVOL_PATH(L"SYSVOLPath");
  28. const String State::OPTION_REPLICA_DOMAIN_NAME(L"ReplicaDomainDNSName");
  29. const String State::OPTION_IS_LAST_DC(L"IsLastDCInDomain");
  30. const String State::VALUE_YES(L"Yes");
  31. const String State::VALUE_NO(L"No");
  32. const String State::OPTION_ADMIN_PASSWORD(L"AdministratorPassword");
  33. const String State::OPTION_REBOOT(L"RebootOnSuccess");
  34. const String State::VALUE_NO_DONT_PROMPT(L"NoAndNoPromptEither");
  35. const String State::OPTION_USERNAME(L"UserName");
  36. const String State::OPTION_PASSWORD(L"Password");
  37. const String State::OPTION_USER_DOMAIN(L"UserDomain");
  38. const String State::OPTION_AUTO_CONFIG_DNS(L"AutoConfigDNS");
  39. const String State::OPTION_ALLOW_ANON_ACCESS(L"AllowAnonymousAccess");
  40. const String State::OPTION_REPLICATION_SOURCE(L"ReplicationSourceDC");
  41. const String State::OPTION_SAFE_MODE_ADMIN_PASSWORD(L"SafeModeAdminPassword");
  42. const String State::OPTION_CRITICAL_REPLICATION_ONLY(L"CriticalReplicationOnly");
  43. const String State::OPTION_SOURCE_PATH(L"ReplicationSourcePath");
  44. const String State::OPTION_SYSKEY(L"Syskey");
  45. const String State::OPTION_GC_CONFIRM(L"ConfirmGc");
  46. const String State::OPTION_SET_FOREST_VERSION("SetForestVersion");
  47. static State* stateInstance;
  48. void
  49. State::Init()
  50. {
  51. ASSERT(!stateInstance);
  52. stateInstance = new State;
  53. }
  54. void
  55. State::Destroy()
  56. {
  57. delete stateInstance;
  58. };
  59. State&
  60. State::GetInstance()
  61. {
  62. ASSERT(stateInstance);
  63. return *stateInstance;
  64. }
  65. // Determines the full file path of the folder where administration (incl. DS)
  66. // tools shortcuts are placed. On success, returns S_OK and sets result to
  67. // the path. On failure, returns a COM error and sets results to empty.
  68. //
  69. // result - receives the folder path on success.
  70. HRESULT
  71. GetAdminToolsPath(String& result)
  72. {
  73. LOG_FUNCTION(GetAdminToolsPath);
  74. result.erase();
  75. TCHAR buf[MAX_PATH];
  76. HRESULT hr =
  77. ::SHGetFolderPath(
  78. 0,
  79. CSIDL_COMMON_ADMINTOOLS,
  80. 0,
  81. SHGFP_TYPE_CURRENT,
  82. buf);
  83. if (SUCCEEDED(hr))
  84. {
  85. result = buf;
  86. }
  87. return hr;
  88. }
  89. State::State()
  90. :
  91. adminPassword(),
  92. allowAnonAccess(false),
  93. answerFile(0),
  94. autoConfigDns(false),
  95. computer(),
  96. context(),
  97. dbPath(),
  98. domainsInForest(),
  99. failureMessage(),
  100. finishMessages(),
  101. installedSite(),
  102. isAdvancedMode(false),
  103. isBackupGc(false),
  104. isDnsOnNet(true),
  105. isLastDc(false),
  106. isUpgrade(false),
  107. logPath(),
  108. needsCommandLineHelp(false),
  109. needsReboot(false),
  110. newDomainDnsName(),
  111. newDomainFlatName(),
  112. operation(NONE),
  113. operationResultsMessage(),
  114. operationResultsStatus(FAILURE),
  115. operationResultsFlags(0),
  116. parentDomainDnsName(),
  117. password(),
  118. reinstallDomain(false),
  119. reinstallDomainController(false),
  120. replicaDnsDomainName(),
  121. replicateFromMedia(false),
  122. replicationPartnerDc(),
  123. restoreGc(false),
  124. runHiddenWhileUnattended(true),
  125. safeModeAdminPassword(),
  126. setForestVersion(false),
  127. shortcutPath(),
  128. siteName(),
  129. splash(0),
  130. sourcePath(),
  131. sysvolPath(),
  132. syskey(),
  133. syskeyLocation(STORED),
  134. useCurrentCredentials(false),
  135. userDomain(),
  136. userForest(),
  137. username()
  138. {
  139. LOG_CTOR(State);
  140. ArgMap args;
  141. MapCommandLineArgs(args);
  142. if (args.size() < 2)
  143. {
  144. LOG(L"no options specified");
  145. }
  146. else
  147. {
  148. // check for answerfile specification
  149. static const wchar_t* ANSWER1 = L"answer";
  150. static const wchar_t* ANSWER2 = L"u";
  151. static const wchar_t* ANSWER3 = L"upgrade";
  152. if (
  153. args.find(ANSWER1) != args.end()
  154. || args.find(ANSWER2) != args.end()
  155. || args.find(ANSWER3) != args.end() )
  156. {
  157. bool isDefaultAnswerfile = false;
  158. String filename = args[ANSWER1];
  159. if (filename.empty())
  160. {
  161. filename = args[ANSWER2];
  162. }
  163. if (filename.empty())
  164. {
  165. filename = args[ANSWER3];
  166. }
  167. if (filename.empty())
  168. {
  169. // default value if none specified
  170. filename = L"%systemdrive%\\dcpromo-ntupg.inf";
  171. // if this file does not exist, don't pop up an error message.
  172. isDefaultAnswerfile = true;
  173. }
  174. SetupAnswerFile(filename, isDefaultAnswerfile);
  175. args.erase(ANSWER1);
  176. args.erase(ANSWER2);
  177. args.erase(ANSWER3);
  178. }
  179. // check for /adv
  180. static const wchar_t* ADV = L"adv";
  181. if (args.find(ADV) != args.end())
  182. {
  183. LOG(L"Enabling advanced mode");
  184. isAdvancedMode = true;
  185. args.erase(ADV);
  186. }
  187. // anything left over gets you command line help, (one arg will always
  188. // remain: the name of the exe)
  189. if (args.size() > 1)
  190. {
  191. LOG(L"Unrecognized command line options specified");
  192. needsCommandLineHelp = true;
  193. }
  194. }
  195. HRESULT hr = computer.Refresh();
  196. // we're confident this will work, as the computer refers to the
  197. // local machine.
  198. ASSERT(SUCCEEDED(hr));
  199. LOG_HRESULT(hr);
  200. DetermineRunContext();
  201. // Disable locking of the console as early as possible to narrow the
  202. // window of opportunity for the user (or the system) to lock the
  203. // console before a valid machine security state is reached. We do this
  204. // early only for upgrades, because upgrades autologon and autostart
  205. // dcpromo, and the console may sit idle for some time. 311161
  206. if (context == PDC_UPGRADE || context == BDC_UPGRADE)
  207. {
  208. DisableConsoleLocking();
  209. }
  210. // We must call this at startup, because once a demote operation is
  211. // complete, it may not be possible for the shell to determine this
  212. // path. 366738
  213. hr = GetAdminToolsPath(shortcutPath);
  214. ASSERT(SUCCEEDED(hr));
  215. LOG_HRESULT(hr);
  216. }
  217. void
  218. State::SetupAnswerFile(const String& filename, bool isDefaultAnswerfile)
  219. {
  220. LOG_FUNCTION2(State::SetupAnswerFile, filename);
  221. String f(filename);
  222. if (f.find(L"\\") == String::npos)
  223. {
  224. // GetPrivateProfileString requires a path: use the current directory
  225. // as a default path.
  226. f = L".\\" + filename;
  227. }
  228. LOG(L"answerfile specified: " + f);
  229. f = Win::ExpandEnvironmentStrings(f);
  230. LOG(L"answerfile resolved to: " + f);
  231. // we don't use FS::PathExist here because that function expects a
  232. // fully-qualified path. The path we have may be relative.
  233. DWORD unused = 0;
  234. HRESULT hr = Win::GetFileAttributes(f, unused);
  235. if (SUCCEEDED(hr))
  236. {
  237. // file found.
  238. LOG(L"answerfile found");
  239. answerFile = new AnswerFile(f);
  240. splash = new UnattendSplashDialog();
  241. splash->ModelessExecute(Win::GetDesktopWindow());
  242. }
  243. else
  244. {
  245. LOG(L"answerfile NOT found");
  246. if (!isDefaultAnswerfile)
  247. {
  248. popup.Error(
  249. Win::GetDesktopWindow(),
  250. String::format(IDS_ANSWERFILE_NOT_FOUND, f.c_str()));
  251. }
  252. }
  253. }
  254. #ifdef LOGGING_BUILD
  255. static const String CONTEXTS[] =
  256. {
  257. L"NT5_DC",
  258. L"NT5_STANDALONE_SERVER",
  259. L"NT5_MEMBER_SERVER",
  260. L"BDC_UPGRADE",
  261. L"PDC_UPGRADE"
  262. };
  263. #endif
  264. void
  265. State::DetermineRunContext()
  266. {
  267. LOG_FUNCTION(State::DetermineRunContext);
  268. DS::PriorServerRole priorRole = DS::GetPriorServerRole(isUpgrade);
  269. if (isUpgrade && priorRole != DS::UNKNOWN)
  270. {
  271. switch (priorRole)
  272. {
  273. case DS::PDC:
  274. {
  275. context = PDC_UPGRADE;
  276. break;
  277. }
  278. case DS::BDC:
  279. {
  280. context = BDC_UPGRADE;
  281. break;
  282. }
  283. default:
  284. {
  285. ASSERT(false);
  286. break;
  287. }
  288. }
  289. }
  290. else
  291. {
  292. switch (computer.GetRole())
  293. {
  294. case Computer::STANDALONE_SERVER:
  295. {
  296. context = NT5_STANDALONE_SERVER;
  297. break;
  298. }
  299. case Computer::MEMBER_SERVER:
  300. {
  301. context = NT5_MEMBER_SERVER;
  302. break;
  303. }
  304. case Computer::PRIMARY_CONTROLLER:
  305. case Computer::BACKUP_CONTROLLER:
  306. {
  307. // we're already an NT5 DC
  308. context = NT5_DC;
  309. break;
  310. }
  311. case Computer::STANDALONE_WORKSTATION:
  312. case Computer::MEMBER_WORKSTATION:
  313. default:
  314. {
  315. // we checked for this at startup
  316. ASSERT(false);
  317. break;
  318. }
  319. }
  320. }
  321. LOG(CONTEXTS[context]);
  322. }
  323. State::~State()
  324. {
  325. LOG_DTOR(State);
  326. delete answerFile;
  327. // closes the splash dialog, if visible.
  328. delete splash;
  329. }
  330. State::RunContext
  331. State::GetRunContext() const
  332. {
  333. LOG_FUNCTION2(State::GetRunContext, CONTEXTS[context]);
  334. return context;
  335. }
  336. bool
  337. State::UsingAnswerFile() const
  338. {
  339. return answerFile != 0;
  340. }
  341. bool
  342. IsPasswordOption(const String& option)
  343. {
  344. if (
  345. option.icompare(State::OPTION_PASSWORD) == 0
  346. || option.icompare(State::OPTION_ADMIN_PASSWORD) == 0
  347. || option.icompare(State::OPTION_SYSKEY) == 0
  348. || option.icompare(State::OPTION_SAFE_MODE_ADMIN_PASSWORD) == 0) // 142313
  349. {
  350. return true;
  351. }
  352. return false;
  353. }
  354. String
  355. State::GetAnswerFileOption(const String& option) const
  356. {
  357. LOG_FUNCTION2(GetAnswerFileOption, option);
  358. ASSERT(UsingAnswerFile());
  359. String result;
  360. if (answerFile)
  361. {
  362. result = answerFile->ReadKey(SECTION_NAME, option);
  363. // wipe out passwords as they are read.
  364. if (IsPasswordOption(option))
  365. {
  366. // caller should be using GetEncodedAnswerFileOption
  367. ASSERT(false);
  368. if (answerFile->IsKeyPresent(SECTION_NAME, option))
  369. {
  370. answerFile->WriteKey(SECTION_NAME, option, String());
  371. }
  372. }
  373. else
  374. {
  375. // only trace non-password fields.
  376. LOG(result);
  377. }
  378. }
  379. return result;
  380. }
  381. EncodedString
  382. State::GetEncodedAnswerFileOption(const String& option) const
  383. {
  384. LOG_FUNCTION2(GetEncodedAnswerFileOption, option);
  385. ASSERT(UsingAnswerFile());
  386. EncodedString result;
  387. if (answerFile)
  388. {
  389. result = answerFile->EncodedReadKey(SECTION_NAME, option);
  390. // wipe out passwords as they are read.
  391. if (IsPasswordOption(option))
  392. {
  393. if (answerFile->IsKeyPresent(SECTION_NAME, option))
  394. {
  395. answerFile->WriteKey(SECTION_NAME, option, String());
  396. }
  397. }
  398. else
  399. {
  400. // should only use the Encoded function for passwords
  401. ASSERT(false);
  402. }
  403. }
  404. return result;
  405. }
  406. #ifdef LOGGING_BUILD
  407. static const String OPERATIONS[] =
  408. {
  409. L"NONE",
  410. L"REPLICA",
  411. L"FOREST",
  412. L"TREE",
  413. L"CHILD",
  414. L"DEMOTE",
  415. L"ABORT_BDC_UPGRADE"
  416. };
  417. #endif
  418. void
  419. State::SetOperation(Operation oper)
  420. {
  421. LOG_FUNCTION2(State::SetOperation, OPERATIONS[oper]);
  422. operation = oper;
  423. }
  424. State::Operation
  425. State::GetOperation() const
  426. {
  427. LOG_FUNCTION2(State::GetOperation, OPERATIONS[operation]);
  428. // if aborting BDC upgrade, context must be BDC upgrade
  429. ASSERT(operation == ABORT_BDC_UPGRADE ? context == BDC_UPGRADE : true);
  430. return operation;
  431. }
  432. void
  433. State::SetReplicaDomainDNSName(const String& dnsName)
  434. {
  435. LOG_FUNCTION2(State:::SetReplicaDomainDNSName, dnsName);
  436. ASSERT(!dnsName.empty());
  437. replicaDnsDomainName = dnsName;
  438. // if the user is changing the domain to be replicated, then any
  439. // previous replication partner DC may no longer apply.
  440. // see ntbug9 #158726
  441. SetReplicationPartnerDC(L"");
  442. }
  443. String
  444. State::GetDatabasePath() const
  445. {
  446. LOG_FUNCTION2(State::GetDatabasePath, dbPath);
  447. return dbPath;
  448. }
  449. String
  450. State::GetLogPath() const
  451. {
  452. LOG_FUNCTION2(State::GetLogPath, logPath);
  453. return logPath;
  454. }
  455. String
  456. State::GetSYSVOLPath() const
  457. {
  458. LOG_FUNCTION2(State::GetSYSVOLPath, sysvolPath);
  459. return sysvolPath;
  460. }
  461. void
  462. State::SetDatabasePath(const String& path)
  463. {
  464. LOG_FUNCTION2(State::SetDatabasePath, path);
  465. ASSERT(!path.empty());
  466. dbPath = path;
  467. }
  468. void
  469. State::SetLogPath(const String& path)
  470. {
  471. LOG_FUNCTION2(State::SetLogPath, path);
  472. ASSERT(!path.empty());
  473. logPath = path;
  474. }
  475. void
  476. State::SetSYSVOLPath(const String& path)
  477. {
  478. LOG_FUNCTION2(State::SetSYSVOLPath, path);
  479. ASSERT(!path.empty());
  480. sysvolPath = path;
  481. }
  482. String
  483. State::GetUsername() const
  484. {
  485. LOG_FUNCTION2(State::GetUsername, username);
  486. // don't assert that this is !empty -- we may use existing credentials
  487. return username;
  488. }
  489. EncodedString
  490. State::GetPassword() const
  491. {
  492. // don't log the password...
  493. LOG_FUNCTION(State::GetPassword);
  494. // don't assert that this is !empty -- we may use existing credentials
  495. return password;
  496. }
  497. void
  498. State::SetUsername(const String& name)
  499. {
  500. LOG_FUNCTION2(State::SetUsername, name);
  501. ASSERT(!name.empty());
  502. username = name;
  503. }
  504. void
  505. State::SetPassword(const EncodedString& password_)
  506. {
  507. LOG_FUNCTION(State::SetPassword);
  508. // password_ may be empty
  509. // ASSERT(!password_.empty());
  510. password = password_;
  511. }
  512. String
  513. State::GetReplicaDomainDNSName() const
  514. {
  515. LOG_FUNCTION2(
  516. State::GetReplicaDomainDNSName,
  517. replicaDnsDomainName);
  518. return replicaDnsDomainName;
  519. }
  520. String
  521. State::GetSiteName() const
  522. {
  523. LOG_FUNCTION2(State::GetSiteName, siteName);
  524. return siteName;
  525. }
  526. void
  527. State::SetSiteName(const String& site)
  528. {
  529. LOG_FUNCTION2(State::SetSiteName, site);
  530. siteName = site;
  531. }
  532. void
  533. State::SetOperationResults(OperationResult result)
  534. {
  535. LOG_FUNCTION2(
  536. State::SetOperationResults,
  537. String::format(L"result %1",
  538. result == SUCCESS ? L"SUCCESS" : L"FAILURE"));
  539. operationResultsStatus = result;
  540. }
  541. void
  542. State::SetOperationResultsMessage(const String& message)
  543. {
  544. LOG_FUNCTION2(State::SetOperationResultsMessage, message);
  545. operationResultsMessage = message;
  546. }
  547. String
  548. State::GetParentDomainDnsName() const
  549. {
  550. LOG_FUNCTION2(
  551. State::GetParentDomainDnsName,
  552. parentDomainDnsName);
  553. return parentDomainDnsName;
  554. }
  555. String
  556. State::GetNewDomainDNSName() const
  557. {
  558. LOG_FUNCTION2(State::GetNewDomainDNSName, newDomainDnsName);
  559. return newDomainDnsName;
  560. }
  561. String
  562. State::GetNewDomainNetbiosName() const
  563. {
  564. LOG_FUNCTION2(
  565. State::GetNewDomainNetbiosName,
  566. newDomainFlatName);
  567. return newDomainFlatName;
  568. }
  569. void
  570. State::SetParentDomainDNSName(const String& name)
  571. {
  572. LOG_FUNCTION2(State::SetParentDomainDNSName, name);
  573. ASSERT(!name.empty());
  574. parentDomainDnsName = name;
  575. }
  576. void
  577. State::SetNewDomainDNSName(const String& name)
  578. {
  579. LOG_FUNCTION2(State::SetNewDomainDNSName, name);
  580. ASSERT(!name.empty());
  581. newDomainDnsName = name;
  582. // This will cause the flat name to be re-generated
  583. newDomainFlatName.erase();
  584. }
  585. void
  586. State::SetNewDomainNetbiosName(const String& name)
  587. {
  588. LOG_FUNCTION2(State::SetNewDomainNetbiosName, name);
  589. ASSERT(!name.empty());
  590. newDomainFlatName = name;
  591. }
  592. void
  593. State::SetUserDomainName(const String& name)
  594. {
  595. LOG_FUNCTION2(State::SetUserDomainName, name);
  596. // name may be empty;
  597. userDomain = name;
  598. }
  599. String
  600. State::GetUserDomainName() const
  601. {
  602. LOG_FUNCTION2(State::GetUserDomainName, userDomain);
  603. return userDomain;
  604. }
  605. void
  606. State::ClearHiddenWhileUnattended()
  607. {
  608. LOG_FUNCTION(State::ClearHiddenWhileUnattended);
  609. runHiddenWhileUnattended = false;
  610. // closes the splash dialog, if visible.
  611. if (splash)
  612. {
  613. // this will delete splash, too
  614. splash->SelfDestruct();
  615. splash = 0;
  616. }
  617. }
  618. bool
  619. State::RunHiddenUnattended() const
  620. {
  621. // LOG_FUNCTION(State::RunHiddenUnattended);
  622. return UsingAnswerFile() && runHiddenWhileUnattended;
  623. }
  624. bool
  625. State::IsLastDCInDomain() const
  626. {
  627. LOG_FUNCTION2(State::IsLastDCInDomain, isLastDc ? L"true" : L"false");
  628. return isLastDc;
  629. }
  630. void
  631. State::SetIsLastDCInDomain(bool yesNo)
  632. {
  633. LOG_FUNCTION2(
  634. State::SetIsLastDCInDomain,
  635. yesNo ? L"is last dc" : L"is NOT last dc");
  636. isLastDc = yesNo;
  637. }
  638. void
  639. State::SetAdminPassword(const EncodedString& password)
  640. {
  641. LOG_FUNCTION(State::SetAdminPassword);
  642. adminPassword = password;
  643. }
  644. EncodedString
  645. State::GetAdminPassword() const
  646. {
  647. LOG_FUNCTION(State::GetAdminPassword);
  648. return adminPassword;
  649. }
  650. String
  651. State::GetOperationResultsMessage() const
  652. {
  653. LOG_FUNCTION2(
  654. State::GetOperationResultsMessage,
  655. operationResultsMessage);
  656. return operationResultsMessage;
  657. }
  658. State::OperationResult
  659. State::GetOperationResultsCode() const
  660. {
  661. LOG_FUNCTION2(
  662. State::GetOperationResultsCode,
  663. operationResultsStatus == SUCCESS ? L"SUCCESS" : L"FAILURE");
  664. return operationResultsStatus;
  665. }
  666. bool
  667. State::AutoConfigureDNS() const
  668. {
  669. LOG_FUNCTION2(
  670. State::AutoConfigureDNS,
  671. autoConfigDns ? L"true" : L"false");
  672. return autoConfigDns;
  673. }
  674. void
  675. State::SetAutoConfigureDNS(bool yesNo)
  676. {
  677. LOG_FUNCTION2(
  678. State::SetAutoConfigureDNS,
  679. yesNo ? L"true" : L"false");
  680. autoConfigDns = yesNo;
  681. }
  682. bool
  683. State::IsDNSOnNetwork() const
  684. {
  685. LOG_FUNCTION2(
  686. State::IsDNSOnNetwork,
  687. isDnsOnNet ? L"true" : L"false");
  688. return isDnsOnNet;
  689. }
  690. void
  691. State::SetDNSOnNetwork(bool yesNo)
  692. {
  693. LOG_FUNCTION2(
  694. State::SetDNSOnNetwork,
  695. yesNo ? L"true" : L"false");
  696. isDnsOnNet = yesNo;
  697. }
  698. String
  699. State::GetInstalledSite() const
  700. {
  701. LOG_FUNCTION2(State::GetInstalledSite, installedSite);
  702. // should be set before we ask for it...
  703. ASSERT(!installedSite.empty());
  704. return installedSite;
  705. }
  706. void
  707. State::SetInstalledSite(const String& site)
  708. {
  709. LOG_FUNCTION2(State::SetInstalledSite, site);
  710. ASSERT(!site.empty());
  711. installedSite = site;
  712. }
  713. void
  714. State::AddFinishMessage(const String& message)
  715. {
  716. LOG_FUNCTION2(State::AddFinishMessage, message);
  717. ASSERT(!message.empty());
  718. if (finishMessages.empty())
  719. {
  720. finishMessages += message;
  721. }
  722. else
  723. {
  724. // add a blank line between each message
  725. finishMessages += L"\r\n\r\n" + message;
  726. }
  727. }
  728. String
  729. State::GetFinishMessages() const
  730. {
  731. LOG_FUNCTION2(State::GetFinishMessages, finishMessages);
  732. return finishMessages;
  733. }
  734. Computer&
  735. State::GetComputer()
  736. {
  737. return computer;
  738. }
  739. void
  740. State::SetFailureMessage(const String& message)
  741. {
  742. LOG_FUNCTION2(State::SetFailureMessage, message);
  743. ASSERT(!message.empty());
  744. failureMessage = message;
  745. }
  746. String
  747. State::GetFailureMessage() const
  748. {
  749. LOG_FUNCTION2(State::GetFailureMessage, failureMessage);
  750. return failureMessage;
  751. }
  752. bool
  753. State::ShouldInstallAndConfigureDns() const
  754. {
  755. if (AutoConfigureDNS() || !IsDNSOnNetwork())
  756. {
  757. return true;
  758. }
  759. return false;
  760. }
  761. String
  762. State::GetUserForestName() const
  763. {
  764. LOG_FUNCTION2(State::GetUserForestName, userForest);
  765. ASSERT(!userForest.empty());
  766. return userForest;
  767. }
  768. void
  769. State::SetUserForestName(const String& forest)
  770. {
  771. LOG_FUNCTION2(State::SetUserForestName, forest);
  772. ASSERT(!forest.empty());
  773. userForest = forest;
  774. }
  775. bool
  776. State::IsDomainInForest(const String& domain) const
  777. {
  778. LOG_FUNCTION2(State::IsDomainInForest, domain);
  779. ASSERT(!domain.empty());
  780. for (
  781. DomainList::iterator i = domainsInForest.begin();
  782. i != domainsInForest.end();
  783. i++)
  784. {
  785. DNS_NAME_COMPARE_STATUS compare = Dns::CompareNames(*i, domain);
  786. if (compare == DnsNameCompareEqual)
  787. {
  788. LOG(L"domain is in forest");
  789. return true;
  790. }
  791. }
  792. return false;
  793. }
  794. HRESULT
  795. State::ReadDomains()
  796. {
  797. LOG_FUNCTION(State::ReadDomains);
  798. domainsInForest.clear();
  799. return ::ReadDomains(domainsInForest);
  800. }
  801. DNS_NAME_COMPARE_STATUS
  802. State::DomainFitsInForest(const String& domain, String& conflictingDomain)
  803. {
  804. LOG_FUNCTION(domainFitsInForest);
  805. ASSERT(!domain.empty());
  806. conflictingDomain.erase();
  807. DNS_NAME_COMPARE_STATUS relation = DnsNameCompareNotEqual;
  808. for (
  809. DomainList::iterator i = domainsInForest.begin();
  810. i != domainsInForest.end();
  811. i++)
  812. {
  813. relation = Dns::CompareNames(domain, *i);
  814. switch (relation)
  815. {
  816. case DnsNameCompareNotEqual:
  817. {
  818. continue;
  819. }
  820. case DnsNameCompareEqual:
  821. {
  822. ASSERT(domain == *i);
  823. // fall thru
  824. }
  825. case DnsNameCompareLeftParent:
  826. case DnsNameCompareRightParent:
  827. case DnsNameCompareInvalid:
  828. default:
  829. {
  830. conflictingDomain = *i;
  831. break;
  832. }
  833. }
  834. break;
  835. }
  836. return relation;
  837. }
  838. bool
  839. State::GetDomainReinstallFlag() const
  840. {
  841. LOG_FUNCTION2(
  842. State::GetDomainReinstallFlag,
  843. reinstallDomain ? L"true" : L"false");
  844. return reinstallDomain;
  845. }
  846. void
  847. State::SetDomainReinstallFlag(bool newValue)
  848. {
  849. LOG_FUNCTION2(
  850. State::SetDomainReinstallFlag,
  851. newValue ? L"true" : L"false");
  852. reinstallDomain = newValue;
  853. }
  854. bool
  855. State::ShouldAllowAnonymousAccess() const
  856. {
  857. LOG_FUNCTION2(
  858. State::ShouldAllowAnonymousAccess,
  859. allowAnonAccess ? L"true" : L"false");
  860. return allowAnonAccess;
  861. }
  862. void
  863. State::SetShouldAllowAnonymousAccess(bool yesNo)
  864. {
  865. LOG_FUNCTION2(
  866. State::ShouldAllowAnonymousAccess,
  867. yesNo ? L"true" : L"false");
  868. allowAnonAccess = yesNo;
  869. }
  870. String
  871. State::GetReplicationPartnerDC() const
  872. {
  873. LOG_FUNCTION2(State::GetReplicationPartnerDC, replicationPartnerDc);
  874. return replicationPartnerDc;
  875. }
  876. void
  877. State::SetReplicationPartnerDC(const String dcName)
  878. {
  879. LOG_FUNCTION2(State::SetReplicationPartnerDC, dcName);
  880. replicationPartnerDc = dcName;
  881. }
  882. // Retrieve domain controller info for all DCs in the domain that this dc
  883. // is a controller. (The result set should include this dc)
  884. // Caller should free the result with DsFreeDomainControllerInfo
  885. HRESULT
  886. State::GetDomainControllerInfoForMyDomain(
  887. DS_DOMAIN_CONTROLLER_INFO_2W*& info,
  888. DWORD& dcCount)
  889. {
  890. LOG_FUNCTION(State::GetDomainControllerInfoForMyDomain);
  891. // if this assertion does not hold, then the DsBind call below should
  892. // fail.
  893. ASSERT(GetComputer().IsDomainController());
  894. dcCount = 0;
  895. info = 0;
  896. HRESULT hr = S_OK;
  897. HANDLE hds = 0;
  898. do
  899. {
  900. String domainDnsName = GetComputer().GetDomainDnsName();
  901. String dcName = Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
  902. ASSERT(!domainDnsName.empty());
  903. ASSERT(!dcName.empty());
  904. // Bind to self
  905. hr =
  906. MyDsBind(
  907. dcName,
  908. domainDnsName,
  909. hds);
  910. BREAK_ON_FAILED_HRESULT(hr);
  911. // find all the dc's for my domain. the list should contain dcName.
  912. // level 2 contains the "is gc" flag
  913. hr =
  914. MyDsGetDomainControllerInfo(
  915. hds,
  916. domainDnsName,
  917. dcCount,
  918. info);
  919. BREAK_ON_FAILED_HRESULT(hr);
  920. }
  921. while (0);
  922. if (hds)
  923. {
  924. ::DsUnBind(&hds);
  925. hds = 0;
  926. }
  927. return hr;
  928. }
  929. // returns true if no other domain controller for this DCs domain can be
  930. // found in the DS. False otherwise
  931. bool
  932. State::IsReallyLastDcInDomain()
  933. {
  934. LOG_FUNCTION(State::IsReallyLastDcInDomain);
  935. // Assume we are alone in the universe.
  936. bool result = true;
  937. do
  938. {
  939. // find all the dc's for my domain. the list should contain dcName.
  940. DS_DOMAIN_CONTROLLER_INFO_2W* info = 0;
  941. DWORD count = 0;
  942. HRESULT hr = GetDomainControllerInfoForMyDomain(info, count);
  943. BREAK_ON_FAILED_HRESULT(hr);
  944. ASSERT(count);
  945. ASSERT(info);
  946. // if there are more than 1 entry (more than the one for this dc),
  947. // then the DS believes that there are other DCs for this domain.
  948. if (count > 1)
  949. {
  950. result = false;
  951. }
  952. #ifdef DBG
  953. // double check that we found ourselves.
  954. if (result && info[0].DnsHostName)
  955. {
  956. LOG(info[0].DnsHostName);
  957. String dcName =
  958. Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
  959. ASSERT(
  960. Dns::CompareNames(info[0].DnsHostName, dcName)
  961. == DnsNameCompareEqual);
  962. }
  963. #endif
  964. MyDsFreeDomainControllerInfo(count, info);
  965. }
  966. while (0);
  967. LOG(
  968. String::format(
  969. L"This box %1 the sole DC for the domain",
  970. result ? L"is" : L"is NOT"));
  971. return result;
  972. }
  973. // Returns true if this computer is a global catalog
  974. bool
  975. State::IsGlobalCatalog()
  976. {
  977. LOG_FUNCTION(State::IsGlobalCatalog);
  978. if (!GetComputer().IsDomainController())
  979. {
  980. // can't possibly be a GC if not a DC
  981. return false;
  982. }
  983. bool result = false;
  984. do
  985. {
  986. String dcName = Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
  987. // find all the dc's for my domain. the list should contain dcName.
  988. // level 2 contains the "is gc" flag
  989. DS_DOMAIN_CONTROLLER_INFO_2W* info = 0;
  990. DWORD count = 0;
  991. HRESULT hr = GetDomainControllerInfoForMyDomain(info, count);
  992. BREAK_ON_FAILED_HRESULT(hr);
  993. // there should be at least 1 entry (ourself)
  994. ASSERT(count);
  995. ASSERT(info);
  996. for (int i = 0; i < count; i++)
  997. {
  998. if (info[i].DnsHostName) // 340723
  999. {
  1000. LOG(info[i].DnsHostName);
  1001. if (
  1002. Dns::CompareNames(info[i].DnsHostName, dcName)
  1003. == DnsNameCompareEqual)
  1004. {
  1005. // we found ourselves in the list
  1006. LOG(L"found!");
  1007. result = info[i].fIsGc ? true : false;
  1008. break;
  1009. }
  1010. }
  1011. }
  1012. MyDsFreeDomainControllerInfo(count, info);
  1013. }
  1014. while (0);
  1015. LOG(
  1016. String::format(
  1017. L"This box %1 a global catalog",
  1018. result ? L"is" : L"is NOT"));
  1019. return result;
  1020. }
  1021. EncodedString
  1022. State::GetSafeModeAdminPassword() const
  1023. {
  1024. LOG_FUNCTION(State::GetSafeModeAdminPassword);
  1025. // don't trace the password!
  1026. return safeModeAdminPassword;
  1027. }
  1028. void
  1029. State::SetSafeModeAdminPassword(const EncodedString& pwd)
  1030. {
  1031. LOG_FUNCTION(State::SetSafeModeAdminPassword);
  1032. // don't trace the password!
  1033. // pwd may be empty.
  1034. safeModeAdminPassword = pwd;
  1035. }
  1036. String
  1037. State::GetAdminToolsShortcutPath() const
  1038. {
  1039. LOG_FUNCTION2(State::GetAdminToolsShortcutPath, shortcutPath);
  1040. return shortcutPath;
  1041. }
  1042. bool
  1043. State::NeedsCommandLineHelp() const
  1044. {
  1045. return needsCommandLineHelp;
  1046. }
  1047. bool
  1048. State::IsAdvancedMode() const
  1049. {
  1050. return isAdvancedMode;
  1051. }
  1052. void
  1053. State::SetReplicateFromMedia(bool yesNo)
  1054. {
  1055. LOG_FUNCTION2(
  1056. State::SetReplicateFromMedia,
  1057. yesNo ? L"true" : L"false");
  1058. replicateFromMedia = yesNo;
  1059. }
  1060. void
  1061. State::SetReplicationSourcePath(const String& path)
  1062. {
  1063. LOG_FUNCTION2(State::SetReplicationSourcePath, path);
  1064. sourcePath = path;
  1065. }
  1066. bool
  1067. State::ReplicateFromMedia() const
  1068. {
  1069. LOG_FUNCTION2(
  1070. State::ReplicateFromMedia,
  1071. replicateFromMedia ? L"true" : L"false");
  1072. return replicateFromMedia;
  1073. }
  1074. String
  1075. State::GetReplicationSourcePath() const
  1076. {
  1077. LOG_FUNCTION2(State::GetReplicationSourcePath, sourcePath);
  1078. return sourcePath;
  1079. }
  1080. void
  1081. State::SetSyskeyLocation(SyskeyLocation loc)
  1082. {
  1083. LOG_FUNCTION2(State::SetSyskeyLocation,
  1084. loc == DISK
  1085. ? L"disk"
  1086. : ((loc == PROMPT) ? L"prompt" : L"stored"));
  1087. syskeyLocation = loc;
  1088. }
  1089. State::SyskeyLocation
  1090. State::GetSyskeyLocation() const
  1091. {
  1092. LOG_FUNCTION2(
  1093. State::IsSyskeyPresent,
  1094. syskeyLocation == DISK
  1095. ? L"disk"
  1096. : ((syskeyLocation == PROMPT) ? L"prompt" : L"stored"));
  1097. return syskeyLocation;
  1098. }
  1099. void
  1100. State::SetIsBackupGc(bool yesNo)
  1101. {
  1102. LOG_FUNCTION2(State::SetIsBackupGc, yesNo ? L"true" : L"false");
  1103. isBackupGc = yesNo;
  1104. }
  1105. bool
  1106. State::IsBackupGc() const
  1107. {
  1108. LOG_FUNCTION2(State::IsBackupGc, isBackupGc ? L"true" : L"false");
  1109. return isBackupGc;
  1110. }
  1111. void
  1112. State::SetSyskey(const EncodedString& syskey_)
  1113. {
  1114. // don't log the syskey!
  1115. LOG_FUNCTION(State::SetSyskey);
  1116. ASSERT(!syskey_.IsEmpty());
  1117. syskey = syskey_;
  1118. }
  1119. EncodedString
  1120. State::GetSyskey() const
  1121. {
  1122. // don't log the syskey!
  1123. LOG_FUNCTION(State::GetSyskey);
  1124. return syskey;
  1125. }
  1126. void
  1127. State::SetRestoreGc(bool yesNo)
  1128. {
  1129. LOG_FUNCTION2(State::SetRestoreGc, yesNo ? L"true" : L"false");
  1130. restoreGc = yesNo;
  1131. }
  1132. bool
  1133. State::GetRestoreGc() const
  1134. {
  1135. LOG_FUNCTION2(State::GetRestoreGc, restoreGc ? L"true" : L"false");
  1136. return restoreGc;
  1137. }
  1138. bool
  1139. State::IsSafeModeAdminPwdOptionPresent() const
  1140. {
  1141. LOG_FUNCTION(State::IsSafeModeAdminPwdOptionPresent);
  1142. ASSERT(UsingAnswerFile());
  1143. bool result = false;
  1144. if (answerFile)
  1145. {
  1146. result =
  1147. answerFile->IsKeyPresent(
  1148. SECTION_NAME,
  1149. OPTION_SAFE_MODE_ADMIN_PASSWORD);
  1150. }
  1151. LOG(result ? L"true" : L"false");
  1152. return result;
  1153. }
  1154. void
  1155. State::SetDomainControllerReinstallFlag(bool newValue)
  1156. {
  1157. LOG_FUNCTION2(
  1158. State::SetDomainControllerReinstallFlag,
  1159. newValue ? L"true" : L"false");
  1160. reinstallDomainController = newValue;
  1161. }
  1162. bool
  1163. State::GetDomainControllerReinstallFlag() const
  1164. {
  1165. LOG_FUNCTION2(
  1166. State::GetDomainControllerReinstallFlag,
  1167. reinstallDomain ? L"true" : L"false");
  1168. return reinstallDomainController;
  1169. }
  1170. void
  1171. State::SetOperationResultsFlags(ULONG flags)
  1172. {
  1173. LOG_FUNCTION2(
  1174. State::SetOperationResultsFlags,
  1175. String::format(L"0x%1!X!", flags));
  1176. operationResultsFlags = flags;
  1177. }
  1178. ULONG
  1179. State::GetOperationResultsFlags() const
  1180. {
  1181. LOG_FUNCTION2(
  1182. State::GetOperationResultsFlags,
  1183. String::format(L"0x%1!X!", operationResultsFlags));
  1184. return operationResultsFlags;
  1185. }
  1186. bool
  1187. State::IsOperationRetryAllowed() const
  1188. {
  1189. LOG_FUNCTION(State::IsOperationRetryAllowed);
  1190. bool result = true;
  1191. if (operationResultsFlags & DSROLE_IFM_RESTORED_DATABASE_FILES_MOVED)
  1192. {
  1193. // don't allow the user to retry the operation again, as one consequence
  1194. // of the failure is that the moved files are now trashed. The user
  1195. // must re-restore the files in order to attempt the operation again.
  1196. // NTRAID#NTBUG9-296872-2001/01/29-sburns
  1197. LOG(L"ifm files moved, retry not allowed");
  1198. result = false;
  1199. }
  1200. LOG(result ? L"true" : L"false");
  1201. return result;
  1202. }
  1203. // needing a reboot is a "sticky" setting: there's no way to turn it off.
  1204. // if you once needed to reboot the machine, you will always need to reboot
  1205. // the machine. (at least, for now).
  1206. void
  1207. State::SetNeedsReboot()
  1208. {
  1209. LOG_FUNCTION(State::SetNeedsReboot);
  1210. needsReboot = true;
  1211. }
  1212. bool
  1213. State::GetNeedsReboot() const
  1214. {
  1215. LOG_FUNCTION2(State::GetNeedsReboot, needsReboot ? L"true" : L"false");
  1216. return needsReboot;
  1217. }
  1218. void
  1219. State::SetSetForestVersionFlag(bool setVersion)
  1220. {
  1221. LOG_FUNCTION2(
  1222. State::SetSetForestVersionFlag,
  1223. setVersion ? L"true" : L"false");
  1224. setForestVersion = setVersion;
  1225. }
  1226. bool
  1227. State::GetSetForestVersionFlag() const
  1228. {
  1229. LOG_FUNCTION2(
  1230. State::GetSetForestVersionFlag,
  1231. setForestVersion ? L"true" : L"false");
  1232. return setForestVersion;
  1233. }