Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1449 lines
39 KiB

//+----------------------------------------------------------------------------
//
// Copyright (C) 2000, Microsoft Corporation
//
// File: DfsStore.hxx
//
// Contents: the base DFS Store class, this contains the common
// store functionality.
//
// Classes: DfsStore.
//
// History: Dec. 8 2000, Author: udayh
//
//-----------------------------------------------------------------------------
#ifndef __DFS_STORE__
#define __DFS_STORE__
#include "DfsGeneric.hxx"
#include "DfsRootFolder.hxx"
#include "lmdfs.h"
#include "rpc.h"
#include "rpcdce.h"
#include <DfsServerLibrary.hxx>
//
// The first part of this file contains the marshalling/unmarshalling
// routines that are used by the old stores (registry and AD)
// These routines help us read a binary blob and unravel their contents.
//
// the latter part defines the common store class for all our stores.
//
#define BYTE_0_MASK 0xFF
#define BYTE_0(Value) (UCHAR)( (Value) & BYTE_0_MASK)
#define BYTE_1(Value) (UCHAR)( ((Value) >> 8) & BYTE_0_MASK)
#define BYTE_2(Value) (UCHAR)( ((Value) >> 16) & BYTE_0_MASK)
#define BYTE_3(Value) (UCHAR)( ((Value) >> 24) & BYTE_0_MASK)
#define MTYPE_BASE_TYPE (0x0000ffffL)
#define MTYPE_COMPOUND (0x00000001L)
#define MTYPE_GUID (0x00000002L)
#define MTYPE_ULONG (0x00000003L)
#define MTYPE_USHORT (0x00000004L)
#define MTYPE_PWSTR (0x00000005L)
#define MTYPE_UCHAR (0x00000006L)
#define _MCode_Base(t,s,m,i)\
{t,offsetof(s,m),0L,0L,i}
#define _MCode_struct(s,m,i)\
_MCode_Base(MTYPE_COMPOUND,s,m,i)
#define _MCode_pwstr(s,m)\
_MCode_Base(MTYPE_PWSTR,s,m,NULL)
#define _MCode_ul(s,m)\
_MCode_Base(MTYPE_ULONG,s,m,NULL)
#define _MCode_guid(s,m)\
_MCode_Base(MTYPE_GUID,s,m,NULL)
#define _mkMarshalInfo(s, i)\
{(ULONG)sizeof(s),(ULONG)(sizeof(i)/sizeof(MARSHAL_TYPE_INFO)),i}
typedef struct _MARSHAL_TYPE_INFO
{
ULONG _type; // the type of item to be marshalled
ULONG _off; // offset of item (in the struct)
ULONG _cntsize; // size of counter for counted array
ULONG _cntoff; // else, offset count item (in the struct)
struct _MARSHAL_INFO * _subinfo;// if compound type, need info
} MARSHAL_TYPE_INFO, *PMARSHAL_TYPE_INFO;
typedef struct _MARSHAL_INFO
{
ULONG _size; // size of item
ULONG _typecnt; // number of type infos
PMARSHAL_TYPE_INFO _typeInfo; // type infos
} MARSHAL_INFO, *PMARSHAL_INFO;
typedef struct _DFS_NAME_INFORMATION_
{
PVOID pData;
ULONG DataSize;
UNICODE_STRING Prefix;
UNICODE_STRING ShortPrefix;
GUID VolumeId;
ULONG State;
ULONG Type;
UNICODE_STRING Comment;
FILETIME PrefixTimeStamp;
FILETIME StateTimeStamp;
FILETIME CommentTimeStamp;
ULONG Timeout;
ULONG Version;
FILETIME LastModifiedTime;
} DFS_NAME_INFORMATION, *PDFS_NAME_INFORMATION;
//
// Defines for ReplicaState.
//
#define REPLICA_STORAGE_STATE_OFFLINE 0x1
typedef struct _DFS_REPLICA_INFORMATION__
{
PVOID pData;
ULONG DataSize;
FILETIME ReplicaTimeStamp;
ULONG ReplicaState;
ULONG ReplicaType;
UNICODE_STRING ServerName;
UNICODE_STRING ShareName;
} DFS_REPLICA_INFORMATION, *PDFS_REPLICA_INFORMATION;
typedef struct _DFS_REPLICA_LIST_INFORMATION_
{
PVOID pData;
ULONG DataSize;
ULONG ReplicaCount;
DFS_REPLICA_INFORMATION *pReplicas;
} DFS_REPLICA_LIST_INFORMATION, *PDFS_REPLICA_LIST_INFORMATION;
extern MARSHAL_INFO MiFileTime;
#define INIT_FILE_TIME_INFO() \
static MARSHAL_TYPE_INFO _MCode_FileTime[] = { \
_MCode_ul(FILETIME, dwLowDateTime), \
_MCode_ul(FILETIME, dwHighDateTime), \
}; \
MARSHAL_INFO MiFileTime = _mkMarshalInfo(FILETIME, _MCode_FileTime);
//
// Marshalling info for DFS_REPLICA_INFO structure
//
extern MARSHAL_INFO MiDfsReplicaInfo;
#define INIT_DFS_REPLICA_INFO_MARSHAL_INFO() \
static MARSHAL_TYPE_INFO _MCode_DfsReplicaInfo[] = { \
_MCode_struct(DFS_REPLICA_INFORMATION, ReplicaTimeStamp, &MiFileTime), \
_MCode_ul(DFS_REPLICA_INFORMATION, ReplicaState), \
_MCode_ul(DFS_REPLICA_INFORMATION, ReplicaType), \
_MCode_pwstr(DFS_REPLICA_INFORMATION, ServerName), \
_MCode_pwstr(DFS_REPLICA_INFORMATION, ShareName), \
}; \
MARSHAL_INFO MiDfsReplicaInfo = _mkMarshalInfo(DFS_REPLICA_INFORMATION, _MCode_DfsReplicaInfo);
enum DfsRootListType {
NewRootList,
DeletedRootList,
OldRootList,
};
#define DFS_REGISTRY_CHILD_NAME_SIZE_MAX MAX_PATH
//
// The unmarshalling routines: the existing registry and AD stores
// store the information in binary blobs, and these routines
// help convert the binary data into meaningful data structures.
//
//+----------------------------------------------------------------------------
//
// Class: DfsStore
//
// Synopsis: This abstract class implements a basic DfsStore
// The DfsStore is derived by the actual store modules
// (such as registry, ad, etc) that implement the store
// specific recognize routines.
//
//-----------------------------------------------------------------------------
class DfsStore: public DfsGeneric
{
private:
CRITICAL_SECTION _Lock; // The lock for this store.
UNICODE_STRING _StoreName; // name of the store.
ULONG _GenerationNumber; // ?? TBD
BOOL _fCritInit;
protected:
DfsRootFolder *_DfsRootList; // The roots that this store
// knows about.
DfsRootFolder *_DfsDeletedRootList; // The roots that this store
// knows about.
DfsRootFolder *_DfsOldRootList;
public:
DfsStore *pNextRegisteredStore; // the next registered store.
private:
//
// Function AcquireLock: Acquires the lock on the store.
//
DFSSTATUS
AcquireLock()
{
DFSSTATUS Status = ERROR_SUCCESS;
EnterCriticalSection(&_Lock);
return Status;
}
protected:
DFSSTATUS
PackGetInformation(
ULONG_PTR Info,
IN OUT PVOID *ppBuffer,
PULONG pSizeRemaining,
PMARSHAL_INFO pMarshalInfo );
DFSSTATUS
PackSetInformation(
ULONG_PTR Info,
IN OUT PVOID *ppBuffer,
PULONG pSizeRemaining,
PMARSHAL_INFO pMarshalInfo );
ULONG
PackSizeInformation(
ULONG_PTR Info,
PMARSHAL_INFO pMarshalInfo );
DFSSTATUS
PackGetReplicaInformation(
PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
IN OUT PVOID *ppBuffer,
PULONG pSizeRemaining);
DFSSTATUS
PackSetReplicaInformation(
PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
IN OUT PVOID *ppBuffer,
PULONG pSizeRemaining);
ULONG
PackSizeReplicaInformation(
PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo );
DFSSTATUS
GetRootPhysicalShare(
HKEY RootKey,
PUNICODE_STRING pRootPhysicalShare );
VOID
ReleaseRootPhysicalShare(
PUNICODE_STRING pRootPhysicalShare );
DFSSTATUS
GetRootLogicalShare(
HKEY RootKey,
PUNICODE_STRING pRootLogicalShare );
VOID
ReleaseRootLogicalShare(
PUNICODE_STRING pRootLogicalShare );
DFSSTATUS
PackageEnumerationInfo(
DWORD Level,
DWORD EntryCount,
LPBYTE pLinkBuffer,
LPBYTE pBuffer,
LPBYTE *ppCurrentBuffer,
PLONG pSizeRemaining );
//
// Function GetDfsRegistryKey: This function takes a Name as the input,
// and looks up all DFS roots in that namespace.
static
DFSSTATUS
GetDfsRegistryKey( IN LPWSTR MachineName,
IN LPWSTR LocationString,
BOOLEAN WritePermission,
OUT BOOLEAN *pMachineContacted,
OUT PHKEY pDfsRegKey )
{
DFSSTATUS Status;
HKEY RootKey;
BOOLEAN Contacted = FALSE;
LPWSTR UseMachineName = NULL;
REGSAM DesiredAccess = KEY_READ;
if (WritePermission == TRUE)
{
DesiredAccess |= KEY_WRITE;
}
if (IsEmptyString(MachineName) == FALSE) {
UseMachineName = MachineName;
}
Status = RegConnectRegistry( UseMachineName,
HKEY_LOCAL_MACHINE,
&RootKey );
if ( Status == ERROR_SUCCESS )
{
Contacted = TRUE;
Status = RegOpenKeyEx( RootKey,
LocationString,
0,
DesiredAccess,
pDfsRegKey );
//
// There appears to be a bug in the registry code. When
// we connect to the local machine, the key that is returned
// in the RegConnectRegistry is HKEY_LOCAL_MACHINE. If we
// then attempt to close it here, it affects other threads
// that are using this code: they get STATUS_INVALID_HANDLE
// in some cases. So, dont close the key if it is
// HKEY_LOCAL_MACHINE.
//
if (RootKey != HKEY_LOCAL_MACHINE)
{
RegCloseKey( RootKey );
}
}
if (pMachineContacted != NULL)
{
*pMachineContacted = Contacted;
}
return Status;
}
static
DFSSTATUS
GetNewDfsRegistryKey( IN LPWSTR MachineName,
BOOLEAN WritePermission,
OUT BOOLEAN *pMachineContacted,
OUT PHKEY pDfsRegKey )
{
return GetDfsRegistryKey (MachineName,
DfsNewRegistryLocation,
WritePermission,
pMachineContacted,
pDfsRegKey );
}
//
// Function ReleaseMetadata: frees up space allocated when we
// got the metadata.
//
VOID
ReleaseMetadataBlob(
IN PVOID pBuffer )
{
if ( pBuffer != NULL )
{
delete [] pBuffer;
}
return NOTHING;
}
DFSSTATUS
AllocateMetadataBlob(
IN PVOID *ppBlob,
IN ULONG BlobSize )
{
DFSSTATUS Status = ERROR_SUCCESS;
*ppBlob = (PVOID)new BYTE [ BlobSize ];
if (*ppBlob == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return Status;
}
VOID
ReleaseMetadataNameBlob(
PVOID pBlob,
ULONG BlobSize )
{
UNREFERENCED_PARAMETER(BlobSize);
ReleaseMetadataBlob( pBlob );
}
VOID
ReleaseMetadataReplicaBlob(
PVOID pBlob,
ULONG BlobSize )
{
UNREFERENCED_PARAMETER(BlobSize);
ReleaseMetadataBlob( pBlob );
}
DFSSTATUS
AllocateMetadataNameBlob(
IN PVOID *ppBlob,
IN ULONG BlobSize )
{
return AllocateMetadataBlob(ppBlob, BlobSize);
}
DFSSTATUS
AllocateMetadataReplicaBlob(
IN PVOID *ppBlob,
IN ULONG BlobSize )
{
return AllocateMetadataBlob(ppBlob, BlobSize);
}
public:
//
// Function DfsStore: the constructor for the store. This initializes
// the critical section, and all the private and public variables
// of the store class.
//
DfsStore(LPWSTR Name, DfsObjectTypeEnumeration ObType, DFSSTATUS *pStatus) :
DfsGeneric(ObType)
{
USHORT NameLen = 0;
DFSSTATUS Status = ERROR_SUCCESS;
UNICODE_STRING Temp;
_fCritInit = FALSE;
_StoreName.Buffer = NULL;
//
// Create a unicode string from the passed in name, and
// initialize our unicode string name to the passed in name.
//
Status = DfsRtlInitUnicodeStringEx(&Temp, Name);
if(Status == ERROR_SUCCESS)
{
NameLen = wcslen(Name) + 1;
_StoreName.MaximumLength = NameLen * sizeof(WCHAR);
_StoreName.Buffer = new WCHAR [NameLen];
if(_StoreName.Buffer == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
}
if(Status == ERROR_SUCCESS)
{
RtlCopyUnicodeString(&_StoreName, &Temp);
_DfsRootList = NULL;
_DfsDeletedRootList = NULL;
_DfsOldRootList = NULL;
pNextRegisteredStore = NULL;
//
// The generation number exists to detect stale dfs folders.
// more on this later.
//
_GenerationNumber = 1;
_fCritInit = InitializeCriticalSectionAndSpinCount( &_Lock, DFS_CRIT_SPIN_COUNT );
if(!_fCritInit)
{
Status = GetLastError();
}
}
*pStatus = Status;
}
//
// Function ~DfsStore: the destructor of dfsstore. Free up
// the allocated resources.
// This is virtual, so that we call the right order of destructors
// for all the instances of classes derived from DfsStore.
//
virtual
~DfsStore()
{
// We could provide a mechanism to run through the list of
// root metadata, and release all of them, but that is
// unnecessary since we dont get rid of stores today.
// Once registered the stores live forever.
//
// Now free up the buffer we had allocated for the storename.
//
if (_StoreName.Buffer != NULL) {
delete [] _StoreName.Buffer;
}
if(_fCritInit)
{
DeleteCriticalSection( &_Lock );
}
}
static
DFSSTATUS
GetOldDfsRegistryKey( IN LPWSTR MachineName,
BOOLEAN WritePermission,
OUT BOOLEAN *pMachineContacted,
OUT PHKEY pDfsRegKey )
{
return GetDfsRegistryKey (MachineName,
DfsOldRegistryLocation,
WritePermission,
pMachineContacted,
pDfsRegKey );
}
static
DFSSTATUS
GetOldStandaloneRegistryKey( IN LPWSTR MachineName,
BOOLEAN WritePermission,
OUT BOOLEAN *pMachineContacted,
OUT PHKEY pDfsRegKey )
{
DFSSTATUS Status = ERROR_SUCCESS;
HKEY DfsKey = NULL;
*pDfsRegKey = NULL;
Status = GetOldDfsRegistryKey (MachineName,
WritePermission,
pMachineContacted,
&DfsKey );
if (Status == ERROR_SUCCESS)
{
*pDfsRegKey = DfsKey;
}
return Status;
}
static
DFSSTATUS
GetNewStandaloneRegistryKey( IN LPWSTR MachineName,
BOOLEAN WritePermission,
OUT BOOLEAN *pMachineContacted,
OUT PHKEY pDfsRegKey )
{
DFSSTATUS Status;
HKEY DfsKey;
Status = GetNewDfsRegistryKey (MachineName,
WritePermission,
pMachineContacted,
&DfsKey );
if (Status == ERROR_SUCCESS)
{
Status = RegOpenKeyEx( DfsKey,
DfsStandaloneChild,
0,
KEY_READ | (WritePermission ? KEY_WRITE : 0),
pDfsRegKey );
RegCloseKey( DfsKey);
}
return Status;
}
static
DFSSTATUS
GetNewADBlobRegistryKey( IN LPWSTR MachineName,
BOOLEAN WritePermission,
OUT BOOLEAN *pMachineContacted,
OUT PHKEY pDfsRegKey )
{
DFSSTATUS Status;
HKEY DfsKey;
Status = GetNewDfsRegistryKey (MachineName,
WritePermission,
pMachineContacted,
&DfsKey );
if (Status == ERROR_SUCCESS)
{
Status = RegOpenKeyEx( DfsKey,
DfsADBlobChild,
0,
KEY_READ | (WritePermission ? KEY_WRITE : 0),
pDfsRegKey );
RegCloseKey( DfsKey);
}
return Status;
}
//
// Function StoreRecognizer: This function takes a Name as the input,
// and looks up all DFS roots in that namespace.
// Since each store has its own mechanisms of identifying a root,
// the base class does not implement the StoreRecognizer. Each of
// the classes that are derived from the DfsStore class are expectged
// to override this function with their own implementation of the
// StoreRecognizer.
//
virtual
DFSSTATUS
StoreRecognizer(LPWSTR Name) = 0;
virtual
DFSSTATUS
StoreRecognizer(
LPWSTR Name,
PUNICODE_STRING Share) = 0;
DFSSTATUS
StoreRecognizeNewDfs(
LPWSTR DfsNameContext,
HKEY DfsKey );
DFSSTATUS
StoreRecognizeNewDfs (
LPWSTR DfsNameContext,
PUNICODE_STRING pLogicalShare );
//
// Function ReleaseLock: release the store lock.
//
VOID
ReleaseLock()
{
LeaveCriticalSection(&_Lock);
return NOTHING;
}
//
// Function AcquireWriteLock: Acquire the store lock exclusively.
// Currently all locks are exclusive, but this could change.
//
DFSSTATUS
AcquireWriteLock()
{
return AcquireLock();
}
//
// Function AcquireReadLock: Acquire the store lock shared.
// Currently all locks are exclusive, but this could change.
//
DFSSTATUS
AcquireReadLock()
{
return AcquireLock();
}
//
// Function AddRootFolder: This function takes a RootFolder and
// adds it to the list of known roots for this store.
// Each store instance keeps a list of all the Roots recognized by
// it.
//
// Make sure that we are adding only one root for a given metadata
// name and context, so that if multiple threads are working, only
// one will succeed.
//
//
DFSSTATUS
AddRootFolder(DfsRootFolder *pNewRoot,
DfsRootListType RootType )
{
DFSSTATUS Status = STATUS_SUCCESS;
DfsRootFolder *pRoot;
DfsRootFolder **ppList;
switch (RootType)
{
case NewRootList:
ppList = &_DfsRootList;
break;
case DeletedRootList:
ppList = &_DfsDeletedRootList;
break;
case OldRootList:
ppList = &_DfsOldRootList;
break;
default:
return STATUS_INVALID_PARAMETER;
break;
}
Status = AcquireWriteLock();
if ( Status != ERROR_SUCCESS )
return Status;
if ( *ppList == NULL )
{
*ppList = pNewRoot;
pNewRoot->pNextRoot = pNewRoot;
pNewRoot->pPrevRoot = pNewRoot;
}
else
{
pRoot = *ppList;
Status = ERROR_SUCCESS;
do
{
if ( (_wcsicmp( pRoot->GetRootRegKeyNameString(),
pNewRoot->GetRootRegKeyNameString()) == 0) &&
(_wcsicmp( pRoot->GetNameContextString(),
pNewRoot->GetNameContextString() ) == 0) )
{
Status = ERROR_FILE_EXISTS;
break;
}
pRoot = pRoot->pNextRoot;
} while ( pRoot != *ppList );
if (Status == ERROR_SUCCESS)
{
pNewRoot->pNextRoot = *ppList;
pNewRoot->pPrevRoot = (*ppList)->pPrevRoot;
(*ppList)->pPrevRoot->pNextRoot = pNewRoot;
(*ppList)->pPrevRoot = pNewRoot;
}
}
if (Status == ERROR_SUCCESS)
{
pNewRoot->AcquireReference();
}
ReleaseLock();
return Status;
}
//
// Function DeleteRootFolder: This function takes a RootFolder and
// removes it from the list of known roots for this store.
// This functions is not supported: any root that has been deleted
// will stay in the root list so that we can get to the statistics
// etc. Future action TBD.
//
DFSSTATUS
DeleteRootFolder(DfsRootFolder *pDfsRoot,
DfsRootListType RootType )
{
DFSSTATUS Status = STATUS_SUCCESS;
DfsRootFolder *pRoot;
DfsRootFolder **ppList;
switch (RootType)
{
case NewRootList:
ppList = &_DfsRootList;
break;
case DeletedRootList:
ppList = &_DfsDeletedRootList;
break;
case OldRootList:
ppList = &_DfsOldRootList;
break;
default:
return STATUS_INVALID_PARAMETER;
break;
}
Status = AcquireWriteLock();
if ( Status != ERROR_SUCCESS )
return Status;
for ( pRoot = *ppList; pRoot != NULL; pRoot = pRoot->pNextRoot )
{
if (pRoot == pDfsRoot)
{
if (pRoot->pNextRoot == pRoot)
{
*ppList = NULL;
}
else
{
pRoot->pNextRoot->pPrevRoot = pRoot->pPrevRoot;
pRoot->pPrevRoot->pNextRoot = pRoot->pNextRoot;
if (pRoot == *ppList)
{
*ppList = pRoot->pNextRoot;
}
}
pRoot->pNextRoot = NULL;
pRoot->pPrevRoot = NULL;
break;
}
}
ReleaseLock();
if (pRoot == NULL)
{
Status = ERROR_NOT_FOUND;
}
else
{
pRoot->ReleaseReference();
}
return Status;
}
DFSSTATUS
RemoveRootFolder( DfsRootFolder *pRootFolder,
BOOLEAN IsPermanent )
{
DFSSTATUS LinkDeleteStatus = ERROR_SUCCESS;
DFSSTATUS Status = ERROR_SUCCESS;
LinkDeleteStatus = pRootFolder->RemoveAllLinkFolders(IsPermanent);
pRootFolder->pStatistics->DumpStatistics(pRootFolder->GetLogicalShare());
Status = DeleteRootFolder( pRootFolder, NewRootList );
#if 0
if (Status == ERROR_SUCCESS) {
Status = AddRootFolder( pRootFolder, DeletedRootList );
}
#endif
return Status;
}
//
// Function LookupRoot: Takes a Dfs name context and logical share,
// and returns a Root that matches the passed in name context and
// logical share, if one exists.
// Note that the same DFS NC and logical share may exist in more than
// one store (though very unlikely). In this case, the first registered
// store wins.
//
DFSSTATUS
LookupRoot( PUNICODE_STRING pMachineName,
PUNICODE_STRING pLogicalShare,
DfsRootFolder **ppRoot );
//
// Function LookupRoot: Takes a Dfs name context and logical share,
// and returns a Root that matches the passed in name context and
// logical share, if one exists.
// Note that the same DFS NC and logical share may exist in more than
// one store (though very unlikely). In this case, the first registered
// store wins.
//
DFSSTATUS
FindFirstRoot( DfsRootFolder **ppRoot )
{
DFSSTATUS Status;
Status = AcquireReadLock();
if ( Status != ERROR_SUCCESS )
{
return Status;
}
*ppRoot = _DfsRootList;
if (*ppRoot == NULL)
{
Status = ERROR_NOT_FOUND;
}
else {
(*ppRoot)->AcquireReference();
}
ReleaseLock();
return Status;
}
DFSSTATUS
GetRootCount(
PULONG pCount)
{
DFSSTATUS Status;
DfsRootFolder *pRoot;
ULONG Count = 0;
*pCount = 0;
Status = AcquireReadLock();
if ( Status != ERROR_SUCCESS )
{
return Status;
}
pRoot = _DfsRootList;
if (pRoot != NULL)
{
do
{
Count++;
pRoot = pRoot->pNextRoot;
} while ( pRoot != _DfsRootList );
}
*pCount = Count;
ReleaseLock();
return Status;
}
ULONG
FindReplicaInReplicaList(
PDFS_REPLICA_LIST_INFORMATION pReplicaList,
LPWSTR Server,
LPWSTR Path )
{
ULONG Index;
PDFS_REPLICA_INFORMATION pReplicaInfo;
UNICODE_STRING Target, TargetPath;
DfsRtlInitUnicodeStringEx(&Target, Server);
DfsRtlInitUnicodeStringEx(&TargetPath, Path);
for (Index = 0; Index < pReplicaList->ReplicaCount; Index++)
{
pReplicaInfo = &pReplicaList->pReplicas[Index];
if ( (RtlCompareUnicodeString( &pReplicaInfo->ServerName,
&Target,
TRUE) == 0) &&
(RtlCompareUnicodeString( &pReplicaInfo->ShareName,
&TargetPath,
TRUE) == 0) )
{
break;
}
}
return Index;
}
DFSSTATUS
DumpStatistics()
{
DFSSTATUS Status = STATUS_SUCCESS;
DfsRootFolder *pRoot;
DfsRootFolder **ppList;
ppList = &_DfsRootList;
Status = AcquireWriteLock();
if ( Status != ERROR_SUCCESS )
return Status;
for ( pRoot = *ppList; pRoot != NULL; pRoot = pRoot->pNextRoot )
{
pRoot->pStatistics->DumpStatistics(pRoot->GetLogicalShare());
if (pRoot->pNextRoot == _DfsRootList)
{
break;
}
}
ReleaseLock();
return Status;
}
virtual
DFSSTATUS
AddChild(
DFS_METADATA_HANDLE DfsHandle,
IN PDFS_NAME_INFORMATION pNameInfo,
IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
IN PUNICODE_STRING pMetadataName ) = 0;
virtual
DFSSTATUS
RemoveChild(
DFS_METADATA_HANDLE DfsHandle,
LPWSTR ChildName ) = 0;
DFSSTATUS
AddChildReplica (
DFS_METADATA_HANDLE DfsHandle,
LPWSTR LinkMetadataName,
LPWSTR Server,
LPWSTR Share );
DFSSTATUS
RemoveChildReplica (
DFS_METADATA_HANDLE DfsHandle,
LPWSTR LinkMetadataName,
LPWSTR Server,
LPWSTR Share,
PBOOLEAN pLastReplica ,
BOOLEAN Force = FALSE);
virtual
DFSSTATUS
EnumerateApiLinks(
DFS_METADATA_HANDLE DfsHandle,
PUNICODE_STRING pRootName,
DWORD Level,
LPBYTE pBuffer,
LONG BufferSize,
LPDWORD pEntriesToRead,
LPDWORD pResumeHandle,
PLONG pNextSizeRequired ) = 0;
DFSSTATUS
GetStoreApiInformation(
DFS_METADATA_HANDLE DfsHandle,
PUNICODE_STRING pRootName,
LPWSTR LinkMetadataName,
DWORD Level,
LPBYTE pBuffer,
LONG BufferSize,
PLONG pSizeRequired );
DFSSTATUS
SetStoreApiInformation(
DFS_METADATA_HANDLE DfsHandle,
LPWSTR LinkMetadataName,
LPWSTR Server,
LPWSTR Share,
DWORD Level,
LPBYTE pBuffer );
DFSSTATUS
GetExtendedAttributes(
IN DFS_METADATA_HANDLE DfsHandle,
LPWSTR LinkMetadataName,
PULONG pAttr);
DFSSTATUS
SetExtendedAttributes(
IN DFS_METADATA_HANDLE DfsHandle,
LPWSTR LinkMetadataName,
ULONG pAttr);
//
// Function GetRootFolder: Runs through our list of RootFolders
// and sees if there is any root folder with the matching name.
// Returns a reference root folder, if found.
//
DFSSTATUS
GetRootFolder (
LPWSTR DfsNameContext,
LPWSTR RootRegistryName,
HKEY DfsRootKey,
DfsRootFolder **ppRootFolder );
//
// Function GetRootFolder: Runs through our list of RootFolders
// and sees if there is any root folder with the matching name.
// Returns a reference root folder, if found.
//
DFSSTATUS
GetRootFolder (
LPWSTR DfsNameContext,
LPWSTR RootRegistryName,
PUNICODE_STRING pLogicalShare,
PUNICODE_STRING pPhysicalShare,
DfsRootFolder **ppRootFolder );
//
// Similar to the above, except for being aware that
// the root isn't on the local machine.
//
DFSSTATUS
GetRootFolder (
LPWSTR DfsNameContextString,
PUNICODE_STRING pLogicalShare,
DfsRootFolder **ppRootFolder );
//
// Function CreateNewRootFolder: Creates a new root folder
// for the passed in name context, and logical share.
//
virtual
DFSSTATUS
CreateNewRootFolder (
LPWSTR MachineName,
LPWSTR RootRegKeyName,
PUNICODE_STRING pLogicalShare,
PUNICODE_STRING pPhysicalShare,
DfsRootFolder **pRoot ) = 0;
virtual
DFSSTATUS
GenerateLinkMetadataName(
UUID *pUid,
PUNICODE_STRING pLinkMetadataName )
{
DFSSTATUS Status = ERROR_SUCCESS;
LPWSTR String = NULL;
Status = UuidToString( pUid,
&String );
if (Status == ERROR_SUCCESS)
{
Status = DfsRtlInitUnicodeStringEx( pLinkMetadataName, String);
}
return Status;
}
virtual
VOID
ReleaseLinkMetadataName(
PUNICODE_STRING pLinkMetadataName )
{
RpcStringFree(&pLinkMetadataName->Buffer );
return;
}
DFSSTATUS
EnumerateRoots(
BOOLEAN DomainRoots,
PULONG_PTR pBuffer,
PULONG BufferSize,
PULONG pEntriesRead,
DWORD MaxEntriesToRead,
PULONG pCurrentNumRoots,
LPDWORD pResumeHandle,
PULONG pSizeRequired );
DFSSTATUS
AddRootEnumerationInfo(
PUNICODE_STRING pVisibleName,
PUNICODE_STRING pRootName,
DWORD Flavor,
PDFS_INFO_300 *ppDfsInfo300,
PULONG pBufferSize,
PULONG pEntriesRead,
PULONG pTotalSize );
DFSSTATUS
AddRootEnumerationInfo200(
PUNICODE_STRING pRootName,
PDFS_INFO_200 *ppDfsInfo300,
PULONG pBufferSize,
PULONG pEntriesRead,
PULONG pTotalSize );
static
DFSSTATUS
SetupADBlobRootKeyInformation(
HKEY DfsKey,
LPWSTR DfsLogicalShare,
LPWSTR DfsPhysicalShare );
virtual
DFSSTATUS
GetMetadataNameInformation(
IN DFS_METADATA_HANDLE RootHandle,
IN LPWSTR MetadataName,
OUT PDFS_NAME_INFORMATION *ppInfo );
virtual
VOID
ReleaseMetadataNameInformation(
IN DFS_METADATA_HANDLE DfsHandle,
IN PDFS_NAME_INFORMATION pNameInfo );
virtual
DFSSTATUS
SetMetadataNameInformation(
IN DFS_METADATA_HANDLE RootHandle,
IN LPWSTR MetadataName,
IN PDFS_NAME_INFORMATION pNameInfo );
DFSSTATUS
GetMetadataReplicaInformation(
IN DFS_METADATA_HANDLE RootHandle,
IN LPWSTR MetadataName,
OUT PDFS_REPLICA_LIST_INFORMATION *ppInfo );
VOID
ReleaseMetadataReplicaInformation(
IN DFS_METADATA_HANDLE DfsHandle,
IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo );
DFSSTATUS
SetMetadataReplicaInformation(
IN DFS_METADATA_HANDLE RootHandle,
IN LPWSTR MetadataName,
IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo );
DFSSTATUS
CreateNameInformationBlob(
IN PDFS_NAME_INFORMATION pDfsNameInfo,
OUT PVOID *ppBlob,
OUT PULONG pDataSize );
virtual
DFSSTATUS
CreateReplicaListInformationBlob(
IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
OUT PVOID *ppBlob,
OUT PULONG pDataSize );
virtual
DFSSTATUS
GetMetadataNameBlob(
DFS_METADATA_HANDLE RootHandle,
LPWSTR MetadataName,
PVOID *ppData,
PULONG pDataSize,
PFILETIME pLastModifiedTime ) = 0;
virtual
DFSSTATUS
GetMetadataReplicaBlob(
DFS_METADATA_HANDLE RootHandle,
LPWSTR MetadataName,
PVOID *ppData,
PULONG pDataSize,
PFILETIME pLastModifiedTime ) = 0;
virtual
DFSSTATUS
SetMetadataNameBlob(
DFS_METADATA_HANDLE RootHandle,
LPWSTR MetadataName,
PVOID pData,
ULONG DataSize ) = 0;
virtual
DFSSTATUS
SetMetadataReplicaBlob(
DFS_METADATA_HANDLE RootHandle,
LPWSTR MetadataName,
PVOID pData,
ULONG DataSize ) = 0;
virtual
DFSSTATUS
PackGetNameInformation(
IN PDFS_NAME_INFORMATION pDfsNameInfo,
IN OUT PVOID *ppBuffer,
IN OUT PULONG pSizeRemaining) = 0;
virtual
ULONG
PackSizeNameInformation(
IN PDFS_NAME_INFORMATION pDfsNameInfo ) = 0;
virtual
DFSSTATUS
PackSetNameInformation(
IN PDFS_NAME_INFORMATION pDfsNameInfo,
IN OUT PVOID *ppBuffer,
IN OUT PULONG pSizeRemaining) = 0;
virtual
DFSSTATUS
GenerateMetadataLogicalName(
PUNICODE_STRING pRootName,
PUNICODE_STRING pInput,
PUNICODE_STRING pOutput ) = 0;
virtual
VOID
ReleaseMetadataLogicalName(
PUNICODE_STRING pName ) = 0;
virtual
DFSSTATUS
GenerateApiLogicalPath (
IN PUNICODE_STRING pRootName,
IN PUNICODE_STRING pMetadataPrefix,
IN PUNICODE_STRING pApiLogicalName ) = 0;
virtual
VOID
ReleaseApiLogicalPath (
PUNICODE_STRING pName ) = 0;
DFSSTATUS
GetStoreApiInformationBuffer(
IN DFS_METADATA_HANDLE DfsHandle,
PUNICODE_STRING pRootName,
LPWSTR LinkMetadataName,
DWORD Level,
LPBYTE *ppBuffer,
PLONG pBufferSize );
DFSSTATUS
ReleaseStoreApiInformationBuffer(
LPBYTE pBuffer )
{
delete [] pBuffer;
return ERROR_SUCCESS;
}
VOID
StoreInitializeNameInformation(
IN PDFS_NAME_INFORMATION pNameInfo,
IN PUNICODE_STRING pLogicalName,
UUID *pGuid,
IN LPWSTR Comment )
{
//
// Zero out our information buffers.
//
RtlZeroMemory( pNameInfo,
sizeof(DFS_NAME_INFORMATION) );
pNameInfo->Prefix = *pLogicalName;
pNameInfo->ShortPrefix = *pLogicalName;
pNameInfo->State = DFS_VOLUME_STATE_OK;
pNameInfo->Type = PKT_ENTRY_TYPE_DFS;
pNameInfo->Timeout = DEFAULT_LINK_TIMEOUT;
pNameInfo->Version = 3;
if (pGuid != NULL)
{
pNameInfo->VolumeId = *pGuid;
}
DfsRtlInitUnicodeStringEx( &(pNameInfo->Comment), Comment);
return NOTHING;
}
VOID
StoreInitializeReplicaInformation(
IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
IN PDFS_REPLICA_INFORMATION pReplicaInfo,
IN LPWSTR ReplicaServer,
IN LPWSTR ReplicaPath )
{
RtlZeroMemory( pReplicaInfo,
sizeof( DFS_REPLICA_INFORMATION ));
RtlZeroMemory( pReplicaListInfo,
sizeof( DFS_REPLICA_LIST_INFORMATION ));
if ( (ReplicaServer != NULL) &&
(ReplicaPath != NULL) )
{
DfsRtlInitUnicodeStringEx( &(pReplicaInfo->ServerName), ReplicaServer);
DfsRtlInitUnicodeStringEx( &(pReplicaInfo->ShareName), ReplicaPath );
pReplicaInfo->ReplicaState = DFS_STORAGE_STATE_ONLINE;
pReplicaInfo->ReplicaType = 2; // dfsdev: hack for backwards compat.
pReplicaListInfo->ReplicaCount = 1;
pReplicaListInfo->pReplicas = pReplicaInfo;
}
return NOTHING;
}
VOID
StoreSynchronizer();
DFSSTATUS
FindNextRoot(
ULONG RootNum,
DfsRootFolder **ppRootFolder );
DFSSTATUS
LoadServerSiteDataPerRoot(void);
//
// Currently this is a ADBlobStore specific implementation.
// This provides dfs support for domain rename.
virtual
DFSSTATUS
RenameLinks(
IN DFS_METADATA_HANDLE RootHandle,
IN PUNICODE_STRING pLinkMetadataName,
IN PUNICODE_STRING OldDomainName,
IN PUNICODE_STRING NewDomainName)
{
UNREFERENCED_PARAMETER(RootHandle);
UNREFERENCED_PARAMETER(pLinkMetadataName);
UNREFERENCED_PARAMETER(OldDomainName);
UNREFERENCED_PARAMETER(NewDomainName);
return ERROR_INVALID_PARAMETER;
}
};
#endif // __DFS_STORE__