390 lines
11 KiB
C++
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;
|
|
}
|
|
|
|
|