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
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__
|