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.

2605 lines
78 KiB

  1. //--------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1999, Microsoft Corporation
  4. //
  5. // File: dfsutil.cxx
  6. //
  7. //--------------------------------------------------------------------------
  8. extern "C" {
  9. #include <stdio.h>
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <shellapi.h>
  15. #include <winldap.h>
  16. #include <stdlib.h>
  17. }
  18. #include <lm.h>
  19. #include <lmdfs.h>
  20. #include <dfsfsctl.h>
  21. #include <dsgetdc.h>
  22. #include <ole2.h>
  23. #include <activeds.h>
  24. #include <dfsprefix.h>
  25. #include <DfsServerLibrary.hxx>
  26. #include <dfsmisc.h>
  27. #include "dsgetdc.h"
  28. #include "dsrole.h"
  29. #include "dfsutil.hxx"
  30. #include "dfspathname.hxx"
  31. #include "struct.hxx"
  32. #include "flush.hxx"
  33. #include "misc.hxx"
  34. #include "info.hxx"
  35. #include "messages.h"
  36. #include "dfsreparse.hxx"
  37. #include "dfswmi.h"
  38. #include "dfsroot.hxx"
  39. #define WPP_BIT_CLI_DRV 0x01
  40. #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)
  41. #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_CLI_DRV ).Level >= lvl)
  42. #define WPP_LEVEL_ERROR_FLAGS_LOGGER(lvl, error, flags) WPP_LEVEL_LOGGER(flags)
  43. #define WPP_LEVEL_ERROR_FLAGS_ENABLED(lvl, error, flags) \
  44. ((!NT_SUCCESS(error) || WPP_LEVEL_ENABLED(flags)) && WPP_CONTROL(WPP_BIT_CLI_DRV ).Level >= lvl)
  45. #include "dfsutil.tmh"
  46. UNICODE_STRING DCToUseFlatDomainName;
  47. UNICODE_STRING DCToUseDNSDomainName;
  48. LPWSTR DCToUse = NULL;
  49. DFSSTATUS DCInfoStatus = ERROR_SUCCESS;
  50. extern
  51. void
  52. SetReferralControl(WPP_CB_TYPE * Control);
  53. DFSSTATUS
  54. ProcessRootForSite(
  55. DfsRoot *pRoot );
  56. DFSSTATUS
  57. PurgeSiteInformationForRoot(
  58. DfsRoot *pRoot );
  59. DFSSTATUS
  60. DumpSiteBlob(
  61. PVOID pBuffer,
  62. ULONG Size,
  63. BOOLEAN Display );
  64. //
  65. // How we make args & switches
  66. //
  67. #define MAKEARG(x) \
  68. WCHAR Arg##x[] = L"/" L#x L":"; \
  69. LONG ArgLen##x = (sizeof(Arg##x) / sizeof(WCHAR)) - 1; \
  70. BOOLEAN fArg##x;
  71. #define SWITCH(x) \
  72. WCHAR Sw##x[] = L"/" L#x ; \
  73. BOOLEAN fSw##x;
  74. #define FMAKEARG(x) \
  75. static WCHAR Arg##x[] = L#x L":"; \
  76. static LONG ArgLen##x = (sizeof(Arg##x) / sizeof(WCHAR)) - 1; \
  77. static BOOLEAN fArg##x;
  78. #define FSWITCH(x) \
  79. static WCHAR Sw##x[] = L"/" L#x ; \
  80. static BOOLEAN fSw##x;
  81. DFSSTATUS
  82. DfsReadFromAD(
  83. LPWSTR DomainName,
  84. LPWSTR Name,
  85. LPWSTR FileName,
  86. LPWSTR UseDC );
  87. DFSSTATUS
  88. DfsReadFromFile(
  89. LPWSTR Name );
  90. LPWSTR pwszServerName = NULL;
  91. LPWSTR pwszDomainName = NULL;
  92. LPWSTR pwszEntryToFlush = NULL;
  93. LPWSTR pwszComment = NULL;
  94. LPWSTR pwszShareName = NULL;
  95. LPWSTR pwszLogicalName = NULL;
  96. LPWSTR pwszHexValue = NULL;
  97. LPWSTR ImportFile = NULL;
  98. DfsPathName OperateNameSpace;
  99. DfsPathName MasterNameSpace;
  100. DfsPathName OldDomainName;
  101. DfsPathName NewDomainName;
  102. DfsString ClientForSiteName;
  103. LPWSTR ExportBlobFile = NULL;
  104. LPWSTR DisplayBlobFile = NULL;
  105. BOOLEAN CmdRequiresDirect = FALSE;
  106. LPWSTR ExportFile = NULL;
  107. LPWSTR DebugFile = NULL;
  108. LPWSTR BackupFile = NULL;
  109. LPWSTR pwszVolumeName = NULL;
  110. LPWSTR pwszDfsDirectoryName = NULL;
  111. LPWSTR pwszDcName = NULL;
  112. DFS_API_MODE Mode = MODE_EITHER;
  113. DFSSTATUS DirectModeFailStatus = ERROR_SUCCESS;
  114. HANDLE ShowHandle= INVALID_HANDLE_VALUE;
  115. HANDLE DebugHandle= INVALID_HANDLE_VALUE;
  116. HANDLE ExportHandle= INVALID_HANDLE_VALUE;
  117. HANDLE BackupHandle = INVALID_HANDLE_VALUE;
  118. MAKEARG(RemFtRoot);
  119. SWITCH(RemFtRoot);
  120. MAKEARG(Domain);
  121. MAKEARG(Server);
  122. MAKEARG(Share);
  123. SWITCH(DisplayBlob);
  124. MAKEARG(DisplayBlob);
  125. MAKEARG(Import);
  126. SWITCH(Import); // The switch is just a cue for Help here.
  127. MAKEARG(Export);
  128. MAKEARG(Backup);
  129. SWITCH(NoBackup);
  130. SWITCH(Export);
  131. MAKEARG(Root);
  132. SWITCH(Root);
  133. MAKEARG(DebugFile);
  134. MAKEARG(OldDomain);
  135. MAKEARG(NewDomain);
  136. SWITCH(UnmapFtRoot);
  137. SWITCH(Unmap);
  138. MAKEARG(UnmapFtRoot);
  139. MAKEARG(SiteName);
  140. SWITCH(SiteName);
  141. MAKEARG(Clean);
  142. SWITCH(Clean);
  143. SWITCH(Insite);
  144. SWITCH(SiteCosting);
  145. SWITCH(RootScalability);
  146. SWITCH(ViewDfsDirs);
  147. MAKEARG(ViewDfsDirs);
  148. //MAKEARG(RemoveReparse);
  149. MAKEARG(DebugDC);
  150. SWITCH(RemoveReparse);
  151. SWITCH(DC);
  152. SWITCH(ExportBlob);
  153. MAKEARG(ExportBlob);
  154. MAKEARG(ImportRoot);
  155. SWITCH(ImportRoot);
  156. SWITCH(PurgeMupCache);
  157. SWITCH(UpdateWin2kStaticSiteTable);
  158. SWITCH(ShowWin2kStaticSiteTable);
  159. SWITCH(PurgeWin2kStaticSiteTable);
  160. SWITCH(CheckBlob);
  161. SWITCH(BlobSize);
  162. //
  163. // Switches (ie '/arg')
  164. //
  165. SWITCH(AddStdRoot);
  166. SWITCH(AddFtRoot);
  167. SWITCH(Debug);
  168. SWITCH(Verbose);
  169. SWITCH(Help);
  170. SWITCH(ScriptHelp);
  171. SWITCH(PktInfo);
  172. SWITCH(Dfs);
  173. SWITCH(All);
  174. SWITCH(Set);
  175. SWITCH(Mirror);
  176. SWITCH(RemStdRoot);
  177. SWITCH(Api);
  178. SWITCH(Compare);
  179. SWITCH(Merge);
  180. SWITCH(Direct);
  181. SWITCH(RenameFtRoot);
  182. SWITCH(View);
  183. SWITCH(Disable);
  184. SWITCH(Enable);
  185. SWITCH(Display);
  186. //
  187. // Either a switch or an arg
  188. //
  189. MAKEARG(PktFlush);
  190. SWITCH(PktFlush);
  191. MAKEARG(SpcFlush);
  192. SWITCH(SpcFlush);
  193. MAKEARG(SpcInfo);
  194. SWITCH(SpcInfo);
  195. MAKEARG(Level);
  196. //
  197. // The macro can not make these
  198. //
  199. WCHAR SwQ[] = L"/?";
  200. BOOLEAN fSwQ;
  201. ULONG AddLinks, RemoveLinks, AddTargets, RemoveTargets, ErrorLinks,
  202. DirectMode, ApiCalls, SetInfoState, SetInfoComment;
  203. ULONG TotalNamespaceCost;
  204. BOOLEAN CommandSucceeded = FALSE;
  205. BOOLEAN ErrorDisplayed = FALSE;
  206. static BOOLEAN LastOptionWasInsite = FALSE;
  207. static BOOLEAN DirectModeOnly = FALSE;
  208. static BOOLEAN UserRequiresDirectMode = FALSE;
  209. DFSSTATUS
  210. CmdInitializeDirectMode(
  211. PBOOLEAN pCoInitialized);
  212. DWORD
  213. Usage();
  214. DWORD
  215. CmdProcessUserCreds(
  216. VOID);
  217. BOOLEAN
  218. CmdProcessArg(
  219. LPWSTR Arg);
  220. DFSSTATUS
  221. CmdCheckSyntax( BOOLEAN& Done );
  222. DFSSTATUS
  223. IsRootStandalone(
  224. DfsPathName *PathComps,
  225. PBOOLEAN pIsAdBlob );
  226. DWORD
  227. IsThisADomainName(
  228. IN LPWSTR wszName,
  229. OUT PWCHAR *ppList OPTIONAL);
  230. DFSSTATUS
  231. CmdCheckExceptions( DfsPathName *Namespace );
  232. extern DFSSTATUS
  233. DfsExtendedWin2kRootAttributes(
  234. DfsPathName *Namespace,
  235. PULONG pAttr,
  236. BOOLEAN Set);
  237. DFSSTATUS
  238. GetDCInformation()
  239. {
  240. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo = NULL;
  241. DFSSTATUS Status = ERROR_SUCCESS;
  242. Status = DsRoleGetPrimaryDomainInformation( DCToUse,
  243. DsRolePrimaryDomainInfoBasic,
  244. (PBYTE *)&pPrimaryDomainInfo);
  245. if (Status != ERROR_SUCCESS)
  246. {
  247. DCInfoStatus = Status;
  248. return ERROR_SUCCESS;
  249. }
  250. if (Status == ERROR_SUCCESS)
  251. {
  252. UNICODE_STRING DomainNameFlat;
  253. Status = DfsRtlInitUnicodeStringEx( &DomainNameFlat,
  254. pPrimaryDomainInfo->DomainNameFlat);
  255. if(Status == ERROR_SUCCESS)
  256. {
  257. Status = DfsCreateUnicodeString( &DCToUseFlatDomainName,
  258. &DomainNameFlat );
  259. }
  260. if (Status == ERROR_SUCCESS)
  261. {
  262. UNICODE_STRING DomainNameDNS;
  263. Status = DfsRtlInitUnicodeStringEx( &DomainNameDNS,
  264. pPrimaryDomainInfo->DomainNameDns);
  265. if(Status == ERROR_SUCCESS)
  266. {
  267. Status = DfsCreateUnicodeString( &DCToUseDNSDomainName,
  268. &DomainNameDNS );
  269. }
  270. }
  271. DsRoleFreeMemory(pPrimaryDomainInfo);
  272. }
  273. return Status;
  274. }
  275. DFSSTATUS
  276. DfsEnumerateDomainDfs(
  277. LPWSTR Domain)
  278. {
  279. DFSSTATUS Status;
  280. PDFS_INFO_200 pBuffer = NULL, pCurBuffer;
  281. DWORD dwEntriesRead = 0;
  282. DWORD dwResumeHandle = 0;
  283. DWORD dwTotalEntries = 0;
  284. do {
  285. dwEntriesRead = 0;
  286. Status = NetDfsEnum( Domain,
  287. 200,
  288. (DWORD)-1,
  289. (LPBYTE *)&pBuffer,
  290. &dwEntriesRead,
  291. &dwResumeHandle );
  292. if (Status == ERROR_SUCCESS)
  293. {
  294. pCurBuffer = pBuffer;
  295. if (dwEntriesRead)
  296. {
  297. if (dwTotalEntries == 0) {
  298. ShowInformation((L"\nRoots on Domain %ws\n\n", Domain));
  299. }
  300. for (DWORD i=0; i<dwEntriesRead; i++)
  301. {
  302. ShowInformation((L"\t%ws\n", pCurBuffer[i].FtDfsName));
  303. dwTotalEntries++;
  304. }
  305. }
  306. }
  307. if (NULL != pBuffer)
  308. {
  309. NetApiBufferFree(pBuffer);
  310. pBuffer = NULL;
  311. }
  312. } while ( Status == ERROR_SUCCESS && dwResumeHandle != NULL );
  313. if (dwTotalEntries > 0)
  314. {
  315. ShowInformation((L"\nDone with Roots on Domain %ws\n", Domain));
  316. if (Status == ERROR_NO_MORE_ITEMS) {
  317. Status = ERROR_SUCCESS;
  318. }
  319. }
  320. else
  321. {
  322. ShowInformation((L"\n\nNo roots exist on domain %ws\n\n", Domain));
  323. }
  324. return Status;
  325. }
  326. DFSSTATUS
  327. DfsEnumerateMachineDfs(
  328. LPWSTR Server)
  329. {
  330. DFSSTATUS Status;
  331. PDFS_INFO_300 pBuffer = NULL, pCurBuffer;
  332. DWORD dwEntriesRead = 0;
  333. DWORD dwResumeHandle = 0;
  334. DWORD dwTotalEntries = 0;
  335. do {
  336. dwEntriesRead = 0;
  337. Status = NetDfsEnum( Server,
  338. 300,
  339. (DWORD)-1,
  340. (LPBYTE *)&pBuffer,
  341. &dwEntriesRead,
  342. &dwResumeHandle );
  343. if (Status == ERROR_SUCCESS)
  344. {
  345. pCurBuffer = pBuffer;
  346. if (dwEntriesRead)
  347. {
  348. if (dwTotalEntries == 0) {
  349. ShowInformation((L"\nRoots on machine %ws\n\n", Server));
  350. }
  351. for (DWORD i=0; i<dwEntriesRead; i++)
  352. {
  353. ShowInformation((L"\t%ws\n", pCurBuffer[i].DfsName));
  354. dwTotalEntries++;
  355. }
  356. }
  357. }
  358. if (NULL != pBuffer)
  359. {
  360. NetApiBufferFree(pBuffer);
  361. pBuffer = NULL;
  362. }
  363. } while ( Status == ERROR_SUCCESS && dwResumeHandle != NULL );
  364. if (dwTotalEntries > 0)
  365. {
  366. ShowInformation((L"\nDone with Roots on machine %ws\n", Server));
  367. if (Status == ERROR_NO_MORE_ITEMS) {
  368. Status = ERROR_SUCCESS;
  369. }
  370. }
  371. else
  372. {
  373. ShowInformation((L"\n\nNo roots exist on machine %ws\n\n", Server));
  374. }
  375. return Status;
  376. }
  377. _cdecl
  378. main(int argc, char *argv[])
  379. {
  380. UNREFERENCED_PARAMETER(argv);
  381. UNREFERENCED_PARAMETER(argc);
  382. DWORD dwErr = ERROR_SUCCESS;
  383. LPWSTR CommandLine;
  384. LPWSTR *argvw;
  385. int argx;
  386. int argcw;
  387. BOOLEAN CoInitialized = FALSE;
  388. BOOLEAN DirectModeInitialized = FALSE;
  389. BOOLEAN Done;
  390. WPP_CB_TYPE *pLogger = NULL;
  391. pLogger = &WPP_CB[WPP_CTRL_NO(WPP_BIT_CLI_DRV)];
  392. WPP_INIT_TRACING(L"DfsUtil");
  393. SetReferralControl(pLogger);
  394. ShowHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  395. DebugHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  396. //
  397. // Do the work
  398. //
  399. do {
  400. ErrorMessage( MSG_COPYRIGHT );
  401. if ((dwErr = DfsPrefixTableInit()) != STATUS_SUCCESS)
  402. {
  403. break;
  404. }
  405. //
  406. // Get the command line in Unicode
  407. //
  408. CommandLine = GetCommandLine();
  409. argvw = CommandLineToArgvW(CommandLine, &argcw);
  410. if ( argvw == NULL ) {
  411. DebugInformation((L"DfsUtil:Can't convert command line to Unicode: %d\r\n", GetLastError()));
  412. dwErr = GetLastError();
  413. break;
  414. }
  415. //
  416. // Get the arguments
  417. //
  418. if (argcw <= 1) {
  419. dwErr = Usage();
  420. break;
  421. }
  422. //
  423. // Process arguments. Direct mode is enabled by default.
  424. //
  425. fSwDirect = TRUE;
  426. UserRequiresDirectMode = FALSE;
  427. Done = FALSE;
  428. for (argx = 1; argx < argcw && !Done; argx++) {
  429. Done = CmdProcessArg(argvw[argx]);
  430. }
  431. if (Done) {
  432. Usage();
  433. break;
  434. }
  435. //
  436. // Some sanity checking of cmd syntax.
  437. // This also prints all appropriate error help messages.
  438. //
  439. dwErr = CmdCheckSyntax( Done );
  440. if (Done) {
  441. break;
  442. }
  443. if (fSwPktFlush == TRUE || fArgPktFlush == TRUE) {
  444. dwErr = PktFlush(pwszEntryToFlush);
  445. break;
  446. } else if (fSwSpcFlush == TRUE || fArgSpcFlush == TRUE) {
  447. dwErr = SpcFlush(pwszEntryToFlush);
  448. break;
  449. } else if (fSwPktInfo == TRUE) {
  450. dwErr = PktInfo(fSwDfs, pwszHexValue);
  451. break;
  452. } else if (fSwSpcInfo == TRUE) {
  453. dwErr = SpcInfo(fSwAll);
  454. break;
  455. }
  456. if(fArgViewDfsDirs)
  457. {
  458. BOOL fRemove = FALSE;
  459. if(fSwRemoveReparse)
  460. {
  461. fRemove =TRUE;
  462. }
  463. dwErr = CountReparsePoints(pwszVolumeName, fRemove);
  464. break;
  465. }
  466. /*
  467. BUG 736596: DeleteReparsePoint as implemented doesn't walk through
  468. all subdirectories of a given directory. In fact, it doesn't seem to work
  469. at all. We should probably address this in the longhorn timeframe.
  470. if(fArgRemoveReparse)
  471. {
  472. dwErr = DeleteReparsePoint(pwszDfsDirectoryName);
  473. break;
  474. }
  475. */
  476. if (fSwAddStdRoot == TRUE) {
  477. dwErr = CmdAddRoot(
  478. FALSE,
  479. pwszServerName,
  480. pwszShareName,
  481. pwszShareName, // Enforce RootName = Sharename
  482. pwszComment);
  483. break;
  484. }
  485. if (fSwAddFtRoot == TRUE) {
  486. dwErr = CmdAddRoot(
  487. TRUE,
  488. pwszServerName,
  489. pwszShareName,
  490. pwszShareName, // Enforce RootName = Sharename
  491. pwszComment);
  492. break;
  493. }
  494. if (fSwRemStdRoot == TRUE) {
  495. dwErr = CmdRemRoot(
  496. FALSE,
  497. pwszServerName,
  498. pwszShareName,
  499. pwszShareName); // Sharename = logicalname.
  500. break;
  501. }
  502. //
  503. // We allow users to delete roots whose logical name don't match
  504. // their physical share names for compatibility reasons.
  505. // DfsUtil itself doesn't allow people to create such roots however.
  506. //
  507. if (fArgRemFtRoot == TRUE || fSwRemFtRoot == TRUE) {
  508. dwErr = CmdRemRoot(
  509. TRUE,
  510. pwszServerName,
  511. pwszShareName,
  512. pwszLogicalName); // logical name may differ.
  513. break;
  514. }
  515. if (fSwClean) {
  516. dwErr = CmdClean( pwszServerName, pwszShareName );
  517. break;
  518. }
  519. if ((Mode == MODE_DIRECT) || (Mode == MODE_EITHER))
  520. {
  521. dwErr = CmdInitializeDirectMode( &CoInitialized);
  522. if (dwErr != ERROR_SUCCESS)
  523. {
  524. DirectModeFailStatus = dwErr;
  525. if (Mode == MODE_DIRECT)
  526. {
  527. DebugInformation((L"DfsUtil: Failed direct communication with DFS metadata, status 0x%x\n", dwErr));
  528. ErrorMessage(MSG_ROOT_DIRECT_FAILED, dwErr);
  529. break;
  530. }
  531. else if (CmdRequiresDirect == TRUE)
  532. {
  533. ErrorMessage(MSG_ROOT_DIRECT_REQUIRED_FAILED, dwErr);
  534. break;
  535. }
  536. else
  537. {
  538. Mode = MODE_API;
  539. }
  540. }
  541. else
  542. {
  543. DirectModeInitialized = TRUE;
  544. }
  545. }
  546. if (CmdRequiresDirect && (DirectModeInitialized == FALSE))
  547. {
  548. ErrorMessage(MSG_ROOT_DIRECT_REQUIRED);
  549. break;
  550. }
  551. if (fSwUpdateWin2kStaticSiteTable)
  552. {
  553. DfsRoot *pOperateRoot = NULL;
  554. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  555. DCToUse,
  556. Mode,
  557. TRUE, // site aware
  558. &pOperateRoot);
  559. if (dwErr == ERROR_SUCCESS)
  560. {
  561. dwErr = ProcessRootForSite(pOperateRoot );
  562. }
  563. if(pOperateRoot)
  564. {
  565. pOperateRoot->Close();
  566. }
  567. break;
  568. }
  569. if (fSwPurgeWin2kStaticSiteTable)
  570. {
  571. DfsRoot *pOperateRoot = NULL;
  572. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  573. DCToUse,
  574. Mode,
  575. FALSE,
  576. &pOperateRoot);
  577. if (dwErr == ERROR_SUCCESS)
  578. {
  579. dwErr = PurgeSiteInformationForRoot(pOperateRoot );
  580. }
  581. if(pOperateRoot)
  582. {
  583. pOperateRoot->Close();
  584. }
  585. break;
  586. }
  587. if (fSwShowWin2kStaticSiteTable)
  588. {
  589. DfsRoot *pOperateRoot = NULL;
  590. PVOID pBuffer = NULL;
  591. ULONG Size = 0;
  592. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  593. DCToUse,
  594. Mode,
  595. FALSE,
  596. &pOperateRoot);
  597. if (dwErr == ERROR_SUCCESS)
  598. {
  599. dwErr = pOperateRoot->RootGetSiteBlob(&pBuffer, &Size);
  600. }
  601. if (dwErr == ERROR_SUCCESS)
  602. {
  603. dwErr = DumpSiteBlob((PVOID)pBuffer, Size, TRUE);
  604. }
  605. if(pOperateRoot)
  606. {
  607. pOperateRoot->Close();
  608. }
  609. break;
  610. }
  611. //
  612. // Importing a namespace from a script file.
  613. //
  614. if (fArgImport) {
  615. DfsRoot *pMasterRoot;
  616. DfsRoot *pOperateRoot;
  617. dwErr = DfsReadDocument( ImportFile,
  618. &pMasterRoot );
  619. if (dwErr == ERROR_SUCCESS)
  620. {
  621. if (fSwBlobSize)
  622. {
  623. ULONG RootBlobSize = 0;
  624. extern DFSSTATUS SizeRoot(DfsRoot *pRoot, PULONG pSize);
  625. dwErr = SizeRoot(pMasterRoot, &RootBlobSize);
  626. if (dwErr == ERROR_SUCCESS)
  627. {
  628. ShowInformation((L"\n\nApproximate blob size for import file is %.2f Megabytes\n\n",
  629. (DOUBLE)RootBlobSize / (1024 * 1024)));
  630. }
  631. }
  632. else if (fSwView)
  633. {
  634. DumpRoots(pMasterRoot, ShowHandle, FALSE);
  635. }
  636. else
  637. {
  638. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  639. DCToUse,
  640. Mode,
  641. FALSE,
  642. &pOperateRoot );
  643. if (dwErr == ERROR_SUCCESS)
  644. {
  645. //
  646. // Iterate over the (real) options.
  647. //
  648. if (fSwCompare)
  649. {
  650. VerifyDfsRoots(pOperateRoot, pMasterRoot);
  651. }
  652. else if (fSwSet)
  653. {
  654. dwErr = SetDfsRoots(pOperateRoot, pMasterRoot, BackupHandle, fSwNoBackup);
  655. }
  656. else if (fSwMerge)
  657. {
  658. dwErr = MergeDfsRoots( pOperateRoot, pMasterRoot, BackupHandle, fSwNoBackup);
  659. }
  660. pOperateRoot->Close();
  661. }
  662. }
  663. pMasterRoot->Close();
  664. }
  665. break;
  666. }
  667. else if (fArgImportRoot)
  668. {
  669. DfsRoot *pMasterRoot;
  670. DfsRoot *pOperateRoot;
  671. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  672. DCToUse,
  673. Mode,
  674. FALSE,
  675. &pOperateRoot );
  676. if (dwErr == ERROR_SUCCESS)
  677. {
  678. dwErr = DfsBuildNameSpaceInformation( &MasterNameSpace,
  679. DCToUse,
  680. Mode,
  681. FALSE,
  682. &pMasterRoot );
  683. if ((dwErr == ERROR_SUCCESS) &&
  684. (fSwVerbose == TRUE))
  685. {
  686. DumpRoots( pMasterRoot, ShowHandle, FALSE);
  687. }
  688. if (dwErr == ERROR_SUCCESS)
  689. {
  690. //
  691. // Iterate over the (real) options.
  692. //
  693. if (fSwCompare)
  694. {
  695. VerifyDfsRoots(pOperateRoot, pMasterRoot);
  696. }
  697. else if (fSwMirror)
  698. {
  699. dwErr = SetDfsRoots(pOperateRoot, pMasterRoot, BackupHandle, fSwNoBackup);
  700. }
  701. pMasterRoot->Close();
  702. }
  703. pOperateRoot->Close();
  704. }
  705. break;
  706. }
  707. else if (fArgDisplayBlob)
  708. {
  709. dwErr = DfsReadFromFile( DisplayBlobFile );
  710. break;
  711. }
  712. else if (fArgExportBlob)
  713. {
  714. dwErr = DfsReadFromAD( OperateNameSpace.GetServerString(),
  715. OperateNameSpace.GetShareString(),
  716. ExportBlobFile,
  717. DCToUse);
  718. break;
  719. }
  720. else if (fSwCheckBlob)
  721. {
  722. dwErr = DfsReadFromAD( OperateNameSpace.GetServerString(),
  723. OperateNameSpace.GetShareString(),
  724. NULL,
  725. DCToUse);
  726. break;
  727. }
  728. else if (fSwView)
  729. {
  730. if (fArgDomain)
  731. {
  732. dwErr = DfsEnumerateDomainDfs(pwszDomainName);
  733. }
  734. else if (fArgServer)
  735. {
  736. dwErr = DfsEnumerateMachineDfs(pwszServerName);
  737. }
  738. else
  739. {
  740. DfsRoot *pOperateRoot;
  741. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  742. DCToUse,
  743. Mode,
  744. TRUE,
  745. &pOperateRoot );
  746. if (dwErr == ERROR_SUCCESS)
  747. {
  748. dwErr = DumpRoots( pOperateRoot, ShowHandle, FALSE);
  749. pOperateRoot->Close();
  750. }
  751. }
  752. break;
  753. }
  754. else if (fArgExport)
  755. {
  756. DfsRoot *pOperateRoot;
  757. dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace,
  758. DCToUse,
  759. Mode,
  760. FALSE,
  761. &pOperateRoot );
  762. if (dwErr == ERROR_SUCCESS)
  763. {
  764. dwErr = DumpRoots( pOperateRoot, ExportHandle, TRUE);
  765. pOperateRoot->Close();
  766. }
  767. break;
  768. }
  769. if (fSwRenameFtRoot) {
  770. PVOID DirectModeHandle = NULL;
  771. dwErr = DfsDirectApiOpen( OperateNameSpace.GetPathString(),
  772. DCToUse,
  773. &DirectModeHandle);
  774. if (dwErr == ERROR_SUCCESS)
  775. {
  776. //
  777. // Now do the rename. Note that we only use the first component.
  778. // If users enter /olddomain:\\xx.y.com\z we simply use xx.y.com without
  779. // the \\ or the sharename.
  780. //
  781. dwErr = DfsRenameLinksToDomain( &OperateNameSpace,
  782. OldDomainName.GetServerString(),
  783. NewDomainName.GetServerString());
  784. if (dwErr == ERROR_SUCCESS)
  785. {
  786. SetDirectHandleWriteable(DirectModeHandle);
  787. dwErr = DfsDirectApiCommitChanges( DirectModeHandle);
  788. }
  789. DfsDirectApiClose( DirectModeHandle);
  790. }
  791. break;
  792. }
  793. if (fSwUnmapFtRoot) {
  794. dwErr = CmdUnmapRootReplica( OperateNameSpace.GetPathString(),
  795. pwszServerName,
  796. pwszShareName );
  797. break;
  798. }
  799. if (fArgSiteName)
  800. {
  801. DfsString Site;
  802. dwErr = GetSites( ClientForSiteName.GetString(),
  803. &Site );
  804. if (dwErr == ERROR_SUCCESS)
  805. {
  806. ShowInformation((L"\n\nSite for %wS is %wS\n\n",
  807. ClientForSiteName.GetString(),
  808. Site.GetString()));
  809. }
  810. break;
  811. }
  812. if (fSwInsite || fSwSiteCosting || fSwRootScalability)
  813. {
  814. PVOID DirectModeHandle = NULL;
  815. ULONG Attrib = 0;
  816. ULONG AttribMask = 0;
  817. LPWSTR AttribString;
  818. if (fSwInsite)
  819. {
  820. AttribMask = PKT_ENTRY_TYPE_INSITE_ONLY;
  821. AttribString = L"InSite Referrals";
  822. }
  823. else if (fSwSiteCosting)
  824. {
  825. AttribMask = PKT_ENTRY_TYPE_COST_BASED_SITE_SELECTION;
  826. AttribString = L"Cost-based Site Selection";
  827. }
  828. else
  829. {
  830. AttribMask = PKT_ENTRY_TYPE_ROOT_SCALABILITY;
  831. AttribString = L"Root Scalability";
  832. }
  833. dwErr = DfsDirectApiOpen( OperateNameSpace.GetPathString(),
  834. DCToUse,
  835. &DirectModeHandle);
  836. if (dwErr == ERROR_SUCCESS)
  837. {
  838. dwErr = DfsExtendedRootAttributes( DirectModeHandle,
  839. &Attrib,
  840. OperateNameSpace.GetRemainingCountedString(),
  841. FALSE );
  842. if (dwErr == ERROR_SUCCESS) {
  843. if (fSwDisplay) {
  844. MyPrintf(L"Namespace %ws: %ws %ws\n",
  845. OperateNameSpace.GetPathString(),
  846. AttribString,
  847. ((Attrib & AttribMask) == AttribMask) ? L"ENABLED" : L"DISABLED");
  848. } else {
  849. SetDirectHandleWriteable(DirectModeHandle);
  850. if (fSwEnable) Attrib |= AttribMask;
  851. else Attrib &= ~AttribMask;
  852. dwErr = DfsExtendedRootAttributes( DirectModeHandle,
  853. &Attrib,
  854. OperateNameSpace.GetRemainingCountedString(),
  855. TRUE );
  856. if (dwErr == ERROR_SUCCESS)
  857. {
  858. dwErr = DfsDirectApiCommitChanges( DirectModeHandle);
  859. }
  860. if (dwErr == ERROR_SUCCESS)
  861. {
  862. (VOID) ReSynchronizeRootTargetsFromPath(&OperateNameSpace);
  863. }
  864. }
  865. }
  866. DfsDirectApiClose( DirectModeHandle);
  867. }
  868. else if (fSwInsite)
  869. {
  870. DWORD PrevErr = dwErr; // Save this error in case of failure
  871. DebugInformation((L"Failure getting Windows .Net ExtendedAttributes for %wZ, Status 0x%x\n",
  872. OperateNameSpace.GetPathCountedString(), dwErr));
  873. // Get the existing attrs. The root name will have to match although it's win2k.
  874. dwErr = DfsExtendedWin2kRootAttributes( &OperateNameSpace, &Attrib, FALSE );
  875. if (dwErr == ERROR_SUCCESS)
  876. {
  877. if (fSwDisplay) {
  878. MyPrintf(L"Namespace %ws: %ws %ws\n",
  879. OperateNameSpace.GetPathString(),
  880. AttribString,
  881. ((Attrib & AttribMask) == AttribMask) ? L"ENABLED" : L"DISABLED");
  882. }
  883. else
  884. {
  885. if (fSwEnable) Attrib |= AttribMask;
  886. else Attrib &= ~AttribMask;
  887. // Set or reset this attr.
  888. dwErr = DfsExtendedWin2kRootAttributes( &OperateNameSpace, &Attrib, TRUE );
  889. }
  890. }
  891. //
  892. // If we couldn't find a win2k root by this name, then return the original error.
  893. //
  894. if (dwErr != ERROR_SUCCESS)
  895. {
  896. dwErr = PrevErr;
  897. }
  898. }
  899. break;
  900. }
  901. if (fSwPurgeMupCache) {
  902. dwErr = PurgeMupCache(NULL);
  903. break;
  904. }
  905. dwErr = Usage();
  906. } while( FALSE );
  907. if (CoInitialized)
  908. {
  909. CoUninitialize();
  910. }
  911. if (dwErr == ERROR_SUCCESS) {
  912. if (CommandSucceeded) {
  913. ErrorMessage( MSG_SUCCESSFUL );
  914. } else {
  915. ErrorMessage( MSG_COMMAND_DONE );
  916. }
  917. } else {
  918. LPWSTR MessageBuffer;
  919. DWORD dwBufferLength;
  920. dwBufferLength = FormatMessage(
  921. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  922. NULL,
  923. dwErr,
  924. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  925. (LPWSTR) &MessageBuffer,
  926. 0,
  927. NULL);
  928. ErrorMessage(MSG_ERROR, dwErr);
  929. if (dwBufferLength > 0) {
  930. MyPrintf(L"%ws\r\n", MessageBuffer);
  931. LocalFree(MessageBuffer);
  932. }
  933. ErrorMessage( MSG_COMMAND_DONE );
  934. }
  935. WPP_CLEANUP();
  936. return dwErr;
  937. }
  938. //
  939. // This is a laborious function that checks the current
  940. // argument for a match. DfsDbgPrints here are just
  941. // examples of random optimism: the /Verbose option has to
  942. // come before the current argument in order for those
  943. // lines to get printed.
  944. //
  945. BOOLEAN
  946. CmdProcessArg(LPWSTR Arg)
  947. {
  948. LONG ArgLen;
  949. BOOLEAN Terminate = FALSE;
  950. BOOLEAN FoundAnArg = FALSE;
  951. DFSSTATUS Status = ERROR_SUCCESS;
  952. if ( Arg != NULL && wcslen(Arg) > 1) {
  953. Terminate = FALSE;
  954. ArgLen = wcslen(Arg);
  955. if (_wcsnicmp(Arg, ArgRemFtRoot, ArgLenRemFtRoot) == 0) {
  956. FoundAnArg = fArgRemFtRoot = TRUE;
  957. if (ArgLen > ArgLenRemFtRoot)
  958. pwszLogicalName = &Arg[ArgLenRemFtRoot];
  959. } else if (_wcsnicmp(Arg, ArgShare, ArgLenShare) == 0) {
  960. FoundAnArg = fArgShare = TRUE;
  961. if (ArgLen > ArgLenShare)
  962. pwszShareName = &Arg[ArgLenShare];
  963. if (pwszLogicalName == NULL)
  964. pwszLogicalName = pwszShareName;
  965. } else if (_wcsnicmp(Arg, ArgServer, ArgLenServer) == 0) {
  966. FoundAnArg = fArgServer = TRUE;
  967. if (ArgLen > ArgLenServer)
  968. pwszServerName = &Arg[ArgLenServer];
  969. } else if (_wcsnicmp(Arg, ArgDomain, ArgLenDomain) == 0) {
  970. FoundAnArg = fArgDomain = TRUE;
  971. if (ArgLen > ArgLenDomain)
  972. pwszDomainName = &Arg[ArgLenDomain];
  973. } else if (_wcsnicmp(Arg, ArgPktFlush, ArgLenPktFlush) == 0) {
  974. FoundAnArg = fArgPktFlush = TRUE;
  975. if (ArgLen > ArgLenPktFlush)
  976. pwszEntryToFlush = &Arg[ArgLenPktFlush];
  977. } else if (_wcsnicmp(Arg, ArgSpcFlush, ArgLenSpcFlush) == 0) {
  978. FoundAnArg = fArgSpcFlush = TRUE;
  979. if (ArgLen > ArgLenSpcFlush)
  980. pwszEntryToFlush = &Arg[ArgLenSpcFlush];
  981. } else if (_wcsnicmp(Arg, ArgLevel, ArgLenLevel) == 0) {
  982. FoundAnArg = fArgLevel = TRUE;
  983. if (ArgLen > ArgLenLevel)
  984. pwszHexValue = &Arg[ArgLenLevel];
  985. }
  986. //
  987. // DfsAdmin options
  988. //
  989. else if (_wcsnicmp(Arg, ArgImport, ArgLenImport) == 0)
  990. {
  991. FoundAnArg = fArgImport = TRUE;
  992. ImportFile = &Arg[ArgLenImport];
  993. if (wcslen(ImportFile) == 0)
  994. {
  995. ErrorMessage( MSG_USAGE_IMPORT );
  996. Terminate = TRUE;
  997. ImportFile = NULL;
  998. }
  999. }
  1000. else if (_wcsnicmp(Arg, ArgDisplayBlob, ArgLenDisplayBlob) == 0)
  1001. {
  1002. FoundAnArg = fArgDisplayBlob = TRUE;
  1003. DisplayBlobFile = &Arg[ArgLenDisplayBlob];
  1004. if (wcslen(DisplayBlobFile) == 0)
  1005. {
  1006. ErrorMessage( MSG_USAGE_DISPLAY_BLOB );
  1007. Terminate = TRUE;
  1008. ImportFile = NULL;
  1009. }
  1010. }
  1011. else if (_wcsnicmp(Arg, ArgExportBlob, ArgLenExportBlob) == 0)
  1012. {
  1013. FoundAnArg = fArgExportBlob = TRUE;
  1014. ExportBlobFile = &Arg[ArgLenExportBlob];
  1015. if (wcslen(ExportBlobFile)==0)
  1016. {
  1017. ErrorMessage( MSG_USAGE_EXPORT_BLOB );
  1018. Terminate = TRUE;
  1019. ExportBlobFile = NULL;
  1020. }
  1021. }
  1022. else if (_wcsnicmp(Arg, ArgExport, ArgLenExport) == 0)
  1023. {
  1024. FoundAnArg = fArgExport = TRUE;
  1025. ExportFile = &Arg[ArgLenExport];
  1026. if (wcslen(ExportFile) == 0)
  1027. {
  1028. ErrorMessage( MSG_USAGE_EXPORT );
  1029. Terminate = TRUE;
  1030. ExportFile = NULL;
  1031. }
  1032. else
  1033. {
  1034. Status = CreateDfsFile(ExportFile, &ExportHandle);
  1035. }
  1036. }
  1037. else if (_wcsnicmp(Arg, ArgBackup, ArgLenBackup) == 0)
  1038. {
  1039. FoundAnArg = fArgBackup = TRUE;
  1040. BackupFile = &Arg[ArgLenBackup];
  1041. if (wcslen(BackupFile) == 0)
  1042. {
  1043. ErrorMessage( MSG_USAGE_EXPORT );
  1044. Terminate = TRUE;
  1045. BackupFile = NULL;
  1046. }
  1047. else
  1048. {
  1049. Status = CreateDfsFile(BackupFile, &BackupHandle);
  1050. }
  1051. }
  1052. else if (_wcsnicmp(Arg, ArgDebugDC, ArgLenDebugDC) == 0)
  1053. {
  1054. FoundAnArg = fArgDebugDC = TRUE;
  1055. DCToUse = &Arg[ArgLenDebugDC];
  1056. Status = GetDCInformation();
  1057. Mode = MODE_DIRECT;
  1058. }
  1059. else if (_wcsnicmp(Arg, ArgRoot, ArgLenRoot) == 0)
  1060. {
  1061. FoundAnArg = fArgRoot = TRUE;
  1062. Status = OperateNameSpace.CreatePathName(&Arg[ArgLenRoot]);
  1063. }
  1064. else if (_wcsnicmp(Arg, ArgImportRoot, ArgLenImportRoot) == 0)
  1065. {
  1066. FoundAnArg = fArgImportRoot = TRUE;
  1067. Status = MasterNameSpace.CreatePathName(&Arg[ArgLenImportRoot]);
  1068. }
  1069. else if (_wcsnicmp(Arg, ArgDebugFile, ArgLenDebugFile) == 0)
  1070. {
  1071. FoundAnArg = fArgDebugFile = TRUE;
  1072. DebugFile = &Arg[ArgLenDebugFile];
  1073. if (wcslen(DebugFile) == 0)
  1074. {
  1075. //Status = ERROR_INVALID_PARAMETER;
  1076. Terminate = TRUE;
  1077. DebugFile = NULL;
  1078. }
  1079. else {
  1080. Status = CreateDfsFile(DebugFile, &DebugHandle);
  1081. }
  1082. }
  1083. else if (_wcsnicmp(Arg, ArgOldDomain, ArgLenOldDomain) == 0)
  1084. {
  1085. FoundAnArg = fArgOldDomain = TRUE;
  1086. Status = OldDomainName.CreatePathName( &Arg[ArgLenOldDomain] );
  1087. }
  1088. else if (_wcsnicmp(Arg, ArgNewDomain, ArgLenNewDomain) == 0)
  1089. {
  1090. FoundAnArg = fArgNewDomain = TRUE;
  1091. Status = NewDomainName.CreatePathName( &Arg[ArgLenNewDomain] );
  1092. }
  1093. else if (_wcsnicmp(Arg, ArgUnmapFtRoot, ArgLenUnmapFtRoot) == 0)
  1094. {
  1095. FoundAnArg = fArgUnmapFtRoot = TRUE;
  1096. }
  1097. else if (_wcsnicmp(Arg, ArgViewDfsDirs, ArgLenViewDfsDirs) == 0) {
  1098. FoundAnArg = fArgViewDfsDirs = TRUE;
  1099. pwszVolumeName = &Arg[ArgLenViewDfsDirs];
  1100. }/*
  1101. else if (_wcsnicmp(Arg, ArgRemoveReparse, ArgLenRemoveReparse) == 0) {
  1102. FoundAnArg = fArgRemoveReparse = TRUE;
  1103. pwszDfsDirectoryName = &Arg[ArgLenRemoveReparse];
  1104. }*/
  1105. else if (_wcsnicmp(Arg, ArgSiteName, ArgLenSiteName) == 0)
  1106. {
  1107. FoundAnArg = fArgSiteName = TRUE;
  1108. Status = ClientForSiteName.CreateString(&Arg[ArgLenSiteName]);
  1109. }
  1110. // Switches go at the end!!
  1111. else if (_wcsicmp(Arg, SwDebug) == 0) {
  1112. FoundAnArg = fSwDebug = TRUE;
  1113. }
  1114. else if (_wcsicmp(Arg, SwNoBackup) == 0) {
  1115. FoundAnArg = fSwNoBackup = TRUE;
  1116. } else if (_wcsicmp(Arg, SwVerbose) == 0) {
  1117. FoundAnArg = fSwVerbose = TRUE;
  1118. } else if (_wcsicmp(Arg, SwPktFlush) == 0) {
  1119. FoundAnArg = fSwPktFlush = TRUE;
  1120. } else if (_wcsicmp(Arg, SwSpcFlush) == 0) {
  1121. FoundAnArg = fSwSpcFlush = TRUE;
  1122. } else if (_wcsicmp(Arg, SwPktInfo) == 0) {
  1123. FoundAnArg = fSwPktInfo = TRUE;
  1124. } else if (_wcsicmp(Arg, SwSpcInfo) == 0) {
  1125. FoundAnArg = fSwSpcInfo = TRUE;
  1126. } else if (_wcsicmp(Arg, SwDfs) == 0) {
  1127. FoundAnArg = fSwDfs = TRUE;
  1128. } else if (_wcsicmp(Arg, SwAll) == 0) {
  1129. FoundAnArg = fSwSpcInfo = TRUE;
  1130. } else if (_wcsicmp(Arg, SwQ) == 0) {
  1131. FoundAnArg = fSwQ = fSwHelp = TRUE;
  1132. } else if (_wcsicmp(Arg, SwScriptHelp) == 0) {
  1133. FoundAnArg = fSwScriptHelp = TRUE;
  1134. } else if (_wcsicmp(Arg, SwHelp) == 0) {
  1135. FoundAnArg = fSwHelp = TRUE;
  1136. } else if (_wcsicmp(Arg, SwSet) == 0) {
  1137. FoundAnArg = fSwSet = TRUE;
  1138. } else if (_wcsicmp(Arg, SwMirror) == 0) {
  1139. FoundAnArg = fSwMirror = TRUE;
  1140. } else if (_wcsicmp(Arg, SwRemStdRoot) == 0) {
  1141. FoundAnArg = fSwRemStdRoot = TRUE;
  1142. } else if (_wcsicmp(Arg, SwRemFtRoot) == 0) {
  1143. FoundAnArg = fSwRemFtRoot = TRUE;
  1144. } else if (_wcsicmp(Arg, SwCompare) == 0) {
  1145. FoundAnArg = fSwCompare = TRUE;
  1146. } else if (_wcsicmp(Arg, SwCheckBlob) == 0) {
  1147. FoundAnArg = fSwCheckBlob = TRUE;
  1148. } else if (_wcsicmp(Arg, SwMerge) == 0) {
  1149. FoundAnArg = fSwMerge = TRUE;
  1150. } else if (_wcsicmp(Arg, SwRenameFtRoot) == 0) {
  1151. FoundAnArg = fSwRenameFtRoot = TRUE;
  1152. CmdRequiresDirect = TRUE;
  1153. } else if (_wcsicmp(Arg, SwDirect) == 0) {
  1154. //
  1155. // This is switched on by default when appropriate.
  1156. // If the user specifies this then it means that
  1157. // she only wants to operate in Direct mode.
  1158. //
  1159. FoundAnArg = TRUE;
  1160. fSwDirect = TRUE;
  1161. UserRequiresDirectMode = TRUE;
  1162. Mode = MODE_DIRECT;
  1163. } else if (_wcsicmp(Arg, SwView) == 0) {
  1164. FoundAnArg = fSwView = TRUE;
  1165. ExportHandle = ShowHandle;
  1166. } else if (_wcsicmp(Arg, SwImport) == 0) {
  1167. FoundAnArg = fSwImport = TRUE;
  1168. } else if (_wcsicmp(Arg, SwImportRoot) == 0) {
  1169. FoundAnArg = fSwImportRoot = TRUE;
  1170. } else if (_wcsicmp(Arg, SwBlobSize) == 0) {
  1171. FoundAnArg = fSwBlobSize = TRUE;
  1172. } else if (_wcsicmp(Arg, SwSiteName) == 0) {
  1173. FoundAnArg = fSwSiteName = TRUE;
  1174. } else if (_wcsicmp(Arg, SwExport) == 0) {
  1175. FoundAnArg = fSwExport = TRUE;
  1176. } else if (_wcsicmp(Arg, SwRoot) == 0) {
  1177. FoundAnArg = fSwRoot = TRUE;
  1178. } else if ((_wcsicmp(Arg, SwUnmapFtRoot) == 0) ||
  1179. (_wcsicmp(Arg, SwUnmap) == 0)) {
  1180. FoundAnArg = fSwUnmapFtRoot = TRUE;
  1181. CmdRequiresDirect = TRUE;
  1182. } else if (_wcsicmp(Arg, SwClean) == 0) {
  1183. //
  1184. // This contacts the target registry directly but doesn't involve a
  1185. // direct mode to do so.
  1186. //
  1187. FoundAnArg = fSwClean = TRUE;
  1188. } else if (_wcsicmp(Arg, SwEnable) == 0) {
  1189. FoundAnArg = fSwEnable = TRUE;
  1190. } else if (_wcsicmp(Arg, SwDisable) == 0) {
  1191. FoundAnArg = fSwDisable = TRUE;
  1192. } else if (_wcsicmp(Arg, SwDisplay) == 0) {
  1193. FoundAnArg = fSwDisplay = TRUE;
  1194. } else if (_wcsicmp(Arg, SwInsite) == 0) {
  1195. FoundAnArg = fSwInsite = TRUE;
  1196. CmdRequiresDirect = TRUE;
  1197. } else if (_wcsicmp(Arg, SwAddStdRoot) == 0) {
  1198. FoundAnArg = fSwAddStdRoot = TRUE;
  1199. } else if (_wcsicmp(Arg, SwAddFtRoot) == 0) {
  1200. FoundAnArg = fSwAddFtRoot = TRUE;
  1201. } else if (_wcsicmp(Arg, SwApi) == 0) {
  1202. FoundAnArg = fSwApi = TRUE;
  1203. Mode = MODE_API;
  1204. } else if (_wcsicmp(Arg, SwRemoveReparse) == 0) {
  1205. FoundAnArg = fSwRemoveReparse = TRUE;
  1206. } else if (_wcsicmp(Arg, SwSiteCosting) == 0) {
  1207. FoundAnArg = fSwSiteCosting = TRUE;
  1208. CmdRequiresDirect = TRUE;
  1209. } else if (_wcsicmp(Arg, SwRootScalability) == 0) {
  1210. FoundAnArg = fSwRootScalability = TRUE;
  1211. CmdRequiresDirect = TRUE;
  1212. } else if (_wcsicmp(Arg, SwPurgeMupCache) == 0) {
  1213. FoundAnArg = fSwPurgeMupCache = TRUE;
  1214. }
  1215. else if (_wcsicmp(Arg, SwUpdateWin2kStaticSiteTable) == 0) {
  1216. FoundAnArg = fSwUpdateWin2kStaticSiteTable = TRUE;
  1217. CmdRequiresDirect = TRUE;
  1218. }
  1219. else if (_wcsicmp(Arg, SwShowWin2kStaticSiteTable) == 0) {
  1220. FoundAnArg = fSwShowWin2kStaticSiteTable = TRUE;
  1221. CmdRequiresDirect = TRUE;
  1222. }
  1223. else if (_wcsicmp(Arg, SwPurgeWin2kStaticSiteTable) == 0) {
  1224. FoundAnArg = fSwPurgeWin2kStaticSiteTable = TRUE;
  1225. CmdRequiresDirect = TRUE;
  1226. }
  1227. else if (_wcsicmp(Arg, SwViewDfsDirs) == 0) {
  1228. FoundAnArg = fSwViewDfsDirs = TRUE;
  1229. }
  1230. else if (_wcsicmp(Arg, SwDisplayBlob) == 0) {
  1231. FoundAnArg = fSwDisplayBlob = TRUE;
  1232. }
  1233. else if (_wcsicmp(Arg, SwExportBlob) == 0) {
  1234. FoundAnArg = fSwExportBlob = TRUE;
  1235. }
  1236. //
  1237. // Done processing Arguments and Switches.
  1238. // Decide whether to terminate or not.
  1239. //
  1240. if (FoundAnArg == FALSE) {
  1241. ErrorMessage(MSG_UNRECOGNIZED_OPTION, &Arg[1]);
  1242. Terminate = TRUE;
  1243. }
  1244. if (Status != ERROR_SUCCESS)
  1245. {
  1246. ErrorMessage(MSG_ERROR, Status);
  1247. Terminate = TRUE;
  1248. }
  1249. }
  1250. return Terminate;
  1251. }
  1252. DWORD
  1253. Usage()
  1254. {
  1255. ErrorMessage(MSG_USAGE);
  1256. return ERROR_SUCCESS;
  1257. }
  1258. DFSSTATUS
  1259. CmdCheckSyntax( BOOLEAN& Done )
  1260. {
  1261. // the following require a namespace to work with
  1262. // BlobSize cmd works without a root.
  1263. #define REQUIRES_ROOT_NAME (fArgExport || fSwRenameFtRoot || fSwInsite || fSwMirror || \
  1264. (fArgImport && !fSwBlobSize) || \
  1265. fSwSiteCosting || fArgDebugDC || \
  1266. fArgImportRoot || fSwRootScalability || \
  1267. fArgExportBlob || fSwCheckBlob)
  1268. DFSSTATUS dwErr = ERROR_SUCCESS;
  1269. Done = FALSE;
  1270. do {
  1271. if ((fSwHelp == TRUE) ||
  1272. ((OperateNameSpace.IsEmptyPath() == TRUE) && (REQUIRES_ROOT_NAME) ))
  1273. {
  1274. if (fArgImport || fSwImport || fSwBlobSize) {
  1275. ErrorMessage( MSG_USAGE_IMPORT );
  1276. } else if (fArgExport || fSwExport) {
  1277. ErrorMessage( MSG_USAGE_EXPORT );
  1278. } else if (fSwRenameFtRoot) {
  1279. ErrorMessage( MSG_USAGE_RENAME );
  1280. } else if (fSwUnmapFtRoot) {
  1281. ErrorMessage( MSG_USAGE_UNMAP );
  1282. } else if (fSwClean) {
  1283. ErrorMessage( MSG_USAGE_CLEAN );
  1284. } else if (fSwInsite) {
  1285. ErrorMessage( MSG_USAGE_INSITE );
  1286. } else if (fSwSiteCosting) {
  1287. ErrorMessage( MSG_USAGE_SITECOSTING );
  1288. } else if (fSwAddFtRoot || fSwAddStdRoot) {
  1289. ErrorMessage( MSG_USAGE_ADDROOT );
  1290. } else if (fSwRemFtRoot || fArgRemFtRoot) {
  1291. ErrorMessage( MSG_USAGE_REM_FTROOT );
  1292. } else if (fSwRemStdRoot) {
  1293. ErrorMessage( MSG_USAGE_REM_STDROOT );
  1294. } else if (fArgSiteName || fSwSiteName) {
  1295. ErrorMessage( MSG_USAGE_SITENAME );
  1296. } else if (fSwView) {
  1297. ErrorMessage( MSG_USAGE_VIEW );
  1298. } else if (fArgImportRoot || fSwImportRoot) {
  1299. ErrorMessage( MSG_USAGE_IMPORT_ROOT);
  1300. } else if (fSwCheckBlob) {
  1301. ErrorMessage( MSG_USAGE_CHECK_BLOB );
  1302. } else if (fSwExportBlob || fArgExportBlob) {
  1303. ErrorMessage( MSG_USAGE_EXPORT_BLOB );
  1304. } else if (fSwDisplayBlob || fArgDisplayBlob) {
  1305. ErrorMessage( MSG_USAGE_DISPLAY_BLOB );
  1306. } else if (fSwRootScalability) {
  1307. ErrorMessage( MSG_USAGE_ROOT_SCALABILITY );
  1308. } else if (fSwViewDfsDirs || fArgViewDfsDirs) {
  1309. ErrorMessage( MSG_USAGE_VIEW_DIRS );
  1310. } else if (fSwRemoveReparse) {
  1311. ErrorMessage( MSG_USAGE_VIEW_DIRS );
  1312. } else if (fSwPurgeMupCache) {
  1313. ErrorMessage( MSG_USAGE_PURGE_MUP_CACHE );
  1314. } else if (fSwUpdateWin2kStaticSiteTable ||
  1315. fSwPurgeWin2kStaticSiteTable ||
  1316. fSwShowWin2kStaticSiteTable) {
  1317. ErrorMessage( MSG_USAGE_W2K_SITETABLE );
  1318. } else if (fSwPktInfo) {
  1319. ErrorMessage( MSG_USAGE_PKT_INFO );
  1320. } else if (fSwPktFlush) {
  1321. ErrorMessage( MSG_USAGE_PKT_FLUSH );
  1322. } else if (fSwSpcInfo) {
  1323. ErrorMessage( MSG_USAGE_SPC_INFO );
  1324. } else if (fSwSpcFlush) {
  1325. ErrorMessage( MSG_USAGE_SPC_FLUSH );
  1326. } else {
  1327. dwErr = Usage();
  1328. }
  1329. Done = TRUE;
  1330. break;
  1331. }
  1332. if (fSwView)
  1333. {
  1334. if (!(fArgDomain || fArgRoot || fArgServer || fArgImport))
  1335. {
  1336. ErrorMessage(MSG_USAGE_VIEW);
  1337. Done = TRUE;
  1338. break;
  1339. }
  1340. }
  1341. // Set, merge and verify work with import.
  1342. if (fArgImport) {
  1343. if (!(fSwSet || fSwMerge || fSwCompare || fSwView || fSwBlobSize)) {
  1344. MyPrintf(L"You must specify one of /View, /Set, /Merge, /BlobSize or /Compare to Import\n");
  1345. ErrorMessage( MSG_USAGE_IMPORT );
  1346. Done = TRUE;
  1347. break;
  1348. }
  1349. }
  1350. if (fSwInsite) {
  1351. if (!(fSwEnable || fSwDisable || fSwDisplay)) {
  1352. MyPrintf(L"You must specify one of /Enable, /Disable or /Display with /Insite command.\n");
  1353. ErrorMessage( MSG_USAGE_INSITE );
  1354. Done = TRUE;
  1355. break;
  1356. }
  1357. if (OperateNameSpace.IsEmptyPath() == TRUE)
  1358. {
  1359. MyPrintf(L"You must specify a DFS root with /Insite command.\n");
  1360. ErrorMessage( MSG_USAGE_INSITE );
  1361. Done = TRUE;
  1362. break;
  1363. }
  1364. if (fSwApi) {
  1365. MyPrintf(L"Insite command does not work in the /Api mode. Use default.\n");
  1366. ErrorMessage( MSG_USAGE_INSITE );
  1367. Done = TRUE;
  1368. break;
  1369. }
  1370. } else if (fSwSiteCosting) {
  1371. if (!(fSwEnable || fSwDisable || fSwDisplay)) {
  1372. MyPrintf(L"You must specify one of /Enable, /Disable or /Display with /SiteCosting command.\n");
  1373. ErrorMessage( MSG_USAGE_SITECOSTING );
  1374. Done = TRUE;
  1375. break;
  1376. }
  1377. if ((OperateNameSpace.IsEmptyPath() == TRUE) ||
  1378. (IsEmptyString(OperateNameSpace.GetRemainingString()) == FALSE))
  1379. {
  1380. MyPrintf(L"You must specify a well-formed DFS root with /SiteCosting command.\n");
  1381. ErrorMessage( MSG_USAGE_SITECOSTING );
  1382. Done = TRUE;
  1383. break;
  1384. }
  1385. if (fSwApi) {
  1386. MyPrintf(L"SiteCosting command does not work in the /Api mode. Use default.\n");
  1387. ErrorMessage( MSG_USAGE_SITECOSTING );
  1388. Done = TRUE;
  1389. break;
  1390. }
  1391. } else if (fSwRootScalability) {
  1392. if (!(fSwEnable || fSwDisable || fSwDisplay)) {
  1393. MyPrintf(L"You must specify one of /Enable, /Disable or /Display with /RootScalability command.\n");
  1394. // ErrorMessage( MSG_USAGE_ROOTSCALABILITY);
  1395. Done = TRUE;
  1396. break;
  1397. }
  1398. if ((OperateNameSpace.IsEmptyPath() == TRUE) ||
  1399. (IsEmptyString(OperateNameSpace.GetRemainingString()) == FALSE))
  1400. {
  1401. MyPrintf(L"You must specify a DFS root with /RootScalability command.\n");
  1402. // ErrorMessage( MSG_USAGE_ROOTSCALABILITY);
  1403. Done = TRUE;
  1404. break;
  1405. }
  1406. if (fSwApi) {
  1407. MyPrintf(L"RootScalability command does not work in the /Api mode. Use default.\n");
  1408. // ErrorMessage( MSG_USAGE_ROOTSCALABILITY);
  1409. Done = TRUE;
  1410. break;
  1411. }
  1412. }
  1413. // These three dont work with any other command (except for /Set with Insite).
  1414. else if ((fSwSet || fSwMerge) &&
  1415. (!fArgImport)) {
  1416. MyPrintf(L"/Set and /Merge options apply only to /Import: command.\n");
  1417. Done = TRUE;
  1418. break;
  1419. }
  1420. else if ((fSwMirror) &&
  1421. (!fArgImportRoot)) {
  1422. MyPrintf(L"/Mirror option applies only to /ImportRoot: command.\n");
  1423. Done = TRUE;
  1424. break;
  1425. }
  1426. else if ((fSwCompare) &&
  1427. ((!fArgImportRoot) && (!fArgImport))) {
  1428. MyPrintf(L"/Compare option applies only to /Import: or /ImportRoot: commands.\n");
  1429. Done = TRUE;
  1430. break;
  1431. }
  1432. if ((fSwView) &&
  1433. (fArgExport || fSwRenameFtRoot)) {
  1434. MyPrintf(L"The /View command cannot be combined with others.\n");
  1435. Usage();
  1436. Done = TRUE;
  1437. break;
  1438. }
  1439. if (fSwRenameFtRoot) {
  1440. if (NewDomainName.IsEmptyPath() == TRUE ||
  1441. OldDomainName.IsEmptyPath() == TRUE ||
  1442. (OperateNameSpace.IsEmptyPath() == TRUE))
  1443. {
  1444. ErrorMessage( MSG_USAGE_RENAME );
  1445. Done = TRUE;
  1446. break;
  1447. }
  1448. DebugInformation((L"DfsUtil: New domain name will be %wS\n", NewDomainName.GetServerString()));
  1449. DebugInformation((L"DfsUtil: Old domain to be renamed is %wS\n", OldDomainName.GetServerString()));
  1450. }
  1451. if ((fArgUnmapFtRoot) || // Arg gets an automatic usage.
  1452. ((fSwUnmapFtRoot) &&
  1453. ( (OperateNameSpace.IsEmptyPath() == TRUE) ||
  1454. (pwszServerName == NULL) ||
  1455. (pwszShareName == NULL)))) {
  1456. ErrorMessage( MSG_USAGE_UNMAP );
  1457. Done = TRUE;
  1458. break;
  1459. }
  1460. if ((fArgClean) || // Arg gets an automatic usage.
  1461. ((fSwClean) &&
  1462. ((pwszServerName == NULL) ||
  1463. (pwszShareName == NULL)))) {
  1464. ErrorMessage( MSG_USAGE_CLEAN );
  1465. Done = TRUE;
  1466. break;
  1467. }
  1468. if (fSwClean)
  1469. {
  1470. DWORD Status;
  1471. //
  1472. // We don't allow domain names here. That can lead to incorrect
  1473. // results as well as data loss.
  1474. //
  1475. Status = IsThisADomainName( pwszServerName, NULL );
  1476. if (Status == ERROR_SUCCESS)
  1477. {
  1478. MyPrintf(L"/Server: parameter must be the name of a DFS root server. It cannot be a domain name\n");
  1479. ErrorMessage( MSG_USAGE_CLEAN );
  1480. Done = TRUE;
  1481. break;
  1482. }
  1483. }
  1484. if ( fSwAddStdRoot &&
  1485. (IsEmptyString( pwszServerName ) || IsEmptyString( pwszShareName ))) {
  1486. MyPrintf(L"You must specify a valid target server and a share for the new root\n");
  1487. ErrorMessage( MSG_USAGE_ADDROOT );
  1488. Done = TRUE;
  1489. break;
  1490. }
  1491. if ((fArgRemFtRoot || fSwRemFtRoot || fSwRemStdRoot) &&
  1492. (IsEmptyString( pwszServerName ) || IsEmptyString( pwszShareName ))) {
  1493. MyPrintf(L"You must specify a valid target server and a share to remove.\n");
  1494. if (fSwRemStdRoot)
  1495. ErrorMessage( MSG_USAGE_REM_STDROOT );
  1496. else
  1497. ErrorMessage( MSG_USAGE_REM_FTROOT );
  1498. Done = TRUE;
  1499. break;
  1500. }
  1501. /*if ((fArgRemoveReparse) && // Arg gets an automatic usage.
  1502. (pwszDfsDirectoryName == NULL)) {
  1503. MyPrintf(L"You must specify a volume name\n");
  1504. Done = TRUE;
  1505. break;
  1506. }*/
  1507. if (fArgViewDfsDirs) {
  1508. if (pwszVolumeName == NULL) {
  1509. MyPrintf(L"You must specify a directory name\n");
  1510. Done = TRUE;
  1511. break;
  1512. }
  1513. if (wcschr(pwszVolumeName, ':') == NULL) {
  1514. MyPrintf(L"The volume drive letter must contain a colon at the end.\n");
  1515. ErrorMessage( MSG_USAGE_VIEW_DIRS );
  1516. Done = TRUE;
  1517. break;
  1518. }
  1519. }
  1520. //
  1521. // If at this point we have a root:\\x\y, we need to make sure that we have
  1522. // exactly two path components. It is too cumbersome to use REQUIRES_ROOT_NAME
  1523. // check here because there are options like /View that needs /Root only for some cases.
  1524. //
  1525. if ((OperateNameSpace.IsEmptyPath() != TRUE) &&
  1526. ((IsEmptyString(OperateNameSpace.GetShareString()) == TRUE) ||
  1527. (IsEmptyString(OperateNameSpace.GetRemainingString()) == FALSE)) &&
  1528. (fSwInsite == FALSE))
  1529. {
  1530. MyPrintf(L"Root must be of the form \\\\DomainOrServer\\RootName.\n");
  1531. Done = TRUE;
  1532. break;
  1533. }
  1534. if (OperateNameSpace.IsEmptyPath() != TRUE)
  1535. {
  1536. //
  1537. // Now that we have valid args, check to see if there are any exceptions to
  1538. // the rules we've applied so far. For example, we Standalone roots
  1539. // and Direct mode won't mix well for some switches of /Import cmd.
  1540. //
  1541. dwErr = CmdCheckExceptions( &OperateNameSpace );
  1542. if (dwErr != ERROR_SUCCESS)
  1543. {
  1544. Done = TRUE;
  1545. break;
  1546. }
  1547. }
  1548. if (MasterNameSpace.IsEmptyPath() != TRUE)
  1549. {
  1550. dwErr = CmdCheckExceptions( &MasterNameSpace );
  1551. if (dwErr != ERROR_SUCCESS)
  1552. {
  1553. Done = TRUE;
  1554. break;
  1555. }
  1556. }
  1557. if (fArgDebugDC != NULL)
  1558. {
  1559. if (DCInfoStatus != ERROR_SUCCESS)
  1560. {
  1561. MyPrintf(L"Could not get information from DC %wS, error 0x%x\n",
  1562. DCToUse, DCInfoStatus);
  1563. Done = TRUE;
  1564. break;
  1565. }
  1566. if (OperateNameSpace.IsEmptyPath() != TRUE)
  1567. {
  1568. if (DfsIsThisADomainName(OperateNameSpace.GetServerString()) == ERROR_SUCCESS)
  1569. {
  1570. if ((RtlCompareUnicodeString(OperateNameSpace.GetServerCountedString(), &DCToUseFlatDomainName, TRUE) != 0)
  1571. &&
  1572. (RtlCompareUnicodeString(OperateNameSpace.GetServerCountedString(), &DCToUseDNSDomainName, TRUE) != 0))
  1573. {
  1574. MyPrintf(L"DC %ws belongs to %wZ domain, and not to %wS domain\n",
  1575. DCToUse, &DCToUseDNSDomainName, OperateNameSpace.GetServerString());
  1576. Done = TRUE;
  1577. break;
  1578. }
  1579. }
  1580. }
  1581. if (MasterNameSpace.IsEmptyPath() != TRUE)
  1582. {
  1583. if (DfsIsThisADomainName(MasterNameSpace.GetServerString()) == ERROR_SUCCESS)
  1584. {
  1585. if ((RtlCompareUnicodeString(MasterNameSpace.GetServerCountedString(), &DCToUseFlatDomainName, TRUE) != 0)
  1586. &&
  1587. (RtlCompareUnicodeString(MasterNameSpace.GetServerCountedString(), &DCToUseDNSDomainName, TRUE) != 0))
  1588. {
  1589. MyPrintf(L"DC %ws belongs to %wZ domain, and not to %wS domain\n",
  1590. DCToUse, &DCToUseDNSDomainName, MasterNameSpace.GetServerString());
  1591. Done = TRUE;
  1592. break;
  1593. }
  1594. }
  1595. }
  1596. }
  1597. } while (FALSE);
  1598. return dwErr;
  1599. }
  1600. DFSSTATUS
  1601. CmdInitializeDirectMode(
  1602. PBOOLEAN pCoInitialized)
  1603. {
  1604. DFSSTATUS Status;
  1605. HRESULT Hr = S_OK;
  1606. *pCoInitialized = FALSE;
  1607. Hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
  1608. if (Hr == S_OK)
  1609. {
  1610. *pCoInitialized = TRUE;
  1611. Status = DfsServerLibraryInitialize(DFS_DIRECT_MODE|DFS_DONT_SUBSTITUTE_PATHS);
  1612. }
  1613. else
  1614. {
  1615. Status = DfsGetErrorFromHr(Hr);
  1616. }
  1617. return Status;
  1618. }
  1619. DWORD
  1620. ReSynchronizeRootTargets(
  1621. IN LPWSTR PathString)
  1622. {
  1623. DfsPathName PathName;
  1624. DFSSTATUS Status;
  1625. Status = PathName.CreatePathName(PathString);
  1626. if (Status == ERROR_SUCCESS)
  1627. {
  1628. Status = ReSynchronizeRootTargetsFromPath(&PathName);
  1629. }
  1630. return Status;
  1631. }
  1632. DWORD
  1633. ReSynchronizeRootTargetsFromPath(
  1634. IN DfsPathName *pPathName)
  1635. {
  1636. DFSSTATUS Status, SetStatus;
  1637. LPBYTE pBuffer = NULL;
  1638. DWORD ResumeHandle = 0;
  1639. DWORD EntriesRead = 0;
  1640. DWORD PrefMaxLen = 1;
  1641. DWORD Level = 4;
  1642. PDFS_INFO_4 pCurrentBuffer;
  1643. DWORD i;
  1644. PDFS_STORAGE_INFO pStorage;
  1645. LPWSTR DfsPathString;
  1646. DfsPathString = pPathName->GetPathString();
  1647. //
  1648. // We are reading in just the ROOT.
  1649. //
  1650. Status = DfsApiEnumerate( MODE_DIRECT,
  1651. DfsPathString,
  1652. Level,
  1653. PrefMaxLen,
  1654. &pBuffer,
  1655. &EntriesRead,
  1656. &ResumeHandle);
  1657. if ((Status == ERROR_SUCCESS) && EntriesRead != 0)
  1658. {
  1659. pCurrentBuffer = (PDFS_INFO_4)pBuffer;
  1660. //
  1661. // Now contact the appropriate server(s) for the root replicas
  1662. // and ask them to re-read their roots. Things have been
  1663. // changed under them.
  1664. //
  1665. for( i = 0, pStorage = pCurrentBuffer->Storage;
  1666. i < pCurrentBuffer->NumberOfStorages;
  1667. i++, pStorage = pCurrentBuffer->Storage + i )
  1668. {
  1669. SetStatus = SetInfoReSynchronize( pStorage->ServerName,
  1670. pPathName->GetShareString());
  1671. //
  1672. // We just go on to the next server since we don't do any undo's anyway.
  1673. //
  1674. if (SetStatus != ERROR_SUCCESS)
  1675. Status = SetStatus;
  1676. }
  1677. //
  1678. // Free the allocated memory.
  1679. //
  1680. DfsFreeApiBuffer(pBuffer);
  1681. }
  1682. return Status;
  1683. }
  1684. //
  1685. // the following code exists to read and write the old style static
  1686. // site table in the AD blob.
  1687. //
  1688. //
  1689. typedef struct _DFS_SITE_UPDATE
  1690. {
  1691. UNICODE_STRING Server;
  1692. UNICODE_STRING Site;
  1693. struct _DFS_SITE_UPDATE *pNext;
  1694. } DFS_SITE_UPDATE, *PDFS_SITE_UPDATE;
  1695. DFS_SITE_UPDATE *pSiteList = NULL;
  1696. PDFS_SITE_UPDATE pSiteNext = NULL;
  1697. struct _DFS_PREFIX_TABLE *pServerSiteTable;
  1698. VOID
  1699. DumpSiteInformation(
  1700. PUNICODE_STRING pServer,
  1701. PUNICODE_STRING pSite )
  1702. {
  1703. ShowInformation((L"Server %wZ, Site %wZ\n", pServer, pSite));
  1704. }
  1705. DFSSTATUS
  1706. DumpSiteBlob(
  1707. PVOID pBuffer,
  1708. ULONG Size,
  1709. BOOLEAN Display )
  1710. {
  1711. PVOID pUseBuffer = pBuffer;
  1712. ULONG RemainingSize = Size;
  1713. GUID SiteGuid;
  1714. UNICODE_STRING Server, Site;
  1715. DFSSTATUS Status = ERROR_SUCCESS;
  1716. ULONG Objects = 0, SiteNum, NumSites, Flags;
  1717. if (Size == 0)
  1718. {
  1719. if (Display)
  1720. {
  1721. ShowInformation((L"\nSite Blob with %d sites\n", Objects));
  1722. }
  1723. return Status;
  1724. }
  1725. Status = PackGetGuid(&SiteGuid, &pUseBuffer, &RemainingSize);
  1726. if (Status == ERROR_SUCCESS)
  1727. {
  1728. Status = PackGetULong( &Objects, &pUseBuffer, &RemainingSize );
  1729. }
  1730. if (Display)
  1731. {
  1732. ShowInformation((L"\nSite Blob with %d sites\n", Objects));
  1733. }
  1734. if (Status == ERROR_SUCCESS)
  1735. {
  1736. for (SiteNum = 0; SiteNum < Objects; SiteNum++)
  1737. {
  1738. Status = PackGetString( &Server, &pUseBuffer, &RemainingSize);
  1739. if (Status == ERROR_SUCCESS)
  1740. {
  1741. Status = PackGetULong( &NumSites, &pUseBuffer, &RemainingSize);
  1742. }
  1743. if (Status == ERROR_SUCCESS)
  1744. {
  1745. Status = PackGetULong( &Flags, &pUseBuffer, &RemainingSize);
  1746. }
  1747. if (Status == ERROR_SUCCESS)
  1748. {
  1749. Status = PackGetString( &Site, &pUseBuffer, &RemainingSize);
  1750. }
  1751. if (Status != ERROR_SUCCESS)
  1752. {
  1753. break;
  1754. }
  1755. if (Display)
  1756. {
  1757. DumpSiteInformation(&Server, &Site);
  1758. }
  1759. }
  1760. }
  1761. return Status;
  1762. }
  1763. DFSSTATUS
  1764. AddServerToSiteList(
  1765. PUNICODE_STRING pServerName,
  1766. PUNICODE_STRING pSiteName )
  1767. {
  1768. NTSTATUS NtStatus = STATUS_SUCCESS;
  1769. BOOLEAN Insert = FALSE;
  1770. PDFS_SITE_UPDATE pSiteUpdate;
  1771. UNICODE_STRING RemainingName;
  1772. PVOID pData;
  1773. BOOLEAN SubStringMatch;
  1774. DFSSTATUS Status = ERROR_SUCCESS;
  1775. NtStatus = DfsPrefixTableAcquireWriteLock( pServerSiteTable );
  1776. if ( NtStatus == STATUS_SUCCESS )
  1777. {
  1778. NtStatus = DfsFindUnicodePrefixLocked( pServerSiteTable,
  1779. pServerName,
  1780. &RemainingName,
  1781. &pData,
  1782. &SubStringMatch );
  1783. if (NtStatus != STATUS_SUCCESS)
  1784. {
  1785. Insert = TRUE;
  1786. NtStatus = DfsInsertInPrefixTableLocked( pServerSiteTable,
  1787. pServerName,
  1788. pSiteName);
  1789. }
  1790. else
  1791. {
  1792. Insert = FALSE;
  1793. NtStatus = STATUS_SUCCESS;
  1794. }
  1795. DfsPrefixTableReleaseLock( pServerSiteTable );
  1796. }
  1797. if (NtStatus != STATUS_SUCCESS)
  1798. {
  1799. Status = RtlNtStatusToDosError(NtStatus);
  1800. }
  1801. if (Status == ERROR_SUCCESS)
  1802. {
  1803. if (Insert)
  1804. {
  1805. pSiteUpdate = new DFS_SITE_UPDATE;
  1806. if (pSiteUpdate == NULL)
  1807. {
  1808. Status = ERROR_NOT_ENOUGH_MEMORY;
  1809. }
  1810. if (Status == ERROR_SUCCESS)
  1811. {
  1812. Status = DfsCreateUnicodeString( &pSiteUpdate->Server, pServerName);
  1813. }
  1814. if (Status == ERROR_SUCCESS)
  1815. {
  1816. Status = DfsCreateUnicodeString( &pSiteUpdate->Site, pSiteName);
  1817. }
  1818. if (Status == ERROR_SUCCESS)
  1819. {
  1820. pSiteUpdate->pNext = NULL;
  1821. if (pSiteList == NULL)
  1822. {
  1823. pSiteList = pSiteUpdate;
  1824. }
  1825. else
  1826. {
  1827. pSiteNext->pNext = pSiteUpdate;
  1828. }
  1829. pSiteNext = pSiteUpdate;
  1830. }
  1831. }
  1832. }
  1833. return Status;
  1834. }
  1835. DFSSTATUS
  1836. ProcessTargetForSite(
  1837. DfsTarget *pTarget )
  1838. {
  1839. PUNICODE_STRING pServer, pSite;
  1840. DFSSTATUS Status = ERROR_SUCCESS;
  1841. for (;
  1842. pTarget != NULL;
  1843. pTarget = pTarget->GetNextTarget())
  1844. {
  1845. pServer = pTarget->GetTargetServerCountedString();
  1846. pSite = pTarget->GetTargetSiteCountedString();
  1847. if (pSite->Length != 0)
  1848. {
  1849. Status = AddServerToSiteList( pServer, pSite);
  1850. }
  1851. if (Status != ERROR_SUCCESS)
  1852. {
  1853. break;
  1854. }
  1855. }
  1856. return Status;
  1857. }
  1858. ULONG
  1859. SizeSiteInformationBlob(
  1860. PDFS_SITE_UPDATE pSiteUpdate)
  1861. {
  1862. ULONG Size = 0;
  1863. Size += PackSizeString(&pSiteUpdate->Server);
  1864. Size += PackSizeULong();
  1865. Size += PackSizeULong();
  1866. Size += PackSizeString(&pSiteUpdate->Site);
  1867. return Size;
  1868. }
  1869. DFSSTATUS
  1870. UpdateSiteBlob(
  1871. DfsRoot *pRoot)
  1872. {
  1873. PDFS_SITE_UPDATE pSiteUpdate;
  1874. GUID NewGuid;
  1875. ULONG TotalObjects = 0;
  1876. DFSSTATUS Status;
  1877. ULONG SiteBlobSize;
  1878. PBYTE pBuffer;
  1879. PVOID pUseBuffer;
  1880. ULONG SizeRemaining;
  1881. pSiteUpdate = pSiteList;
  1882. Status = UuidCreate(&NewGuid);
  1883. if (Status != ERROR_SUCCESS)
  1884. {
  1885. return Status;
  1886. }
  1887. SiteBlobSize = sizeof(ULONG) + sizeof(GUID);
  1888. pSiteUpdate = pSiteList;
  1889. while (pSiteUpdate != NULL)
  1890. {
  1891. SiteBlobSize += SizeSiteInformationBlob(pSiteUpdate);
  1892. TotalObjects++;
  1893. pSiteUpdate = pSiteUpdate->pNext;
  1894. }
  1895. pBuffer = new BYTE[SiteBlobSize];
  1896. if (pBuffer == NULL)
  1897. {
  1898. return ERROR_NOT_ENOUGH_MEMORY;
  1899. }
  1900. pUseBuffer = pBuffer;
  1901. SizeRemaining = SiteBlobSize;
  1902. Status = PackSetGuid( &NewGuid, &pUseBuffer, &SizeRemaining);
  1903. if (Status == ERROR_SUCCESS)
  1904. {
  1905. Status = PackSetULong( TotalObjects, &pUseBuffer, &SizeRemaining );
  1906. }
  1907. pSiteUpdate = pSiteList;
  1908. while (pSiteUpdate != NULL)
  1909. {
  1910. Status = PackSetString( &pSiteUpdate->Server, &pUseBuffer, &SizeRemaining );
  1911. if (Status == ERROR_SUCCESS)
  1912. {
  1913. //
  1914. // We allow only 1 site information for each server.
  1915. //
  1916. Status = PackSetULong( 1, &pUseBuffer, &SizeRemaining );
  1917. }
  1918. if (Status == ERROR_SUCCESS)
  1919. {
  1920. //
  1921. // Flags: alwyas 0.
  1922. //
  1923. Status = PackSetULong( 0, &pUseBuffer, &SizeRemaining );
  1924. }
  1925. if (Status == ERROR_SUCCESS)
  1926. {
  1927. Status = PackSetString( &pSiteUpdate->Site, &pUseBuffer, &SizeRemaining );
  1928. }
  1929. pSiteUpdate = (PDFS_SITE_UPDATE)(pSiteUpdate->pNext);
  1930. }
  1931. if (Status == ERROR_SUCCESS)
  1932. {
  1933. PUNICODE_STRING pRootToUpdate = pRoot->GetLinkNameCountedString();
  1934. pRoot->SetRootApiName(pRootToUpdate);
  1935. pRoot->SetRootWriteable();
  1936. Status = pRoot->RootSetSiteBlob(pBuffer, SiteBlobSize);
  1937. if (Status == ERROR_SUCCESS)
  1938. {
  1939. Status = pRoot->UpdateMetadata();
  1940. }
  1941. }
  1942. delete [] pBuffer;
  1943. return Status;
  1944. }
  1945. DFSSTATUS
  1946. PurgeSiteBlob(
  1947. DfsRoot *pRoot)
  1948. {
  1949. PDFS_SITE_UPDATE pSiteUpdate = NULL;
  1950. GUID NewGuid;
  1951. ULONG TotalObjects = 0;
  1952. DFSSTATUS Status = ERROR_SUCCESS;
  1953. ULONG SiteBlobSize = 0;
  1954. PBYTE pBuffer = NULL;
  1955. PVOID pUseBuffer = NULL;
  1956. ULONG SizeRemaining = 0;
  1957. pSiteUpdate = pSiteList;
  1958. Status = UuidCreate(&NewGuid);
  1959. if (Status != ERROR_SUCCESS)
  1960. {
  1961. return Status;
  1962. }
  1963. SiteBlobSize = sizeof(ULONG) + sizeof(GUID);
  1964. pBuffer = new BYTE[SiteBlobSize];
  1965. if (pBuffer == NULL)
  1966. {
  1967. return ERROR_NOT_ENOUGH_MEMORY;
  1968. }
  1969. pUseBuffer = pBuffer;
  1970. SizeRemaining = SiteBlobSize;
  1971. Status = PackSetGuid( &NewGuid, &pUseBuffer, &SizeRemaining);
  1972. if (Status == ERROR_SUCCESS)
  1973. {
  1974. Status = PackSetULong( TotalObjects, &pUseBuffer, &SizeRemaining );
  1975. }
  1976. if (Status == ERROR_SUCCESS)
  1977. {
  1978. PUNICODE_STRING pRootToUpdate = pRoot->GetLinkNameCountedString();
  1979. pRoot->SetRootApiName(pRootToUpdate);
  1980. pRoot->SetRootWriteable();
  1981. Status = pRoot->RootSetSiteBlob(pBuffer, SiteBlobSize);
  1982. if (Status == ERROR_SUCCESS)
  1983. {
  1984. pRoot->UpdateMetadata();
  1985. }
  1986. }
  1987. delete [] pBuffer;
  1988. return Status;
  1989. }
  1990. DFSSTATUS
  1991. ProcessRootForSite(
  1992. DfsRoot *pRoot )
  1993. {
  1994. DFSSTATUS Status = ERROR_SUCCESS;
  1995. DfsLink *pLink = NULL;
  1996. Status = DfsInitializePrefixTable( &pServerSiteTable,
  1997. FALSE,
  1998. NULL );
  1999. if ( Status != ERROR_SUCCESS )
  2000. {
  2001. return Status;
  2002. }
  2003. Status = ProcessTargetForSite(pRoot->GetFirstTarget());
  2004. if (Status == ERROR_SUCCESS)
  2005. {
  2006. for (pLink = pRoot->GetFirstLink();
  2007. pLink != NULL;
  2008. pLink = pLink->GetNextLink())
  2009. {
  2010. Status = ProcessTargetForSite( pLink->GetFirstTarget());
  2011. if (Status != ERROR_SUCCESS)
  2012. {
  2013. break;
  2014. }
  2015. }
  2016. }
  2017. if (Status == ERROR_SUCCESS)
  2018. {
  2019. Status = UpdateSiteBlob(pRoot);
  2020. }
  2021. return Status;
  2022. }
  2023. DFSSTATUS
  2024. PurgeSiteInformationForRoot(
  2025. DfsRoot *pRoot )
  2026. {
  2027. DFSSTATUS Status = ERROR_SUCCESS;
  2028. Status = DfsInitializePrefixTable( &pServerSiteTable,
  2029. FALSE,
  2030. NULL );
  2031. if ( Status != ERROR_SUCCESS )
  2032. {
  2033. return Status;
  2034. }
  2035. if (Status == ERROR_SUCCESS)
  2036. {
  2037. Status = PurgeSiteBlob(pRoot);
  2038. }
  2039. return Status;
  2040. }
  2041. DFSSTATUS
  2042. IsRootStandalone(
  2043. DfsPathName *Namespace,
  2044. BOOLEAN& IsStandalone )
  2045. {
  2046. DFSSTATUS Status;
  2047. LPBYTE pBuffer = NULL;
  2048. DWORD RootFlavor = 0;
  2049. IsStandalone = FALSE;
  2050. Status = NetDfsGetInfo( Namespace->GetPathCountedString()->Buffer, NULL, NULL, 3, &pBuffer );
  2051. if (Status == ERROR_SUCCESS) {
  2052. RootFlavor = ((PDFS_INFO_3)pBuffer)->State & DFS_VOLUME_FLAVORS;
  2053. //
  2054. // There is no real easy way to find out the type of a Win2K root. The FLAVORS bit
  2055. // is post-win2k. In that case, err on the safe side and return Standalone.
  2056. //
  2057. if (RootFlavor == 0)
  2058. {
  2059. DebugInformation((L"NetDfsGetInfo returns 0 for DFS_VOLUME_FLAVORS. Assuming a standalone root\n"));
  2060. IsStandalone = TRUE;
  2061. }
  2062. else if (RootFlavor == DFS_VOLUME_FLAVOR_STANDALONE)
  2063. {
  2064. IsStandalone = TRUE;
  2065. }
  2066. NetApiBufferFree( pBuffer );
  2067. }
  2068. return Status;
  2069. }
  2070. //+----------------------------------------------------------------------------
  2071. //
  2072. // Function: IsThisADomainName
  2073. //
  2074. // Synopsis: Calls the mup to have it check the special name table to see if the
  2075. // name matches a domain name. Returns a list of DC's in the domain,
  2076. // as a list of strings. The list is terminated with a double-null.
  2077. //
  2078. // Arguments: [wszName] -- Name to check
  2079. // [ppList] -- Pointer to pointer for results.
  2080. //
  2081. // Returns: [ERROR_SUCCESS] -- Name is indeed a domain name.
  2082. //
  2083. // [ERROR_FILE_NOT_FOUND] -- Name is not a domain name
  2084. //
  2085. //-----------------------------------------------------------------------------
  2086. DWORD
  2087. IsThisADomainName(
  2088. IN LPWSTR wszName,
  2089. OUT PWCHAR *ppList OPTIONAL)
  2090. {
  2091. NTSTATUS NtStatus;
  2092. IO_STATUS_BLOCK IoStatusBlock;
  2093. OBJECT_ATTRIBUTES objectAttributes;
  2094. UNICODE_STRING DfsDriverName;
  2095. HANDLE DriverHandle = NULL;
  2096. DWORD dwErr;
  2097. PCHAR OutBuf = NULL;
  2098. ULONG Size = 0x100;
  2099. ULONG Count = 0;
  2100. RtlInitUnicodeString(&DfsDriverName, DFS_DRIVER_NAME);
  2101. InitializeObjectAttributes(
  2102. &objectAttributes,
  2103. &DfsDriverName,
  2104. OBJ_CASE_INSENSITIVE,
  2105. NULL,
  2106. NULL
  2107. );
  2108. NtStatus = NtCreateFile(
  2109. &DriverHandle,
  2110. SYNCHRONIZE,
  2111. &objectAttributes,
  2112. &IoStatusBlock,
  2113. NULL,
  2114. FILE_ATTRIBUTE_NORMAL,
  2115. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  2116. FILE_OPEN_IF,
  2117. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  2118. NULL,
  2119. 0
  2120. );
  2121. if (!NT_SUCCESS(NtStatus)) {
  2122. return ERROR_FILE_NOT_FOUND;
  2123. }
  2124. Retry:
  2125. OutBuf = (PCHAR)malloc(Size);
  2126. if (OutBuf == NULL) {
  2127. NtClose(DriverHandle);
  2128. return ERROR_NOT_ENOUGH_MEMORY;
  2129. }
  2130. NtStatus = NtFsControlFile(
  2131. DriverHandle,
  2132. NULL, // Event,
  2133. NULL, // ApcRoutine,
  2134. NULL, // ApcContext,
  2135. &IoStatusBlock,
  2136. FSCTL_DFS_GET_SPC_TABLE,
  2137. wszName,
  2138. (wcslen(wszName) + 1) * sizeof(WCHAR),
  2139. OutBuf,
  2140. Size
  2141. );
  2142. if (NtStatus == STATUS_SUCCESS) {
  2143. dwErr = ERROR_SUCCESS;
  2144. } else if (NtStatus == STATUS_BUFFER_OVERFLOW && ++Count < 5) {
  2145. Size = *((ULONG *)OutBuf);
  2146. free(OutBuf);
  2147. goto Retry;
  2148. } else {
  2149. dwErr = ERROR_FILE_NOT_FOUND;
  2150. }
  2151. NtClose(DriverHandle);
  2152. if (ppList == NULL)
  2153. {
  2154. free(OutBuf);
  2155. OutBuf = NULL;
  2156. }
  2157. else
  2158. {
  2159. *ppList = (WCHAR *)OutBuf;
  2160. }
  2161. return dwErr;
  2162. }
  2163. DFSSTATUS
  2164. CmdCheckExceptions(
  2165. DfsPathName *pNameSpace)
  2166. {
  2167. DFSSTATUS Status = ERROR_SUCCESS;
  2168. //
  2169. // 733898 : disable /Import and /ImportRoot writable operations
  2170. // over direct mode for standalone roots. This is so that
  2171. // we won't race with DfsSvc's synchronize and possibly
  2172. // create inconsistencies.
  2173. // Besides since direct mode registry blob updates aren't
  2174. // 'atomic' import can create inconsistencies anyway.
  2175. //
  2176. if ((fArgImport && (fSwSet || fSwMerge))
  2177. ||
  2178. (fArgImportRoot && (fSwMirror)))
  2179. {
  2180. BOOLEAN IsStandalone = FALSE;
  2181. do {
  2182. Status = IsRootStandalone( pNameSpace, IsStandalone );
  2183. // Err on the safe side if we get an error doing GetInfo.
  2184. if (Status != ERROR_SUCCESS || (IsStandalone))
  2185. {
  2186. if (UserRequiresDirectMode)
  2187. {
  2188. MyPrintf(L"Import /Set, /Merge and ImportRoot /Mirror commands on Standalone roots must use API mode.\n");
  2189. ErrorMessage( MSG_USAGE_IMPORT );
  2190. Status = ERROR_INVALID_PARAMETER;
  2191. break;
  2192. }
  2193. DebugInformation((L"%ws is a Standalone root. Switching to API mode for this operation.\n",
  2194. pNameSpace->GetPathCountedString()->Buffer));
  2195. Mode = MODE_API;
  2196. }
  2197. // Don't return GetInfo errors. Those aren't fatal.
  2198. Status = ERROR_SUCCESS;
  2199. } while (FALSE);
  2200. }
  2201. return Status;
  2202. }