Leaked source code of windows server 2003
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.

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