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.
 
 
 
 
 
 

361 lines
11 KiB

//+----------------------------------------------------------------------------
//
// Copyright (C) 2000, Microsoft Corporation
//
// File: DfsRegistryRootFolder.cxx
//
// Contents: the Root DFS Folder class for Registry Store
//
// Classes: DfsRegistryRootFolder
//
// History: Dec. 8 2000, Author: udayh
//
//-----------------------------------------------------------------------------
#include "DfsRegistryRootFolder.hxx"
#include "DfsReplica.hxx"
#include "lmdfs.h"
#include "DfsClusterSupport.hxx"
//
// logging specific includes
//
#include "DfsRegistryRootFolder.tmh"
//+----------------------------------------------------------------------------
//
// Class: DfsRegistryRootFolder
//
// Synopsis: This class implements The Dfs Registry root folder.
//
//-----------------------------------------------------------------------------
//+-------------------------------------------------------------------------
//
// Function: DfsRegistryRootFolder - constructor
//
// Arguments: NameContext - the dfs name context
// pLogicalShare - the logical share
// pParentStore - the parent store for this root.
// pStatus - the return status
//
// Returns: NONE
//
// Description: This routine initializes a RegistryRootFolder instance
//
//--------------------------------------------------------------------------
DfsRegistryRootFolder::DfsRegistryRootFolder(
LPWSTR NameContext,
LPWSTR pRootRegKeyNameString,
PUNICODE_STRING pLogicalShare,
PUNICODE_STRING pPhysicalShare,
DfsRegistryStore *pParentStore,
DFSSTATUS *pStatus ) : DfsRootFolder ( NameContext,
pRootRegKeyNameString,
pLogicalShare,
pPhysicalShare,
DFS_OBJECT_TYPE_REGISTRY_ROOT_FOLDER,
pStatus )
{
DFSSTATUS Status = *pStatus;
_pStore = pParentStore;
if (_pStore != NULL)
{
_pStore->AcquireReference();
}
_RootFlavor = DFS_VOLUME_FLAVOR_STANDALONE;
//
// If the namecontext that we are passed is an emptry string,
// then we are dealing with the referral server running on the root
// itself. We are required to ignore the name context for such
// roots during lookups, so that aliasing works. (Aliasing is where
// someone may access the root with an aliased machine name or ip
// address)
//
if (IsEmptyString(NameContext) == TRUE)
{
SetIgnoreNameContext();
_LocalCreate = TRUE;
}
//
// dfsdev: If this is cluster resource, we should set the visible name
// to virtual server name of this resource.
//
// The constructor for DfsRootFolder will be called before we
// get here, and pstatus will be initialized
//
if (Status == ERROR_SUCCESS)
{
if (DfsIsMachineCluster())
{
DFSSTATUS ClusterStatus;
ClusterStatus = GetRootClusterInformation( pLogicalShare,
&_DfsVisibleContext);
if (ClusterStatus != ERROR_SUCCESS)
{
RtlInitUnicodeString(&_DfsVisibleContext, NULL);
}
}
if (IsEmptyString(_DfsVisibleContext.Buffer))
{
Status = DfsGetMachineName( &_DfsVisibleContext );
}
}
*pStatus = Status;
}
//+-------------------------------------------------------------------------
//
// Function: Synchronize
//
// Arguments: None
//
// Returns: Status: Success or Error status code
//
// Description: This routine synchronizes the children folders
// of this root.
//
//--------------------------------------------------------------------------
DFSSTATUS
DfsRegistryRootFolder::Synchronize( BOOLEAN fForceSynch, BOOLEAN CalledByApi )
{
DFSSTATUS Status = ERROR_SUCCESS;
HKEY RootKey = NULL;
ULONG ChildNum = 0;
DWORD CchMaxName = 0;
DWORD CchChildName = 0;
LPWSTR ChildName = NULL;
FILETIME LastModifiedTime;
UNICODE_STRING NewClusterName;
UNREFERENCED_PARAMETER(fForceSynch);
DFS_TRACE_NORM(REFERRAL_SERVER, "Synchronize for %p\n", this);
RtlInitUnicodeString(&NewClusterName, NULL);
if (DfsIsMachineCluster())
{
DFSSTATUS IgnoreStatus;
IgnoreStatus = GetRootClusterInformation( GetLogicalShare(),
&NewClusterName);
ASSERT((IgnoreStatus == ERROR_SUCCESS) ||
(NewClusterName.Buffer == NULL));
}
Status = AcquireRootLock();
if (Status != ERROR_SUCCESS)
{
return Status;
}
if (NewClusterName.Length != 0)
{
DFSSTATUS ClusterNameStatus;
BOOLEAN Changed = FALSE;
ClusterNameStatus = SetVisibleContext( &NewClusterName, &Changed );
//
// if the cluster information has changed, get rid of cached
// referral.
//
if (ClusterNameStatus == ERROR_SUCCESS)
{
if (Changed)
{
RemoveReferralData(NULL, NULL);
}
}
DfsFreeUnicodeString(&NewClusterName);
DFS_TRACE_LOW(REFERRAL_SERVER, "SetVisbleContext, status %x\n",
ClusterNameStatus);
}
if (CheckRootFolderSkipSynchronize() == TRUE)
{
ReleaseRootLock();
return ERROR_SUCCESS;
}
//
// now acquire the root share directory. If this
// fails, we continue our operation: we can continue
// with synchonize and not create directories.
// dfsdev:we need to post a eventlog or something when
// we run into this.
//
do
{
DFSSTATUS RootStatus = AcquireRootShareDirectory();
if(CalledByApi && (RootStatus != ERROR_SUCCESS))
{
DFS_TRACE_ERROR_LOW(RootStatus, REFERRAL_SERVER, "Recognize Dfs: Root folder for %p, validate status %x\n",
this, RootStatus );
Status = RootStatus;
break;
}
//
// if we are in a standby mode, we dont synchronize, till we obtain
// ownership again.
//
Status = GetMetadataKey( &RootKey );
if ( Status == ERROR_SUCCESS )
{
{
DFS_METADATA_HANDLE DfsHandle;
DfsHandle = CreateMetadataHandle(RootKey);
UpdateLinkInformation( DfsHandle, NULL );
DestroyMetadataHandle(DfsHandle );
}
//
// Iterate over all our folders to make sure they actually
// exist in the registry.
//
CheckPreSynchronize( RootKey );
//
// First find the length of the longest subkey
// and allocate a buffer big enough for it.
//
Status = RegQueryInfoKey( RootKey, // Key
NULL, // Class string
NULL, // Size of class string
NULL, // Reserved
NULL, // # of subkeys
&CchMaxName, // max size of subkey name in TCHARs
NULL, // max size of class name
NULL, // # of values
NULL, // max size of value name
NULL, // max size of value data,
NULL, // security descriptor
NULL ); // Last write time
if (Status == ERROR_SUCCESS)
{
// Space for the NULL terminator.
CchMaxName++;
ChildName = (LPWSTR) new WCHAR [CchMaxName];
if (ChildName == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
}
if (Status == ERROR_SUCCESS)
{
do
{
//
// For each child, get the child name.
//
CchChildName = CchMaxName;
Status = RegEnumKeyEx( RootKey,
ChildNum,
ChildName,
&CchChildName,
NULL,
NULL,
NULL,
&LastModifiedTime );
ChildNum++;
//
// Call update on the child. This either adds a new folder
// or if it exists, ensure the child folder is upto date.
//
if ( Status == ERROR_SUCCESS )
{
DFS_METADATA_HANDLE DfsHandle;
DfsHandle = CreateMetadataHandle(RootKey);
Status = UpdateLinkInformation( DfsHandle,
ChildName );
DestroyMetadataHandle(DfsHandle );
}
} while ( Status == ERROR_SUCCESS );
delete [] ChildName;
}
if ( Status == ERROR_NO_MORE_ITEMS )
{
Status = ERROR_SUCCESS;
}
//
// We are done with synchronize.
// update the Root folder, so that this root folder may be made
// either available or unavailable, as the case may be.
//
if (Status == ERROR_SUCCESS)
{
SetRootFolderSynchronized();
}
else
{
ClearRootFolderSynchronized();
}
//
// Now release the Root metadata key.
//
ReleaseMetadataKey( RootKey );
}
if(CalledByApi && (Status != ERROR_SUCCESS))
{
DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "Recognize Dfs: Registry Synchronize Root folder for %p, validate status %x\n",
this, Status );
(void) ReleaseRootShareDirectory();
}
} while (0);
DFS_TRACE_NORM(REFERRAL_SERVER, "Synchronize for %p, Status %x\n", this, Status);
ReleaseRootLock();
return Status;
}