WindowsXP/base/fs/remotefs/dfs/dfsserver/serverlibrary/dfsregistryrootfolder.cxx
2025-04-27 07:49:33 -04:00

255 lines
7.1 KiB
C++

//+----------------------------------------------------------------------------
//
// 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();
}
//
// 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())
{
GetRootClusterInformation( pLogicalShare,
&_DfsVisibleContext);
}
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( )
{
DFSSTATUS Status;
HKEY RootKey;
ULONG ChildNum = 0;
FILETIME LastModifiedTime;
DFS_TRACE_HIGH(REFERRAL_SERVER, "Synchronize for %p\n", this);
Status = AcquireRootLock();
if (Status != ERROR_SUCCESS)
{
return Status;
}
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.
//
DFSSTATUS RootStatus = AcquireRootShareDirectory();
DFS_TRACE_ERROR_LOW(RootStatus, REFERRAL_SERVER, "Recognize Dfs: Root folder for %p, validate status %x\n",
this, RootStatus );
//
// if we are in a standby mode, we dont synchronize, till we obtain
// ownership again.
//
Status = GetMetadataKey( &RootKey );
if ( Status == ERROR_SUCCESS )
{
do
{
//
// For each child, get the child name.
//
DWORD ChildNameLen = DFS_REGISTRY_CHILD_NAME_SIZE_MAX;
WCHAR ChildName[DFS_REGISTRY_CHILD_NAME_SIZE_MAX];
Status = RegEnumKeyEx( RootKey,
ChildNum,
ChildName,
&ChildNameLen,
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 );
}
//
// If the child is holding information we dont understand, just
// skip that child.
//
if ( Status == ERROR_INVALID_DATA )
{
DFSLOG("DfsREgistryRootFolder: synchronize: skipping child %wS\n", ChildName );
Status = ERROR_SUCCESS;
}
} while ( Status == ERROR_SUCCESS );
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 );
}
DFS_TRACE_HIGH(REFERRAL_SERVER, "Synchronize for %p, Status %x\n", this, Status);
ReleaseRootLock();
return Status;
}