2025-04-27 07:49:33 -04:00

390 lines
11 KiB
C++

//+----------------------------------------------------------------------------
//
// Copyright (C) 2000, Microsoft Corporation
//
// File: DfsADBlobRootFolder.cxx
//
// Contents: the Root DFS Folder class for ADBlob Store
//
// Classes: DfsADBlobRootFolder
//
// History: Dec. 8 2000, Author: udayh
// April 14 2001 Rohanp - Modified to use ADSI code
//
//-----------------------------------------------------------------------------
#include "DfsADBlobRootFolder.hxx"
#include "DfsReplica.hxx"
#include "lmdfs.h"
#include "dfserror.hxx"
#include "dfsmisc.h"
#include "dfsadsiapi.hxx"
#include "domaincontrollersupport.hxx"
#include "DfsSynchronizeRoots.hxx"
#if !defined(DFS_STORAGE_STATE_MASTER)
#define DFS_STORAGE_STATE_MASTER 0x0010
#endif
#if !defined(DFS_STORAGE_STATE_STANDBY)
#define DFS_STORAGE_STATE_STANDBY 0x0020
#endif
//
// logging specific includes
//
#include "DfsADBlobRootFolder.tmh"
//+----------------------------------------------------------------------------
//
// Class: DfsADBlobRootFolder
//
// Synopsis: This class implements The Dfs ADBlob root folder.
//
//-----------------------------------------------------------------------------
DFSSTATUS
GetBinaryFromVariant(VARIANT *ovData, BYTE ** ppBuf,
unsigned long * pcBufLen);
//+-------------------------------------------------------------------------
//
// Function: DfsADBlobRootFolder - 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 ADBlobRootFolder instance
//
//--------------------------------------------------------------------------
DfsADBlobRootFolder::DfsADBlobRootFolder(
LPWSTR NameContext,
LPWSTR pRootRegistryNameString,
PUNICODE_STRING pLogicalShare,
PUNICODE_STRING pPhysicalShare,
DfsADBlobStore *pParentStore,
DFSSTATUS *pStatus ) : DfsRootFolder ( NameContext,
pRootRegistryNameString,
pLogicalShare,
pPhysicalShare,
DFS_OBJECT_TYPE_ADBLOB_ROOT_FOLDER,
pStatus )
{
_pStore = pParentStore;
if (_pStore != NULL)
{
_pStore->AcquireReference();
}
*pStatus = ERROR_SUCCESS;
//
// 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;
}
_pBlobCache = new DfsADBlobCache(pStatus, GetLogicalShare());
if ( _pBlobCache == NULL )
{
*pStatus = ERROR_NOT_ENOUGH_MEMORY;
}
//
// Now we update our visible context, which is the dfs name context
// seen by people when they do api calls.
// For the ad blob root folder, this will be the domain name of this
// machine.
//
if(*pStatus == STATUS_SUCCESS)
{
*pStatus = DfsGetDomainName( &_DfsVisibleContext );
}
DFS_TRACE_LOW(REFERRAL_SERVER, "Created new root folder,%p, cache %p, name %wZ\n",
this, _pBlobCache, GetLogicalShare());
}
//+-------------------------------------------------------------------------
//
// Function: Synchronize
//
// Arguments: None
//
// Returns: Status: Success or Error status code
//
// Description: This routine synchronizes the children folders
// of this root.
//
//--------------------------------------------------------------------------
DFSSTATUS
DfsADBlobRootFolder::Synchronize( )
{
DFSSTATUS Status = ERROR_SUCCESS;
//
// Read from the metadata store, and unravel the blob.
// Update the ADBlobCache with the information of each individual
// link, deleting old inof, adding new info, and/or modifying
// existing information.
//
//
// if we are in a standby mode, we dont synchronize, till we obtain
// ownership again.
//
DFS_TRACE_LOW(REFERRAL_SERVER, "Synchronize started on root %p (%wZ)\n", this, GetLogicalShare());
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 (GetMetadataBlobCache()->CacheRefresh())
{
Status = EnumerateBlobCacheAndCreateFolders( );
if (Status == ERROR_SUCCESS)
{
SetRootFolderSynchronized();
}
else
{
ClearRootFolderSynchronized();
}
}
ReleaseRootLock();
DFS_TRACE_LOW(REFERRAL_SERVER, "Synchronize done on root %p, Status %x\n", this, Status);
return Status;
}
DFSSTATUS
DfsADBlobRootFolder::EnumerateBlobCacheAndCreateFolders( )
{
DFSSTATUS UpdateStatus;
DFSSTATUS Status = STATUS_SUCCESS;
DfsADBlobCache * pBlobCache = NULL;
PDFSBLOB_DATA pBlobData = NULL;
DFSBOB_ITER Iter;
pBlobCache = GetMetadataBlobCache();
pBlobData = pBlobCache->FindFirstBlob(&Iter);
while (pBlobData)
{
if (pBlobCache->IsStaleBlob(pBlobData))
{
DFSSTATUS RemoveStatus;
RemoveStatus = RemoveLinkFolder( pBlobData->BlobName.Buffer );
if (RemoveStatus == ERROR_SUCCESS)
{
RemoveStatus = pBlobCache->RemoveNamedBlob( &pBlobData->BlobName );
}
DFS_TRACE_ERROR_LOW(RemoveStatus, REFERRAL_SERVER, "Remove stale folder %ws, status %x\n",
pBlobData->BlobName.Buffer,
RemoveStatus );
}
else
{
UpdateStatus = UpdateLinkInformation((DFS_METADATA_HANDLE) pBlobCache,
pBlobData->BlobName.Buffer);
DFS_TRACE_ERROR_LOW(UpdateStatus, REFERRAL_SERVER,
"Root %p (%wZ) Ad Blob enumerate, update link returned %x for %wZ\n",
this, GetLogicalShare(), UpdateStatus, &pBlobData->BlobName);
if (UpdateStatus != ERROR_SUCCESS)
{
Status = UpdateStatus;
}
}
pBlobData = pBlobCache->FindNextBlob(&Iter);
}
pBlobCache->FindCloseBlob(&Iter);
DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER,
"Root %p (%wZ) Done with Enumerate blob and create folders, Status %x\n",
this, GetLogicalShare(), Status);
return Status;
}
DFSSTATUS
GetBinaryFromVariant(VARIANT *ovData, BYTE ** ppBuf,
unsigned long * pcBufLen)
{
DFSSTATUS Status = ERROR_INVALID_PARAMETER;
void * pArrayData = NULL;
//Binary data is stored in the variant as an array of unsigned char
if(ovData->vt == (VT_ARRAY|VT_UI1))
{
//Retrieve size of array
*pcBufLen = ovData->parray->rgsabound[0].cElements;
*ppBuf = new BYTE[*pcBufLen]; //Allocate a buffer to store the data
if(*ppBuf != NULL)
{
//Obtain safe pointer to the array
SafeArrayAccessData(ovData->parray,&pArrayData);
//Copy the bitmap into our buffer
memcpy(*ppBuf, pArrayData, *pcBufLen);
//Unlock the variant data
SafeArrayUnaccessData(ovData->parray);
Status = ERROR_SUCCESS;
}
else
{
Status = ERROR_NOT_ENOUGH_MEMORY;
DFS_TRACE_HIGH( REFERRAL_SERVER, "GetBinaryFromVariant failed error %d\n",Status);
}
}
return Status;
}
VOID
DfsADBlobRootFolder::SynchronizeRoots( )
{
DfsReferralData *pReferralData;
DFS_INFO_101 DfsState;
DFSSTATUS Status, SyncStatus;
DfsReplica *pReplica;
ULONG Target;
UNICODE_STRING DfsName;
PUNICODE_STRING pRootShare;
ULONG SyncCount = 0, ReplicaCount = 0;
BOOLEAN ImpersonationDisabled = FALSE;
DfsDisableRpcImpersonation(&ImpersonationDisabled);
DfsState.State = DFS_STORAGE_STATE_MASTER;
pRootShare = GetLogicalShare();
Status = DfsGenerateReferralDataFromRemoteServerNames( pRootShare->Buffer,
&pReferralData );
if (Status == ERROR_SUCCESS)
{
ReplicaCount = pReferralData->ReplicaCount;
for (Target = 0; Target < pReferralData->ReplicaCount; Target++)
{
PUNICODE_STRING pTargetServer, pTargetFolder;
pReplica = &pReferralData->pReplicas[ Target ];
pTargetServer = pReplica->GetTargetServer();
pTargetFolder = pRootShare;
if (DfsIsTargetCurrentMachine(pTargetServer))
{
continue;
}
Status = DfsCreateUnicodePathString( &DfsName,
2,
pTargetServer->Buffer,
pTargetFolder->Buffer );
if (Status == ERROR_SUCCESS)
{
SyncStatus = AddRootToSyncrhonize( &DfsName );
#if 0
SyncStatus = NetDfsSetInfo( DfsName.Buffer,
NULL,
NULL,
101,
(LPBYTE)&DfsState);
#endif
if (SyncStatus == ERROR_SUCCESS)
{
SyncCount++;
}
DfsFreeUnicodeString( &DfsName );
}
}
pReferralData->ReleaseReference();
}
if (ImpersonationDisabled)
{
DfsReEnableRpcImpersonation();
}
DFS_TRACE_LOW( REFERRAL_SERVER, "Synchronize roots %wZ done: %x roots, %x succeeded\n",
pRootShare, ReplicaCount, SyncCount);
return NOTHING;
}