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.

494 lines
9.7 KiB

  1. // Copyright (C) 1997-2000 Microsoft Corporation
  2. //
  3. // install replica from media page
  4. //
  5. // 7 Feb 2000 sburns
  6. #include "headers.hxx"
  7. #include "resource.h"
  8. #include "common.hpp"
  9. #include "page.hpp"
  10. #include "ReplicateFromMediaPage.hpp"
  11. #include "state.hpp"
  12. #include "SyskeyDiskDialog.hpp"
  13. #include "SyskeyPromptDialog.hpp"
  14. ReplicateFromMediaPage::ReplicateFromMediaPage()
  15. :
  16. DCPromoWizardPage(
  17. IDD_REPLICATE_FROM_MEDIA,
  18. IDS_REPLICATE_FROM_MEDIA_PAGE_TITLE,
  19. IDS_REPLICATE_FROM_MEDIA_PAGE_SUBTITLE)
  20. {
  21. LOG_CTOR(ReplicateFromMediaPage);
  22. }
  23. ReplicateFromMediaPage::~ReplicateFromMediaPage()
  24. {
  25. LOG_DTOR(ReplicateFromMediaPage);
  26. }
  27. String
  28. FirstFixedDisk()
  29. {
  30. LOG_FUNCTION(FirstFixedDisk);
  31. String result;
  32. do
  33. {
  34. StringVector dl;
  35. HRESULT hr = FS::GetValidDrives(std::back_inserter(dl));
  36. BREAK_ON_FAILED_HRESULT(hr);
  37. ASSERT(dl.size());
  38. for (
  39. StringVector::iterator i = dl.begin();
  40. i != dl.end();
  41. ++i)
  42. {
  43. String rootPath = *i + L"\\";
  44. if (Win::GetDriveType(rootPath) == DRIVE_FIXED)
  45. {
  46. result = *i;
  47. break;
  48. }
  49. }
  50. }
  51. while (0);
  52. if (result.empty())
  53. {
  54. // This is deadcode, really, cause we're sure to find a fixed volume
  55. // somewhere
  56. result = FS::GetRootFolder(Win::GetSystemDirectory()).substr(0, 3);
  57. }
  58. LOG(result);
  59. return result;
  60. }
  61. void
  62. ReplicateFromMediaPage::OnInit()
  63. {
  64. LOG_FUNCTION(ReplicateFromMediaPage::OnInit);
  65. Win::Edit_LimitText(Win::GetDlgItem(hwnd, IDC_SOURCE), MAX_PATH);
  66. State& state = State::GetInstance();
  67. if (state.UsingAnswerFile())
  68. {
  69. String option = state.GetAnswerFileOption(State::OPTION_SOURCE_PATH);
  70. if (!option.empty())
  71. {
  72. Win::CheckDlgButton(hwnd, IDC_USE_FILES, BST_CHECKED);
  73. Win::SetDlgItemText(
  74. hwnd,
  75. IDC_SOURCE,
  76. Win::ExpandEnvironmentStrings(
  77. state.GetAnswerFileOption(State::OPTION_SOURCE_PATH)));
  78. return;
  79. }
  80. }
  81. Win::CheckDlgButton(hwnd, IDC_USE_NET, BST_CHECKED);
  82. String root = FirstFixedDisk();
  83. Win::SetDlgItemText(
  84. hwnd,
  85. IDC_SOURCE,
  86. root + String::load(IDS_SOURCE_SUFFIX));
  87. }
  88. void
  89. ReplicateFromMediaPage::Enable()
  90. {
  91. int next = PSWIZB_NEXT;
  92. bool useFiles = Win::IsDlgButtonChecked(hwnd, IDC_USE_FILES);
  93. if (useFiles)
  94. {
  95. // if using files, the edit box must have some text.
  96. if (Win::GetTrimmedDlgItemText(hwnd, IDC_SOURCE).empty())
  97. {
  98. next = 0;
  99. }
  100. }
  101. Win::PropSheet_SetWizButtons(
  102. Win::GetParent(hwnd),
  103. PSWIZB_BACK | next);
  104. Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_SOURCE), useFiles);
  105. Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_BROWSE), useFiles);
  106. }
  107. bool
  108. ReplicateFromMediaPage::OnCommand(
  109. HWND /* windowFrom */ ,
  110. unsigned controlIDFrom,
  111. unsigned code)
  112. {
  113. // LOG_FUNCTION(ReplicateFromMediaPage::OnCommand);
  114. switch (controlIDFrom)
  115. {
  116. case IDC_USE_NET:
  117. case IDC_USE_FILES:
  118. {
  119. if (code == BN_CLICKED)
  120. {
  121. SetChanged(controlIDFrom);
  122. Enable();
  123. return true;
  124. }
  125. }
  126. case IDC_BROWSE:
  127. {
  128. if (code == BN_CLICKED)
  129. {
  130. String path = BrowseForFolder(hwnd, IDS_SOURCE_BROWSE_TITLE);
  131. if (!path.empty())
  132. {
  133. Win::SetDlgItemText(hwnd, IDC_SOURCE, path);
  134. }
  135. return true;
  136. }
  137. break;
  138. }
  139. case IDC_SOURCE:
  140. {
  141. if (code == EN_CHANGE)
  142. {
  143. SetChanged(controlIDFrom);
  144. Enable();
  145. return true;
  146. }
  147. break;
  148. }
  149. default:
  150. {
  151. // do nothing
  152. break;
  153. }
  154. }
  155. return false;
  156. }
  157. bool
  158. ReplicateFromMediaPage::OnSetActive()
  159. {
  160. LOG_FUNCTION(ReplicateFromMediaPage::OnSetActive);
  161. ASSERT(State::GetInstance().GetOperation() == State::REPLICA);
  162. Win::PropSheet_SetWizButtons(
  163. Win::GetParent(hwnd),
  164. PSWIZB_BACK);
  165. State& state = State::GetInstance();
  166. if (state.RunHiddenUnattended() || !state.IsAdvancedMode())
  167. {
  168. LOG(L"skipping ReplicateFromMediaPage");
  169. Wizard& wiz = GetWizard();
  170. if (wiz.IsBacktracking())
  171. {
  172. // backup once again
  173. wiz.Backtrack(hwnd);
  174. return true;
  175. }
  176. int nextPage = ReplicateFromMediaPage::Validate();
  177. if (nextPage != -1)
  178. {
  179. wiz.SetNextPageID(hwnd, nextPage);
  180. }
  181. else
  182. {
  183. state.ClearHiddenWhileUnattended();
  184. }
  185. }
  186. Enable();
  187. return true;
  188. }
  189. bool
  190. ValidateSourcePath(HWND parent, const String& path, int editResId)
  191. {
  192. LOG_FUNCTION2(ValidateSourcePath, path);
  193. bool result = false;
  194. do
  195. {
  196. if (path.empty())
  197. {
  198. popup.Gripe(
  199. parent,
  200. editResId,
  201. IDS_MUST_ENTER_SOURCE_PATH);
  202. break;
  203. }
  204. // Path must have a drive letter
  205. FS::PathSyntax syn = FS::GetPathSyntax(path);
  206. if (syn != FS::SYNTAX_ABSOLUTE_DRIVE)
  207. {
  208. popup.Gripe(
  209. parent,
  210. editResId,
  211. String::format(IDS_BAD_PATH_FORMAT, path.c_str()));
  212. break;
  213. }
  214. // mapped network drives are not ok. This is because the DsRole apis
  215. // copy the restored files on the server side of the api, in the
  216. // system context.
  217. // NTRAID#NTBUG9-309422-2001/02/12-sburns
  218. UINT type = Win::GetDriveType(path);
  219. if (type != DRIVE_FIXED)
  220. {
  221. popup.Gripe(
  222. parent,
  223. editResId,
  224. String::format(IDS_BAD_DRIVE_TYPE, path.c_str()));
  225. break;
  226. }
  227. result = true;
  228. }
  229. while (0);
  230. LOG(result ? L"true" : L"false")
  231. return result;
  232. }
  233. // Return true on success, false on failure
  234. bool
  235. GetDatabaseFacts(HWND parent, const String& sourcePath)
  236. {
  237. LOG_FUNCTION2(GetDatabaseFacts, sourcePath);
  238. ASSERT(Win::IsWindow(parent));
  239. ASSERT(!sourcePath.empty());
  240. bool result = false;
  241. PWSTR dnsDomainName = 0;
  242. State& state = State::GetInstance();
  243. state.SetIsBackupGc(false);
  244. state.SetSyskeyLocation(State::STORED);
  245. LOG(L"Calling DsRoleGetDatabaseFacts");
  246. LOG(String::format(L"lpRestorePath: %1", sourcePath.c_str()));
  247. ULONG facts = 0;
  248. HRESULT hr =
  249. Win32ToHresult(
  250. ::DsRoleGetDatabaseFacts(
  251. 0, // this server
  252. sourcePath.c_str(),
  253. &dnsDomainName,
  254. &facts));
  255. LOG_HRESULT(hr);
  256. if (SUCCEEDED(hr))
  257. {
  258. LOG(String::format(L"lpDNSDomainName: %1", dnsDomainName ? dnsDomainName : L"(null)"));
  259. LOG(String::format(L"State : 0x%1!X!", facts));
  260. if (dnsDomainName)
  261. {
  262. // Save this domain name. This will allow us to skip the ReplicaPage
  263. // since we now know the domain name.
  264. state.SetReplicaDomainDNSName(dnsDomainName);
  265. MIDL_user_free(dnsDomainName);
  266. }
  267. if (facts & DSROLE_DC_IS_GC)
  268. {
  269. LOG(L"is gc");
  270. state.SetIsBackupGc(true);
  271. }
  272. if (facts & DSROLE_KEY_DISK)
  273. {
  274. LOG(L"syskey on disk");
  275. state.SetSyskeyLocation(State::DISK);
  276. }
  277. else if (facts & DSROLE_KEY_PROMPT)
  278. {
  279. LOG(L"prompt for syskey");
  280. state.SetSyskeyLocation(State::PROMPT);
  281. }
  282. else if (facts & DSROLE_KEY_STORED)
  283. {
  284. LOG(L"syskey stored");
  285. // we set this as the default value, above.
  286. }
  287. else
  288. {
  289. // The api is insane.
  290. ASSERT(false);
  291. LOG(L"unexpected State value");
  292. }
  293. result = true;
  294. }
  295. else
  296. {
  297. popup.Error(
  298. parent,
  299. hr,
  300. String::format(IDS_GET_FACTS_FAILED, sourcePath.c_str()));
  301. }
  302. LOG(result ? L"true" : L"false");
  303. return result;
  304. }
  305. int
  306. ReplicateFromMediaPage::Validate()
  307. {
  308. LOG_FUNCTION(ReplicateFromMediaPage::Validate);
  309. State& state = State::GetInstance();
  310. int nextPage = -1;
  311. bool useFiles = Win::IsDlgButtonChecked(hwnd, IDC_USE_FILES);
  312. do
  313. {
  314. if (WasChanged(IDC_USE_FILES) || WasChanged(IDC_USE_NET))
  315. {
  316. state.SetReplicateFromMedia(useFiles);
  317. }
  318. if (!useFiles)
  319. {
  320. LOG(L"not using source media for replication");
  321. nextPage = IDD_CONFIG_DNS_CLIENT;
  322. break;
  323. }
  324. String sourcePath = Win::GetTrimmedDlgItemText(hwnd, IDC_SOURCE);
  325. if (ValidateSourcePath(hwnd, sourcePath, IDC_SOURCE) )
  326. {
  327. String s =
  328. FS::NormalizePath(Win::GetTrimmedDlgItemText(hwnd, IDC_SOURCE));
  329. state.SetReplicationSourcePath(s);
  330. }
  331. else
  332. {
  333. break;
  334. }
  335. // check the restored backup for the syskey, the domain name, and the DC
  336. // type.
  337. if (!GetDatabaseFacts(hwnd, sourcePath))
  338. {
  339. break;
  340. }
  341. State::SyskeyLocation loc = state.GetSyskeyLocation();
  342. if (loc == State::DISK)
  343. {
  344. if (SyskeyDiskDialog().ModalExecute(hwnd) != IDOK)
  345. {
  346. break;
  347. }
  348. }
  349. else if (loc == State::PROMPT)
  350. {
  351. if (SyskeyPromptDialog().ModalExecute(hwnd) != IDOK)
  352. {
  353. break;
  354. }
  355. }
  356. // The syskey is present, do we need to jump to the GC confirmation?
  357. if (state.IsBackupGc())
  358. {
  359. nextPage = IDD_GC_CONFIRM;
  360. break;
  361. }
  362. // The syskey is present, the backup is not a gc, so move along
  363. nextPage = IDD_CONFIG_DNS_CLIENT;
  364. }
  365. while (0);
  366. if (nextPage != -1)
  367. {
  368. // only clear changes when the user has specified valid options.
  369. // otherwise, we want to go thru the validation until he gets it
  370. // right.
  371. ClearChanges();
  372. }
  373. LOG(String::format(L"next = %1!d!", nextPage));
  374. return nextPage;
  375. }