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.

2293 lines
66 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. frs.c
  5. Abstract:
  6. This module is a development tool. It exercises the dcpromo and poke
  7. APIs.
  8. Author:
  9. Billy J. Fuller 12-Dec-1997
  10. Environment
  11. User mode winnt
  12. --*/
  13. #include <ntreppch.h>
  14. #pragma hdrstop
  15. #include <frs.h>
  16. #include <ntfrsapi.h>
  17. #define FREE(_x_) { if (_x_) LocalFree(_x_); _x_ = NULL; }
  18. VOID
  19. Win32ToMsg (
  20. IN PWCHAR Prefix,
  21. IN DWORD WStatus
  22. )
  23. /*++
  24. Routine Description:
  25. Translate a error code into a error message using FormatMessage()
  26. and print to stderr. If no message is available, the error code
  27. is printed in decimal and hex.
  28. Arguments:
  29. Prefix - prefix to error message
  30. WStatus - Standard win32 error code.
  31. Return Value:
  32. None.
  33. --*/
  34. {
  35. DWORD NumChar;
  36. PWCHAR Buffer;
  37. if (WIN_SUCCESS(WStatus)) {
  38. return;
  39. }
  40. // Use the system formatter for standard error codes
  41. NumChar = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
  42. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  43. NULL,
  44. WStatus,
  45. 0,
  46. (PWCHAR)&Buffer,
  47. 0,
  48. NULL);
  49. if (NumChar) {
  50. fprintf(stderr, "%ws %ws\n", Prefix, Buffer);
  51. } else {
  52. fprintf(stderr, "%ws Status %d (0x%08x)\n", Prefix, WStatus, WStatus);
  53. }
  54. }
  55. VOID
  56. Usage(
  57. IN DWORD ExitStatus
  58. )
  59. /*++
  60. Routine Description:
  61. Print usage and exit
  62. Arguments:
  63. ExitStatus - exits with this status
  64. Return Value:
  65. Exit(ExitStatus)
  66. --*/
  67. {
  68. printf("frs restore | backup [/all /auth /nonauth /primary /system /ds /normal /key /restart] [dir nonauth|primary|auth ....]\n");
  69. printf("\t = excercise the backup/restore api\n");
  70. printf("\t WARNING - deletes database\n");
  71. printf("\trestore = excercise restore\n");
  72. printf("\tbackup = excercise backup\n");
  73. printf("\t/all = set all flag (all dirs)\n");
  74. printf("\t/auth = set auth flag\n");
  75. printf("\t/nonauth = set nonauth flag\n");
  76. printf("\t/primary = set primary flag\n");
  77. printf("\t/system = set system flag\n");
  78. printf("\t/ds = set active directory flag\n");
  79. printf("\t/normal = set normal flag\n");
  80. printf("\t/key = expect keypath-when-done\n");
  81. printf("\t/restart = set restart-service-when-done\n");
  82. printf("\tSUPPORTED = restore /system /all /nonauth /restart\n");
  83. printf("\tSUPPORTED = restore /system /all /primary /restart\n");
  84. printf("\tSUPPORTED = restore /system /all /nonauth /key \n");
  85. printf("\tSUPPORTED = restore /system /all /primary /key \n");
  86. printf("\tSUPPORTED = restore /ds /all /nonauth /restart\n");
  87. printf("\tSUPPORTED = restore /ds /all /primary /restart\n");
  88. printf("\tSUPPORTED = restore /ds /all /nonauth /key \n");
  89. printf("\tSUPPORTED = restore /ds /all /primary /key \n");
  90. printf("\tSUPPORTED = restore /ds /all /nonauth /restart dir primary|nonauth ...\n");
  91. printf("\tSUPPORTED = restore /ds /all /primary /restart dir primary|nonauth ...\n");
  92. printf("\tSUPPORTED = restore /ds /all /nonauth /key dir primary|nonauth ...\n");
  93. printf("\tSUPPORTED = restore /ds /all /primary /key dir primary|nonauth ...\n");
  94. printf("\tSUPPORTED = restore /ds /nonauth /restart dir primary|nonauth ...\n");
  95. printf("\tSUPPORTED = restore /ds /primary /restart dir primary|nonauth ...\n");
  96. printf("\tSUPPORTED = restore /ds /nonauth /key dir primary|nonauth ...\n");
  97. printf("\tSUPPORTED = restore /ds /primary /key dir primary|nonauth ...\n");
  98. printf("\tSUPPORTED = restore /normal /all /auth\n");
  99. printf("\tSUPPORTED = backup /normal\n");
  100. printf("\n");
  101. printf("frs install stagepath [targetpath]\n");
  102. printf("\t = install the staging file\n");
  103. printf("\tstagepath = path of staging file.\n");
  104. printf("\ttargetpath= path of target file to OVERWRITE!.\n");
  105. printf("\n");
  106. printf("frs [idtable|inlog|outlog] [computer]\n");
  107. printf("\t = enumerate the service's idtable/inlog/outlog \n");
  108. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  109. printf("\n");
  110. printf("frs [memory|threads|stage] [computer]\n");
  111. printf("\t = list the service's memory usage\n");
  112. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  113. printf("\n");
  114. printf("frs ds [computer]\n");
  115. printf("\t = list the service's view of the DS\n");
  116. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  117. printf("\n");
  118. printf("frs sets [computer]\n");
  119. printf("\t = list the active replica sets\n");
  120. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  121. printf("\n");
  122. printf("frs version [computer]\n");
  123. printf("\t = list the api and service versions\n");
  124. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  125. printf("\n");
  126. printf("frs poll [/quickly[=[N]]] [/slowly[=[N]]] [/now] [computer]\n");
  127. printf("\t = list the current polling intervals.\n");
  128. printf("\tnow = Poll now.\n");
  129. printf("\tquickly = Poll quickly until stable configuration retrieved.\n");
  130. printf("\tquickly= = Poll quickly every default minutes.\n");
  131. printf("\tquickly=N = Poll quickly every N minutes.\n");
  132. printf("\tslowly = Poll slowly until stable configuration retrieved.\n");
  133. printf("\tslowly= = Poll slowly every default minutes.\n");
  134. printf("\tslowly=N = Poll slowly every N minutes.\n");
  135. printf("\tcomputer = talk to the NtFrs service on this machine.\n");
  136. printf("\n");
  137. printf("frs promote Parent Account Password Set Type Primary Stage Root\n");
  138. printf("\tParent = RPC bindable name of parent DC.\n");
  139. printf("\tAccount = Account on Parent.\n");
  140. printf("\tPassword = Password for Account on Parent.\n");
  141. printf("\tSet = Name of replica set.\n");
  142. printf("\tType = Type of replica set (Enterprise or Domain).\n");
  143. printf("\tPrimary = Is this the primary member? (1=yes or 0=no)\n");
  144. printf("\tStage = Staging path.\n");
  145. printf("\tRoot = Root path.\n");
  146. printf("\n");
  147. printf("frs demote Set\n");
  148. printf("\tSet = Name of replica set.\n");
  149. printf("\n");
  150. printf("frs promotesysvols Parent Account Password PrimaryEnterprise PrimaryDomain Stage RootEnterprise RootDomain\n");
  151. printf("\tParent = RPC bindable name of parent DC.\n");
  152. printf("\tAccount = Account on Parent.\n");
  153. printf("\tPassword = Password for Account on Parent.\n");
  154. printf("\tPrimaryEnterprise = Is this the primary member? (1=yes or 0=no)\n");
  155. printf("\tPrimaryDomain = Is this the primary member? (1=yes or 0=no)\n");
  156. printf("\tStage = Staging path.\n");
  157. printf("\tRootEnterprise = Root path.\n");
  158. printf("\tRootDomain = Root path.\n");
  159. printf("\n");
  160. printf("frs demotesysvols\n");
  161. exit(ExitStatus);
  162. }
  163. PWCHAR *
  164. ConvertArgv(
  165. DWORD argc,
  166. PCHAR *argv
  167. )
  168. /*++
  169. Routine Description:
  170. Convert short char argv into wide char argv
  171. Arguments:
  172. argc - From main
  173. argv - From main
  174. Return Value:
  175. Address of the new argv
  176. --*/
  177. {
  178. PWCHAR *wideargv;
  179. wideargv = LocalAlloc(LMEM_FIXED, (argc + 1) * sizeof(PWCHAR));
  180. if (wideargv == NULL) {
  181. fprintf(stderr, "Can't get memory; Win32 Status %d\n",
  182. GetLastError());
  183. exit(1);
  184. }
  185. wideargv[argc] = NULL;
  186. while (argc-- >= 1) {
  187. wideargv[argc] = LocalAlloc(LMEM_FIXED,
  188. (strlen(argv[argc]) + 1) * sizeof(WCHAR));
  189. if (wideargv[argc] == NULL) {
  190. fprintf(stderr, "Can't get memory; Win32 Status %d\n",
  191. GetLastError());
  192. exit(1);
  193. }
  194. wsprintf(wideargv[argc], L"%hs", argv[argc]);
  195. FRS_WCSLWR(wideargv[argc]);
  196. }
  197. return wideargv;
  198. }
  199. DWORD
  200. Display(
  201. IN PWCHAR StrW
  202. )
  203. /*++
  204. Routine Description:
  205. Display the string
  206. Arguments:
  207. StrW
  208. Return Value:
  209. None.
  210. --*/
  211. {
  212. printf("DISPLAY %ws\n", StrW);
  213. return ERROR_SUCCESS;
  214. }
  215. DWORD
  216. FrsErrorCallBack(
  217. IN PWCHAR Msg,
  218. IN DWORD WStatus
  219. )
  220. /*++
  221. Routine Description:
  222. Arguments:
  223. Return Value:
  224. --*/
  225. {
  226. fprintf(stderr, "%ws (%d)\n", Msg, WStatus);
  227. return ERROR_SUCCESS;
  228. }
  229. VOID
  230. ProcessPromote(
  231. IN DWORD argc,
  232. IN PWCHAR *Argv
  233. )
  234. /*++
  235. Routine Description:
  236. Process the command line for the subcommand promote.
  237. Arguments:
  238. argc
  239. Argv
  240. Return Value:
  241. Exits with 0 if everything went okay. Otherwise, 1.
  242. --*/
  243. {
  244. DWORD WStatus;
  245. PWCHAR Parent;
  246. PWCHAR Account;
  247. PWCHAR Password;
  248. PWCHAR Set;
  249. PWCHAR Type;
  250. PWCHAR Primary;
  251. PWCHAR Stage;
  252. PWCHAR Root;
  253. DWORD IsPrimary;
  254. if (argc != 10) {
  255. Usage(1);
  256. }
  257. Parent = Argv[2];
  258. Account = Argv[3];
  259. Password = Argv[4];
  260. Set = Argv[5];
  261. Type = Argv[6];
  262. Primary = Argv[7];
  263. Stage = Argv[8];
  264. Root = Argv[9];
  265. //
  266. // No account; use impersonation
  267. //
  268. if (Account && !*Account) {
  269. Account = NULL;
  270. Password = NULL;
  271. }
  272. printf("%ws %ws %ws ... %ws\n",
  273. Argv[0], Argv[1], Parent, Root);
  274. printf("PROMOTE WITH COMMIT\n");
  275. //
  276. // Check params
  277. //
  278. if (_wcsicmp(Primary, L"0") && _wcsicmp(Primary, L"1")) {
  279. printf("Primary must be 0 or 1; not %ws\n", Primary);
  280. Usage(1);
  281. }
  282. if (_wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE) &&
  283. _wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_DOMAIN)) {
  284. printf("Type must be Enterprise or Domain; not %ws\n", Type);
  285. Usage(1);
  286. }
  287. IsPrimary = wcstoul(Primary, NULL, 10);
  288. //
  289. // Prepare
  290. //
  291. WStatus = NtFrsApi_PrepareForPromotionW( FrsErrorCallBack );
  292. if (WStatus == ERROR_SUCCESS) {
  293. printf("success prepare\n");
  294. } else {
  295. printf("failure prepare %08x\n", WStatus);
  296. Win32ToMsg (L"Promote:", WStatus);
  297. }
  298. //
  299. // Start
  300. //
  301. WStatus = NtFrsApi_StartPromotionW(Parent,
  302. Account,
  303. Password,
  304. Display,
  305. FrsErrorCallBack,
  306. Set,
  307. Type,
  308. IsPrimary,
  309. Stage,
  310. Root);
  311. if (WStatus == ERROR_SUCCESS) {
  312. printf("success start\n");
  313. } else {
  314. printf("failure start %08x\n", WStatus);
  315. Win32ToMsg (L"Promote:", WStatus);
  316. }
  317. //
  318. // Wait
  319. //
  320. printf("Waiting on promotion\n");
  321. WStatus = NtFrsApi_WaitForPromotionW(30 * 60 * 1000, FrsErrorCallBack);
  322. if (WStatus == ERROR_SUCCESS) {
  323. printf("Wait succeeded\n");
  324. Win32ToMsg (L"Promote:", WStatus);
  325. } else {
  326. printf("failure wait %08x\n", WStatus);
  327. Win32ToMsg (L"Promote:", WStatus);
  328. }
  329. //
  330. // Commit (or Abort)
  331. //
  332. // WStatus = NtFrsApi_AbortPromotionW();
  333. WStatus = NtFrsApi_CommitPromotionW(0, FrsErrorCallBack);
  334. if (WStatus == ERROR_SUCCESS) {
  335. printf("success commit\n");
  336. } else {
  337. printf("failure commit %08x\n", WStatus);
  338. Win32ToMsg (L"Promote:", WStatus);
  339. }
  340. exit(0);
  341. }
  342. VOID
  343. ProcessPromoteSysVols(
  344. IN DWORD argc,
  345. IN PWCHAR *Argv
  346. )
  347. /*++
  348. Routine Description:
  349. Process the command line for the subcommand promotesysvols.
  350. Arguments:
  351. argc
  352. Argv
  353. Return Value:
  354. Exits with 0 if everything went okay. Otherwise, 1.
  355. --*/
  356. {
  357. DWORD WStatus;
  358. PWCHAR Parent;
  359. PWCHAR Account;
  360. PWCHAR Password;
  361. PWCHAR PrimaryEnterprise;
  362. PWCHAR PrimaryDomain;
  363. PWCHAR Stage;
  364. PWCHAR RootEnterprise;
  365. PWCHAR RootDomain;
  366. DWORD IsPrimaryEnterprise;
  367. DWORD IsPrimaryDomain;
  368. DWORD WaitStatus;
  369. if (argc != 10) {
  370. Usage(1);
  371. }
  372. Parent = Argv[2];
  373. Account = Argv[3];
  374. Password = Argv[4];
  375. PrimaryEnterprise = Argv[5];
  376. PrimaryDomain = Argv[6];
  377. Stage = Argv[7];
  378. RootEnterprise = Argv[8];
  379. RootDomain = Argv[9];
  380. printf("%ws %ws %ws %ws %ws %ws %ws %ws %ws %ws\n",
  381. Argv[0], Argv[1],
  382. Parent,
  383. Account,
  384. Password,
  385. PrimaryEnterprise,
  386. PrimaryDomain,
  387. Stage,
  388. RootEnterprise,
  389. RootDomain);
  390. printf("PROMOTE SYSVOLS WITH COMMIT\n");
  391. //
  392. // Check params
  393. //
  394. if (_wcsicmp(PrimaryEnterprise, L"0") &&
  395. _wcsicmp(PrimaryEnterprise, L"1")) {
  396. printf("Primary Enterprise must be 0 or 1; not %ws\n",
  397. PrimaryEnterprise);
  398. Usage(1);
  399. }
  400. if (_wcsicmp(PrimaryDomain, L"0") &&
  401. _wcsicmp(PrimaryDomain, L"1")) {
  402. printf("Primary Domain must be 0 or 1; not %ws\n",
  403. PrimaryDomain);
  404. Usage(1);
  405. }
  406. IsPrimaryEnterprise = wcstoul(PrimaryEnterprise, NULL, 10);
  407. IsPrimaryDomain = wcstoul(PrimaryDomain, NULL, 10);
  408. //
  409. // Prepare
  410. //
  411. WStatus = NtFrsApi_PrepareForPromotionW(FrsErrorCallBack);
  412. if (WStatus == ERROR_SUCCESS) {
  413. printf("success sysvol prepare\n");
  414. } else {
  415. printf("ERROR sysvol prepare %d\n", WStatus);
  416. }
  417. //
  418. // Start Enterprise
  419. //
  420. WStatus = NtFrsApi_StartPromotionW(Parent,
  421. Account,
  422. Password,
  423. Display,
  424. FrsErrorCallBack,
  425. NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE,
  426. NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE,
  427. IsPrimaryEnterprise,
  428. Stage,
  429. RootEnterprise);
  430. if (WStatus == ERROR_SUCCESS) {
  431. printf("success sysvol enterprise start\n");
  432. } else {
  433. printf("ERROR sysvol enterprise start %d\n", WStatus);
  434. }
  435. //
  436. // Start Domain
  437. //
  438. WStatus = NtFrsApi_StartPromotionW(Parent,
  439. Account,
  440. Password,
  441. Display,
  442. FrsErrorCallBack,
  443. NTFRSAPI_REPLICA_SET_TYPE_DOMAIN,
  444. NTFRSAPI_REPLICA_SET_TYPE_DOMAIN,
  445. IsPrimaryDomain,
  446. Stage,
  447. RootDomain);
  448. if (WStatus == ERROR_SUCCESS) {
  449. printf("success sysvol domain start\n");
  450. } else {
  451. printf("ERROR sysvol domain start %d\n", WStatus);
  452. }
  453. //
  454. // Wait
  455. //
  456. printf("Waiting on promotion\n");
  457. WaitStatus = NtFrsApi_WaitForPromotionW(5 * 60 * 1000,FrsErrorCallBack);
  458. if (WaitStatus == WAIT_TIMEOUT) {
  459. printf("Wait timed out\n");
  460. } else if (WaitStatus == WAIT_FAILED) {
  461. WStatus = GetLastError();
  462. printf("ERROR wait sysvols %d\n", WStatus);
  463. } else {
  464. printf("Wait sysvols succeeded\n");
  465. }
  466. //
  467. // Commit (or Abort)
  468. //
  469. // WStatus = NtFrsApi_AbortPromotionW();
  470. WStatus = NtFrsApi_CommitPromotionW(0,FrsErrorCallBack);
  471. if (WStatus == ERROR_SUCCESS) {
  472. printf("success sysvols commit\n");
  473. } else {
  474. printf("ERROR sysvols commit %d\n", WStatus);
  475. }
  476. exit(0);
  477. }
  478. VOID
  479. ProcessPromoteAbort(
  480. IN DWORD argc,
  481. IN PWCHAR *Argv
  482. )
  483. /*++
  484. Routine Description:
  485. Process the command line for the subcommand promoteabort.
  486. Arguments:
  487. argc
  488. Argv
  489. Return Value:
  490. Exits with 0 if everything went okay. Otherwise, 1.
  491. --*/
  492. {
  493. DWORD WStatus;
  494. PWCHAR Parent;
  495. PWCHAR Account;
  496. PWCHAR Password;
  497. PWCHAR Set;
  498. PWCHAR Type;
  499. PWCHAR Primary;
  500. PWCHAR Stage;
  501. PWCHAR Root;
  502. DWORD IsPrimary;
  503. DWORD WaitStatus;
  504. if (argc != 10) {
  505. Usage(1);
  506. }
  507. Parent = Argv[2];
  508. Account = Argv[3];
  509. Password = Argv[4];
  510. Set = Argv[5];
  511. Type = Argv[6];
  512. Primary = Argv[7];
  513. Stage = Argv[8];
  514. Root = Argv[9];
  515. printf("%ws %ws %ws ... %ws\n",
  516. Argv[0], Argv[1], Parent, Root);
  517. printf("PROMOTE WITH ABORT\n");
  518. //
  519. // Check params
  520. //
  521. if (_wcsicmp(Primary, L"0") && _wcsicmp(Primary, L"1")) {
  522. printf("Primary must be 0 or 1; not %ws\n", Primary);
  523. Usage(1);
  524. }
  525. if (_wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE) &&
  526. _wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_DOMAIN)) {
  527. printf("Type must be Enterprise or Domain; not %ws\n", Type);
  528. Usage(1);
  529. }
  530. IsPrimary = wcstoul(Primary, NULL, 10);
  531. //
  532. // Prepare
  533. //
  534. WStatus = NtFrsApi_PrepareForPromotionW(FrsErrorCallBack);
  535. if (WStatus == ERROR_SUCCESS) {
  536. printf("success prepare\n");
  537. } else {
  538. printf("failure prepare %d\n", WStatus);
  539. }
  540. //
  541. // Start
  542. //
  543. WStatus = NtFrsApi_StartPromotionW(Parent,
  544. Account,
  545. Password,
  546. NULL,
  547. FrsErrorCallBack,
  548. Set,
  549. Type,
  550. IsPrimary,
  551. Stage,
  552. Root);
  553. if (WStatus == ERROR_SUCCESS) {
  554. printf("success start\n");
  555. } else {
  556. printf("failure start %d\n", WStatus);
  557. }
  558. //
  559. // Abort
  560. //
  561. WStatus = NtFrsApi_AbortPromotionW();
  562. if (WStatus == ERROR_SUCCESS) {
  563. printf("success abort\n");
  564. } else {
  565. printf("failure abort %d\n", WStatus);
  566. }
  567. exit(0);
  568. }
  569. VOID
  570. ProcessDemote(
  571. IN DWORD argc,
  572. IN PWCHAR *Argv
  573. )
  574. /*++
  575. Routine Description:
  576. Process the command line for the subcommand demote.
  577. Arguments:
  578. argc
  579. Argv
  580. Return Value:
  581. Exits with 0 if everything went okay. Otherwise, 1.
  582. --*/
  583. {
  584. DWORD WStatus;
  585. PWCHAR Set;
  586. DWORD WaitStatus;
  587. if (argc != 3) {
  588. Usage(1);
  589. }
  590. Set = Argv[2];
  591. printf("%ws %ws %ws\n", Argv[0], Argv[1], Set);
  592. printf("***** DEMOTE WITH COMMIT\n");
  593. //
  594. // Prepare
  595. //
  596. WStatus = NtFrsApi_PrepareForDemotionW(FrsErrorCallBack);
  597. if (WStatus == ERROR_SUCCESS) {
  598. printf("success demote prepare\n");
  599. } else {
  600. printf("failure demote prepare %d\n", WStatus);
  601. }
  602. //
  603. // Start
  604. //
  605. WStatus = NtFrsApi_StartDemotionW(Set,FrsErrorCallBack);
  606. if (WStatus == ERROR_SUCCESS) {
  607. printf("success demote start\n");
  608. } else {
  609. printf("failure demote start %d\n", WStatus);
  610. }
  611. //
  612. // Wait
  613. //
  614. WStatus = NtFrsApi_WaitForDemotionW(5 * 60 * 1000,FrsErrorCallBack);
  615. if (WStatus == ERROR_SUCCESS) {
  616. printf("success demote wait\n");
  617. } else {
  618. printf("failure demote wait %d\n", WStatus);
  619. }
  620. //
  621. // Wait
  622. //
  623. printf("Waiting on demotion\n");
  624. WaitStatus = NtFrsApi_WaitForPromotionW(5 * 60 * 1000,FrsErrorCallBack);
  625. if (WaitStatus == WAIT_TIMEOUT) {
  626. printf("Wait timed out\n");
  627. } else if (WaitStatus == WAIT_FAILED) {
  628. WStatus = GetLastError();
  629. printf("failure wait %d\n", WStatus);
  630. } else {
  631. printf("Wait succeeded\n");
  632. }
  633. //
  634. // Commit (or Abort)
  635. //
  636. WStatus = NtFrsApi_CommitDemotionW(0,FrsErrorCallBack);
  637. if (WStatus == ERROR_SUCCESS) {
  638. printf("success demote commit\n");
  639. } else {
  640. printf("failure demote commit %d\n", WStatus);
  641. }
  642. exit(0);
  643. }
  644. VOID
  645. ProcessDemoteSysVols(
  646. IN DWORD argc,
  647. IN PWCHAR *Argv
  648. )
  649. /*++
  650. Routine Description:
  651. Process the command line for the subcommand demotesysvols.
  652. Arguments:
  653. argc
  654. Argv
  655. Return Value:
  656. Exits with 0 if everything went okay. Otherwise, 1.
  657. --*/
  658. {
  659. DWORD WStatus;
  660. DWORD WaitStatus;
  661. if (argc != 2) {
  662. Usage(1);
  663. }
  664. printf("%ws %ws\n", Argv[0], Argv[1]);
  665. printf("***** DEMOTE SYSVOLS WITH COMMIT\n");
  666. //
  667. // Prepare
  668. //
  669. WStatus = NtFrsApi_PrepareForDemotionW(FrsErrorCallBack);
  670. if (WStatus == ERROR_SUCCESS) {
  671. printf("success demote sysvols prepare\n");
  672. } else {
  673. printf("ERROR demote sysvols prepare %d\n", WStatus);
  674. }
  675. //
  676. // Start
  677. //
  678. WStatus = NtFrsApi_StartDemotionW(NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE,NULL);
  679. if (WStatus == ERROR_SUCCESS) {
  680. printf("success demote enterprise start\n");
  681. } else {
  682. printf("ERROR demote enterprise start %d\n", WStatus);
  683. }
  684. //
  685. // Start
  686. //
  687. WStatus = NtFrsApi_StartDemotionW(NTFRSAPI_REPLICA_SET_TYPE_DOMAIN, FrsErrorCallBack);
  688. if (WStatus == ERROR_SUCCESS) {
  689. printf("success demote domain start\n");
  690. } else {
  691. printf("ERROR demote domain start %d\n", WStatus);
  692. }
  693. //
  694. // Wait
  695. //
  696. WStatus = NtFrsApi_WaitForDemotionW(5 * 60 * 1000, FrsErrorCallBack);
  697. if (WStatus == ERROR_SUCCESS) {
  698. printf("success demote sysvols wait\n");
  699. } else {
  700. printf("ERROR demote sysvols wait %d\n", WStatus);
  701. }
  702. //
  703. // Wait
  704. //
  705. printf("Waiting on demotion\n");
  706. WaitStatus = NtFrsApi_WaitForPromotionW(5 * 60 * 1000, FrsErrorCallBack);
  707. if (WaitStatus == WAIT_TIMEOUT) {
  708. printf("Wait timed out\n");
  709. } else if (WaitStatus == WAIT_FAILED) {
  710. WStatus = GetLastError();
  711. printf("ERROR wait %d\n", WStatus);
  712. } else {
  713. printf("Wait demote sysvols succeeded\n");
  714. }
  715. //
  716. // Commit (or Abort)
  717. //
  718. WStatus = NtFrsApi_CommitDemotionW(0, FrsErrorCallBack);
  719. if (WStatus == ERROR_SUCCESS) {
  720. printf("success demote sysvols commit\n");
  721. } else {
  722. printf("ERROR demote sysvols commit %d\n", WStatus);
  723. }
  724. exit(0);
  725. }
  726. VOID
  727. ProcessDemoteAbort(
  728. IN DWORD argc,
  729. IN PWCHAR *Argv
  730. )
  731. /*++
  732. Routine Description:
  733. Process the command line for the subcommand demoteabort.
  734. Arguments:
  735. argc
  736. Argv
  737. Return Value:
  738. Exits with 0 if everything went okay. Otherwise, 1.
  739. --*/
  740. {
  741. DWORD WStatus;
  742. PWCHAR Set;
  743. DWORD WaitStatus;
  744. if (argc != 3) {
  745. Usage(1);
  746. }
  747. Set = Argv[2];
  748. printf("%ws %ws %ws\n", Argv[0], Argv[1], Set);
  749. printf("***** DEMOTE WITH ABORT\n");
  750. //
  751. // Prepare
  752. //
  753. WStatus = NtFrsApi_PrepareForDemotionW(FrsErrorCallBack);
  754. if (WStatus == ERROR_SUCCESS) {
  755. printf("success demote prepare\n");
  756. } else {
  757. printf("failure demote prepare %d\n", WStatus);
  758. }
  759. //
  760. // Start
  761. //
  762. WStatus = NtFrsApi_StartDemotionW(Set, FrsErrorCallBack);
  763. if (WStatus == ERROR_SUCCESS) {
  764. printf("success demote start\n");
  765. } else {
  766. printf("failure demote start %d\n", WStatus);
  767. }
  768. //
  769. // Abort
  770. //
  771. WStatus = NtFrsApi_AbortDemotionW();
  772. if (WStatus == ERROR_SUCCESS) {
  773. printf("success demote abort\n");
  774. } else {
  775. printf("failure demote abort %d\n", WStatus);
  776. }
  777. exit(0);
  778. }
  779. VOID
  780. ProcessPoll(
  781. IN DWORD argc,
  782. IN PWCHAR *Argv
  783. )
  784. /*++
  785. Routine Description:
  786. Process the command line for the subcommand poll.
  787. Arguments:
  788. argc
  789. Argv
  790. Return Value:
  791. Exits with 0 if everything went okay. Otherwise, 1.
  792. --*/
  793. {
  794. DWORD WStatus;
  795. DWORD i;
  796. ULONG LongInterval;
  797. ULONG ShortInterval;
  798. ULONG UseShortInterval;
  799. ULONG Interval;
  800. DWORD ComputerLen;
  801. PWCHAR ComputerName;
  802. BOOL SetInterval;
  803. //
  804. // Initialize the input parameters
  805. //
  806. LongInterval = 0;
  807. ShortInterval = 0;
  808. UseShortInterval = 0;
  809. ComputerName = NULL;
  810. SetInterval = FALSE;
  811. for (i = 2; i < argc; ++i) {
  812. //
  813. // Process options for poll
  814. //
  815. //
  816. // Not a parameter; must be the computer name
  817. //
  818. if (*Argv[i] != L'/' && *Argv[i] != L'-') {
  819. if (ComputerName) {
  820. fprintf(stderr, "Multiple computer names are not allowed\n");
  821. Usage(1);
  822. }
  823. ComputerName = Argv[i];
  824. //
  825. // /?
  826. //
  827. } else if (wcsstr(Argv[i] + 1, L"?") == Argv[i] + 1) {
  828. Usage(0);
  829. //
  830. // /quickly
  831. //
  832. } else if (!_wcsnicmp(Argv[i], L"/quickly", 8)) {
  833. SetInterval = TRUE;
  834. UseShortInterval = 1;
  835. if (*(Argv[i] + 8) != L'\0') {
  836. if (*(Argv[i] + 8) != L'=') {
  837. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  838. Usage(1);
  839. }
  840. if (*(Argv[i] + 9) == L'\0') {
  841. ShortInterval = NTFRSAPI_DEFAULT_SHORT_INTERVAL;
  842. } else {
  843. ShortInterval = wcstoul(Argv[i] + 9, NULL, 10);
  844. }
  845. if (ShortInterval < NTFRSAPI_MIN_INTERVAL ||
  846. ShortInterval > NTFRSAPI_MAX_INTERVAL) {
  847. fprintf(stderr, "Interval must be between %d and %d\n",
  848. NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL);
  849. Usage(1);
  850. }
  851. }
  852. //
  853. // /slowly
  854. //
  855. } else if (!_wcsnicmp(Argv[i], L"/slowly", 7)) {
  856. SetInterval = TRUE;
  857. if (*(Argv[i] + 7) != L'\0') {
  858. if (*(Argv[i] + 7) != L'=') {
  859. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  860. Usage(1);
  861. }
  862. if (*(Argv[i] + 8) == L'\0') {
  863. LongInterval = NTFRSAPI_DEFAULT_LONG_INTERVAL;
  864. } else {
  865. LongInterval = wcstoul(Argv[i] + 8, NULL, 10);
  866. }
  867. if (LongInterval < NTFRSAPI_MIN_INTERVAL ||
  868. LongInterval > NTFRSAPI_MAX_INTERVAL) {
  869. fprintf(stderr, "Interval must be between %d and %d\n",
  870. NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL);
  871. Usage(1);
  872. }
  873. }
  874. //
  875. // /now
  876. //
  877. } else if (!_wcsnicmp(Argv[i], L"/now", 4)) {
  878. SetInterval = TRUE;
  879. if (*(Argv[i] + 4) != L'\0') {
  880. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  881. Usage(1);
  882. }
  883. //
  884. // Don't understand
  885. //
  886. } else {
  887. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  888. Usage(1);
  889. }
  890. }
  891. if (SetInterval) {
  892. //
  893. // Set the interval and initiate a new polling cycle
  894. //
  895. WStatus = NtFrsApi_Set_DsPollingIntervalW(ComputerName,
  896. UseShortInterval,
  897. LongInterval,
  898. ShortInterval);
  899. if (!WIN_SUCCESS(WStatus)) {
  900. Win32ToMsg(L"Can't set interval:", WStatus);
  901. exit(1);
  902. }
  903. } else {
  904. //
  905. // Get the current polling cycles
  906. //
  907. WStatus = NtFrsApi_Get_DsPollingIntervalW(ComputerName,
  908. &Interval,
  909. &LongInterval,
  910. &ShortInterval);
  911. if (!WIN_SUCCESS(WStatus)) {
  912. Win32ToMsg(L"Can't get intervals:", WStatus);
  913. exit(1);
  914. }
  915. printf("Current Interval: %6d minutes\n", Interval);
  916. printf("Short Interval : %6d minutes\n", ShortInterval);
  917. printf("Long Interval : %6d minutes\n", LongInterval);
  918. }
  919. exit(0);
  920. }
  921. VOID
  922. ProcessDump(
  923. IN DWORD argc,
  924. IN PWCHAR *Argv,
  925. IN DWORD TypeOfInformation
  926. )
  927. /*++
  928. Routine Description:
  929. Dump bunches of stuff
  930. Arguments:
  931. argc
  932. Argv
  933. TypeOfInformation
  934. Return Value:
  935. Exits with 0 if everything went okay. Otherwise, 1.
  936. --*/
  937. {
  938. DWORD WStatus;
  939. PCHAR Line;
  940. BOOL FirstTime = TRUE;
  941. PVOID Info = NULL;
  942. PWCHAR ComputerName = NULL;
  943. if (argc > 2) {
  944. ComputerName = Argv[2];
  945. }
  946. do {
  947. WStatus = NtFrsApi_InfoW(ComputerName,
  948. TypeOfInformation,
  949. 0,
  950. &Info);
  951. if (!WIN_SUCCESS(WStatus)) {
  952. fprintf(stderr, "ERROR NtFrsApi_InfoW() Error %d\n", WStatus);
  953. NtFrsApi_InfoFreeW(&Info);
  954. exit(1);
  955. }
  956. if (Info) {
  957. if (!FirstTime) {
  958. printf("===== THE FOLLOWING INFO MAY BE INCONSISTENT DUE TO REFETCH =====\n");
  959. }
  960. FirstTime = FALSE;
  961. Line = NULL;
  962. do {
  963. WStatus = NtFrsApi_InfoLineW(Info, &Line);
  964. if (!WIN_SUCCESS(WStatus)) {
  965. fprintf(stderr, "ERROR NtFrsApi_InfoLineW() Error %d\n", WStatus);
  966. NtFrsApi_InfoFreeW(&Info);
  967. exit(1);
  968. }
  969. if (Line) {
  970. printf("%s", Line);
  971. }
  972. } while (Line);
  973. }
  974. } while (Info);
  975. exit(0);
  976. }
  977. typedef struct _DIRS DIRS, *PDIRS;
  978. struct _DIRS {
  979. PDIRS Next;
  980. PWCHAR Dir;
  981. PVOID BurSet;
  982. };
  983. VOID
  984. ProcessBackupRestore(
  985. IN DWORD argc,
  986. IN PWCHAR *Argv,
  987. IN DWORD BurFlags
  988. )
  989. /*++
  990. Routine Description:
  991. Dump replicated dirs
  992. Arguments:
  993. argc
  994. Argv
  995. Return Value:
  996. Exits with 0 if everything went okay. Otherwise, 1.
  997. --*/
  998. {
  999. DWORD WStatus;
  1000. DWORD i;
  1001. DWORD BurSetIndex;
  1002. DWORD DestroyBurFlags = NTFRSAPI_BUR_FLAGS_NONE;
  1003. PVOID BurContext;
  1004. PVOID BurSet;
  1005. BOOL IsSysvol;
  1006. BOOL ExpectKey = FALSE;
  1007. BOOL Spin = FALSE;
  1008. HKEY HKey;
  1009. PWCHAR DirPath;
  1010. PWCHAR DirType;
  1011. PDIRS Dirs = NULL;
  1012. PDIRS Dir = NULL;
  1013. DWORD BufferSize;
  1014. WCHAR Buffer[1024];
  1015. DWORD Buffer2Size;
  1016. WCHAR Buffer2[1024];
  1017. DWORD FiltersSize;
  1018. WCHAR Filters[1024];
  1019. PWCHAR Str;
  1020. for (i = 2; i < argc; ++i) {
  1021. printf("%ws\n", Argv[i]);
  1022. if (!_wcsicmp(Argv[i], L"/auth")) {
  1023. BurFlags |= NTFRSAPI_BUR_FLAGS_AUTHORITATIVE;
  1024. } else if (!_wcsicmp(Argv[i], L"/nonauth")) {
  1025. BurFlags |= NTFRSAPI_BUR_FLAGS_NON_AUTHORITATIVE;
  1026. } else if (!_wcsicmp(Argv[i], L"/primary")) {
  1027. BurFlags |= NTFRSAPI_BUR_FLAGS_PRIMARY;
  1028. } else if (!_wcsicmp(Argv[i], L"/system")) {
  1029. BurFlags |= NTFRSAPI_BUR_FLAGS_SYSTEM;
  1030. } else if (!_wcsicmp(Argv[i], L"/ds")) {
  1031. BurFlags |= NTFRSAPI_BUR_FLAGS_ACTIVE_DIRECTORY;
  1032. } else if (!_wcsicmp(Argv[i], L"/normal")) {
  1033. BurFlags |= NTFRSAPI_BUR_FLAGS_NORMAL;
  1034. } else if (!_wcsicmp(Argv[i], L"/all")) {
  1035. BurFlags |= NTFRSAPI_BUR_FLAGS_ALL_DIRECTORIES_AND_VOLUMES;
  1036. } else if (!_wcsicmp(Argv[i], L"/restart")) {
  1037. DestroyBurFlags |= NTFRSAPI_BUR_FLAGS_RESTART;
  1038. } else if (!_wcsicmp(Argv[i], L"/unknown")) {
  1039. BurFlags |= 0x80000000;
  1040. } else if (!_wcsicmp(Argv[i], L"/destroyunknown")) {
  1041. DestroyBurFlags |= 0x80000000;
  1042. } else if (!_wcsicmp(Argv[i], L"/key")) {
  1043. ExpectKey = TRUE;
  1044. } else if (!_wcsicmp(Argv[i], L"/spin")) {
  1045. Spin = TRUE;
  1046. } else if (*Argv[i] == L'/') {
  1047. fprintf(stderr, "Don't understand %ws\n", Argv[i]);
  1048. exit(1);
  1049. }
  1050. }
  1051. SPIN_ON_INITIALIZE:
  1052. WStatus = NtFrsApiInitializeBackupRestore(FrsErrorCallBack,
  1053. BurFlags,
  1054. &BurContext);
  1055. if (!WIN_SUCCESS(WStatus)) {
  1056. fprintf(stderr,
  1057. "ERROR NtFrsApiInitializeBackupRestore(%08x) Error %d\n",
  1058. BurFlags,
  1059. WStatus);
  1060. if (Spin) {
  1061. Sleep(2 * 1000);
  1062. goto SPIN_ON_INITIALIZE;
  1063. }
  1064. exit(1);
  1065. }
  1066. WStatus = NtFrsApiGetBackupRestoreSets(BurContext);
  1067. if (!WIN_SUCCESS(WStatus)) {
  1068. fprintf(stderr,
  1069. "WARN NtFrsApiGetBackupRestoreSets() Error %d\n",
  1070. WStatus);
  1071. goto DESTROY;
  1072. }
  1073. BurSetIndex = 0;
  1074. while (TRUE) {
  1075. WStatus = NtFrsApiEnumBackupRestoreSets(BurContext,
  1076. BurSetIndex,
  1077. &BurSet);
  1078. if (!WIN_SUCCESS(WStatus)) {
  1079. break;
  1080. }
  1081. WStatus = NtFrsApiIsBackupRestoreSetASysvol(BurContext,
  1082. BurSet,
  1083. &IsSysvol);
  1084. if (!WIN_SUCCESS(WStatus)) {
  1085. fprintf(stderr,
  1086. "ERROR NtFrsApiIsBackupRestoreSetASysvol(%d) Error %d\n",
  1087. BurSetIndex,
  1088. WStatus);
  1089. goto DESTROY;
  1090. }
  1091. //
  1092. // Directory
  1093. //
  1094. BufferSize = 1;
  1095. WStatus = NtFrsApiGetBackupRestoreSetDirectory(BurContext,
  1096. BurSet,
  1097. &BufferSize,
  1098. Buffer);
  1099. if (WStatus != ERROR_INSUFFICIENT_BUFFER) {
  1100. fprintf(stderr,
  1101. "ERROR NtFrsApiIsBackupRestoreSetASysvol(%d) Error %d\n",
  1102. BurSetIndex,
  1103. WStatus);
  1104. }
  1105. BufferSize = 1024;
  1106. WStatus = NtFrsApiGetBackupRestoreSetDirectory(BurContext,
  1107. BurSet,
  1108. &BufferSize,
  1109. Buffer);
  1110. if (!WIN_SUCCESS(WStatus)) {
  1111. fprintf(stderr,
  1112. "ERROR NtFrsApiIsBackupRestoreSetASysvol(%d) Error %d\n",
  1113. BurSetIndex,
  1114. WStatus);
  1115. goto DESTROY;
  1116. }
  1117. //
  1118. // Paths
  1119. //
  1120. Buffer2Size = 1;
  1121. FiltersSize = 1;
  1122. WStatus = NtFrsApiGetBackupRestoreSetPaths(BurContext,
  1123. BurSet,
  1124. &Buffer2Size,
  1125. Buffer2,
  1126. &FiltersSize,
  1127. Filters);
  1128. if (WStatus != ERROR_INSUFFICIENT_BUFFER) {
  1129. fprintf(stderr,
  1130. "ERROR NtFrsApiGetBackupRestorePaths(%d) Error %d\n",
  1131. BurSetIndex,
  1132. WStatus);
  1133. }
  1134. Buffer2Size = 1024;
  1135. FiltersSize = 1;
  1136. WStatus = NtFrsApiGetBackupRestoreSetPaths(BurContext,
  1137. BurSet,
  1138. &Buffer2Size,
  1139. Buffer2,
  1140. &FiltersSize,
  1141. Filters);
  1142. if (WStatus != ERROR_INSUFFICIENT_BUFFER) {
  1143. fprintf(stderr,
  1144. "ERROR NtFrsApiGetBackupRestorePaths(FILTERS %d) Error %d\n",
  1145. BurSetIndex,
  1146. WStatus);
  1147. }
  1148. Buffer2Size = 1024;
  1149. FiltersSize = 1024;
  1150. WStatus = NtFrsApiGetBackupRestoreSetPaths(BurContext,
  1151. BurSet,
  1152. &Buffer2Size,
  1153. Buffer2,
  1154. &FiltersSize,
  1155. Filters);
  1156. if (!WIN_SUCCESS(WStatus)) {
  1157. fprintf(stderr,
  1158. "ERROR NtFrsApiGetBackupRestorePaths(%d) Error %d\n",
  1159. BurSetIndex,
  1160. WStatus);
  1161. goto DESTROY;
  1162. }
  1163. if (IsSysvol) {
  1164. printf("BurSet %d: %ws is a sysvol\n",
  1165. BurSetIndex,
  1166. Buffer);
  1167. } else {
  1168. printf("BurSet %d: %ws\n",
  1169. BurSetIndex,
  1170. Buffer);
  1171. }
  1172. if (Buffer2Size) {
  1173. Str = Buffer2;
  1174. while(*Str) {
  1175. printf(" Path : %ws\n", Str);
  1176. Str += wcslen(Str) + 1;
  1177. }
  1178. }
  1179. if (FiltersSize) {
  1180. Str = Filters;
  1181. while(*Str) {
  1182. printf(" Filter: %ws\n", Str);
  1183. Str += wcslen(Str) + 1;
  1184. }
  1185. }
  1186. Dir = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(DIRS));
  1187. Dir->Dir = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, BufferSize);
  1188. CopyMemory(Dir->Dir, Buffer, BufferSize);
  1189. Dir->BurSet = BurSet;
  1190. Dir->Next = Dirs;
  1191. Dirs = Dir;
  1192. ++BurSetIndex;
  1193. }
  1194. if (!WIN_SUCCESS(WStatus) && WStatus != ERROR_NO_MORE_ITEMS) {
  1195. fprintf(stderr,
  1196. "ERROR NtFrsApiEnumBackupRestoreSets(%d) Error %d\n",
  1197. BurSetIndex,
  1198. WStatus);
  1199. goto DESTROY;
  1200. }
  1201. for (i = 2; i < argc; ++i) {
  1202. if (*Argv[i] == L'/') {
  1203. continue;
  1204. }
  1205. DirPath = Argv[i++];
  1206. if (i >= argc) {
  1207. printf("%ws does not have a corresponding primary|nonauth\n",
  1208. DirPath);
  1209. continue;
  1210. }
  1211. DirType = Argv[i];
  1212. printf("Processing %ws %ws\n", DirPath, DirType);
  1213. if (!_wcsicmp(DirType, L"primary")) {
  1214. BurFlags = NTFRSAPI_BUR_FLAGS_PRIMARY;
  1215. } else if (!_wcsicmp(DirType, L"nonauth")) {
  1216. BurFlags = NTFRSAPI_BUR_FLAGS_NON_AUTHORITATIVE;
  1217. } else {
  1218. printf("Don't understand %ws\n", DirType);
  1219. continue;
  1220. }
  1221. for (Dir = Dirs; Dir; Dir = Dir->Next) {
  1222. if (!_wcsicmp(Dir->Dir, DirPath)) {
  1223. break;
  1224. }
  1225. }
  1226. if (!Dir) {
  1227. printf("%ws not found\n", DirPath);
  1228. continue;
  1229. }
  1230. WStatus = NtFrsApiRestoringDirectory(BurContext,
  1231. Dir->BurSet,
  1232. BurFlags);
  1233. if (!WIN_SUCCESS(WStatus)) {
  1234. fprintf(stderr,
  1235. "ERROR NtFrsApiRestoringDirectory(%ws, %08x) Error %d\n",
  1236. DirPath,
  1237. BurFlags,
  1238. WStatus);
  1239. continue;
  1240. }
  1241. WStatus = NtFrsApiFinishedRestoringDirectory(BurContext,
  1242. Dir->BurSet,
  1243. NTFRSAPI_BUR_FLAGS_NONE);
  1244. if (!WIN_SUCCESS(WStatus)) {
  1245. fprintf(stderr,
  1246. "ERROR NtFrsApiFinishedRestoringDirectory(%ws, %08x) Error %d\n",
  1247. DirPath,
  1248. BurFlags,
  1249. WStatus);
  1250. continue;
  1251. }
  1252. printf("Finished restoring %ws\n", DirPath);
  1253. }
  1254. DESTROY:
  1255. if (Spin) {
  1256. printf("Spinning...\n");
  1257. }
  1258. while (Spin) {
  1259. Sleep(2 * 1000);
  1260. }
  1261. BufferSize = 1024;
  1262. WStatus = NtFrsApiDestroyBackupRestore(&BurContext,
  1263. DestroyBurFlags,
  1264. (ExpectKey) ? &HKey : NULL,
  1265. (ExpectKey) ? &BufferSize : NULL,
  1266. (ExpectKey) ? Buffer : NULL);
  1267. if (!WIN_SUCCESS(WStatus)) {
  1268. fprintf(stderr,
  1269. "ERROR NtFrsApiDestroyBackupRestore(%08x) Error %d\n",
  1270. DestroyBurFlags,
  1271. WStatus);
  1272. exit(1);
  1273. }
  1274. if (ExpectKey) {
  1275. printf("%08x HKey, %d KeySize, %ws\n", HKey, BufferSize, Buffer);
  1276. }
  1277. #if 0
  1278. WStatus = NtFrsApi_GetReplicatedDirectoriesW(FrsErrorCallBack, &Dirs);
  1279. if (!WIN_SUCCESS(WStatus)) {
  1280. fprintf(stderr, "ERROR NtFrsApi_GetReplicatedDirectories() Error %d\n", WStatus);
  1281. exit(1);
  1282. }
  1283. if (Dirs) {
  1284. while (*Dirs != L'\0') {
  1285. fprintf(stdout, "Dirs:%ws:\n", Dirs);
  1286. Dirs = &Dirs[wcslen(Dirs) + 1];
  1287. }
  1288. LocalFree(Dirs);
  1289. }
  1290. WStatus = NtFrsApi_StopServiceForFullNonAuthRestoreW(Primary,
  1291. FrsErrorCallBack);
  1292. if (!WIN_SUCCESS(WStatus)) {
  1293. fprintf(stderr, "ERROR NtFrsApi_StopServiceForFullNonAuth() Error %d\n", WStatus);
  1294. exit(1);
  1295. }
  1296. WStatus = NtFrsApi_StartServiceAfterFullNonAuthRestoreW(FrsErrorCallBack);
  1297. if (!WIN_SUCCESS(WStatus)) {
  1298. fprintf(stderr, "ERROR NtFrsApi_StartServiceAfterFullNonAuth() Error %d\n", WStatus);
  1299. exit(1);
  1300. }
  1301. #endif 0
  1302. exit(0);
  1303. }
  1304. VOID
  1305. ProcessComm(
  1306. IN DWORD argc,
  1307. IN PWCHAR *Argv,
  1308. IN DWORD CommCommand
  1309. )
  1310. /*++
  1311. Routine Description:
  1312. Dump bunches of stuff
  1313. Arguments:
  1314. argc
  1315. Argv
  1316. CommCommand
  1317. Return Value:
  1318. Exits with 0 if everything went okay. Otherwise, 1.
  1319. --*/
  1320. {
  1321. DWORD WStatus;
  1322. PWCHAR Line;
  1323. PWCHAR ComputerName1 = NULL;
  1324. PWCHAR ComputerName2 = NULL;
  1325. PWCHAR Account = NULL;
  1326. PWCHAR Password = NULL;
  1327. PVOID Info = NULL;
  1328. if (argc > 2) {
  1329. ComputerName1 = Argv[2];
  1330. if (ComputerName1 && !*ComputerName1) {
  1331. ComputerName1 = NULL;
  1332. }
  1333. }
  1334. if (argc > 3) {
  1335. ComputerName2 = Argv[3];
  1336. if (ComputerName2 && !*ComputerName2) {
  1337. ComputerName2 = NULL;
  1338. }
  1339. }
  1340. if (argc > 4) {
  1341. Account = Argv[4];
  1342. if (Account && !*Account) {
  1343. Account = NULL;
  1344. }
  1345. }
  1346. if (argc > 5) {
  1347. Password = Argv[5];
  1348. if (Password && !*Password) {
  1349. Password = NULL;
  1350. }
  1351. }
  1352. #if 0
  1353. not yet implemented
  1354. WStatus = NtFrsApi_CommW(CommCommand,
  1355. ComputerName1,
  1356. ComputerName2,
  1357. Account,
  1358. Password,
  1359. &Info);
  1360. if (!WIN_SUCCESS(WStatus)) {
  1361. fprintf(stderr, "NtFrsApi_CommW() -> %d\n", WStatus);
  1362. exit(1);
  1363. }
  1364. Line = NULL;
  1365. AGAIN:
  1366. WStatus = NtFrsApi_InfoLineW(Info, &Line);
  1367. if (!WIN_SUCCESS(WStatus)) {
  1368. fprintf(stderr, "NtFrsApi_InfoLineW() -> %d\n", WStatus);
  1369. exit(1);
  1370. }
  1371. if (Line) {
  1372. printf("%ws", Line);
  1373. goto AGAIN;
  1374. }
  1375. NtFrsApi_Free_InfoW(&Info);
  1376. #endif 0
  1377. exit(0);
  1378. }
  1379. #define PRIV_BUF_LENGTH (1024)
  1380. VOID
  1381. LogOnAsComputer(
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. Check if the caller is a member of Groups
  1386. Arguments:
  1387. ServerHandle
  1388. Groups
  1389. Return Value:
  1390. Win32 Status
  1391. --*/
  1392. {
  1393. #define DEBSUB "CheckGroups:"
  1394. DWORD WStatus;
  1395. PVOID PrivBuf;
  1396. DWORD PrivBufLen;
  1397. DWORD LastPrivBufLen;
  1398. HANDLE IdHandle;
  1399. HANDLE TokenHandle;
  1400. DWORD i;
  1401. DWORD j;
  1402. TOKEN_PRIVILEGES *Tp;
  1403. DWORD ComputerLen;
  1404. WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1405. DWORD PrivLen;
  1406. WCHAR PrivName[MAX_PATH + 1];
  1407. ComputerLen = MAX_COMPUTERNAME_LENGTH;
  1408. ComputerName[0] = L'\0';
  1409. if (!GetComputerName(ComputerName, &ComputerLen)) {
  1410. printf("FRS: Cannot get the computer's name\n");
  1411. return;
  1412. }
  1413. printf("Computer name is %ws\n", ComputerName);
  1414. //
  1415. // For this process
  1416. //
  1417. IdHandle = GetCurrentProcess();
  1418. if (!OpenProcessToken(IdHandle, TOKEN_QUERY, &TokenHandle)) {
  1419. WStatus = GetLastError();
  1420. printf("Can't open process token; WStatus %d\n", WStatus);
  1421. goto cleanup;
  1422. }
  1423. //
  1424. // Get the groups from the access token for this thread or process
  1425. //
  1426. PrivBufLen = PRIV_BUF_LENGTH;
  1427. do {
  1428. PrivBuf = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, PrivBufLen);
  1429. LastPrivBufLen = PrivBufLen;
  1430. if (!GetTokenInformation(TokenHandle,
  1431. TokenPrivileges,
  1432. PrivBuf,
  1433. PrivBufLen,
  1434. &PrivBufLen)) {
  1435. WStatus = GetLastError();
  1436. printf("Can't get privs groups; WStatus %d (lastlen %d; curlen %d\n",
  1437. WStatus,
  1438. LastPrivBufLen,
  1439. PrivBufLen);
  1440. FREE(PrivBuf);
  1441. } else {
  1442. WStatus = ERROR_SUCCESS;
  1443. }
  1444. } while (!WIN_SUCCESS(WStatus) && LastPrivBufLen < PrivBufLen);
  1445. if (!WIN_SUCCESS(WStatus)) {
  1446. goto cleanup;
  1447. }
  1448. Tp = (TOKEN_PRIVILEGES *)PrivBuf;
  1449. for (i = 0; i < Tp->PrivilegeCount; ++i) {
  1450. PrivLen = MAX_PATH + 1;
  1451. if (!LookupPrivilegeName(NULL,
  1452. &Tp->Privileges[i].Luid,
  1453. PrivName,
  1454. &PrivLen)) {
  1455. printf("lookuppriv error %d\n", GetLastError());
  1456. exit(0);
  1457. }
  1458. printf("Priv %d is %ws\n", i, PrivName);
  1459. }
  1460. printf("Okay\n");
  1461. CloseHandle(TokenHandle);
  1462. if (!LogonUser(L"Administrator",
  1463. NULL,
  1464. NULL,
  1465. LOGON32_LOGON_SERVICE,
  1466. LOGON32_PROVIDER_DEFAULT,
  1467. &TokenHandle)) {
  1468. printf("ERROR - %d logon\n", GetLastError());
  1469. exit(0);
  1470. }
  1471. cleanup:
  1472. CloseHandle(TokenHandle);
  1473. CloseHandle(IdHandle);
  1474. FREE(PrivBuf);
  1475. }
  1476. // --------------- Process Install Stage
  1477. BOOL
  1478. FrsSetCompression(
  1479. IN PWCHAR Path,
  1480. IN HANDLE Handle,
  1481. IN USHORT TypeOfCompression
  1482. )
  1483. /*++
  1484. Routine Description:
  1485. Enable compression on Handle.
  1486. Arguments:
  1487. Path
  1488. Handle
  1489. TypeOfCompression
  1490. Return Value:
  1491. Set the compression mode on a file
  1492. --*/
  1493. {
  1494. DWORD BytesReturned;
  1495. if (!DeviceIoControl(Handle,
  1496. FSCTL_SET_COMPRESSION,
  1497. &TypeOfCompression,
  1498. sizeof(TypeOfCompression),
  1499. NULL,
  1500. 0,
  1501. &BytesReturned,
  1502. NULL)) {
  1503. Win32ToMsg(Path, GetLastError());
  1504. return FALSE;
  1505. }
  1506. return TRUE;
  1507. }
  1508. BOOL
  1509. FrsSetFileAttributes(
  1510. PWCHAR Path,
  1511. HANDLE Handle,
  1512. ULONG FileAttributes
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. This routine sets the file's attributes
  1517. Arguments:
  1518. Path - for error messages
  1519. Handle - Supplies a handle to the file that is to be marked for delete.
  1520. Attributes - Attributes for the file
  1521. Return Value:
  1522. TRUE - attributes have been set
  1523. FALSE
  1524. --*/
  1525. {
  1526. IO_STATUS_BLOCK IoStatus;
  1527. FILE_BASIC_INFORMATION BasicInformation;
  1528. NTSTATUS Status;
  1529. //
  1530. // Set the attributes
  1531. //
  1532. ZeroMemory(&BasicInformation, sizeof(BasicInformation));
  1533. BasicInformation.FileAttributes = FileAttributes | FILE_ATTRIBUTE_NORMAL;
  1534. Status = NtSetInformationFile(Handle,
  1535. &IoStatus,
  1536. &BasicInformation,
  1537. sizeof(BasicInformation),
  1538. FileBasicInformation);
  1539. if (!NT_SUCCESS(Status)) {
  1540. fprintf(stderr, "NtSetFileInformationFile(%ws); NtStatus 0x%08x\n",
  1541. Path,
  1542. Status);
  1543. return FALSE;
  1544. }
  1545. return TRUE;
  1546. }
  1547. DWORD
  1548. FrsSetFilePointer(
  1549. IN PWCHAR Name,
  1550. IN HANDLE Handle,
  1551. IN ULONG High,
  1552. IN ULONG Low
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. Position file pointer
  1557. Arguments:
  1558. Handle
  1559. Name
  1560. High
  1561. Low
  1562. Return Value:
  1563. Win32 Error Status
  1564. --*/
  1565. {
  1566. #undef DEBSUB
  1567. #define DEBSUB "FrsSetFilePointer:"
  1568. DWORD WStatus;
  1569. Low = SetFilePointer(Handle, Low, &High, FILE_BEGIN);
  1570. if (Low == INVALID_SET_FILE_POINTER) {
  1571. WStatus = GetLastError();
  1572. if (WStatus != NO_ERROR) {
  1573. Win32ToMsg(Name, WStatus);
  1574. return WStatus;
  1575. }
  1576. }
  1577. return ERROR_SUCCESS;
  1578. }
  1579. BOOL
  1580. StuReadFile(
  1581. IN PWCHAR Path,
  1582. IN HANDLE Handle,
  1583. IN PVOID Buf,
  1584. IN DWORD BytesToRead,
  1585. OUT PDWORD BytesRead
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. Read data from a file
  1590. Arguments:
  1591. Path
  1592. Handle
  1593. Buf
  1594. BytesToRead
  1595. Return Value:
  1596. TRUE - no problem
  1597. FALSE - couldn't read
  1598. --*/
  1599. {
  1600. BOOL DidRead;
  1601. //
  1602. // Read the file's name into the file
  1603. //
  1604. DidRead = ReadFile(Handle, Buf, BytesToRead, BytesRead, NULL);
  1605. //
  1606. // Read error
  1607. //
  1608. if (!DidRead) {
  1609. Win32ToMsg(Path, GetLastError());
  1610. return FALSE;
  1611. }
  1612. //
  1613. // Done
  1614. //
  1615. return TRUE;
  1616. }
  1617. BOOL
  1618. FrsSetFileTime(
  1619. IN PWCHAR Path,
  1620. IN HANDLE Handle,
  1621. IN FILETIME *CreateTime,
  1622. IN FILETIME *AccessTime,
  1623. IN FILETIME *WriteTime
  1624. )
  1625. /*++
  1626. Routine Description:
  1627. Position file pointer
  1628. Arguments:
  1629. Path
  1630. Handle
  1631. Attributes
  1632. CreateTime
  1633. AccessTime
  1634. WriteTime
  1635. Return Value:
  1636. TRUE - no problem
  1637. FALSE - couldn't set size
  1638. --*/
  1639. {
  1640. if (!SetFileTime(Handle, CreateTime, AccessTime, WriteTime)) {
  1641. Win32ToMsg(Path, GetLastError());
  1642. return FALSE;
  1643. }
  1644. return TRUE;
  1645. }
  1646. #define IOSIZE (64 * 1024)
  1647. VOID
  1648. ProcessInstall(
  1649. IN DWORD argc,
  1650. IN PWCHAR *Argv
  1651. )
  1652. /*++
  1653. Routine Description:
  1654. Restore the StagePath to TargetPath if TargetPath is non-NULL.
  1655. Arguments:
  1656. argc - number of argv's
  1657. Argv - stagepath and, optionally, targetpath
  1658. Return Value:
  1659. Win32 status
  1660. --*/
  1661. {
  1662. BOOL IsDir;
  1663. BOOL ExistingOid;
  1664. ULONG High;
  1665. ULONG Low;
  1666. ULONG WStatus;
  1667. ULONG Restored;
  1668. ULONG ToRestore;
  1669. ULONG FileOffset;
  1670. PUCHAR RestoreBuf = NULL;
  1671. PVOID RestoreContext = NULL;
  1672. DWORD BytesRead = 0;
  1673. HANDLE StageHandle = INVALID_HANDLE_VALUE;
  1674. PWCHAR StagePath = NULL;
  1675. PWCHAR TargetPath = NULL;
  1676. HANDLE TargetHandle = INVALID_HANDLE_VALUE;
  1677. STAGE_HEADER Header;
  1678. WIN32_STREAM_ID *StreamId = NULL;
  1679. DWORD RestoreStreamOffset = 0;
  1680. #if 0
  1681. typedef struct _WIN32_STREAM_ID {
  1682. DWORD dwStreamId ;
  1683. DWORD dwStreamAttributes ;
  1684. LARGE_INTEGER Size ;
  1685. DWORD dwStreamNameSize ;
  1686. WCHAR cStreamName[ ANYSIZE_ARRAY ] ;
  1687. } WIN32_STREAM_ID, *LPWIN32_STREAM_ID ;
  1688. #endif 0
  1689. //
  1690. // Check params
  1691. //
  1692. if (argc < 3 || argc > 4) {
  1693. Usage(1);
  1694. }
  1695. StagePath = Argv[2];
  1696. if (argc == 4) {
  1697. TargetPath = Argv[3];
  1698. }
  1699. printf("%ws %ws %ws %ws\n",
  1700. Argv[0],
  1701. Argv[1],
  1702. Argv[2],
  1703. (argc == 4) ? Argv[3] : L"");
  1704. //
  1705. // Open the stage file for shared, sequential reads
  1706. //
  1707. //
  1708. // Open the file
  1709. //
  1710. printf("Stage path: %ws\n", StagePath);
  1711. StageHandle = CreateFile(StagePath,
  1712. GENERIC_READ,
  1713. FILE_SHARE_READ,
  1714. NULL,
  1715. OPEN_EXISTING,
  1716. FILE_FLAG_SEQUENTIAL_SCAN |
  1717. FILE_FLAG_BACKUP_SEMANTICS,
  1718. NULL);
  1719. if (StageHandle == INVALID_HANDLE_VALUE) {
  1720. Win32ToMsg(StagePath, GetLastError());
  1721. Win32ToMsg(L"CreateFile(StagePath)", GetLastError());
  1722. goto CLEANUP;
  1723. }
  1724. //
  1725. // Read the header
  1726. //
  1727. if (!ReadFile(StageHandle,
  1728. &Header,
  1729. sizeof(STAGE_HEADER),
  1730. &BytesRead,
  1731. NULL)) {
  1732. Win32ToMsg(StagePath, GetLastError());
  1733. goto CLEANUP;
  1734. }
  1735. if (BytesRead != sizeof(STAGE_HEADER)) {
  1736. fprintf(stderr, "%ws: Read %d bytes, not %d\n",
  1737. StagePath,
  1738. BytesRead,
  1739. sizeof(STAGE_HEADER));
  1740. goto CLEANUP;
  1741. }
  1742. printf("Stage Header:\n");
  1743. printf("\tName : %ws\n", Header.ChangeOrderCommand.FileName);
  1744. printf("\tMajor : %08x\n", Header.Major);
  1745. printf("\tMinor : %08x\n", Header.Minor);
  1746. printf("\tDataHigh : %08x\n", Header.DataHigh);
  1747. printf("\tDataLow : %08x\n", Header.DataLow);
  1748. printf("\tCompression: %08x\n", Header.Compression);
  1749. printf("\tAttributes : %08x\n", Header.Attributes.FileAttributes);
  1750. //
  1751. // Don't understand this header format
  1752. //
  1753. if (Header.Major != NTFRS_MAJOR) {
  1754. fprintf(stderr, "%ws: Major %d != NtFrsMajor %d\n",
  1755. StagePath,
  1756. Header.Major,
  1757. NTFRS_MAJOR);
  1758. goto CLEANUP;
  1759. }
  1760. if (!TargetPath) {
  1761. goto CLEANUP;
  1762. }
  1763. //
  1764. // INSTALL STAGE FILE
  1765. //
  1766. //
  1767. // Open the file
  1768. //
  1769. printf("Target path: %ws\n", TargetPath);
  1770. IsDir = Header.Attributes.FileAttributes & FILE_ATTRIBUTE_DIRECTORY;
  1771. TargetHandle = CreateFile(TargetPath,
  1772. RESTORE_ACCESS,
  1773. 0,
  1774. NULL,
  1775. OPEN_ALWAYS,
  1776. OPEN_OPTIONS,
  1777. NULL);
  1778. if (TargetHandle == INVALID_HANDLE_VALUE) {
  1779. Win32ToMsg(TargetPath, GetLastError());
  1780. Win32ToMsg(L"CreateFile(TargetPath)", GetLastError());
  1781. goto CLEANUP;
  1782. }
  1783. //
  1784. // Truncate the file if not a directory
  1785. //
  1786. if (!IsDir && !SetEndOfFile(TargetHandle)) {
  1787. Win32ToMsg(TargetPath, GetLastError());
  1788. goto CLEANUP;
  1789. }
  1790. //
  1791. // Set compression mode
  1792. //
  1793. if (!FrsSetCompression(TargetPath,
  1794. TargetHandle,
  1795. Header.Compression)) {
  1796. goto CLEANUP;
  1797. }
  1798. //
  1799. // Set attributes
  1800. //
  1801. if (!FrsSetFileAttributes(TargetPath,
  1802. TargetHandle,
  1803. Header.Attributes.FileAttributes &
  1804. ~NOREPL_ATTRIBUTES)) {
  1805. goto CLEANUP;
  1806. }
  1807. //
  1808. // Seek to the first byte of data in the stage file
  1809. //
  1810. if (FrsSetFilePointer(StagePath,
  1811. StageHandle,
  1812. Header.DataHigh,
  1813. Header.DataLow) != ERROR_SUCCESS) {
  1814. goto CLEANUP;
  1815. }
  1816. FileOffset = Header.DataLow;
  1817. //
  1818. // Restore the stage file into the temporary file
  1819. //
  1820. RestoreBuf = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, IOSIZE);
  1821. do {
  1822. //
  1823. // read stage
  1824. //
  1825. printf("Reading %d bytes at %08x\n", IOSIZE, FileOffset);
  1826. if (!StuReadFile(StagePath,
  1827. StageHandle,
  1828. RestoreBuf,
  1829. IOSIZE,
  1830. &ToRestore)) {
  1831. goto CLEANUP;
  1832. }
  1833. printf("Read %d bytes at %08x\n", ToRestore, FileOffset);
  1834. FileOffset += ToRestore;
  1835. if (ToRestore == 0) {
  1836. break;
  1837. }
  1838. //
  1839. // Dump stream heads in first restore buffer
  1840. // Increase buffer size to catch all heads OR
  1841. // enhance code to remember stream head offsets
  1842. // across restore bufs.
  1843. //
  1844. if (StreamId == NULL) {
  1845. RestoreStreamOffset = 0;
  1846. while (RestoreStreamOffset < ToRestore) {
  1847. StreamId = (WIN32_STREAM_ID *)(RestoreBuf + RestoreStreamOffset);
  1848. printf("StreamId: %08x %d (%08x)\n", StreamId, RestoreStreamOffset);
  1849. printf("dwStreamId: %d\n", StreamId->dwStreamId);
  1850. printf("dwStreamAttributes: %08x\n", StreamId->dwStreamAttributes);
  1851. printf("Size High: %08x\n", StreamId->Size.HighPart);
  1852. printf("Size Low: %08x\n", StreamId->Size.LowPart);
  1853. printf("dwStreamNameSize: %d\n", StreamId->dwStreamNameSize);
  1854. RestoreStreamOffset += (sizeof(WIN32_STREAM_ID) - 4);
  1855. RestoreStreamOffset += StreamId->dwStreamNameSize;
  1856. RestoreStreamOffset += StreamId->Size.LowPart;
  1857. }
  1858. }
  1859. if (!BackupWrite(TargetHandle,
  1860. RestoreBuf,
  1861. ToRestore,
  1862. &Restored,
  1863. FALSE,
  1864. TRUE,
  1865. &RestoreContext)) {
  1866. WStatus = GetLastError();
  1867. printf("BackupWrite(%08x, %d) returned %d\n",
  1868. RestoreContext,
  1869. ToRestore,
  1870. WStatus);
  1871. if (IsDir && WStatus == ERROR_ALREADY_EXISTS) {
  1872. fprintf(stderr, "%ws: WStatus %d IGNORED; dirs and altstreams\n",
  1873. TargetPath,
  1874. WStatus);
  1875. }
  1876. //
  1877. // Uknown stream header or couldn't apply object id
  1878. //
  1879. if (WStatus == ERROR_INVALID_DATA ||
  1880. WStatus == ERROR_DUP_NAME ||
  1881. (IsDir && WStatus == ERROR_ALREADY_EXISTS)) {
  1882. //
  1883. // Seek to the next stream. Stop if there are none.
  1884. //
  1885. printf("BackupWrite() returned %d; try to seek past bad data\n", WStatus);
  1886. BackupSeek(TargetHandle,
  1887. -1,
  1888. -1,
  1889. &Low,
  1890. &High,
  1891. &RestoreContext);
  1892. if (Low == 0 && High == 0) {
  1893. printf("BackupSeek failed; abort\n");
  1894. break;
  1895. }
  1896. fprintf(stderr, "%ws: WStatus %d IGNORED; BackupSeek() okay\n",
  1897. TargetPath,
  1898. WStatus);
  1899. } else {
  1900. //
  1901. // Unknown error; abort
  1902. //
  1903. Win32ToMsg(TargetPath, GetLastError());
  1904. goto CLEANUP;
  1905. }
  1906. } else {
  1907. printf("BackupWrite(%08x, %d) okay\n", RestoreContext, ToRestore);
  1908. }
  1909. } while (TRUE);
  1910. #if 0
  1911. //
  1912. // Insure the correct object ID is on the file.
  1913. //
  1914. FRS_ASSERT(!memcmp(Header->FileObjId.ObjectId, &Coc->FileGuid, sizeof(GUID)));
  1915. bugbug("do we have to write the extend OID data here???")
  1916. WStatus = FrsGetOrSetFileObjectId(DstHandle,
  1917. Coc->FileName,
  1918. TRUE,
  1919. &Header->FileObjId);
  1920. if (WStatus == ERROR_DUP_NAME) {
  1921. DPRINT2(0, "Stealing object id for %ws; WStatus %d\n",
  1922. Coc->FileName,
  1923. WStatus);
  1924. ZeroMemory(&FileObjID, sizeof(FileObjID));
  1925. FrsUuidCreate((GUID *)(&FileObjID.ObjectId[0]));
  1926. ExistingOid = FALSE;
  1927. WStatus = ChgOrdHammerObjectId(Coc->FileName,
  1928. &Coc->FileGuid,
  1929. OBJECT_ID_LENGTH,
  1930. Coc->NewReplica->pVme,
  1931. TRUE,
  1932. NULL,
  1933. &FileObjID,
  1934. &ExistingOid);
  1935. if (WIN_SUCCESS(WStatus)) {
  1936. WStatus = FrsGetOrSetFileObjectId(DstHandle,
  1937. Coc->FileName,
  1938. TRUE,
  1939. &Header->FileObjId);
  1940. }
  1941. if (!WIN_SUCCESS(WStatus)) {
  1942. DPRINT2(0, "Retry install of %ws because of object id; WStatus %d\n",
  1943. Coc->FileName,
  1944. WStatus);
  1945. WStatus = ERROR_RETRY;
  1946. }
  1947. }
  1948. if (!WIN_SUCCESS(WStatus)) {
  1949. goto out;
  1950. }
  1951. #endif 0
  1952. //
  1953. // Set times
  1954. //
  1955. if (!FrsSetFileTime(TargetPath,
  1956. TargetHandle,
  1957. (PFILETIME)&Header.Attributes.CreationTime.QuadPart,
  1958. (PFILETIME)&Header.Attributes.LastAccessTime.QuadPart,
  1959. (PFILETIME)&Header.Attributes.LastWriteTime.QuadPart)) {
  1960. goto CLEANUP;
  1961. }
  1962. //
  1963. // Set final attributes
  1964. //
  1965. if (!FrsSetFileAttributes(TargetPath,
  1966. TargetHandle,
  1967. Header.Attributes.FileAttributes)) {
  1968. goto CLEANUP;
  1969. }
  1970. //
  1971. // Make sure all of the data is on disk. We don't want to lose
  1972. // it across reboots
  1973. //
  1974. if (!FlushFileBuffers(TargetHandle)) {
  1975. Win32ToMsg(TargetPath, GetLastError());
  1976. goto CLEANUP;
  1977. }
  1978. CLEANUP:
  1979. //
  1980. // Free up the restore context before we close TmpHandle (just in case)
  1981. //
  1982. if (RestoreContext) {
  1983. printf("Discard BackupWrite(%08x)\n", RestoreContext);
  1984. BackupWrite(TargetHandle,
  1985. NULL,
  1986. 0,
  1987. NULL,
  1988. TRUE,
  1989. TRUE,
  1990. &RestoreContext);
  1991. }
  1992. if (StageHandle && StageHandle != INVALID_HANDLE_VALUE) {
  1993. CloseHandle(StageHandle);
  1994. }
  1995. if (TargetHandle && TargetHandle != INVALID_HANDLE_VALUE) {
  1996. CloseHandle(TargetHandle);
  1997. }
  1998. FREE(RestoreBuf);
  1999. printf("Install of %ws into %ws complete\n",
  2000. StagePath,
  2001. TargetPath);
  2002. }
  2003. // ----------------
  2004. VOID _cdecl
  2005. main(
  2006. IN DWORD argc,
  2007. IN PCHAR *argv
  2008. )
  2009. /*++
  2010. Routine Description:
  2011. Process the command line.
  2012. Arguments:
  2013. argc
  2014. argv
  2015. Return Value:
  2016. Exits with 0 if everything went okay. Otherwise, 1.
  2017. --*/
  2018. {
  2019. PWCHAR *Argv;
  2020. //
  2021. // Print usage and exit
  2022. //
  2023. if (argc == 1) {
  2024. Usage(0);
  2025. }
  2026. //
  2027. // Use wide char parameters
  2028. //
  2029. Argv = ConvertArgv(argc, argv);
  2030. //
  2031. // Find the subcommand
  2032. //
  2033. if (!wcscmp(Argv[1], L"poll")) {
  2034. ProcessPoll(argc, Argv);
  2035. } else if (!_wcsicmp(Argv[1], L"promote")) {
  2036. ProcessPromote(argc, Argv);
  2037. } else if (!_wcsicmp(Argv[1], L"promoteabort")) {
  2038. ProcessPromoteAbort(argc, Argv);
  2039. } else if (!_wcsicmp(Argv[1], L"promotesysvols")) {
  2040. ProcessPromoteSysVols(argc, Argv);
  2041. } else if (!_wcsicmp(Argv[1], L"demote")) {
  2042. ProcessDemote(argc, Argv);
  2043. } else if (!_wcsicmp(Argv[1], L"demoteabort")) {
  2044. ProcessDemoteAbort(argc, Argv);
  2045. } else if (!_wcsicmp(Argv[1], L"demotesysvols")) {
  2046. ProcessDemoteSysVols(argc, Argv);
  2047. } else if (!_wcsicmp(Argv[1], L"version")) {
  2048. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_VERSION);
  2049. } else if (!_wcsicmp(Argv[1], L"sets")) {
  2050. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_SETS);
  2051. } else if (!_wcsicmp(Argv[1], L"ds")) {
  2052. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_DS);
  2053. } else if (!_wcsicmp(Argv[1], L"memory")) {
  2054. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_MEMORY);
  2055. } else if (!_wcsicmp(Argv[1], L"idtable")) {
  2056. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_IDTABLE);
  2057. } else if (!_wcsicmp(Argv[1], L"inlog")) {
  2058. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_INLOG);
  2059. } else if (!_wcsicmp(Argv[1], L"outlog")) {
  2060. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_OUTLOG);
  2061. } else if (!_wcsicmp(Argv[1], L"threads")) {
  2062. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_THREADS);
  2063. } else if (!_wcsicmp(Argv[1], L"stage")) {
  2064. ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_STAGE);
  2065. } else if (!_wcsicmp(Argv[1], L"install")) {
  2066. ProcessInstall(argc, Argv);
  2067. } else if (!_wcsicmp(Argv[1], L"restore")) {
  2068. ProcessBackupRestore(argc, Argv, NTFRSAPI_BUR_FLAGS_RESTORE);
  2069. } else if (!_wcsicmp(Argv[1], L"backup")) {
  2070. ProcessBackupRestore(argc, Argv, NTFRSAPI_BUR_FLAGS_BACKUP);
  2071. } else if (!_wcsicmp(Argv[1], L"comm")) {
  2072. // Not implemented
  2073. // ProcessComm(argc, Argv, NTFRSAPI_COMM_COMMAND_TEST);
  2074. } else {
  2075. fprintf(stderr, "Don't understand %ws\n", Argv[1]);
  2076. Usage(1);
  2077. }
  2078. exit(0);
  2079. }