windows-nt/Source/XPSP1/NT/base/fs/dfs/dfsm/server/cdfsvol.cxx
2020-09-26 16:20:57 +08:00

656 lines
16 KiB
C++

//+----------------------------------------------------------------------------
//
// Copyright (C) 1995, Microsoft Corporation
//
// File: cdfsvol.cxx
//
// Contents: Class to abstract a Dfs Volume object and all the
// administration operations that can be performed on a
// volume object.
//
// Classes: CDfsVolume
//
// Functions:
//
// History: 05/10/93 Sudk Created.
// 12/19/95 Milans Ported to NT.
//
//-----------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
#include <cguid.h>
#include "cdfsvol.hxx"
#include "cldap.hxx"
extern "C" {
#include <winldap.h>
#include <dsgetdc.h>
}
#include "setup.hxx"
const GUID CLSID_CDfsVolume = {
0xd9918520, 0xb074, 0x11cd, { 0x47, 0x94, 0x26, 0x8a, 0x82, 0x6b, 0x00, 0x00 }
};
extern "C"
DWORD
DfsGetFtServersFromDs(
PLDAP pLDAP,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR **List);
extern CLdap *pDfsmLdap;
//---------------------------------------------------------------------------
//
// Class CDfsVolume Member Function Implementations
//
//---------------------------------------------------------------------------
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::CDfsVolume
//
// Synopsis: Constructor
//
//--------------------------------------------------------------------------
CDfsVolume::CDfsVolume()
{
IDfsVolInlineDebOut((
DEB_TRACE, "CDfsVolume::+CDfsVolume(0x%x)\n",
this));
_pStorage = NULL;
_pwzFileName = _FileNameBuffer;
_pwszParentName = _ParentNameBuffer;
_dwRotRegistration = NULL;
memset(&_peid, 0, sizeof(DFS_PKT_ENTRY_ID));
_peid.Prefix.Buffer = _EntryPathBuffer;
_peid.ShortPrefix.Buffer = _ShortPathBuffer;
_pRecoverySvc = NULL;
_Deleted = TRUE;
_State = DFS_VOLUME_STATE_OK;
_Timeout = GTimeout;
_pwszComment = NULL;
memset( &_ftEntryPath, 0, sizeof(FILETIME));
memset( &_ftState, 0, sizeof(FILETIME));
memset( &_ftComment, 0, sizeof(FILETIME));
}
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::~CDfsVolume
//
// Synopsis: Destructor
//
//--------------------------------------------------------------------------
CDfsVolume::~CDfsVolume()
{
IDfsVolInlineDebOut((
DEB_TRACE, "CDfsVolume::~CDfsVolume(0x%x)\n",
this));
#if DBG
if (DfsSvcVerbose & 0x80000000) {
DbgPrint("CDfsVolume::~CDfsVolume @0x%x\n", this);
DbgPrint(" _DfsSvcList@0x%x\n", &_DfsSvcList);
}
#endif
if (_pStorage != NULL)
_pStorage->Release();
if (_pwzFileName != NULL && _pwzFileName != _FileNameBuffer)
delete [] _pwzFileName;
if (_pwszParentName != NULL && _pwszParentName != _ParentNameBuffer)
delete [] _pwszParentName;
if (_peid.Prefix.Buffer != NULL && _peid.Prefix.Buffer != _EntryPathBuffer)
delete [] _peid.Prefix.Buffer;
if (_peid.ShortPrefix.Buffer != NULL && _peid.ShortPrefix.Buffer != _ShortPathBuffer) {
delete [] _peid.ShortPrefix.Buffer;
}
if (_pwszComment != NULL)
delete [] _pwszComment;
if (_pRecoverySvc != NULL)
delete _pRecoverySvc;
}
//+-------------------------------------------------------------------------
// IPersist Methods
//--------------------------------------------------------------------------
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::GetClassID
//
// Synopsis: Return classid - This is the implementation for both the
// IPersistStorage and IPersistFile Interfaces.
//
//--------------------------------------------------------------------------
DWORD
CDfsVolume::GetClassID(LPCLSID lpClassID)
{
*lpClassID = CLSID_CDfsVolume;
return(ERROR_SUCCESS);
}
//+-------------------------------------------------------------------------
// IPersistStorage Methods
//--------------------------------------------------------------------------
//+----------------------------------------------------------------------------
//
// Function: GetNameFromStorage
//
// Synopsis: Given an IStorage, this routine computes the name of the
// object.
//
// Arguments: [pstg] -- The storage whose name is to be computed
// [ppwszName] -- Points to a buffer containing the name
// [wszBuffer] -- The buffer to use if name is <= MAX_PATH
//
// Returns: ERROR_SUCCESS if successful
// ERROR_OUTOFMEMORY if out of memory
// NERR_DfsInternalError if any other error
//
//-----------------------------------------------------------------------------
DWORD
GetNameFromStorage(
CStorage *pstg,
LPWSTR *ppwszName,
WCHAR wszBuffer[])
{
DWORD dwErr;
ULONG cLen;
LPWSTR pwszName = NULL;
DFSMSTATSTG statstg;
ZeroMemory( &statstg, sizeof(statstg) );
dwErr = pstg->Stat( &statstg, STATFLAG_DEFAULT );
if (dwErr == ERROR_SUCCESS) {
cLen = 2 + wcslen( statstg.pwcsName ) + 1;
if (cLen > MAX_PATH) {
pwszName = new WCHAR[ cLen ];
if (pwszName == NULL) {
IDfsVolInlineDebOut((
DEB_ERROR, "Unable to allocate %d bytes\n",
cLen * sizeof(WCHAR)));
dwErr = ERROR_OUTOFMEMORY;
} else {
wcscpy( pwszName, statstg.pwcsName );
*ppwszName = pwszName;
}
} else { // Use given buffer
pwszName = wszBuffer;
wcscpy( pwszName, statstg.pwcsName );
*ppwszName = pwszName;
}
delete [] statstg.pwcsName;
} else {
IDfsVolInlineDebOut((
DEB_ERROR, "Error %08lx getting storage stats\n", dwErr ));
dwErr = NERR_DfsInternalError;
}
return( dwErr );
}
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::InitNew
//
// Synopsis: InitNew is only called by the reconciler when a new
// volume object is created as a result of a reconciliation.
// We simply create all the appropriate property sets so that
// the volume object reconciler can reconcile the property sets
//
//--------------------------------------------------------------------------
DWORD
CDfsVolume::InitNew(CStorage *pStg)
{
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::InitNew()\n"));
DWORD dwErr;
ASSERT( _pStorage == NULL );
//
// Save and AddRef the storage so it wont go away from us.
//
_pStorage = pStg;
_pStorage->AddRef();
//
// First thing we do now is to setup the Class ID.
//
dwErr = _pStorage->SetClass(CLSID_CDfsVolume);
//
// Next, we Initialize the property sets.
//
if (dwErr == ERROR_SUCCESS)
dwErr = SetVersion( TRUE );
if (dwErr == ERROR_SUCCESS) {
_Recover.Initialize(_pStorage);
_Recover.SetDefaultProps();
}
if (dwErr == ERROR_SUCCESS)
dwErr = _DfsSvcList.SetNullSvcList( _pStorage );
//
// Need to initialize our _pwzFileName member
//
if (dwErr == ERROR_SUCCESS) {
ASSERT( _pwzFileName == _FileNameBuffer );
dwErr = GetNameFromStorage(
_pStorage,
&_pwzFileName,
_FileNameBuffer );
}
if (dwErr == ERROR_SUCCESS) {
_Deleted = FALSE;
IDfsVolInlineDebOut((
DEB_TRACE, "Volume Object [%ws] successfully inited\n",
_pwzFileName));
}
return( dwErr );
}
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::Save
//
// Synopsis: Saves the persistent state of the object. We really don't need
// to support this. It really makes no sense to support this?
//
//--------------------------------------------------------------------------
DWORD
CDfsVolume::Save(
CStorage *pStgSave,
BOOL fSameAsLoad)
{
return(ERROR_SUCCESS);
}
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::Load
//
// Synopsis: Loads a DfsVolume and the components it contains from
// storage.
//
//--------------------------------------------------------------------------
DWORD
CDfsVolume::Load(
CStorage *pStg)
{
DWORD dwErr = ERROR_SUCCESS;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::Load()\n"));
ASSERT(_pStorage == NULL);
_pStorage = pStg;
_pStorage->AddRef();
if (dwErr == ERROR_SUCCESS)
dwErr = GetVersion( &_Version );
//
// Out here we are passing in the _pPSStorage. The called people will
// Addref and release this _pStorage on their own.
//
if (dwErr == ERROR_SUCCESS) {
_Recover.Initialize(_pStorage);
dwErr = _DfsSvcList.InitializeServiceList(_pStorage);
}
if (dwErr == ERROR_SUCCESS) {
dwErr = GetIdProps( &_EntryType,
&_peid.Prefix.Buffer,
&_peid.ShortPrefix.Buffer,
&_pwszComment,
&_peid.Uid,
&_State,
&_Timeout,
&_ftEntryPath,
&_ftState,
&_ftComment);
}
if (dwErr == ERROR_SUCCESS) {
_peid.Prefix.Length = wcslen(_peid.Prefix.Buffer) * sizeof(WCHAR);
_peid.Prefix.MaximumLength = _peid.Prefix.Length + sizeof(WCHAR);
_peid.ShortPrefix.Length = wcslen(_peid.ShortPrefix.Buffer) * sizeof(WCHAR);
_peid.ShortPrefix.MaximumLength = _peid.ShortPrefix.Length + sizeof(WCHAR);
dwErr = _Recover.GetRecoveryProps(&_RecoveryState, &_pRecoverySvc);
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR,
"CouldNot read RecoveryProps off Stg %08lx\n",
dwErr));
_RecoveryState = DFS_RECOVERY_STATE_NONE;
_pRecoverySvc = NULL;
dwErr = ERROR_SUCCESS;
}
}
if (dwErr == ERROR_SUCCESS) {
_Deleted = FALSE;
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::Load() exit\n"));
return( dwErr );
};
//+-------------------------------------------------------------------------
// IPersistFile Methods
//--------------------------------------------------------------------------
DWORD
CDfsVolume::Load(LPCWSTR pwszFileName, DWORD grfMode)
{
DWORD dwErr;
dwErr = LoadNoRegister( pwszFileName, grfMode );
return( dwErr );
}
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::LoadNoRegister
//
// Synopsis: Load the DfsVolume from a volume object. This is where all the
// initialization takes place.
//
//--------------------------------------------------------------------------
DWORD
CDfsVolume::LoadNoRegister(
LPCWSTR pwszFileName,
DWORD grfMode)
{
DWORD dwErr = ERROR_SUCCESS;
IDfsVolInlineDebOut((
DEB_TRACE, "CDfsVolume::LoadNoRegister(%ws)\n", pwszFileName));
dwErr = DfsmOpenStorage(
pwszFileName,
(CStorage FAR* FAR*)&_pStorage);
if (dwErr == ERROR_SUCCESS) {
ULONG uLen = wcslen(pwszFileName);
if (uLen > MAX_PATH)
_pwzFileName = new WCHAR[(uLen+1)];
else
_pwzFileName = _FileNameBuffer;
if (_pwzFileName == NULL)
dwErr = ERROR_OUTOFMEMORY;
else
wcscpy(_pwzFileName, pwszFileName);
} else {
IDfsVolInlineDebOut((
DEB_TRACE, "Unable to open %ws, %08lx\n", pwszFileName, dwErr));
}
//
// Before we do anything, lets see if the volume object is current.
//
if (dwErr == ERROR_SUCCESS)
dwErr = UpgradeObject();
if (dwErr == ERROR_SUCCESS)
dwErr = GetVersion( &_Version );
if (dwErr == ERROR_SUCCESS) {
//
// Out here we are passing in the _pPSStorage. The called people
// will Addref and release this _pStorage on their own.
//
_Recover.Initialize(_pStorage);
dwErr = _DfsSvcList.InitializeServiceList(_pStorage);
}
if (dwErr == ERROR_SUCCESS) {
dwErr = GetIdProps( &_EntryType,
&(_peid.Prefix.Buffer),
&(_peid.ShortPrefix.Buffer),
&_pwszComment,
&(_peid.Uid),
&_State,
&_Timeout,
&_ftEntryPath,
&_ftState,
&_ftComment);
}
if (dwErr == ERROR_SUCCESS) {
_peid.Prefix.Length = wcslen(_peid.Prefix.Buffer) * sizeof(WCHAR);
_peid.Prefix.MaximumLength = _peid.Prefix.Length + sizeof(WCHAR);
_peid.ShortPrefix.Length = wcslen(_peid.ShortPrefix.Buffer) * sizeof(WCHAR);
_peid.ShortPrefix.MaximumLength = _peid.ShortPrefix.Length + sizeof(WCHAR);
dwErr = _Recover.GetRecoveryProps(&_RecoveryState, &_pRecoverySvc);
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR,
"CouldNot read RecoveryProps off %ws\n",
_pwzFileName));
IDfsVolInlineDebOut((DEB_ERROR,"\tError = %08lx\n",dwErr));
_RecoveryState = DFS_RECOVERY_STATE_NONE;
_pRecoverySvc = NULL;
dwErr = ERROR_SUCCESS;
}
}
if (dwErr == ERROR_SUCCESS) {
_Deleted = FALSE;
}
IDfsVolInlineDebOut((
DEB_TRACE, "CDfsVolume::LoadNoRegister() exit\n"));
return( dwErr );
}
//+-------------------------------------------------------------------------
//
// Function: CDfsVolume::Save
//
// Synopsis: Not Implemented
//
//--------------------------------------------------------------------------
DWORD
CDfsVolume::Save(LPCWSTR pwzFileName, BOOL fRemember)
{
DWORD dwErr = ERROR_SUCCESS;
return( dwErr );
}
DWORD
CDfsVolume::SyncWithRemoteServerNameInDs(void)
{
DWORD InfoSize = 0;
DWORD dwError = NO_ERROR;
DFS_INFO_3 DfsInfo;
BOOLEAN Found = FALSE;;
PDFSM_ROOT_LIST pRootList = NULL;
DFS_REPLICA_INFO *pReplicaInfo = NULL;
WCHAR* ServerShare = NULL;
DWORD Length = 0;
WCHAR* DcName = NULL;
DWORD i,j;
PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL;
LPWSTR *pList = NULL;
WCHAR wszFtDfsName[MAX_PATH+1];
ULONG start = 0;
ULONG end = 0;
CDfsService *pService;
LPWSTR DfsName = NULL;
RtlZeroMemory(wszFtDfsName, sizeof(wszFtDfsName));
RtlCopyMemory(wszFtDfsName, _peid.Prefix.Buffer, _peid.Prefix.Length);
//
// Extract the ftdfs name from the DfsInfo.EntryPath
//
for (DfsName = &wszFtDfsName[1];
*DfsName != UNICODE_PATH_SEP && *DfsName != UNICODE_NULL;
DfsName++) {
NOTHING;
}
if (*DfsName == UNICODE_PATH_SEP)
DfsName++;
if(dwError == ERROR_SUCCESS) {
dwError = DfsGetFtServersFromDs(
NULL,
NULL,
DfsName,
&pList
);
}
if(dwError == ERROR_SUCCESS) {
pService=_DfsSvcList.GetFirstService();
while(pService) {
Found = FALSE;
for(j=0;pList[j]!=NULL;j++) {
Length = sizeof(WCHAR) * 2; // whackwhack
Length += sizeof(WCHAR) * wcslen(pService->GetServiceName()); // server
Length += sizeof(WCHAR); // whack
Length += sizeof(WCHAR) * wcslen(pService->GetShareName()); // share
Length += sizeof(WCHAR); // terminating null
ServerShare = (WCHAR *)malloc(Length);
if(ServerShare == NULL) {
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto exit;
}
wcscpy(ServerShare, L"\\\\");
wcscat(ServerShare, pService->GetServiceName());
wcscat(ServerShare, L"\\");
wcscat(ServerShare, pService->GetShareName());
if(wcscmp(ServerShare, pList[j]) == 0) {
Found = TRUE;
break;
}
free(ServerShare);
ServerShare = NULL;
}
if(!Found) {
// after we delete the service we can no longer get the next in the list,
// so we grab it first.
CDfsService *NextService = _DfsSvcList.GetNextService(pService);
dwError = _DfsSvcList.DeleteService(pService, FALSE);
if(dwError != ERROR_SUCCESS) {
break;
}
pService = NextService;
} else {
pService=_DfsSvcList.GetNextService(pService);
}
}
}
exit:
if(pList) {
NetApiBufferFree(pList);
}
return dwError;
}