Leaked source code of windows server 2003
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.
 
 
 
 
 
 

546 lines
13 KiB

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