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
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;
|
|
}
|
|
|
|
|
|
|