//+------------------------------------------------------------------------- // // 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; iCurrent; 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 ); }