|
|
//--------------------------------------------------------------------------
//
// Copyright (C) 1999, Microsoft Corporation
//
// File: dfsutil.cxx
//
//--------------------------------------------------------------------------
extern "C" { #include <stdio.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <shellapi.h>
#include <winldap.h>
#include <stdlib.h>
} #include <lm.h>
#include <lmdfs.h>
#include <dfsfsctl.h>
#include <dsgetdc.h>
#include <ole2.h>
#include <activeds.h>
#include <dfsprefix.h>
#include <DfsServerLibrary.hxx>
#include <dfsmisc.h>
#include "dsgetdc.h"
#include "dsrole.h"
#include "dfsutil.hxx"
#include "dfspathname.hxx"
#include "struct.hxx"
#include "flush.hxx"
#include "misc.hxx"
#include "info.hxx"
#include "messages.h"
#include "dfsreparse.hxx"
#include "dfswmi.h"
#include "dfsroot.hxx"
#define WPP_BIT_CLI_DRV 0x01
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_CLI_DRV ).Level >= lvl)
#define WPP_LEVEL_ERROR_FLAGS_LOGGER(lvl, error, flags) WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_ERROR_FLAGS_ENABLED(lvl, error, flags) \
((!NT_SUCCESS(error) || WPP_LEVEL_ENABLED(flags)) && WPP_CONTROL(WPP_BIT_CLI_DRV ).Level >= lvl)
#include "dfsutil.tmh"
UNICODE_STRING DCToUseFlatDomainName; UNICODE_STRING DCToUseDNSDomainName; LPWSTR DCToUse = NULL; DFSSTATUS DCInfoStatus = ERROR_SUCCESS;
extern void SetReferralControl(WPP_CB_TYPE * Control);
DFSSTATUS ProcessRootForSite( DfsRoot *pRoot );
DFSSTATUS PurgeSiteInformationForRoot( DfsRoot *pRoot );
DFSSTATUS DumpSiteBlob( PVOID pBuffer, ULONG Size, BOOLEAN Display );
//
// How we make args & switches
//
#define MAKEARG(x) \
WCHAR Arg##x[] = L"/" L#x L":"; \ LONG ArgLen##x = (sizeof(Arg##x) / sizeof(WCHAR)) - 1; \ BOOLEAN fArg##x;
#define SWITCH(x) \
WCHAR Sw##x[] = L"/" L#x ; \ BOOLEAN fSw##x;
#define FMAKEARG(x) \
static WCHAR Arg##x[] = L#x L":"; \ static LONG ArgLen##x = (sizeof(Arg##x) / sizeof(WCHAR)) - 1; \ static BOOLEAN fArg##x;
#define FSWITCH(x) \
static WCHAR Sw##x[] = L"/" L#x ; \ static BOOLEAN fSw##x;
DFSSTATUS DfsReadFromAD( LPWSTR DomainName, LPWSTR Name, LPWSTR FileName, LPWSTR UseDC );
DFSSTATUS DfsReadFromFile( LPWSTR Name );
LPWSTR pwszServerName = NULL; LPWSTR pwszDomainName = NULL; LPWSTR pwszEntryToFlush = NULL; LPWSTR pwszComment = NULL; LPWSTR pwszShareName = NULL; LPWSTR pwszLogicalName = NULL; LPWSTR pwszHexValue = NULL; LPWSTR ImportFile = NULL;
DfsPathName OperateNameSpace; DfsPathName MasterNameSpace; DfsPathName OldDomainName; DfsPathName NewDomainName;
DfsString ClientForSiteName;
LPWSTR ExportBlobFile = NULL; LPWSTR DisplayBlobFile = NULL;
BOOLEAN CmdRequiresDirect = FALSE; LPWSTR ExportFile = NULL; LPWSTR DebugFile = NULL; LPWSTR BackupFile = NULL; LPWSTR pwszVolumeName = NULL; LPWSTR pwszDfsDirectoryName = NULL; LPWSTR pwszDcName = NULL;
DFS_API_MODE Mode = MODE_EITHER; DFSSTATUS DirectModeFailStatus = ERROR_SUCCESS;
HANDLE ShowHandle= INVALID_HANDLE_VALUE; HANDLE DebugHandle= INVALID_HANDLE_VALUE; HANDLE ExportHandle= INVALID_HANDLE_VALUE; HANDLE BackupHandle = INVALID_HANDLE_VALUE;
MAKEARG(RemFtRoot); SWITCH(RemFtRoot);
MAKEARG(Domain); MAKEARG(Server); MAKEARG(Share);
SWITCH(DisplayBlob); MAKEARG(DisplayBlob);
MAKEARG(Import); SWITCH(Import); // The switch is just a cue for Help here.
MAKEARG(Export); MAKEARG(Backup); SWITCH(NoBackup); SWITCH(Export); MAKEARG(Root); SWITCH(Root); MAKEARG(DebugFile); MAKEARG(OldDomain); MAKEARG(NewDomain); SWITCH(UnmapFtRoot); SWITCH(Unmap); MAKEARG(UnmapFtRoot);
MAKEARG(SiteName); SWITCH(SiteName); MAKEARG(Clean); SWITCH(Clean); SWITCH(Insite); SWITCH(SiteCosting); SWITCH(RootScalability);
SWITCH(ViewDfsDirs); MAKEARG(ViewDfsDirs);
//MAKEARG(RemoveReparse);
MAKEARG(DebugDC); SWITCH(RemoveReparse); SWITCH(DC);
SWITCH(ExportBlob); MAKEARG(ExportBlob);
MAKEARG(ImportRoot); SWITCH(ImportRoot);
SWITCH(PurgeMupCache); SWITCH(UpdateWin2kStaticSiteTable); SWITCH(ShowWin2kStaticSiteTable); SWITCH(PurgeWin2kStaticSiteTable);
SWITCH(CheckBlob); SWITCH(BlobSize);
//
// Switches (ie '/arg')
//
SWITCH(AddStdRoot); SWITCH(AddFtRoot); SWITCH(Debug); SWITCH(Verbose); SWITCH(Help); SWITCH(ScriptHelp); SWITCH(PktInfo); SWITCH(Dfs); SWITCH(All); SWITCH(Set); SWITCH(Mirror); SWITCH(RemStdRoot); SWITCH(Api);
SWITCH(Compare); SWITCH(Merge); SWITCH(Direct); SWITCH(RenameFtRoot); SWITCH(View); SWITCH(Disable); SWITCH(Enable); SWITCH(Display);
//
// Either a switch or an arg
//
MAKEARG(PktFlush); SWITCH(PktFlush); MAKEARG(SpcFlush); SWITCH(SpcFlush); MAKEARG(SpcInfo); SWITCH(SpcInfo); MAKEARG(Level);
//
// The macro can not make these
//
WCHAR SwQ[] = L"/?"; BOOLEAN fSwQ;
ULONG AddLinks, RemoveLinks, AddTargets, RemoveTargets, ErrorLinks, DirectMode, ApiCalls, SetInfoState, SetInfoComment; ULONG TotalNamespaceCost;
BOOLEAN CommandSucceeded = FALSE; BOOLEAN ErrorDisplayed = FALSE; static BOOLEAN LastOptionWasInsite = FALSE; static BOOLEAN DirectModeOnly = FALSE; static BOOLEAN UserRequiresDirectMode = FALSE;
DFSSTATUS CmdInitializeDirectMode( PBOOLEAN pCoInitialized); DWORD Usage();
DWORD CmdProcessUserCreds( VOID);
BOOLEAN CmdProcessArg( LPWSTR Arg);
DFSSTATUS CmdCheckSyntax( BOOLEAN& Done );
DFSSTATUS IsRootStandalone( DfsPathName *PathComps, PBOOLEAN pIsAdBlob );
DWORD IsThisADomainName( IN LPWSTR wszName, OUT PWCHAR *ppList OPTIONAL);
DFSSTATUS CmdCheckExceptions( DfsPathName *Namespace );
extern DFSSTATUS DfsExtendedWin2kRootAttributes( DfsPathName *Namespace, PULONG pAttr, BOOLEAN Set);
DFSSTATUS GetDCInformation() { PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo = NULL; DFSSTATUS Status = ERROR_SUCCESS;
Status = DsRoleGetPrimaryDomainInformation( DCToUse, DsRolePrimaryDomainInfoBasic, (PBYTE *)&pPrimaryDomainInfo); if (Status != ERROR_SUCCESS) { DCInfoStatus = Status; return ERROR_SUCCESS; }
if (Status == ERROR_SUCCESS) { UNICODE_STRING DomainNameFlat; Status = DfsRtlInitUnicodeStringEx( &DomainNameFlat, pPrimaryDomainInfo->DomainNameFlat); if(Status == ERROR_SUCCESS) { Status = DfsCreateUnicodeString( &DCToUseFlatDomainName, &DomainNameFlat );
}
if (Status == ERROR_SUCCESS) { UNICODE_STRING DomainNameDNS; Status = DfsRtlInitUnicodeStringEx( &DomainNameDNS, pPrimaryDomainInfo->DomainNameDns); if(Status == ERROR_SUCCESS) { Status = DfsCreateUnicodeString( &DCToUseDNSDomainName, &DomainNameDNS );
} }
DsRoleFreeMemory(pPrimaryDomainInfo); }
return Status; }
DFSSTATUS DfsEnumerateDomainDfs( LPWSTR Domain) { DFSSTATUS Status; PDFS_INFO_200 pBuffer = NULL, pCurBuffer; DWORD dwEntriesRead = 0; DWORD dwResumeHandle = 0; DWORD dwTotalEntries = 0;
do {
dwEntriesRead = 0;
Status = NetDfsEnum( Domain, 200, (DWORD)-1, (LPBYTE *)&pBuffer, &dwEntriesRead, &dwResumeHandle ); if (Status == ERROR_SUCCESS) { pCurBuffer = pBuffer; if (dwEntriesRead) { if (dwTotalEntries == 0) { ShowInformation((L"\nRoots on Domain %ws\n\n", Domain)); } for (DWORD i=0; i<dwEntriesRead; i++) { ShowInformation((L"\t%ws\n", pCurBuffer[i].FtDfsName)); dwTotalEntries++; } } } if (NULL != pBuffer) { NetApiBufferFree(pBuffer); pBuffer = NULL; } } while ( Status == ERROR_SUCCESS && dwResumeHandle != NULL );
if (dwTotalEntries > 0) { ShowInformation((L"\nDone with Roots on Domain %ws\n", Domain));
if (Status == ERROR_NO_MORE_ITEMS) { Status = ERROR_SUCCESS; } } else { ShowInformation((L"\n\nNo roots exist on domain %ws\n\n", Domain)); }
return Status; }
DFSSTATUS DfsEnumerateMachineDfs( LPWSTR Server) { DFSSTATUS Status; PDFS_INFO_300 pBuffer = NULL, pCurBuffer; DWORD dwEntriesRead = 0; DWORD dwResumeHandle = 0; DWORD dwTotalEntries = 0;
do {
dwEntriesRead = 0;
Status = NetDfsEnum( Server, 300, (DWORD)-1, (LPBYTE *)&pBuffer, &dwEntriesRead, &dwResumeHandle ); if (Status == ERROR_SUCCESS) { pCurBuffer = pBuffer; if (dwEntriesRead) { if (dwTotalEntries == 0) { ShowInformation((L"\nRoots on machine %ws\n\n", Server)); } for (DWORD i=0; i<dwEntriesRead; i++) { ShowInformation((L"\t%ws\n", pCurBuffer[i].DfsName)); dwTotalEntries++; } } } if (NULL != pBuffer) { NetApiBufferFree(pBuffer); pBuffer = NULL; }
} while ( Status == ERROR_SUCCESS && dwResumeHandle != NULL );
if (dwTotalEntries > 0) { ShowInformation((L"\nDone with Roots on machine %ws\n", Server));
if (Status == ERROR_NO_MORE_ITEMS) { Status = ERROR_SUCCESS; } } else { ShowInformation((L"\n\nNo roots exist on machine %ws\n\n", Server)); }
return Status; } _cdecl main(int argc, char *argv[]) { UNREFERENCED_PARAMETER(argv); UNREFERENCED_PARAMETER(argc); DWORD dwErr = ERROR_SUCCESS; LPWSTR CommandLine; LPWSTR *argvw; int argx; int argcw; BOOLEAN CoInitialized = FALSE; BOOLEAN DirectModeInitialized = FALSE; BOOLEAN Done; WPP_CB_TYPE *pLogger = NULL;
pLogger = &WPP_CB[WPP_CTRL_NO(WPP_BIT_CLI_DRV)];
WPP_INIT_TRACING(L"DfsUtil"); SetReferralControl(pLogger);
ShowHandle = GetStdHandle(STD_OUTPUT_HANDLE); DebugHandle = GetStdHandle(STD_OUTPUT_HANDLE); //
// Do the work
//
do { ErrorMessage( MSG_COPYRIGHT ); if ((dwErr = DfsPrefixTableInit()) != STATUS_SUCCESS) { break; } //
// Get the command line in Unicode
//
CommandLine = GetCommandLine();
argvw = CommandLineToArgvW(CommandLine, &argcw);
if ( argvw == NULL ) { DebugInformation((L"DfsUtil:Can't convert command line to Unicode: %d\r\n", GetLastError())); dwErr = GetLastError(); break; }
//
// Get the arguments
//
if (argcw <= 1) { dwErr = Usage(); break; }
//
// Process arguments. Direct mode is enabled by default.
//
fSwDirect = TRUE; UserRequiresDirectMode = FALSE; Done = FALSE; for (argx = 1; argx < argcw && !Done; argx++) { Done = CmdProcessArg(argvw[argx]); } if (Done) { Usage(); break; }
//
// Some sanity checking of cmd syntax.
// This also prints all appropriate error help messages.
//
dwErr = CmdCheckSyntax( Done ); if (Done) { break; } if (fSwPktFlush == TRUE || fArgPktFlush == TRUE) { dwErr = PktFlush(pwszEntryToFlush); break; } else if (fSwSpcFlush == TRUE || fArgSpcFlush == TRUE) { dwErr = SpcFlush(pwszEntryToFlush); break; } else if (fSwPktInfo == TRUE) { dwErr = PktInfo(fSwDfs, pwszHexValue); break; } else if (fSwSpcInfo == TRUE) { dwErr = SpcInfo(fSwAll); break; }
if(fArgViewDfsDirs) { BOOL fRemove = FALSE;
if(fSwRemoveReparse) { fRemove =TRUE; }
dwErr = CountReparsePoints(pwszVolumeName, fRemove); break; } /*
BUG 736596: DeleteReparsePoint as implemented doesn't walk through all subdirectories of a given directory. In fact, it doesn't seem to work at all. We should probably address this in the longhorn timeframe. if(fArgRemoveReparse) { dwErr = DeleteReparsePoint(pwszDfsDirectoryName); break; } */ if (fSwAddStdRoot == TRUE) { dwErr = CmdAddRoot( FALSE, pwszServerName, pwszShareName, pwszShareName, // Enforce RootName = Sharename
pwszComment); break; }
if (fSwAddFtRoot == TRUE) { dwErr = CmdAddRoot( TRUE, pwszServerName, pwszShareName, pwszShareName, // Enforce RootName = Sharename
pwszComment); break; }
if (fSwRemStdRoot == TRUE) { dwErr = CmdRemRoot( FALSE, pwszServerName, pwszShareName, pwszShareName); // Sharename = logicalname.
break; }
//
// We allow users to delete roots whose logical name don't match
// their physical share names for compatibility reasons.
// DfsUtil itself doesn't allow people to create such roots however.
//
if (fArgRemFtRoot == TRUE || fSwRemFtRoot == TRUE) { dwErr = CmdRemRoot( TRUE, pwszServerName, pwszShareName, pwszLogicalName); // logical name may differ.
break; }
if (fSwClean) { dwErr = CmdClean( pwszServerName, pwszShareName ); break; }
if ((Mode == MODE_DIRECT) || (Mode == MODE_EITHER)) { dwErr = CmdInitializeDirectMode( &CoInitialized);
if (dwErr != ERROR_SUCCESS) { DirectModeFailStatus = dwErr; if (Mode == MODE_DIRECT) { DebugInformation((L"DfsUtil: Failed direct communication with DFS metadata, status 0x%x\n", dwErr)); ErrorMessage(MSG_ROOT_DIRECT_FAILED, dwErr); break; } else if (CmdRequiresDirect == TRUE) { ErrorMessage(MSG_ROOT_DIRECT_REQUIRED_FAILED, dwErr); break; } else { Mode = MODE_API; } } else { DirectModeInitialized = TRUE; } }
if (CmdRequiresDirect && (DirectModeInitialized == FALSE)) { ErrorMessage(MSG_ROOT_DIRECT_REQUIRED); break; }
if (fSwUpdateWin2kStaticSiteTable) { DfsRoot *pOperateRoot = NULL; dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, TRUE, // site aware
&pOperateRoot); if (dwErr == ERROR_SUCCESS) { dwErr = ProcessRootForSite(pOperateRoot ); }
if(pOperateRoot) { pOperateRoot->Close(); } break; }
if (fSwPurgeWin2kStaticSiteTable) { DfsRoot *pOperateRoot = NULL; dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, FALSE, &pOperateRoot); if (dwErr == ERROR_SUCCESS) { dwErr = PurgeSiteInformationForRoot(pOperateRoot ); }
if(pOperateRoot) { pOperateRoot->Close(); } break; } if (fSwShowWin2kStaticSiteTable)
{ DfsRoot *pOperateRoot = NULL; PVOID pBuffer = NULL; ULONG Size = 0;
dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, FALSE, &pOperateRoot);
if (dwErr == ERROR_SUCCESS) { dwErr = pOperateRoot->RootGetSiteBlob(&pBuffer, &Size); }
if (dwErr == ERROR_SUCCESS) { dwErr = DumpSiteBlob((PVOID)pBuffer, Size, TRUE); } if(pOperateRoot) { pOperateRoot->Close(); } break; }
//
// Importing a namespace from a script file.
//
if (fArgImport) {
DfsRoot *pMasterRoot; DfsRoot *pOperateRoot;
dwErr = DfsReadDocument( ImportFile, &pMasterRoot );
if (dwErr == ERROR_SUCCESS) { if (fSwBlobSize) { ULONG RootBlobSize = 0;
extern DFSSTATUS SizeRoot(DfsRoot *pRoot, PULONG pSize);
dwErr = SizeRoot(pMasterRoot, &RootBlobSize); if (dwErr == ERROR_SUCCESS) { ShowInformation((L"\n\nApproximate blob size for import file is %.2f Megabytes\n\n", (DOUBLE)RootBlobSize / (1024 * 1024)));
} } else if (fSwView) { DumpRoots(pMasterRoot, ShowHandle, FALSE); } else { dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, FALSE, &pOperateRoot );
if (dwErr == ERROR_SUCCESS) { //
// Iterate over the (real) options.
//
if (fSwCompare) { VerifyDfsRoots(pOperateRoot, pMasterRoot); } else if (fSwSet) { dwErr = SetDfsRoots(pOperateRoot, pMasterRoot, BackupHandle, fSwNoBackup); } else if (fSwMerge) { dwErr = MergeDfsRoots( pOperateRoot, pMasterRoot, BackupHandle, fSwNoBackup); } pOperateRoot->Close(); } } pMasterRoot->Close(); } break; } else if (fArgImportRoot) { DfsRoot *pMasterRoot; DfsRoot *pOperateRoot; dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, FALSE, &pOperateRoot );
if (dwErr == ERROR_SUCCESS) { dwErr = DfsBuildNameSpaceInformation( &MasterNameSpace, DCToUse, Mode, FALSE, &pMasterRoot ); if ((dwErr == ERROR_SUCCESS) && (fSwVerbose == TRUE)) { DumpRoots( pMasterRoot, ShowHandle, FALSE); }
if (dwErr == ERROR_SUCCESS) { //
// Iterate over the (real) options.
//
if (fSwCompare) { VerifyDfsRoots(pOperateRoot, pMasterRoot); } else if (fSwMirror) { dwErr = SetDfsRoots(pOperateRoot, pMasterRoot, BackupHandle, fSwNoBackup); } pMasterRoot->Close(); } pOperateRoot->Close(); } break; } else if (fArgDisplayBlob) { dwErr = DfsReadFromFile( DisplayBlobFile ); break; } else if (fArgExportBlob) { dwErr = DfsReadFromAD( OperateNameSpace.GetServerString(), OperateNameSpace.GetShareString(), ExportBlobFile, DCToUse); break; } else if (fSwCheckBlob) { dwErr = DfsReadFromAD( OperateNameSpace.GetServerString(), OperateNameSpace.GetShareString(), NULL, DCToUse); break; } else if (fSwView) { if (fArgDomain) { dwErr = DfsEnumerateDomainDfs(pwszDomainName); } else if (fArgServer) { dwErr = DfsEnumerateMachineDfs(pwszServerName); } else { DfsRoot *pOperateRoot;
dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, TRUE, &pOperateRoot ); if (dwErr == ERROR_SUCCESS) { dwErr = DumpRoots( pOperateRoot, ShowHandle, FALSE);
pOperateRoot->Close(); } } break; } else if (fArgExport) { DfsRoot *pOperateRoot; dwErr = DfsBuildNameSpaceInformation( &OperateNameSpace, DCToUse, Mode, FALSE, &pOperateRoot ); if (dwErr == ERROR_SUCCESS) { dwErr = DumpRoots( pOperateRoot, ExportHandle, TRUE);
pOperateRoot->Close(); } break; }
if (fSwRenameFtRoot) { PVOID DirectModeHandle = NULL; dwErr = DfsDirectApiOpen( OperateNameSpace.GetPathString(), DCToUse, &DirectModeHandle);
if (dwErr == ERROR_SUCCESS) { //
// Now do the rename. Note that we only use the first component.
// If users enter /olddomain:\\xx.y.com\z we simply use xx.y.com without
// the \\ or the sharename.
//
dwErr = DfsRenameLinksToDomain( &OperateNameSpace, OldDomainName.GetServerString(), NewDomainName.GetServerString()); if (dwErr == ERROR_SUCCESS) { SetDirectHandleWriteable(DirectModeHandle); dwErr = DfsDirectApiCommitChanges( DirectModeHandle); } DfsDirectApiClose( DirectModeHandle); } break; }
if (fSwUnmapFtRoot) { dwErr = CmdUnmapRootReplica( OperateNameSpace.GetPathString(), pwszServerName, pwszShareName );
break; }
if (fArgSiteName) { DfsString Site;
dwErr = GetSites( ClientForSiteName.GetString(), &Site );
if (dwErr == ERROR_SUCCESS) { ShowInformation((L"\n\nSite for %wS is %wS\n\n", ClientForSiteName.GetString(), Site.GetString())); } break; }
if (fSwInsite || fSwSiteCosting || fSwRootScalability) { PVOID DirectModeHandle = NULL; ULONG Attrib = 0; ULONG AttribMask = 0; LPWSTR AttribString;
if (fSwInsite) { AttribMask = PKT_ENTRY_TYPE_INSITE_ONLY; AttribString = L"InSite Referrals"; } else if (fSwSiteCosting) { AttribMask = PKT_ENTRY_TYPE_COST_BASED_SITE_SELECTION; AttribString = L"Cost-based Site Selection"; } else { AttribMask = PKT_ENTRY_TYPE_ROOT_SCALABILITY; AttribString = L"Root Scalability"; }
dwErr = DfsDirectApiOpen( OperateNameSpace.GetPathString(), DCToUse, &DirectModeHandle);
if (dwErr == ERROR_SUCCESS) {
dwErr = DfsExtendedRootAttributes( DirectModeHandle, &Attrib, OperateNameSpace.GetRemainingCountedString(), FALSE ); if (dwErr == ERROR_SUCCESS) { if (fSwDisplay) { MyPrintf(L"Namespace %ws: %ws %ws\n", OperateNameSpace.GetPathString(), AttribString, ((Attrib & AttribMask) == AttribMask) ? L"ENABLED" : L"DISABLED"); } else {
SetDirectHandleWriteable(DirectModeHandle);
if (fSwEnable) Attrib |= AttribMask; else Attrib &= ~AttribMask;
dwErr = DfsExtendedRootAttributes( DirectModeHandle, &Attrib, OperateNameSpace.GetRemainingCountedString(), TRUE ); if (dwErr == ERROR_SUCCESS) { dwErr = DfsDirectApiCommitChanges( DirectModeHandle); }
if (dwErr == ERROR_SUCCESS) { (VOID) ReSynchronizeRootTargetsFromPath(&OperateNameSpace); } } } DfsDirectApiClose( DirectModeHandle); } else if (fSwInsite) { DWORD PrevErr = dwErr; // Save this error in case of failure
DebugInformation((L"Failure getting Windows .Net ExtendedAttributes for %wZ, Status 0x%x\n", OperateNameSpace.GetPathCountedString(), dwErr));
// Get the existing attrs. The root name will have to match although it's win2k.
dwErr = DfsExtendedWin2kRootAttributes( &OperateNameSpace, &Attrib, FALSE ); if (dwErr == ERROR_SUCCESS) { if (fSwDisplay) { MyPrintf(L"Namespace %ws: %ws %ws\n", OperateNameSpace.GetPathString(), AttribString, ((Attrib & AttribMask) == AttribMask) ? L"ENABLED" : L"DISABLED"); } else { if (fSwEnable) Attrib |= AttribMask; else Attrib &= ~AttribMask;
// Set or reset this attr.
dwErr = DfsExtendedWin2kRootAttributes( &OperateNameSpace, &Attrib, TRUE ); } } //
// If we couldn't find a win2k root by this name, then return the original error.
//
if (dwErr != ERROR_SUCCESS) { dwErr = PrevErr; } } break; }
if (fSwPurgeMupCache) {
dwErr = PurgeMupCache(NULL); break; } dwErr = Usage();
} while( FALSE );
if (CoInitialized) { CoUninitialize(); }
if (dwErr == ERROR_SUCCESS) { if (CommandSucceeded) { ErrorMessage( MSG_SUCCESSFUL ); } else { ErrorMessage( MSG_COMMAND_DONE ); } } else { LPWSTR MessageBuffer; DWORD dwBufferLength;
dwBufferLength = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &MessageBuffer, 0, NULL);
ErrorMessage(MSG_ERROR, dwErr); if (dwBufferLength > 0) { MyPrintf(L"%ws\r\n", MessageBuffer); LocalFree(MessageBuffer); } ErrorMessage( MSG_COMMAND_DONE ); } WPP_CLEANUP(); return dwErr; }
//
// This is a laborious function that checks the current
// argument for a match. DfsDbgPrints here are just
// examples of random optimism: the /Verbose option has to
// come before the current argument in order for those
// lines to get printed.
//
BOOLEAN CmdProcessArg(LPWSTR Arg) { LONG ArgLen; BOOLEAN Terminate = FALSE; BOOLEAN FoundAnArg = FALSE; DFSSTATUS Status = ERROR_SUCCESS;
if ( Arg != NULL && wcslen(Arg) > 1) {
Terminate = FALSE; ArgLen = wcslen(Arg);
if (_wcsnicmp(Arg, ArgRemFtRoot, ArgLenRemFtRoot) == 0) { FoundAnArg = fArgRemFtRoot = TRUE; if (ArgLen > ArgLenRemFtRoot) pwszLogicalName = &Arg[ArgLenRemFtRoot]; } else if (_wcsnicmp(Arg, ArgShare, ArgLenShare) == 0) { FoundAnArg = fArgShare = TRUE; if (ArgLen > ArgLenShare) pwszShareName = &Arg[ArgLenShare]; if (pwszLogicalName == NULL) pwszLogicalName = pwszShareName; } else if (_wcsnicmp(Arg, ArgServer, ArgLenServer) == 0) { FoundAnArg = fArgServer = TRUE; if (ArgLen > ArgLenServer) pwszServerName = &Arg[ArgLenServer]; } else if (_wcsnicmp(Arg, ArgDomain, ArgLenDomain) == 0) { FoundAnArg = fArgDomain = TRUE; if (ArgLen > ArgLenDomain) pwszDomainName = &Arg[ArgLenDomain]; } else if (_wcsnicmp(Arg, ArgPktFlush, ArgLenPktFlush) == 0) { FoundAnArg = fArgPktFlush = TRUE; if (ArgLen > ArgLenPktFlush) pwszEntryToFlush = &Arg[ArgLenPktFlush]; } else if (_wcsnicmp(Arg, ArgSpcFlush, ArgLenSpcFlush) == 0) { FoundAnArg = fArgSpcFlush = TRUE; if (ArgLen > ArgLenSpcFlush) pwszEntryToFlush = &Arg[ArgLenSpcFlush]; } else if (_wcsnicmp(Arg, ArgLevel, ArgLenLevel) == 0) { FoundAnArg = fArgLevel = TRUE; if (ArgLen > ArgLenLevel) pwszHexValue = &Arg[ArgLenLevel]; } //
// DfsAdmin options
//
else if (_wcsnicmp(Arg, ArgImport, ArgLenImport) == 0) { FoundAnArg = fArgImport = TRUE; ImportFile = &Arg[ArgLenImport]; if (wcslen(ImportFile) == 0) { ErrorMessage( MSG_USAGE_IMPORT ); Terminate = TRUE; ImportFile = NULL; } } else if (_wcsnicmp(Arg, ArgDisplayBlob, ArgLenDisplayBlob) == 0) { FoundAnArg = fArgDisplayBlob = TRUE; DisplayBlobFile = &Arg[ArgLenDisplayBlob]; if (wcslen(DisplayBlobFile) == 0) { ErrorMessage( MSG_USAGE_DISPLAY_BLOB ); Terminate = TRUE; ImportFile = NULL; } } else if (_wcsnicmp(Arg, ArgExportBlob, ArgLenExportBlob) == 0) { FoundAnArg = fArgExportBlob = TRUE; ExportBlobFile = &Arg[ArgLenExportBlob]; if (wcslen(ExportBlobFile)==0) { ErrorMessage( MSG_USAGE_EXPORT_BLOB ); Terminate = TRUE; ExportBlobFile = NULL; } } else if (_wcsnicmp(Arg, ArgExport, ArgLenExport) == 0) { FoundAnArg = fArgExport = TRUE; ExportFile = &Arg[ArgLenExport]; if (wcslen(ExportFile) == 0) { ErrorMessage( MSG_USAGE_EXPORT ); Terminate = TRUE; ExportFile = NULL; } else { Status = CreateDfsFile(ExportFile, &ExportHandle); } } else if (_wcsnicmp(Arg, ArgBackup, ArgLenBackup) == 0) { FoundAnArg = fArgBackup = TRUE; BackupFile = &Arg[ArgLenBackup]; if (wcslen(BackupFile) == 0) { ErrorMessage( MSG_USAGE_EXPORT ); Terminate = TRUE; BackupFile = NULL; } else { Status = CreateDfsFile(BackupFile, &BackupHandle); } } else if (_wcsnicmp(Arg, ArgDebugDC, ArgLenDebugDC) == 0) { FoundAnArg = fArgDebugDC = TRUE; DCToUse = &Arg[ArgLenDebugDC]; Status = GetDCInformation(); Mode = MODE_DIRECT; } else if (_wcsnicmp(Arg, ArgRoot, ArgLenRoot) == 0) { FoundAnArg = fArgRoot = TRUE; Status = OperateNameSpace.CreatePathName(&Arg[ArgLenRoot]); } else if (_wcsnicmp(Arg, ArgImportRoot, ArgLenImportRoot) == 0) { FoundAnArg = fArgImportRoot = TRUE; Status = MasterNameSpace.CreatePathName(&Arg[ArgLenImportRoot]); } else if (_wcsnicmp(Arg, ArgDebugFile, ArgLenDebugFile) == 0) { FoundAnArg = fArgDebugFile = TRUE; DebugFile = &Arg[ArgLenDebugFile]; if (wcslen(DebugFile) == 0) { //Status = ERROR_INVALID_PARAMETER;
Terminate = TRUE; DebugFile = NULL; } else { Status = CreateDfsFile(DebugFile, &DebugHandle); } } else if (_wcsnicmp(Arg, ArgOldDomain, ArgLenOldDomain) == 0) { FoundAnArg = fArgOldDomain = TRUE; Status = OldDomainName.CreatePathName( &Arg[ArgLenOldDomain] ); } else if (_wcsnicmp(Arg, ArgNewDomain, ArgLenNewDomain) == 0) { FoundAnArg = fArgNewDomain = TRUE; Status = NewDomainName.CreatePathName( &Arg[ArgLenNewDomain] ); } else if (_wcsnicmp(Arg, ArgUnmapFtRoot, ArgLenUnmapFtRoot) == 0) { FoundAnArg = fArgUnmapFtRoot = TRUE; } else if (_wcsnicmp(Arg, ArgViewDfsDirs, ArgLenViewDfsDirs) == 0) { FoundAnArg = fArgViewDfsDirs = TRUE; pwszVolumeName = &Arg[ArgLenViewDfsDirs]; }/*
else if (_wcsnicmp(Arg, ArgRemoveReparse, ArgLenRemoveReparse) == 0) { FoundAnArg = fArgRemoveReparse = TRUE; pwszDfsDirectoryName = &Arg[ArgLenRemoveReparse]; }*/ else if (_wcsnicmp(Arg, ArgSiteName, ArgLenSiteName) == 0) { FoundAnArg = fArgSiteName = TRUE; Status = ClientForSiteName.CreateString(&Arg[ArgLenSiteName]); }
// Switches go at the end!!
else if (_wcsicmp(Arg, SwDebug) == 0) { FoundAnArg = fSwDebug = TRUE; } else if (_wcsicmp(Arg, SwNoBackup) == 0) { FoundAnArg = fSwNoBackup = TRUE; } else if (_wcsicmp(Arg, SwVerbose) == 0) { FoundAnArg = fSwVerbose = TRUE; } else if (_wcsicmp(Arg, SwPktFlush) == 0) { FoundAnArg = fSwPktFlush = TRUE; } else if (_wcsicmp(Arg, SwSpcFlush) == 0) { FoundAnArg = fSwSpcFlush = TRUE; } else if (_wcsicmp(Arg, SwPktInfo) == 0) { FoundAnArg = fSwPktInfo = TRUE; } else if (_wcsicmp(Arg, SwSpcInfo) == 0) { FoundAnArg = fSwSpcInfo = TRUE; } else if (_wcsicmp(Arg, SwDfs) == 0) { FoundAnArg = fSwDfs = TRUE; } else if (_wcsicmp(Arg, SwAll) == 0) { FoundAnArg = fSwSpcInfo = TRUE; } else if (_wcsicmp(Arg, SwQ) == 0) { FoundAnArg = fSwQ = fSwHelp = TRUE; } else if (_wcsicmp(Arg, SwScriptHelp) == 0) { FoundAnArg = fSwScriptHelp = TRUE; } else if (_wcsicmp(Arg, SwHelp) == 0) { FoundAnArg = fSwHelp = TRUE; } else if (_wcsicmp(Arg, SwSet) == 0) { FoundAnArg = fSwSet = TRUE; } else if (_wcsicmp(Arg, SwMirror) == 0) { FoundAnArg = fSwMirror = TRUE; } else if (_wcsicmp(Arg, SwRemStdRoot) == 0) { FoundAnArg = fSwRemStdRoot = TRUE; } else if (_wcsicmp(Arg, SwRemFtRoot) == 0) { FoundAnArg = fSwRemFtRoot = TRUE; } else if (_wcsicmp(Arg, SwCompare) == 0) { FoundAnArg = fSwCompare = TRUE; } else if (_wcsicmp(Arg, SwCheckBlob) == 0) { FoundAnArg = fSwCheckBlob = TRUE; } else if (_wcsicmp(Arg, SwMerge) == 0) { FoundAnArg = fSwMerge = TRUE; } else if (_wcsicmp(Arg, SwRenameFtRoot) == 0) { FoundAnArg = fSwRenameFtRoot = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwDirect) == 0) { //
// This is switched on by default when appropriate.
// If the user specifies this then it means that
// she only wants to operate in Direct mode.
//
FoundAnArg = TRUE; fSwDirect = TRUE; UserRequiresDirectMode = TRUE; Mode = MODE_DIRECT; } else if (_wcsicmp(Arg, SwView) == 0) { FoundAnArg = fSwView = TRUE; ExportHandle = ShowHandle; } else if (_wcsicmp(Arg, SwImport) == 0) { FoundAnArg = fSwImport = TRUE; } else if (_wcsicmp(Arg, SwImportRoot) == 0) { FoundAnArg = fSwImportRoot = TRUE; } else if (_wcsicmp(Arg, SwBlobSize) == 0) { FoundAnArg = fSwBlobSize = TRUE; } else if (_wcsicmp(Arg, SwSiteName) == 0) { FoundAnArg = fSwSiteName = TRUE; } else if (_wcsicmp(Arg, SwExport) == 0) { FoundAnArg = fSwExport = TRUE; } else if (_wcsicmp(Arg, SwRoot) == 0) { FoundAnArg = fSwRoot = TRUE; } else if ((_wcsicmp(Arg, SwUnmapFtRoot) == 0) || (_wcsicmp(Arg, SwUnmap) == 0)) { FoundAnArg = fSwUnmapFtRoot = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwClean) == 0) { //
// This contacts the target registry directly but doesn't involve a
// direct mode to do so.
//
FoundAnArg = fSwClean = TRUE; } else if (_wcsicmp(Arg, SwEnable) == 0) { FoundAnArg = fSwEnable = TRUE; } else if (_wcsicmp(Arg, SwDisable) == 0) { FoundAnArg = fSwDisable = TRUE; } else if (_wcsicmp(Arg, SwDisplay) == 0) { FoundAnArg = fSwDisplay = TRUE; } else if (_wcsicmp(Arg, SwInsite) == 0) { FoundAnArg = fSwInsite = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwAddStdRoot) == 0) { FoundAnArg = fSwAddStdRoot = TRUE; } else if (_wcsicmp(Arg, SwAddFtRoot) == 0) { FoundAnArg = fSwAddFtRoot = TRUE; } else if (_wcsicmp(Arg, SwApi) == 0) { FoundAnArg = fSwApi = TRUE; Mode = MODE_API; } else if (_wcsicmp(Arg, SwRemoveReparse) == 0) { FoundAnArg = fSwRemoveReparse = TRUE; } else if (_wcsicmp(Arg, SwSiteCosting) == 0) { FoundAnArg = fSwSiteCosting = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwRootScalability) == 0) { FoundAnArg = fSwRootScalability = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwPurgeMupCache) == 0) { FoundAnArg = fSwPurgeMupCache = TRUE; } else if (_wcsicmp(Arg, SwUpdateWin2kStaticSiteTable) == 0) { FoundAnArg = fSwUpdateWin2kStaticSiteTable = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwShowWin2kStaticSiteTable) == 0) { FoundAnArg = fSwShowWin2kStaticSiteTable = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwPurgeWin2kStaticSiteTable) == 0) { FoundAnArg = fSwPurgeWin2kStaticSiteTable = TRUE; CmdRequiresDirect = TRUE; } else if (_wcsicmp(Arg, SwViewDfsDirs) == 0) { FoundAnArg = fSwViewDfsDirs = TRUE; } else if (_wcsicmp(Arg, SwDisplayBlob) == 0) { FoundAnArg = fSwDisplayBlob = TRUE; } else if (_wcsicmp(Arg, SwExportBlob) == 0) { FoundAnArg = fSwExportBlob = TRUE; }
//
// Done processing Arguments and Switches.
// Decide whether to terminate or not.
//
if (FoundAnArg == FALSE) { ErrorMessage(MSG_UNRECOGNIZED_OPTION, &Arg[1]); Terminate = TRUE; }
if (Status != ERROR_SUCCESS) { ErrorMessage(MSG_ERROR, Status); Terminate = TRUE; } }
return Terminate; }
DWORD Usage() {
ErrorMessage(MSG_USAGE);
return ERROR_SUCCESS; }
DFSSTATUS CmdCheckSyntax( BOOLEAN& Done ) {
// the following require a namespace to work with
// BlobSize cmd works without a root.
#define REQUIRES_ROOT_NAME (fArgExport || fSwRenameFtRoot || fSwInsite || fSwMirror || \
(fArgImport && !fSwBlobSize) || \ fSwSiteCosting || fArgDebugDC || \ fArgImportRoot || fSwRootScalability || \ fArgExportBlob || fSwCheckBlob)
DFSSTATUS dwErr = ERROR_SUCCESS; Done = FALSE; do { if ((fSwHelp == TRUE) || ((OperateNameSpace.IsEmptyPath() == TRUE) && (REQUIRES_ROOT_NAME) )) { if (fArgImport || fSwImport || fSwBlobSize) { ErrorMessage( MSG_USAGE_IMPORT ); } else if (fArgExport || fSwExport) { ErrorMessage( MSG_USAGE_EXPORT ); } else if (fSwRenameFtRoot) { ErrorMessage( MSG_USAGE_RENAME ); } else if (fSwUnmapFtRoot) { ErrorMessage( MSG_USAGE_UNMAP ); } else if (fSwClean) { ErrorMessage( MSG_USAGE_CLEAN ); } else if (fSwInsite) { ErrorMessage( MSG_USAGE_INSITE ); } else if (fSwSiteCosting) { ErrorMessage( MSG_USAGE_SITECOSTING ); } else if (fSwAddFtRoot || fSwAddStdRoot) { ErrorMessage( MSG_USAGE_ADDROOT ); } else if (fSwRemFtRoot || fArgRemFtRoot) { ErrorMessage( MSG_USAGE_REM_FTROOT ); } else if (fSwRemStdRoot) { ErrorMessage( MSG_USAGE_REM_STDROOT ); } else if (fArgSiteName || fSwSiteName) { ErrorMessage( MSG_USAGE_SITENAME ); } else if (fSwView) { ErrorMessage( MSG_USAGE_VIEW ); } else if (fArgImportRoot || fSwImportRoot) { ErrorMessage( MSG_USAGE_IMPORT_ROOT); } else if (fSwCheckBlob) { ErrorMessage( MSG_USAGE_CHECK_BLOB ); } else if (fSwExportBlob || fArgExportBlob) { ErrorMessage( MSG_USAGE_EXPORT_BLOB ); } else if (fSwDisplayBlob || fArgDisplayBlob) { ErrorMessage( MSG_USAGE_DISPLAY_BLOB ); } else if (fSwRootScalability) { ErrorMessage( MSG_USAGE_ROOT_SCALABILITY ); } else if (fSwViewDfsDirs || fArgViewDfsDirs) { ErrorMessage( MSG_USAGE_VIEW_DIRS ); } else if (fSwRemoveReparse) { ErrorMessage( MSG_USAGE_VIEW_DIRS ); } else if (fSwPurgeMupCache) { ErrorMessage( MSG_USAGE_PURGE_MUP_CACHE ); } else if (fSwUpdateWin2kStaticSiteTable || fSwPurgeWin2kStaticSiteTable || fSwShowWin2kStaticSiteTable) { ErrorMessage( MSG_USAGE_W2K_SITETABLE ); } else if (fSwPktInfo) { ErrorMessage( MSG_USAGE_PKT_INFO ); } else if (fSwPktFlush) { ErrorMessage( MSG_USAGE_PKT_FLUSH ); } else if (fSwSpcInfo) { ErrorMessage( MSG_USAGE_SPC_INFO ); } else if (fSwSpcFlush) { ErrorMessage( MSG_USAGE_SPC_FLUSH ); } else { dwErr = Usage(); } Done = TRUE; break; }
if (fSwView) { if (!(fArgDomain || fArgRoot || fArgServer || fArgImport)) { ErrorMessage(MSG_USAGE_VIEW); Done = TRUE; break; } }
// Set, merge and verify work with import.
if (fArgImport) { if (!(fSwSet || fSwMerge || fSwCompare || fSwView || fSwBlobSize)) {
MyPrintf(L"You must specify one of /View, /Set, /Merge, /BlobSize or /Compare to Import\n"); ErrorMessage( MSG_USAGE_IMPORT ); Done = TRUE; break; }
}
if (fSwInsite) { if (!(fSwEnable || fSwDisable || fSwDisplay)) { MyPrintf(L"You must specify one of /Enable, /Disable or /Display with /Insite command.\n"); ErrorMessage( MSG_USAGE_INSITE ); Done = TRUE; break; }
if (OperateNameSpace.IsEmptyPath() == TRUE) { MyPrintf(L"You must specify a DFS root with /Insite command.\n"); ErrorMessage( MSG_USAGE_INSITE ); Done = TRUE; break; } if (fSwApi) { MyPrintf(L"Insite command does not work in the /Api mode. Use default.\n"); ErrorMessage( MSG_USAGE_INSITE ); Done = TRUE; break; } } else if (fSwSiteCosting) { if (!(fSwEnable || fSwDisable || fSwDisplay)) { MyPrintf(L"You must specify one of /Enable, /Disable or /Display with /SiteCosting command.\n"); ErrorMessage( MSG_USAGE_SITECOSTING ); Done = TRUE; break; } if ((OperateNameSpace.IsEmptyPath() == TRUE) || (IsEmptyString(OperateNameSpace.GetRemainingString()) == FALSE)) { MyPrintf(L"You must specify a well-formed DFS root with /SiteCosting command.\n"); ErrorMessage( MSG_USAGE_SITECOSTING ); Done = TRUE; break; }
if (fSwApi) { MyPrintf(L"SiteCosting command does not work in the /Api mode. Use default.\n"); ErrorMessage( MSG_USAGE_SITECOSTING ); Done = TRUE; break; } } else if (fSwRootScalability) { if (!(fSwEnable || fSwDisable || fSwDisplay)) { MyPrintf(L"You must specify one of /Enable, /Disable or /Display with /RootScalability command.\n"); // ErrorMessage( MSG_USAGE_ROOTSCALABILITY);
Done = TRUE; break; } if ((OperateNameSpace.IsEmptyPath() == TRUE) || (IsEmptyString(OperateNameSpace.GetRemainingString()) == FALSE)) { MyPrintf(L"You must specify a DFS root with /RootScalability command.\n"); // ErrorMessage( MSG_USAGE_ROOTSCALABILITY);
Done = TRUE; break; }
if (fSwApi) { MyPrintf(L"RootScalability command does not work in the /Api mode. Use default.\n"); // ErrorMessage( MSG_USAGE_ROOTSCALABILITY);
Done = TRUE; break; } }
// These three dont work with any other command (except for /Set with Insite).
else if ((fSwSet || fSwMerge) && (!fArgImport)) {
MyPrintf(L"/Set and /Merge options apply only to /Import: command.\n"); Done = TRUE; break; } else if ((fSwMirror) && (!fArgImportRoot)) {
MyPrintf(L"/Mirror option applies only to /ImportRoot: command.\n"); Done = TRUE; break; } else if ((fSwCompare) && ((!fArgImportRoot) && (!fArgImport))) {
MyPrintf(L"/Compare option applies only to /Import: or /ImportRoot: commands.\n"); Done = TRUE; break; }
if ((fSwView) && (fArgExport || fSwRenameFtRoot)) {
MyPrintf(L"The /View command cannot be combined with others.\n"); Usage(); Done = TRUE; break; }
if (fSwRenameFtRoot) {
if (NewDomainName.IsEmptyPath() == TRUE || OldDomainName.IsEmptyPath() == TRUE || (OperateNameSpace.IsEmptyPath() == TRUE)) { ErrorMessage( MSG_USAGE_RENAME ); Done = TRUE; break; } DebugInformation((L"DfsUtil: New domain name will be %wS\n", NewDomainName.GetServerString())); DebugInformation((L"DfsUtil: Old domain to be renamed is %wS\n", OldDomainName.GetServerString())); }
if ((fArgUnmapFtRoot) || // Arg gets an automatic usage.
((fSwUnmapFtRoot) && ( (OperateNameSpace.IsEmptyPath() == TRUE) || (pwszServerName == NULL) || (pwszShareName == NULL)))) {
ErrorMessage( MSG_USAGE_UNMAP ); Done = TRUE; break; }
if ((fArgClean) || // Arg gets an automatic usage.
((fSwClean) && ((pwszServerName == NULL) || (pwszShareName == NULL)))) {
ErrorMessage( MSG_USAGE_CLEAN ); Done = TRUE; break; }
if (fSwClean) { DWORD Status; //
// We don't allow domain names here. That can lead to incorrect
// results as well as data loss.
//
Status = IsThisADomainName( pwszServerName, NULL ); if (Status == ERROR_SUCCESS) { MyPrintf(L"/Server: parameter must be the name of a DFS root server. It cannot be a domain name\n"); ErrorMessage( MSG_USAGE_CLEAN ); Done = TRUE; break; } } if ( fSwAddStdRoot && (IsEmptyString( pwszServerName ) || IsEmptyString( pwszShareName ))) { MyPrintf(L"You must specify a valid target server and a share for the new root\n"); ErrorMessage( MSG_USAGE_ADDROOT ); Done = TRUE; break; }
if ((fArgRemFtRoot || fSwRemFtRoot || fSwRemStdRoot) && (IsEmptyString( pwszServerName ) || IsEmptyString( pwszShareName ))) {
MyPrintf(L"You must specify a valid target server and a share to remove.\n"); if (fSwRemStdRoot) ErrorMessage( MSG_USAGE_REM_STDROOT ); else ErrorMessage( MSG_USAGE_REM_FTROOT ); Done = TRUE; break; }
/*if ((fArgRemoveReparse) && // Arg gets an automatic usage.
(pwszDfsDirectoryName == NULL)) { MyPrintf(L"You must specify a volume name\n"); Done = TRUE; break; }*/
if (fArgViewDfsDirs) { if (pwszVolumeName == NULL) { MyPrintf(L"You must specify a directory name\n"); Done = TRUE; break; } if (wcschr(pwszVolumeName, ':') == NULL) { MyPrintf(L"The volume drive letter must contain a colon at the end.\n"); ErrorMessage( MSG_USAGE_VIEW_DIRS ); Done = TRUE; break; } }
//
// If at this point we have a root:\\x\y, we need to make sure that we have
// exactly two path components. It is too cumbersome to use REQUIRES_ROOT_NAME
// check here because there are options like /View that needs /Root only for some cases.
//
if ((OperateNameSpace.IsEmptyPath() != TRUE) && ((IsEmptyString(OperateNameSpace.GetShareString()) == TRUE) || (IsEmptyString(OperateNameSpace.GetRemainingString()) == FALSE)) && (fSwInsite == FALSE)) { MyPrintf(L"Root must be of the form \\\\DomainOrServer\\RootName.\n"); Done = TRUE; break; }
if (OperateNameSpace.IsEmptyPath() != TRUE) { //
// Now that we have valid args, check to see if there are any exceptions to
// the rules we've applied so far. For example, we Standalone roots
// and Direct mode won't mix well for some switches of /Import cmd.
//
dwErr = CmdCheckExceptions( &OperateNameSpace ); if (dwErr != ERROR_SUCCESS) { Done = TRUE; break; } }
if (MasterNameSpace.IsEmptyPath() != TRUE) { dwErr = CmdCheckExceptions( &MasterNameSpace ); if (dwErr != ERROR_SUCCESS) { Done = TRUE; break; } } if (fArgDebugDC != NULL) { if (DCInfoStatus != ERROR_SUCCESS) { MyPrintf(L"Could not get information from DC %wS, error 0x%x\n", DCToUse, DCInfoStatus); Done = TRUE; break; } if (OperateNameSpace.IsEmptyPath() != TRUE) { if (DfsIsThisADomainName(OperateNameSpace.GetServerString()) == ERROR_SUCCESS) { if ((RtlCompareUnicodeString(OperateNameSpace.GetServerCountedString(), &DCToUseFlatDomainName, TRUE) != 0) && (RtlCompareUnicodeString(OperateNameSpace.GetServerCountedString(), &DCToUseDNSDomainName, TRUE) != 0)) { MyPrintf(L"DC %ws belongs to %wZ domain, and not to %wS domain\n", DCToUse, &DCToUseDNSDomainName, OperateNameSpace.GetServerString());
Done = TRUE; break; } } } if (MasterNameSpace.IsEmptyPath() != TRUE) { if (DfsIsThisADomainName(MasterNameSpace.GetServerString()) == ERROR_SUCCESS) { if ((RtlCompareUnicodeString(MasterNameSpace.GetServerCountedString(), &DCToUseFlatDomainName, TRUE) != 0) && (RtlCompareUnicodeString(MasterNameSpace.GetServerCountedString(), &DCToUseDNSDomainName, TRUE) != 0)) { MyPrintf(L"DC %ws belongs to %wZ domain, and not to %wS domain\n", DCToUse, &DCToUseDNSDomainName, MasterNameSpace.GetServerString()); Done = TRUE; break;
} } } } } while (FALSE);
return dwErr; }
DFSSTATUS CmdInitializeDirectMode( PBOOLEAN pCoInitialized) { DFSSTATUS Status; HRESULT Hr = S_OK; *pCoInitialized = FALSE;
Hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE); if (Hr == S_OK) { *pCoInitialized = TRUE; Status = DfsServerLibraryInitialize(DFS_DIRECT_MODE|DFS_DONT_SUBSTITUTE_PATHS); } else { Status = DfsGetErrorFromHr(Hr); }
return Status; }
DWORD ReSynchronizeRootTargets( IN LPWSTR PathString) { DfsPathName PathName; DFSSTATUS Status;
Status = PathName.CreatePathName(PathString); if (Status == ERROR_SUCCESS) { Status = ReSynchronizeRootTargetsFromPath(&PathName); } return Status; }
DWORD ReSynchronizeRootTargetsFromPath( IN DfsPathName *pPathName) { DFSSTATUS Status, SetStatus; LPBYTE pBuffer = NULL; DWORD ResumeHandle = 0; DWORD EntriesRead = 0; DWORD PrefMaxLen = 1; DWORD Level = 4; PDFS_INFO_4 pCurrentBuffer; DWORD i; PDFS_STORAGE_INFO pStorage; LPWSTR DfsPathString;
DfsPathString = pPathName->GetPathString(); //
// We are reading in just the ROOT.
//
Status = DfsApiEnumerate( MODE_DIRECT, DfsPathString, Level, PrefMaxLen, &pBuffer, &EntriesRead, &ResumeHandle); if ((Status == ERROR_SUCCESS) && EntriesRead != 0) { pCurrentBuffer = (PDFS_INFO_4)pBuffer;
//
// Now contact the appropriate server(s) for the root replicas
// and ask them to re-read their roots. Things have been
// changed under them.
//
for( i = 0, pStorage = pCurrentBuffer->Storage; i < pCurrentBuffer->NumberOfStorages; i++, pStorage = pCurrentBuffer->Storage + i ) { SetStatus = SetInfoReSynchronize( pStorage->ServerName, pPathName->GetShareString()); //
// We just go on to the next server since we don't do any undo's anyway.
//
if (SetStatus != ERROR_SUCCESS) Status = SetStatus; }
//
// Free the allocated memory.
//
DfsFreeApiBuffer(pBuffer);
} return Status; }
//
// the following code exists to read and write the old style static
// site table in the AD blob.
//
//
typedef struct _DFS_SITE_UPDATE { UNICODE_STRING Server; UNICODE_STRING Site; struct _DFS_SITE_UPDATE *pNext; } DFS_SITE_UPDATE, *PDFS_SITE_UPDATE;
DFS_SITE_UPDATE *pSiteList = NULL; PDFS_SITE_UPDATE pSiteNext = NULL; struct _DFS_PREFIX_TABLE *pServerSiteTable;
VOID DumpSiteInformation( PUNICODE_STRING pServer, PUNICODE_STRING pSite ) { ShowInformation((L"Server %wZ, Site %wZ\n", pServer, pSite)); }
DFSSTATUS DumpSiteBlob( PVOID pBuffer, ULONG Size, BOOLEAN Display ) {
PVOID pUseBuffer = pBuffer; ULONG RemainingSize = Size; GUID SiteGuid; UNICODE_STRING Server, Site; DFSSTATUS Status = ERROR_SUCCESS; ULONG Objects = 0, SiteNum, NumSites, Flags;
if (Size == 0) { if (Display) { ShowInformation((L"\nSite Blob with %d sites\n", Objects)); } return Status; }
Status = PackGetGuid(&SiteGuid, &pUseBuffer, &RemainingSize); if (Status == ERROR_SUCCESS) { Status = PackGetULong( &Objects, &pUseBuffer, &RemainingSize ); }
if (Display) { ShowInformation((L"\nSite Blob with %d sites\n", Objects)); } if (Status == ERROR_SUCCESS) { for (SiteNum = 0; SiteNum < Objects; SiteNum++) { Status = PackGetString( &Server, &pUseBuffer, &RemainingSize); if (Status == ERROR_SUCCESS) { Status = PackGetULong( &NumSites, &pUseBuffer, &RemainingSize); } if (Status == ERROR_SUCCESS) { Status = PackGetULong( &Flags, &pUseBuffer, &RemainingSize); } if (Status == ERROR_SUCCESS) { Status = PackGetString( &Site, &pUseBuffer, &RemainingSize); } if (Status != ERROR_SUCCESS) { break; }
if (Display) { DumpSiteInformation(&Server, &Site); } } } return Status; }
DFSSTATUS AddServerToSiteList( PUNICODE_STRING pServerName, PUNICODE_STRING pSiteName ) { NTSTATUS NtStatus = STATUS_SUCCESS; BOOLEAN Insert = FALSE; PDFS_SITE_UPDATE pSiteUpdate; UNICODE_STRING RemainingName; PVOID pData; BOOLEAN SubStringMatch; DFSSTATUS Status = ERROR_SUCCESS;
NtStatus = DfsPrefixTableAcquireWriteLock( pServerSiteTable ); if ( NtStatus == STATUS_SUCCESS ) { NtStatus = DfsFindUnicodePrefixLocked( pServerSiteTable, pServerName, &RemainingName, &pData, &SubStringMatch ); if (NtStatus != STATUS_SUCCESS) { Insert = TRUE;
NtStatus = DfsInsertInPrefixTableLocked( pServerSiteTable, pServerName, pSiteName); } else { Insert = FALSE; NtStatus = STATUS_SUCCESS; } DfsPrefixTableReleaseLock( pServerSiteTable ); }
if (NtStatus != STATUS_SUCCESS) { Status = RtlNtStatusToDosError(NtStatus); }
if (Status == ERROR_SUCCESS) { if (Insert) { pSiteUpdate = new DFS_SITE_UPDATE;
if (pSiteUpdate == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; }
if (Status == ERROR_SUCCESS) { Status = DfsCreateUnicodeString( &pSiteUpdate->Server, pServerName); }
if (Status == ERROR_SUCCESS) { Status = DfsCreateUnicodeString( &pSiteUpdate->Site, pSiteName); }
if (Status == ERROR_SUCCESS) { pSiteUpdate->pNext = NULL;
if (pSiteList == NULL) { pSiteList = pSiteUpdate;
} else { pSiteNext->pNext = pSiteUpdate; } pSiteNext = pSiteUpdate; } } }
return Status; }
DFSSTATUS ProcessTargetForSite( DfsTarget *pTarget ) { PUNICODE_STRING pServer, pSite; DFSSTATUS Status = ERROR_SUCCESS;
for (; pTarget != NULL; pTarget = pTarget->GetNextTarget()) { pServer = pTarget->GetTargetServerCountedString(); pSite = pTarget->GetTargetSiteCountedString(); if (pSite->Length != 0) { Status = AddServerToSiteList( pServer, pSite); } if (Status != ERROR_SUCCESS) { break; } } return Status; }
ULONG SizeSiteInformationBlob( PDFS_SITE_UPDATE pSiteUpdate) { ULONG Size = 0;
Size += PackSizeString(&pSiteUpdate->Server); Size += PackSizeULong(); Size += PackSizeULong(); Size += PackSizeString(&pSiteUpdate->Site);
return Size; }
DFSSTATUS UpdateSiteBlob( DfsRoot *pRoot) { PDFS_SITE_UPDATE pSiteUpdate;
GUID NewGuid; ULONG TotalObjects = 0; DFSSTATUS Status; ULONG SiteBlobSize; PBYTE pBuffer; PVOID pUseBuffer; ULONG SizeRemaining;
pSiteUpdate = pSiteList;
Status = UuidCreate(&NewGuid); if (Status != ERROR_SUCCESS) { return Status; }
SiteBlobSize = sizeof(ULONG) + sizeof(GUID);
pSiteUpdate = pSiteList; while (pSiteUpdate != NULL) { SiteBlobSize += SizeSiteInformationBlob(pSiteUpdate); TotalObjects++; pSiteUpdate = pSiteUpdate->pNext; }
pBuffer = new BYTE[SiteBlobSize]; if (pBuffer == NULL) { return ERROR_NOT_ENOUGH_MEMORY; }
pUseBuffer = pBuffer; SizeRemaining = SiteBlobSize;
Status = PackSetGuid( &NewGuid, &pUseBuffer, &SizeRemaining); if (Status == ERROR_SUCCESS) { Status = PackSetULong( TotalObjects, &pUseBuffer, &SizeRemaining ); }
pSiteUpdate = pSiteList; while (pSiteUpdate != NULL) { Status = PackSetString( &pSiteUpdate->Server, &pUseBuffer, &SizeRemaining ); if (Status == ERROR_SUCCESS) { //
// We allow only 1 site information for each server.
//
Status = PackSetULong( 1, &pUseBuffer, &SizeRemaining ); }
if (Status == ERROR_SUCCESS) { //
// Flags: alwyas 0.
//
Status = PackSetULong( 0, &pUseBuffer, &SizeRemaining ); }
if (Status == ERROR_SUCCESS) { Status = PackSetString( &pSiteUpdate->Site, &pUseBuffer, &SizeRemaining ); }
pSiteUpdate = (PDFS_SITE_UPDATE)(pSiteUpdate->pNext); }
if (Status == ERROR_SUCCESS) { PUNICODE_STRING pRootToUpdate = pRoot->GetLinkNameCountedString(); pRoot->SetRootApiName(pRootToUpdate); pRoot->SetRootWriteable();
Status = pRoot->RootSetSiteBlob(pBuffer, SiteBlobSize); if (Status == ERROR_SUCCESS) { Status = pRoot->UpdateMetadata(); } }
delete [] pBuffer;
return Status; }
DFSSTATUS PurgeSiteBlob( DfsRoot *pRoot) { PDFS_SITE_UPDATE pSiteUpdate = NULL;
GUID NewGuid; ULONG TotalObjects = 0; DFSSTATUS Status = ERROR_SUCCESS; ULONG SiteBlobSize = 0; PBYTE pBuffer = NULL; PVOID pUseBuffer = NULL; ULONG SizeRemaining = 0;
pSiteUpdate = pSiteList;
Status = UuidCreate(&NewGuid); if (Status != ERROR_SUCCESS) { return Status; }
SiteBlobSize = sizeof(ULONG) + sizeof(GUID);
pBuffer = new BYTE[SiteBlobSize]; if (pBuffer == NULL) { return ERROR_NOT_ENOUGH_MEMORY; }
pUseBuffer = pBuffer; SizeRemaining = SiteBlobSize;
Status = PackSetGuid( &NewGuid, &pUseBuffer, &SizeRemaining); if (Status == ERROR_SUCCESS) { Status = PackSetULong( TotalObjects, &pUseBuffer, &SizeRemaining ); }
if (Status == ERROR_SUCCESS) { PUNICODE_STRING pRootToUpdate = pRoot->GetLinkNameCountedString(); pRoot->SetRootApiName(pRootToUpdate); pRoot->SetRootWriteable();
Status = pRoot->RootSetSiteBlob(pBuffer, SiteBlobSize); if (Status == ERROR_SUCCESS) { pRoot->UpdateMetadata(); } }
delete [] pBuffer;
return Status; }
DFSSTATUS ProcessRootForSite( DfsRoot *pRoot ) { DFSSTATUS Status = ERROR_SUCCESS; DfsLink *pLink = NULL;
Status = DfsInitializePrefixTable( &pServerSiteTable, FALSE, NULL ); if ( Status != ERROR_SUCCESS ) { return Status; }
Status = ProcessTargetForSite(pRoot->GetFirstTarget());
if (Status == ERROR_SUCCESS) { for (pLink = pRoot->GetFirstLink(); pLink != NULL; pLink = pLink->GetNextLink()) { Status = ProcessTargetForSite( pLink->GetFirstTarget()); if (Status != ERROR_SUCCESS) { break; } } }
if (Status == ERROR_SUCCESS) { Status = UpdateSiteBlob(pRoot); } return Status; }
DFSSTATUS PurgeSiteInformationForRoot( DfsRoot *pRoot ) { DFSSTATUS Status = ERROR_SUCCESS;
Status = DfsInitializePrefixTable( &pServerSiteTable, FALSE, NULL ); if ( Status != ERROR_SUCCESS ) { return Status; }
if (Status == ERROR_SUCCESS) { Status = PurgeSiteBlob(pRoot); } return Status; }
DFSSTATUS IsRootStandalone( DfsPathName *Namespace, BOOLEAN& IsStandalone ) { DFSSTATUS Status; LPBYTE pBuffer = NULL; DWORD RootFlavor = 0; IsStandalone = FALSE; Status = NetDfsGetInfo( Namespace->GetPathCountedString()->Buffer, NULL, NULL, 3, &pBuffer );
if (Status == ERROR_SUCCESS) { RootFlavor = ((PDFS_INFO_3)pBuffer)->State & DFS_VOLUME_FLAVORS;
//
// There is no real easy way to find out the type of a Win2K root. The FLAVORS bit
// is post-win2k. In that case, err on the safe side and return Standalone.
//
if (RootFlavor == 0) { DebugInformation((L"NetDfsGetInfo returns 0 for DFS_VOLUME_FLAVORS. Assuming a standalone root\n")); IsStandalone = TRUE; } else if (RootFlavor == DFS_VOLUME_FLAVOR_STANDALONE) { IsStandalone = TRUE; } NetApiBufferFree( pBuffer ); }
return Status; }
//+----------------------------------------------------------------------------
//
// Function: IsThisADomainName
//
// Synopsis: Calls the mup to have it check the special name table to see if the
// name matches a domain name. Returns a list of DC's in the domain,
// as a list of strings. The list is terminated with a double-null.
//
// Arguments: [wszName] -- Name to check
// [ppList] -- Pointer to pointer for results.
//
// Returns: [ERROR_SUCCESS] -- Name is indeed a domain name.
//
// [ERROR_FILE_NOT_FOUND] -- Name is not a domain name
//
//-----------------------------------------------------------------------------
DWORD IsThisADomainName( IN LPWSTR wszName, OUT PWCHAR *ppList OPTIONAL) { NTSTATUS NtStatus; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING DfsDriverName; HANDLE DriverHandle = NULL; DWORD dwErr; PCHAR OutBuf = NULL; ULONG Size = 0x100; ULONG Count = 0;
RtlInitUnicodeString(&DfsDriverName, DFS_DRIVER_NAME);
InitializeObjectAttributes( &objectAttributes, &DfsDriverName, OBJ_CASE_INSENSITIVE, NULL, NULL );
NtStatus = NtCreateFile( &DriverHandle, SYNCHRONIZE, &objectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
if (!NT_SUCCESS(NtStatus)) { return ERROR_FILE_NOT_FOUND; }
Retry:
OutBuf = (PCHAR)malloc(Size);
if (OutBuf == NULL) {
NtClose(DriverHandle); return ERROR_NOT_ENOUGH_MEMORY;
}
NtStatus = NtFsControlFile( DriverHandle, NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock, FSCTL_DFS_GET_SPC_TABLE, wszName, (wcslen(wszName) + 1) * sizeof(WCHAR), OutBuf, Size );
if (NtStatus == STATUS_SUCCESS) {
dwErr = ERROR_SUCCESS;
} else if (NtStatus == STATUS_BUFFER_OVERFLOW && ++Count < 5) {
Size = *((ULONG *)OutBuf); free(OutBuf); goto Retry; } else {
dwErr = ERROR_FILE_NOT_FOUND;
}
NtClose(DriverHandle);
if (ppList == NULL) { free(OutBuf); OutBuf = NULL; } else { *ppList = (WCHAR *)OutBuf; } return dwErr; }
DFSSTATUS CmdCheckExceptions( DfsPathName *pNameSpace) { DFSSTATUS Status = ERROR_SUCCESS;
//
// 733898 : disable /Import and /ImportRoot writable operations
// over direct mode for standalone roots. This is so that
// we won't race with DfsSvc's synchronize and possibly
// create inconsistencies.
// Besides since direct mode registry blob updates aren't
// 'atomic' import can create inconsistencies anyway.
//
if ((fArgImport && (fSwSet || fSwMerge)) || (fArgImportRoot && (fSwMirror))) { BOOLEAN IsStandalone = FALSE; do { Status = IsRootStandalone( pNameSpace, IsStandalone );
// Err on the safe side if we get an error doing GetInfo.
if (Status != ERROR_SUCCESS || (IsStandalone)) { if (UserRequiresDirectMode) { MyPrintf(L"Import /Set, /Merge and ImportRoot /Mirror commands on Standalone roots must use API mode.\n"); ErrorMessage( MSG_USAGE_IMPORT ); Status = ERROR_INVALID_PARAMETER; break; }
DebugInformation((L"%ws is a Standalone root. Switching to API mode for this operation.\n", pNameSpace->GetPathCountedString()->Buffer)); Mode = MODE_API; }
// Don't return GetInfo errors. Those aren't fatal.
Status = ERROR_SUCCESS; } while (FALSE); } return Status; }
|