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