WindowsXP/base/fs/dfs/dfsm/server/svclist.cxx
2025-04-27 07:49:33 -04:00

1437 lines
41 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+-------------------------------------------------------------------------
//
// File: svclist.cxx
//
// Contents: A Class for the serviceList on volume objects. This is the
// implementation for this class.
//
//
// History: 28-Jan-93 SudK Created
// 11-May-93 SudK Ported to Cairole with changes.
//
//--------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
extern "C" {
#include "dfsmrshl.h"
}
#include "marshal.hxx"
#include "recon.hxx"
#include "svclist.hxx"
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::CDfsServiceList, public
//
// Synopsis: This is the constructor and it does nothing.
//
// Arguments: None
//
// Returns: Nothing.
//
// History: 28-Jan-1993 Sudk Created.
//
//-------------------------------------------------------------------------
CDfsServiceList::CDfsServiceList(void)
{
IDfsVolInlineDebOut((
DEB_TRACE, "CDfsServiceList::+CDfsServiceList(0x%x)\n",
this));
//
// Actually we do nothing at this point but to set the private variables
// to NULL etc. We need an IProp reference to do anything.
//
_fInitialised = FALSE;
_pDfsSvcList = NULL;
_cSvc = 0;
_pDeletedSvcList = NULL;
_cDeletedSvc = 0;
_SvcListBuffer = NULL;
_pPSStg = NULL;
memset(&_ReplicaSetID, 0, sizeof(GUID));
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::CDfsServiceList() exit\n"));
}
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::InitializeServiceList, public
//
// Synopsis: This is the routine that initialises the serviceList
// by reading off the property. This is the function which will
// read off the ServiceList property and setup the list in the
// private section.
//
// Arguments: [pPSStg] -- The IPropertySetStg interface is passed here.
//
// Returns: ERROR_SUCCESS -- If all went well.
// NERR_DfsVolumeDataCorrupt - If service list not found etc.
//
// Notes: Will throw an exception if memory failure occurs.
//
// History: 28-Jan-1993 Sudk Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::InitializeServiceList(
CStorage *pPSStg)
{
DWORD dwErr;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::InitServiceList()\n"));
ASSERT( _pPSStg == NULL );
_pPSStg = pPSStg;
_pPSStg->AddRef();
dwErr = ReadServiceListProperty();
if (dwErr != ERROR_SUCCESS)
return( dwErr );
//
// Now we get the SvcList and put it into the private section of
// our class. Notice that the following function directly manipulates
// the private list that we have. This is a private member of this class.
//
dwErr = DeSerializeSvcList();
if (dwErr != ERROR_SUCCESS)
return( dwErr );
//
// Now we have initialised the ServiceList class and can take all requests.
//
_fInitialised = TRUE;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::InitServiceList() exit\n"));
return( dwErr );
}
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::~CDfsServiceList, public
//
// Synopsis: The Destructor. Gets rid of all the memory.
//
// Arguments: None
//
// Returns: Nothing.
//
// Notes: This assumes that the constructor used "new" to allocate
// memory for the strings in the private structure.
//
// History: 26-Jan-93 SudK Created.
//
//-------------------------------------------------------------------------
CDfsServiceList::~CDfsServiceList(void)
{
CDfsService *tempSvc, *nextSvc;
ULONG i;
IDfsVolInlineDebOut((
DEB_TRACE, "CDfsServiceList::~CDfsServiceList(0x%x)\n",
this));
#if DBG
if (DfsSvcVerbose & 0x80000000)
DbgPrint("CDfsServiceList::~CDfsServiceList @0x%x\n", this);
#endif
//
// Deallocate some memory that might still be hanging around here.
//
if (_SvcListBuffer != NULL)
delete [] _SvcListBuffer;
//
// We walk through the list that we have and destroy each of the
// elements in the list that we maintain. This should take care of
// cases of zero elements etc. cleanly. This is So Simple!
//
tempSvc = _pDfsSvcList;
for (i = 0; i < _cSvc; i++) {
nextSvc = GetNextService(tempSvc);
delete tempSvc;
tempSvc = nextSvc;
}
tempSvc = _pDeletedSvcList;
for (i = 0; i < _cDeletedSvc; i++) {
nextSvc = GetNextDeletedService(tempSvc);
delete tempSvc;
tempSvc = nextSvc;
}
if (_pPSStg != NULL)
_pPSStg->Release();
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::~CDfsServiceList() exit\n"));
}
//+------------------------------------------------------------------------
//
// Member: SetNullSvcList, public
//
// Synopsis: This method sets a Null SvcList in the ReplicaList Property
//
// Arguments: [pPSStg] -- The CStorage pointer where props are to be
// saved
//
// History: May-17-1993 SudK Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::SetNullSvcList(
CStorage *pPSStg)
{
DWORD dwErr = ERROR_SUCCESS;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SetNullSvcList()\n"));
ASSERT( _pPSStg == NULL );
_pPSStg = pPSStg;
_pPSStg->AddRef();
//
// pBuffer gets allocated here. Use Smart Pointers to avoid memory leaks.
//
dwErr = SerializeSvcList();
if (dwErr != ERROR_SUCCESS) {
return( dwErr );
}
//
// Now we get the SvcList and put it into the private section of
// our class. Notice that the following function directly manipulates
// the private list that we have. This is a private member of this class.
//
dwErr = SetServiceListProperty(TRUE);
if (dwErr != ERROR_SUCCESS) {
return( dwErr );
}
//
// Now we have initialised the ServiceList class and can take all requests.
//
_fInitialised = TRUE;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SetNullSvcList() exit\n"));
return( dwErr );
}
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::GetServiceFromPrincipalName(), public
//
// Synopsis: Returns the Service structure in the form of the class for
// the requested service.
//
// Arguments: [pwszSvcName] -- The Service for which PktService
// is requested.
// [ppService] -- The pointer to CDfsService is returned here.
//
// Returns: ERROR_SUCCESS - If everything was OK.
// NERR_DfsNoSuchShare - If service requested not found.
//
// Notes: Note that this method returns a pointer to the structures in
// the private section of its class. This memory should not be
// modified or released.
//
// History: 28-Jan-93 SudK Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::GetServiceFromPrincipalName(
WCHAR CONST *pwszServiceName,
CDfsService **ppDfsSvc
)
{
IDfsVolInlineDebOut((DEB_TRACE,
"CDfsServiceList::GetServiceFromPrincipalName(%ws)\n",
pwszServiceName));
CDfsService *tempSvcPtr;
PWCHAR pwch;
if (pwszServiceName == NULL)
return(NERR_DfsNoSuchShare);
tempSvcPtr = GetFirstService();
while (tempSvcPtr != NULL) {
pwch = tempSvcPtr->GetServiceName();
if ((pwch == NULL) || (_wcsicmp(pwszServiceName, pwch))) {
tempSvcPtr = GetNextService(tempSvcPtr);
} else {
*ppDfsSvc = tempSvcPtr;
IDfsVolInlineDebOut(
(DEB_TRACE,
"CDfsServiceList::GetServiceFromPrincipalName() exit\n"));
return(ERROR_SUCCESS);
}
}
//
// Could not find anything with the ServiceName passed in.
//
*ppDfsSvc = NULL;
IDfsVolInlineDebOut(
(DEB_TRACE,"CDfsServiceList::GetServiceFromPrincipalName() exit\n"));
return(NERR_DfsNoSuchShare);
}
//+----------------------------------------------------------------------------
//
// Function: CDfsServiceList::GetDeletedServiceFromPrincipalName, private
//
// Synopsis: Searches the deleted svc list for a service with the given
// principal name.
//
// Arguments: [pwszSvcName] -- The Service for which PktService
// is requested.
// [ppService] -- The pointer to CDfsService is returned here.
//
// Returns: ERROR_SUCCESS - If everything was OK.
// NERR_DfsNoSuchShare - If service requested not found.
//
// Notes: Note that this method returns a pointer to the structures in
// the private section of its class. This memory should not be
// modified or released.
//
// History: 20-April-95 Milans Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::GetDeletedServiceFromPrincipalName(
WCHAR CONST *pwszServiceName,
CDfsService **ppDfsSvc
)
{
CDfsService *tempSvcPtr;
PWCHAR pwch;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::GetDeletedServiceFromPrincipalName(%ws)\n",
pwszServiceName));
if (pwszServiceName == NULL)
return(NERR_DfsNoSuchShare);
tempSvcPtr = GetFirstDeletedService();
//
// This routine is really a little flaky since not all services have
// PrincipalNames associated with them.
//
while (tempSvcPtr != NULL) {
pwch = tempSvcPtr->GetServiceName();
if ((pwch == NULL) || (_wcsicmp(pwszServiceName, pwch))) {
tempSvcPtr = GetNextDeletedService(tempSvcPtr);
}
else {
*ppDfsSvc = tempSvcPtr;
IDfsVolInlineDebOut(
(DEB_TRACE,
"CDfsServiceList::GetDeletedServiceFromPrincipalName() exit\n"));
return(ERROR_SUCCESS);
}
}
//
// Could not find anything with the PrincipalName passed in.
//
*ppDfsSvc = NULL;
IDfsVolInlineDebOut(
(DEB_TRACE, "CDfsServiceList::GetDeletedServiceFromPrincipalName() exit\n"));
return(NERR_DfsNoSuchShare);
}
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::GetService(), public
//
// Synopsis: Returns the Service structure in the form of the class for
// the requested service.
//
// Arguments: [pReplicaInfo] -- The ReplicaInfo for which CDfsService
// is requested.
// [ppService] -- The pointer to CDfsService is returned here.
//
// Returns: ERROR_SUCCESS - If everything was OK.
// NERR_DfsNoSuchShare - If service requested not found.
//
// Notes: Note that this method returns a pointer to the structures in
// the private section of its class. This memory should not be
// modified or released.
//
// History: 28-Jan-93 SudK Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::GetService(
PDFS_REPLICA_INFO pReplicaInfo,
CDfsService **ppDfsSvc)
{
CDfsService *tempSvcPtr;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::GetService()\n"));
tempSvcPtr = GetFirstService();
while (tempSvcPtr != NULL) {
//
// Check whether this ReplicaInfo struct represents the same service
//
if (tempSvcPtr->IsEqual(pReplicaInfo)) {
*ppDfsSvc = tempSvcPtr;
IDfsVolInlineDebOut(
(DEB_TRACE,
"CDfsServiceList::GetService() exit\n"));
return(ERROR_SUCCESS);
}
tempSvcPtr = GetNextService(tempSvcPtr);
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::GetService() exit\n"));
return(NERR_DfsNoSuchShare);
}
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::GetDeletedService(), public
//
// Synopsis: Returns the Service structure in the form of the class for
// the requested service.
//
// Arguments: [pReplicaInfo] -- The ReplicaInfo for which CDfsService
// is requested.
// [ppService] -- The pointer to CDfsService is returned here.
//
// Returns: ERROR_SUCCESS - If everything was OK.
// NERR_DfsNoSuchShare - If service requested not found.
//
// Notes: Note that this method returns a pointer to the structures in
// the private section of its class. This memory should not be
// modified or released.
//
// History: 28-Jan-93 SudK Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::GetDeletedService(
PDFS_REPLICA_INFO pReplicaInfo,
CDfsService **ppDfsSvc)
{
CDfsService *tempSvcPtr;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::GetDeletedService()\n"));
tempSvcPtr = GetFirstDeletedService();
while (tempSvcPtr != NULL) {
//
// Check whether this ReplicaInfo struct represents the same service
//
if (tempSvcPtr->IsEqual(pReplicaInfo)) {
*ppDfsSvc = tempSvcPtr;
IDfsVolInlineDebOut(
(DEB_TRACE, "CDfsServiceList::GetDeletedService() exit\n"));
return(ERROR_SUCCESS);
}
tempSvcPtr = GetNextDeletedService(tempSvcPtr);
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::GetDeletedService() exit\n"));
return(NERR_DfsNoSuchShare);
}
//+------------------------------------------------------------------------
//
// Member: CDfsServiceList::SetNewService(), public
//
// Synopsis: This method takes a new service description and associates
// this with the volume object. It also makes sure that the
// service being associated does not already exist in the list.
//
// Arguments: [pSvcEntry] -- The Svc that needs to be added to service List.
//
// Returns: ERROR_SUCCESS - If it succeeded.
// NERR_DfsVolumeDataCorrupt - If it cannot set properties.
// NERR_DfsDuplicateService - If service already exists.
//
// Notes: The ptr to the CDfsService class passed in here should not be
// deallocated by the caller. The instance is gobbled up by
// this method.
//
// History: 28-Jan-93 SudK Created.
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::SetNewService(CDfsService *pService)
{
CDfsService *tempSvcPtr = NULL;
DWORD dwErr = ERROR_SUCCESS;
PWCHAR pwszName;
SYSTEMTIME st;
FILETIME ftService;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SetNewService()\n"));
//
// First we need to make sure that this service is not there in the list
// already. If so we return an error code.
//
dwErr = GetService(pService->GetReplicaInfo(), &tempSvcPtr);
if (dwErr == ERROR_SUCCESS) {
pwszName = pService->GetServiceName();
LogMessage(DEB_TRACE,
&pwszName,
1,
DFS_SERVICE_ALREADY_EXISTS_MSG);
#if DBG
if (DfsSvcVerbose)
DbgPrint("CDfsServiceList::SetNewService: returning NERR_DfsDuplicateService\n");
#endif
return(NERR_DfsDuplicateService);
}
//
// We just take the Service instance that we got and goble it up.
//
GetSystemTime( &st );
SystemTimeToFileTime( &st, &ftService );
pService->SetModificationTime( ftService );
InsertNewService(pService);
//
// Now we have to update the Service list on the disk as well.
// Serialize the list and then call SetServiceProperty to set the property
// on the volume object. However, if we fail to do that then we should
// remove the service that we just added into the list. That will be a
// simple INLINE operation. Ofcourse we also need to delete it.
//
dwErr = SerializeSvcList();
if (dwErr == ERROR_SUCCESS)
dwErr = SetServiceListProperty(FALSE);
if (dwErr != ERROR_SUCCESS) {
RemoveService(pService);
IDfsVolInlineDebOut((
DEB_TRACE,
"Failed to SetNewService %ws and got Error: %x\n",
pService->GetServiceName(),
dwErr));
delete pService;
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SetNewService() exit\n"));
return( dwErr );
}
//+------------------------------------------------------------------------
//
// Function: CDfsServiceList::DeleteService(), public
//
// Synopsis: This method deletes a service from the service list on the
// volume object. This only deals with the ServiceList property.
//
// Arguments: [pService] -- The Service to be deleted.
// [fAddToDeletedList] -- If true, the deleted service will be
// added to the deleted list for reconciliation.
//
// Returns: ERROR_SUCCESS - If all went well.
// DFS_E_NOSUCH_SERVICE - If service does not exist at all.
// NERR_DfsVolumeDataCorrupt - If volume object seems to be bad.
//
// Notes: If this operation succeeds, the service instance passed in
// will be deleted and should not be touched after this call.
//
// However, if this operation fails, the service instance passed
// in will NOT be freed and the caller is responsible for
// freeing it.
//
// History: 28-Jan-93 SudK Created
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::DeleteService(
CDfsService *pService,
CONST BOOLEAN fAddToDeletedList)
{
DWORD dwErr = ERROR_SUCCESS;
SYSTEMTIME st;
FILETIME ftDelete;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeleteService()\n"));
//
// We remove this service from the private Service List that we have.
//
RemoveService(pService);
GetSystemTime( &st );
SystemTimeToFileTime( &st, &ftDelete );
pService->SetModificationTime( ftDelete );
if (fAddToDeletedList) {
InsertDeletedService(pService);
}
//
// Now we go and set the serviceList on the volume object itself.
// If we fail to do so we must bring back our service list to the
// original state itself.
//
dwErr = SerializeSvcList();
CHECK_RESULT(dwErr)
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR, "Serialization failed for some unknown reason %08lx\n", dwErr));
dwErr = SetNewService(pService);
CHECK_RESULT(dwErr)
return( dwErr );
}
dwErr = SetServiceListProperty(FALSE);
CHECK_RESULT(dwErr)
if (dwErr != ERROR_SUCCESS) {
dwErr = SetNewService(pService);
CHECK_RESULT(dwErr)
return( dwErr );
} else {
if (!fAddToDeletedList) {
delete pService;
}
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeleteService() exit\n"));
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CDfsServiceList::ReconcileSvcList
//
// Synopsis: Reconciles this service list with that from a remote object.
//
// Arguments: [cSvc] -- The number of services in the remote svc list.
// [pSvcList] -- The remote svc list.
// [cDeletedSvc] -- The number of services in the deleted list.
// [pDeletedSvcList] -- The list of deleted services.
//
// Returns: [ERROR_SUCCESS] -- If changes were successfully made, and if the
// resulting service list is not identical to the remote
// [RES_S_OBJECTSIDENTICAL] -- If changes were successfully
// made and the resulting service list is identical to
// the remote.
//
//-----------------------------------------------------------------------------
DWORD
CDfsServiceList::ReconcileSvcList(
ULONG cSvc,
CDfsService *pSvcList,
ULONG cDeletedSvc,
CDfsService *pDeletedSvcList)
{
DWORD dwErrReturn = ERROR_SUCCESS, dwErr;
CDfsService *pSrcSvc, *pTgtSvc;
FILETIME ftSrc, ftTgt;
ULONG i;
//
// We first handle the remote deleted service list.
// For each service in deleted list:
// if (Found(OurSvcList))
// if (OurSvcModTime < DeleteTime))
// DeleteFrom(OurSvcList);
// else
// InsertInto(OurDeletedSvcList);
// else
// if (Found(OurDeletedSvcList))
// UpdateDeletionTime();
// else
// InsertInto(OurDeletedSvcList);
// End For
//
for (i = 0, pSrcSvc = pDeletedSvcList;
i < cDeletedSvc;
i++, pSrcSvc = pSrcSvc->Next) {
BOOL fAddToDeletedList;
fAddToDeletedList = FALSE;
dwErr = GetService(
pSrcSvc->GetReplicaInfo(),
&pTgtSvc);
if (dwErr == ERROR_SUCCESS) {
//
// Found a service with the same principal name in our Svc List
//
ftSrc = pSrcSvc->GetModificationTime();
ftTgt = pTgtSvc->GetModificationTime();
if (IsFTOlder(ftTgt, ftSrc)) {
RemoveService( pTgtSvc );
pTgtSvc->SetModificationTime( ftSrc );
InsertDeletedService( pTgtSvc );
} else {
fAddToDeletedList = TRUE;
}
} else { // Unable to find the service in our active list...
dwErr = GetDeletedService(
pSrcSvc->GetReplicaInfo(),
&pTgtSvc);
if (dwErr == ERROR_SUCCESS) {
ftSrc = pSrcSvc->GetModificationTime();
ftTgt = pTgtSvc->GetModificationTime();
if (IsFTOlder( ftTgt, ftSrc )) {
pTgtSvc->SetModificationTime( ftSrc );
}
} else {
fAddToDeletedList = TRUE;
}
}
if (fAddToDeletedList) {
CDfsService *pNewDeletedSvc;
pNewDeletedSvc = new CDfsService(
pSrcSvc->GetReplicaInfo(),
FALSE,
&dwErr);
if (pNewDeletedSvc != NULL) {
if (dwErr == ERROR_SUCCESS) {
pNewDeletedSvc->SetModificationTime( ftSrc );
InsertDeletedService( pNewDeletedSvc );
} else {
delete pNewDeletedSvc;
dwErrReturn = dwErr;
}
} else {
IDfsVolInlineDebOut((
DEB_ERROR,
"Dfs Manager: Out of memory reconciling deleted svc\n"
));
dwErrReturn = ERROR_OUTOFMEMORY;
}
}
}
//
// Next, we reconcile the active list. This is simple - for each service
// in the remote active list, if we find it in our active list, we
// reconcile the two services. If we don't find it in our active list,
// we add it in.
//
for (i = 0, pSrcSvc = pSvcList;
i < cSvc;
i++, pSrcSvc = pSrcSvc->Next) {
dwErr = GetService(
pSrcSvc->GetReplicaInfo(),
&pTgtSvc);
ftSrc = pSrcSvc->GetModificationTime();
if (dwErr == ERROR_SUCCESS) {
ftTgt = pTgtSvc->GetModificationTime();
if (IsFTOlder( ftTgt, ftSrc )) {
pTgtSvc->SetModificationTime( ftSrc );
}
} else { // Newly added service, add it to our list
CDfsService *pNewSvc;
pNewSvc = new CDfsService(
pSrcSvc->GetReplicaInfo(),
TRUE,
&dwErr );
if (pNewSvc != NULL) {
if (dwErr == ERROR_SUCCESS) {
pNewSvc->SetModificationTime( ftSrc );
InsertNewService( pNewSvc );
} else {
delete pNewSvc;
dwErrReturn = dwErr;
}
} else {
IDfsVolInlineDebOut((
DEB_ERROR,
"Dfs Manager: Out of memory reconciling new svc\n"
));
dwErrReturn = ERROR_OUTOFMEMORY;
}
}
}
//
// Save the reconciled list on the volume object.
//
if (dwErrReturn == ERROR_SUCCESS) {
dwErrReturn = SerializeSvcList();
if (dwErrReturn == ERROR_SUCCESS) {
dwErrReturn = SetServiceListProperty( FALSE );
if (FAILED(dwErrReturn)) {
IDfsVolInlineDebOut((
DEB_ERROR, "Error %08lx setting service list property\n",
dwErrReturn));
}
} else {
IDfsVolInlineDebOut((
DEB_ERROR, "Error %08lx serializing service list\n",
dwErrReturn));
}
}
//
// Finally, see if the two lists are identical, so that we can return
// REC_S_OBJECTSIDENTICAL when appropriate
//
if (dwErrReturn == ERROR_SUCCESS) {
if (_cSvc == cSvc && _cDeletedSvc == cDeletedSvc) {
dwErrReturn = NERR_DfsDataIsIdentical;
//
// It is sufficient for _cSvc == cSvc and
// _cDeletedSvc == cDeletedSvc to prove that the svc lists are
// identical.
//
}
}
return( dwErrReturn );
}
//+------------------------------------------------------------------------
//
// Function: CDfsServiceList::ReadServiceListProperty(), private
//
// Synopsis: This method reads the service list property and puts the
// buffer in the private section of this instance.
//
// Arguments: None
//
// Returns: ERROR_SUCCESS - If all went well.
// NERR_DfsVolumeDataCorrupt - Volume object is corrupt.
//
// Notes:
//
// History: 28-Jan-93 SudK Created
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::ReadServiceListProperty(void)
{
DWORD dwErr = ERROR_SUCCESS;
BYTE *pBuffer;
ULONG size;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::ReadServiceListProperty()\n"));
dwErr = _pPSStg->GetSvcProps( &pBuffer, &size );
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut(
(DEB_ERROR, "Unable to read serviceList Props %08lx\n", dwErr));
return( dwErr );
}
if (_SvcListBuffer != NULL)
delete [] _SvcListBuffer;
_SvcListBuffer = new BYTE[size + sizeof(ULONG)];
if (_SvcListBuffer == NULL) {
dwErr = ERROR_OUTOFMEMORY;
goto Cleanup;
}
*(PULONG) _SvcListBuffer = size;
memcpy(_SvcListBuffer + sizeof(ULONG), pBuffer, size);
Cleanup:
//
// We need to dismiss the results now.
//
delete [] pBuffer;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::ReadServiceListProperty() exit\n"));
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CDfsServiceList::DeSerializeBuffer
//
// Synopsis: Helper function that deserializes a marshalled service list
//
// Arguments: [pBuffer] -- The buffer to deserialize
// [pcSvc] -- The count of services in *ppSvcList is returned
// here
// [ppSvcList] -- The service list is returned here.
// [pcDeletedSvc] -- The count of deleted services in
// *ppDeletedSvcList.
// [ppDeletedSvcList] -- The list of deleted services is
// returned here.
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CDfsServiceList::DeSerializeBuffer(
PBYTE pBuffer,
ULONG *pcSvc,
CDfsService **ppSvcList,
ULONG *pcDeletedSvc,
CDfsService **ppDeletedSvcList)
{
PBYTE pBufferEnd;
DWORD dwErr = ERROR_SUCCESS;
CDfsService *pSvcPtr = NULL;
ULONG count, i, size, bufsize;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeSerializeBuffer()\n"));
*pcSvc = 0;
*ppSvcList = NULL;
*pcDeletedSvc = 0;
*ppDeletedSvcList = NULL;
__try
{
_GetULong(pBuffer, bufsize);
pBufferEnd = pBuffer + bufsize;
pBuffer = pBuffer + sizeof(ULONG);
//
// Get the number of elements that exist in the buffer.
//
_GetULong(pBuffer, count);
pBuffer = pBuffer + sizeof(ULONG);
for (i=0; i<count; i++) {
//
// Unmarshall each entry. Remember the size of the entry
// comes first in the buffer, then the marshalled entry
// itself.
//
_GetULong(pBuffer, size);
pBuffer = pBuffer + sizeof(ULONG);
//
// This will not throw an exception even if the buffer is
// corrupt. So we are safe here. If this fails we will still
// go on to the next service and try to unmarshall and
// initialise ourselves with it.
//
dwErr = CDfsService::DeSerialize(pBuffer, size, &pSvcPtr);
if (dwErr == ERROR_SUCCESS) {
InsertServiceInList(*ppSvcList, pSvcPtr);
(*pcSvc)++;
}
pBuffer = pBuffer + size;
}
//
// Get the number of deleted svcs.
//
if (pBuffer < pBufferEnd) {
_GetULong(pBuffer, count);
pBuffer = pBuffer + sizeof(ULONG);
for (i=0; i<count; i++) {
_GetULong(pBuffer, size);
pBuffer = pBuffer + sizeof(ULONG);
dwErr = CDfsService::DeSerialize(pBuffer, size, &pSvcPtr);
if (dwErr == ERROR_SUCCESS) {
InsertServiceInList(*ppDeletedSvcList, pSvcPtr);
(*pcDeletedSvc)++;
}
pBuffer = pBuffer + size;
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//
// The only reason that we could get this is if the buffer above
// were corrupt which means that the serviceList property is corrupt.
//
dwErr = NERR_DfsVolumeDataCorrupt;
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeSerializeBuffer() exit\n"));
return( dwErr );
}
//+------------------------------------------------------------------------
//
// Function: CDfsServiceList::DeSerializeSvcList(), private
//
// Synopsis: This method takes in a binary buffer and unmarshalls the
// serviceEntries and plugs them into the ServiceList in the
// private section of this class instance.
//
// Arguments: This method picks up requried args from Private section.
//
// Returns: ERROR_SUCCESS -- If all went well.
//
// Notes: We have a TRY/CATCH block just in case the buffer is corrupt.
//
// History: 28-Jan-93 SudK Created
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::DeSerializeSvcList(void)
{
DWORD dwErr = ERROR_SUCCESS;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeSerializeSvcList()\n"));
ASSERT( _SvcListBuffer != NULL );
dwErr = DeSerializeBuffer(
(PBYTE) _SvcListBuffer,
&_cSvc,
&_pDfsSvcList,
&_cDeletedSvc,
&_pDeletedSvcList);
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeSerializeSvcList() exit\n"));
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CDfsServiceList::DeSerializeReconcileList
//
// Synopsis: Deserializes a service list retrieved from a remote volume.
//
// Arguments: [pMarshalBuffer] -- The marshal buffer from which to
// deserialize the svc list.
// [pcSvc] -- The count of services in *ppSvcList is returned
// here
// [ppSvcList] -- The service list is returned here.
// [pcDeletedSvc] -- The count of deleted services in
// *ppDeletedSvcList.
// [ppDeletedSvcList] -- The list of deleted services is
// returned here.
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CDfsServiceList::DeSerializeReconcileList(
MARSHAL_BUFFER *pMarshalBuffer,
ULONG *pcSvc,
CDfsService **ppSvcList,
ULONG *pcDeletedSvc,
CDfsService **ppDeletedSvcList)
{
DWORD dwErr;
PBYTE pBuffer;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeSerializeReconcileList()\n"));
pBuffer = (PBYTE) pMarshalBuffer->Current;
dwErr = DeSerializeBuffer(
pBuffer,
pcSvc,
ppSvcList,
pcDeletedSvc,
ppDeletedSvcList);
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::DeSerializeReconcileList() exit\n"));
return( dwErr );
}
//+------------------------------------------------------------------------
//
// Function: CDfsServiceList::SerializeSvcList(), private
//
// Synopsis: This method serializes a given service list into a binary
// buffer. The service list in the private section of this class
// is used as the source. The serialised target buffer is also
// kept in the private section.
//
// Arguments: None
//
// Returns: [ERROR_SUCCESS] -- If all went well.
//
// [ERROR_OUTOFMEMORY] - If unable to allocate the target buffer.
//
// History: 28-Jan-93 SudK Created
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::SerializeSvcList(void)
{
DWORD dwErr = ERROR_SUCCESS;
ULONG totalSize, i, *psize;
BYTE *buffer;
CDfsService *pSvcPtr = NULL;
ULONG *sizeBuffer = NULL;
FILETIME ftService;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SerializeSvcList()\n"));
totalSize = 0;
sizeBuffer = new ULONG[_cSvc + _cDeletedSvc];
if (sizeBuffer == NULL) {
return ERROR_OUTOFMEMORY;
}
//
// Need all the size values now and later for marshalling stuff.
// So we collect them here into an array.
//
psize = sizeBuffer;
pSvcPtr = GetFirstService();
for (i=0;i<_cSvc;i++) {
*psize = pSvcPtr->GetMarshalSize();
totalSize = totalSize + *psize;
pSvcPtr = GetNextService(pSvcPtr);
psize++;
}
pSvcPtr = GetFirstDeletedService();
for (i=0;i<_cDeletedSvc;i++) {
*psize = pSvcPtr->GetMarshalSize();
totalSize = totalSize + *psize;
pSvcPtr = GetNextDeletedService(pSvcPtr);
psize++;
}
//
// Allocate the byte buffer that we need to pass to IProp interface.
//
// totalsize is the size required just to marshal all the services and
// their last-modification-timestamps.
//
// In addition, we need:
//
// 1 ULONG for store the buffersize, since we are storing this as a
// VT_BLOB property.
//
// 1 ULONG for storing the count of services
//
// _cSvc ULONGs for storing the marshal size of each service.
//
// 1 ULONG for count of deleted services
//
// _cDeletedSvc ULONGS for storing the marshal size of each deleted svc
//
if (_SvcListBuffer != NULL)
delete [] _SvcListBuffer;
_cbSvcListBuffer = totalSize +
sizeof(ULONG) * (2 + _cSvc + 1 + _cDeletedSvc);
_SvcListBuffer = new BYTE[_cbSvcListBuffer];
if (_SvcListBuffer != NULL) {
buffer = _SvcListBuffer;
//
// First set the size of the buffer. Since this will be used
// as a BLOB property. The size does NOT include the size field
// itself, hence the (1 + _cSvc + 1 + _cDeletedSvc).
//
totalSize = totalSize + sizeof(ULONG)*(1 + _cSvc + 1 + _cDeletedSvc);
_PutULong(buffer, totalSize);
buffer = buffer + sizeof(ULONG);
//
// Set the number of entries to follow in the buffer at the start.
//
_PutULong(buffer, _cSvc);
buffer = buffer + sizeof(ULONG);
psize = sizeBuffer;
pSvcPtr = GetFirstService();
for (i=0;i<_cSvc;i++) {
//
// Marshall each service Entry into the buffer.
// Remember we first need to put the size of the marshalled
// service entry to follow, then the FILETIME for the service,
// and finally, the marshalled service entry structure.
//
_PutULong( buffer, (*psize));
buffer = buffer + sizeof(ULONG);
pSvcPtr->Serialize(buffer, *psize);
buffer = buffer + *psize;
psize = psize + 1;
pSvcPtr = GetNextService(pSvcPtr);
}
//
// Now marshal the delete svc list.
//
pSvcPtr = GetFirstDeletedService();
_PutULong(buffer, _cDeletedSvc);
buffer += sizeof(ULONG);
for (i=0; i<_cDeletedSvc; i++) {
_PutULong(buffer, *psize);
buffer = buffer + sizeof(ULONG);
pSvcPtr->Serialize(buffer, *psize);
buffer = buffer + *psize;
psize = psize + 1;
pSvcPtr = GetNextDeletedService(pSvcPtr);
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
if (sizeBuffer != NULL) {
delete [] sizeBuffer;
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SerializeSvcList() exit\n"));
return( dwErr );
}
//+------------------------------------------------------------------------
//
// Function: CDfsServiceList::SetServiceListProperty(), private
//
// Synopsis: This method sets the service list property on the vol object.
// Picks up the property from the Private section.
//
// Arguments: None
//
// Returns: ERROR_SUCCESS -- If all went well.
// NERR_DfsVolumeDataCorrupt - If volume object is corrupt.
//
// Notes:
//
// History: 28-Jan-93 SudK Created
//
//-------------------------------------------------------------------------
DWORD
CDfsServiceList::SetServiceListProperty(BOOLEAN bCreate)
{
DWORD dwErr = ERROR_SUCCESS;
BYTE *pBuffer;
ULONG cbSize;
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SetSvcListProp()\n"));
//
// Set the ReplicaList property first.
//
cbSize = *((ULONG *) _SvcListBuffer);
pBuffer = _SvcListBuffer + sizeof(ULONG);
//
// Now set the Property itself
//
dwErr = _pPSStg->SetSvcProps(pBuffer, cbSize);
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut(( DEB_ERROR,
"Unable to Set RecoveryProperties %08lx\n",
dwErr));
return( dwErr );
}
IDfsVolInlineDebOut((DEB_TRACE, "CDfsServiceList::SetSvcListProp() exit\n"));
return( dwErr );
}