//-------------------------------------------------------------------------- // // Copyright (C) 1999, Microsoft Corporation // // File: dfslink.hxx // //-------------------------------------------------------------------------- #ifndef __DFS_UTIL_LINK__ #define __DFS_UTIL_LINK__ #include "DfsTarget.hxx" #include "Dfsheader.h" #include "dfsStrings.hxx" #include "dfsutil.hxx" #define LINK_NAME_ADDED 1 #define STATE_INITIALIZED 0x10 #define COMMENT_INITIALIZED 0x20 #define TIMEOUT_INITIALIZED 0x40 #define MARK_LINK_DELETE 0x0010 #define MARK_LINK_ADD 0x0020 #define UPDATE_LINK_STATE 0x0040 #define UPDATE_LINK_TIMEOUT 0x0080 #define UPDATE_LINK_COMMENT 0x0100 class DfsLink { protected: ULONG _Flags; ULONG _ChangeStatus; DfsString _Name; DfsString _Comment; ULONG _Timeout; ULONG _State; ULONG _TargetCount; DfsLink *_pNextLink; DfsTarget *_pTargets; DfsTarget *_pLastTarget; public: DfsLink( ) { _Flags = 0; _Timeout = 300; _State = DFS_VOLUME_STATE_OK; _pNextLink = NULL; _pTargets = NULL; _pLastTarget = NULL; _ChangeStatus = 0; _TargetCount = 0; } ~DfsLink( ) { // // take care to free up all // resources here. // } VOID ResetChangeStatus() { _ChangeStatus = 0; } VOID SetChangeStatus( ULONG State) { _ChangeStatus |= State; } DFSSTATUS ValidateLinkName( PUNICODE_STRING pLinkName) { pLinkName; return ERROR_SUCCESS; } DFSSTATUS SetLinkName (PUNICODE_STRING pLinkName ) { DFSSTATUS Status = ERROR_SUCCESS; if (_Flags & LINK_NAME_ADDED) { Status = ERROR_INVALID_PARAMETER; } if (Status == ERROR_SUCCESS) { Status = ValidateLinkName( pLinkName); if (Status == ERROR_SUCCESS) { Status = _Name.CreateString(pLinkName); if (Status == ERROR_SUCCESS) { _Flags |= LINK_NAME_ADDED; } } } return Status; } DFSSTATUS SetLinkName (LPWSTR LinkNameString ) { UNICODE_STRING LinkName; RtlInitUnicodeString(&LinkName, LinkNameString); return SetLinkName(&LinkName); } BOOLEAN IsValidLink() { return ((_Flags & LINK_NAME_ADDED) == LINK_NAME_ADDED); } BOOLEAN IsMatchingState( ULONG State) { return (_State == State); } BOOLEAN IsMatchingTimeout( ULONG Timeout) { return (_Timeout == Timeout); } BOOLEAN IsMatchingComment(PUNICODE_STRING pComment) { return (_Comment == pComment); } VOID SetLinkState( ULONG State) { _Flags |= STATE_INITIALIZED; _State = State; } DFSSTATUS SetLinkComment( PUNICODE_STRING pComment ) { _Flags |= COMMENT_INITIALIZED; return _Comment.CreateString(pComment); } DFSSTATUS SetLinkComment( LPWSTR Comment ) { UNICODE_STRING CommentString; RtlInitUnicodeString(&CommentString, Comment); return SetLinkComment(&CommentString); } VOID SetLinkTimeout( ULONG Timeout) { _Flags |= TIMEOUT_INITIALIZED; _Timeout = Timeout; } DFSSTATUS AddTargets(DfsTarget *pTarget, ULONG Count) { DfsTarget *pLastTarget; ULONG Target; if (_pLastTarget != NULL) { _pLastTarget->AddNextTarget(pTarget); } else { _pTargets = pTarget; } _TargetCount += Count; for (Target = 0, pLastTarget = pTarget; Target < Count; Target++, pLastTarget = pLastTarget->GetNextTarget()) { _pLastTarget = pLastTarget; } return ERROR_SUCCESS; } DFSSTATUS AddTarget( DfsTarget *pTarget ) { if (_pLastTarget != NULL) { _pLastTarget->AddNextTarget(pTarget); } else { _pTargets = pTarget; } _TargetCount++; _pLastTarget = pTarget; return ERROR_SUCCESS; } VOID AddNextLink( DfsLink *pLink ) { _pNextLink = pLink; } PUNICODE_STRING GetLinkNameCountedString() { return _Name.GetCountedString(); } PUNICODE_STRING GetLinkCommentCountedString() { return _Comment.GetCountedString(); } LPWSTR GetLinkNameString() { return _Name.GetString(); } LPWSTR GetLinkCommentString() { return _Comment.GetString(); } DfsString * GetLinkName() { return &_Name; } DfsString * GetLinkComment() { return &_Comment; } DWORD GetLinkState() { return _State; } DWORD GetLinkTimeout() { return _Timeout; } DfsTarget * GetFirstTarget() { return _pTargets; } DfsLink * GetNextLink() { return _pNextLink; } BOOLEAN MarkedForDelete() { return ((_ChangeStatus & MARK_LINK_DELETE) == MARK_LINK_DELETE); } BOOLEAN MarkedForAddition() { return ((_ChangeStatus & MARK_LINK_ADD) == MARK_LINK_ADD); } BOOLEAN MarkedForStateUpdate() { return ((_ChangeStatus & UPDATE_LINK_STATE) == UPDATE_LINK_STATE); } BOOLEAN MarkedForTimeoutUpdate() { return ((_ChangeStatus & UPDATE_LINK_TIMEOUT) == UPDATE_LINK_TIMEOUT); } BOOLEAN MarkedForCommentUpdate() { return ((_ChangeStatus & UPDATE_LINK_COMMENT) == UPDATE_LINK_COMMENT); } DFSSTATUS ApplyApiChanges( LPWSTR RootName, DFS_API_MODE Mode, ULONG Version, PDFS_UPDATE_STATISTICS pStatistics ) { DFS_API_INFO ApiInfo, *pApiInfo; DFSSTATUS Status = ERROR_SUCCESS; UNICODE_STRING LinkName; DfsString *pUseComment = NULL; ULONG Flags = 0; BOOLEAN TargetAdded = FALSE; RtlInitUnicodeString(&LinkName, NULL); Status = DfsCreateUnicodePathString (&LinkName, 0, RootName, _Name.GetString()); if (Status != ERROR_SUCCESS) { return Status; } if (MarkedForDelete()) { if (Version >= 4) { Status = DfsApiRemove(Mode, LinkName.Buffer, NULL, NULL); if (Status != ERROR_SUCCESS) { ShowInformation((L"DfsRemove failed for %wS, Status %x\n", LinkName.Buffer, Status)); } pStatistics->LinkDeleted++; pStatistics->TargetDeleted += _TargetCount; pStatistics->ApiCount++; return Status; } } if (MarkedForAddition()) { pUseComment = &_Comment; Flags = DFS_ADD_VOLUME | DFS_RESTORE_VOLUME; _ChangeStatus &= ~UPDATE_LINK_COMMENT; pStatistics->LinkAdded++; } if (Status == ERROR_SUCCESS) { DfsTarget *pTarget; for (pTarget = _pTargets; ((pTarget != NULL) && (Status == ERROR_SUCCESS)); pTarget = pTarget->GetNextTarget()) { Status = pTarget->ApplyApiChanges(Mode, &LinkName, pUseComment, Flags, pStatistics); if (Status != ERROR_SUCCESS) { break; } TargetAdded = TRUE; pUseComment = NULL; Flags &= ~DFS_ADD_VOLUME; } } if (Status == ERROR_SUCCESS) { if (MarkedForStateUpdate()) { ApiInfo.Info101.State = GetLinkState(); pApiInfo = &ApiInfo; Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 101, &pApiInfo); if (Status != ERROR_SUCCESS) { ShowInformation((L"DfsSetInfo State %d failed for %wS, Status %x\n", ApiInfo.Info101.State, LinkName.Buffer, Status)); } pStatistics->LinkModified++; pStatistics->ApiCount++; } else { // // if this is not a new link, update timestamp // on link so target changes are picked up. // this is a workaround so that we dont need to make // these changes in dfssvc itself. // if (!MarkedForAddition() && TargetAdded && (Mode == MODE_DIRECT)) { ApiInfo.Info101.State = GetLinkState(); pApiInfo = &ApiInfo; Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 101, &pApiInfo); } } } if (Status == ERROR_SUCCESS) { if (MarkedForCommentUpdate()) { ApiInfo.Info100.Comment = GetLinkCommentString(); pApiInfo = &ApiInfo; Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 100, &pApiInfo); if (Status != ERROR_SUCCESS) { ShowInformation((L"DfsSetInfo Comment %wS failed for %wS, Status %x\n", ApiInfo.Info100.Comment, LinkName.Buffer, Status)); } pStatistics->LinkModified++; pStatistics->ApiCount++; } } if (Status == ERROR_SUCCESS) { if (MarkedForTimeoutUpdate()) { ApiInfo.Info102.Timeout = GetLinkTimeout(); pApiInfo = &ApiInfo; Status = DfsApiSetInfo( Mode, LinkName.Buffer, NULL, NULL, 102, &pApiInfo); if (Status != ERROR_SUCCESS) { ShowInformation((L"DfsSetInfo Timeout %d failed for %wS, Status %x\n", ApiInfo.Info102.Timeout, LinkName.Buffer, Status)); } pStatistics->LinkModified++; pStatistics->ApiCount++; } } DfsFreeUnicodeString(&LinkName); return Status; } VOID MarkForDelete() { DfsTarget *pTarget; _ChangeStatus = MARK_LINK_DELETE; for (pTarget = _pTargets; (pTarget != NULL); pTarget = pTarget->GetNextTarget()) { pTarget->MarkForDelete(); } } VOID MarkForAddition() { DfsTarget *pTarget; _ChangeStatus = MARK_LINK_ADD; for (pTarget = _pTargets; (pTarget != NULL); pTarget = pTarget->GetNextTarget()) { pTarget->MarkForAddition(); } } DFSSTATUS FindMatchingTarget( DfsString *pServer, DfsString *pFolder, DfsTarget **ppTarget ) { DfsTarget *pTarget; DFSSTATUS Status = ERROR_NOT_FOUND; for (pTarget = _pTargets; (pTarget != NULL); pTarget = pTarget->GetNextTarget()) { if (pTarget->IsMatchingName(pServer, pFolder)) { *ppTarget = pTarget; Status = ERROR_SUCCESS; } } return Status; } }; #endif // __DFS_UTIL_LINK__