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.
 
 
 
 
 
 

590 lines
17 KiB

//--------------------------------------------------------------------------
//
// Copyright (C) 1999, Microsoft Corporation
//
// File: dfsprocessroots.cxx
//
//--------------------------------------------------------------------------
#include <stdio.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <shellapi.h>
#include <winldap.h>
#include <stdlib.h>
#include <dfslink.hxx>
#include <dfsroot.hxx>
#include <dfstarget.hxx>
#include "dfsutil.hxx"
#include "dfspathname.hxx"
#include "misc.hxx"
#include <strsafe.h>
#define MAX_APPEND_SIZE 16
#define MAX_BACKUP_NAME_SIZE 512
#define TIME_STR_LEN 256
WCHAR BackupName[MAX_BACKUP_NAME_SIZE];
WCHAR TimeStr[TIME_STR_LEN];
DFSSTATUS
CreateBackupFile(
DfsRoot *pOperateRoot,
HANDLE *pBackupHandle )
{
size_t CurrentChCount;
SYSTEMTIME CurrentTime;
LPWSTR Prefix = L"dfsutil.backup.";
DfsPathName PathName;
HANDLE BackupHandle;
DFSSTATUS Status;
HRESULT Hr = S_OK;
Status = PathName.CreatePathName(pOperateRoot->GetLinkNameString());
if (Status != ERROR_SUCCESS)
{
return Status;
}
GetLocalTime( &CurrentTime );
Hr = StringCchPrintf(TimeStr,
TIME_STR_LEN,
L"%02d.%02d.%04d.%02d.%02d.%02d.%03d",
CurrentTime.wMonth,
CurrentTime.wDay,
CurrentTime.wYear,
CurrentTime.wHour,
CurrentTime.wMinute,
CurrentTime.wSecond,
CurrentTime.wMilliseconds );
CurrentChCount = MAX_BACKUP_NAME_SIZE;
if (SUCCEEDED(Hr))
{
Hr = StringCchCopyEx( BackupName,
CurrentChCount,
PathName.GetServerString(),
NULL,
&CurrentChCount,
STRSAFE_IGNORE_NULLS);
}
if (SUCCEEDED(Hr))
{
Hr = StringCchCatNEx( BackupName,
CurrentChCount,
L".",
sizeof( L"." ) / sizeof( WCHAR ),
NULL,
&CurrentChCount,
STRSAFE_IGNORE_NULLS);
}
if (SUCCEEDED(Hr))
{
Hr = StringCchCatNEx( BackupName,
CurrentChCount,
PathName.GetShareString(),
MAX_APPEND_SIZE,
NULL,
&CurrentChCount,
STRSAFE_IGNORE_NULLS);
}
if (SUCCEEDED(Hr))
{
Hr = StringCchCatNEx( BackupName,
CurrentChCount,
L".",
sizeof( L"." ) / sizeof( WCHAR ),
NULL,
&CurrentChCount,
STRSAFE_IGNORE_NULLS);
}
if (SUCCEEDED(Hr))
{
Hr = StringCchCatNEx( BackupName,
CurrentChCount,
Prefix,
MAX_APPEND_SIZE,
NULL,
&CurrentChCount,
STRSAFE_IGNORE_NULLS);
}
if (SUCCEEDED(Hr))
{
Hr = StringCchCatEx( BackupName,
CurrentChCount,
TimeStr,
NULL,
&CurrentChCount,
STRSAFE_IGNORE_NULLS);
}
if (!SUCCEEDED(Hr))
{
return HRESULT_CODE(Hr);
}
Status = CreateDfsFile(BackupName, &BackupHandle);
if (Status == ERROR_SUCCESS)
{
*pBackupHandle = BackupHandle;
ShowInformation((L"Backup of %ws before modifications being written to %ws\n",
PathName.GetPathString(),
BackupName));
}
return Status;
}
DFSSTATUS
DfsGenerateBackupFile(
DfsRoot *pOperateRoot,
HANDLE BackupHandle )
{
DFSSTATUS Status = ERROR_SUCCESS;
HANDLE UseBackup = BackupHandle;
if (BackupHandle == INVALID_HANDLE_VALUE)
{
Status = CreateBackupFile(pOperateRoot, &UseBackup);
}
if (Status == ERROR_SUCCESS)
{
Status = DumpRoots( pOperateRoot, UseBackup, TRUE);
}
if (Status == ERROR_SUCCESS)
{
FlushFileBuffers(BackupHandle);
}
return Status;
}
DFSSTATUS
DfsUpdateMetadata(
DfsRoot *pOperateRoot,
DfsRoot *pMasterRoot )
{
DFSSTATUS Status = ERROR_SUCCESS;
DfsString *pRootString = pOperateRoot->GetRootApiName();
DebugInformation((L"UpdateMetadata for roots %x and %x\n",
pOperateRoot, pMasterRoot));
if (pOperateRoot != NULL)
{
Status = pOperateRoot->ApplyApiChanges( pRootString->GetString(),
pOperateRoot->GetMode(),
pOperateRoot->GetVersion() );
DebugInformation((L"ApplyApiChanges for root %x, Status %x\n",
pOperateRoot, Status));
}
if (Status == ERROR_SUCCESS)
{
if (pMasterRoot != NULL)
{
Status = pMasterRoot->ApplyApiChanges(pRootString->GetString(),
pOperateRoot->GetMode(),
pOperateRoot->GetVersion() );
DebugInformation((L"ApplyApiChanges for root %x, Status %x\n",
pMasterRoot, Status));
}
}
DebugInformation((L"UpdateMetadata for roots %x and %x, done Status %x\n",
pOperateRoot, pMasterRoot, Status));
return Status;
}
DFSSTATUS
DfsProcessRoots(
DfsRoot *pOperateRoot,
DfsRoot *pMasterRoot )
{
DFSSTATUS Status = ERROR_SUCCESS;
DfsLink *pLink, *pExistingLink;
DfsTarget *pTarget, *pExistingTarget;
for (pLink = pMasterRoot->GetFirstLink();
pLink != NULL;
pLink = pLink->GetNextLink())
{
DFSSTATUS LinkStatus;
LinkStatus = pOperateRoot->FindMatchingLink( pLink->GetLinkNameCountedString(),
&pExistingLink );
if (LinkStatus == ERROR_SUCCESS)
{
for (pTarget = pLink->GetFirstTarget();
pTarget != NULL;
pTarget = pTarget->GetNextTarget())
{
DFSSTATUS TargetStatus;
TargetStatus = pExistingLink->FindMatchingTarget( pTarget->GetTargetServer(),
pTarget->GetTargetFolder(),
&pExistingTarget);
if (TargetStatus == ERROR_SUCCESS)
{
pExistingTarget->ResetChangeStatus();
pTarget->ResetChangeStatus();
if ((pTarget->IsMatchingState(pExistingTarget->GetTargetState())) == FALSE)
{
pTarget->SetChangeStatus(UPDATE_TARGET_STATE);
}
pExistingLink->ResetChangeStatus();
pLink->ResetChangeStatus();
}
else
{
if (pTarget->IsMatchingState(DEFAULT_TARGET_STATE) == FALSE)
{
pTarget->SetChangeStatus(UPDATE_TARGET_STATE);
}
}
}
if (pExistingLink->GetFirstTarget() == NULL)
{
pExistingLink->ResetChangeStatus();
}
if (pLink->IsMatchingState(pExistingLink->GetLinkState()) == FALSE)
{
pLink->SetChangeStatus(UPDATE_LINK_STATE);
}
if (pLink->IsMatchingTimeout(pExistingLink->GetLinkTimeout()) == FALSE)
{
pLink->SetChangeStatus(UPDATE_LINK_TIMEOUT);
}
if (pLink->IsMatchingComment(pExistingLink->GetLinkCommentCountedString())== FALSE)
{
pLink->SetChangeStatus(UPDATE_LINK_COMMENT);
}
}
else
{
if (pLink->IsMatchingState(DEFAULT_LINK_STATE) == FALSE)
{
pLink->SetChangeStatus(UPDATE_LINK_STATE);
}
if (pLink->IsMatchingTimeout(DEFAULT_LINK_TIMEOUT) == FALSE)
{
pLink->SetChangeStatus(UPDATE_LINK_TIMEOUT);
}
for (pTarget = pLink->GetFirstTarget();
pTarget != NULL;
pTarget = pTarget->GetNextTarget())
{
if (pTarget->IsMatchingState(DEFAULT_TARGET_STATE) == FALSE)
{
pTarget->SetChangeStatus(UPDATE_TARGET_STATE);
}
}
}
}
DebugInformation((L"DfsProcessRoots for %x and %x, done Status %x\n",
pOperateRoot,
pMasterRoot,
Status));
return Status;
}
DFSSTATUS
DfsUpdate(
DfsRoot *pOperateRoot,
DfsRoot *pMasterRoot )
{
DFSSTATUS Status;
Status = DfsProcessRoots( pOperateRoot,
pMasterRoot );
if (Status == ERROR_SUCCESS)
{
Status = DfsUpdateMetadata(pOperateRoot,
pMasterRoot);
}
if (Status == ERROR_SUCCESS)
{
PDFS_UPDATE_STATISTICS pOperateStats;
PDFS_UPDATE_STATISTICS pMasterStats;
pOperateStats = pOperateRoot->GetRootStatistics();
pMasterStats = pMasterRoot->GetRootStatistics();
pOperateStats->LinkModified += pMasterStats->LinkModified;
pOperateStats->LinkAdded += pMasterStats->LinkAdded;
pOperateStats->LinkDeleted += pMasterStats->LinkDeleted;
pOperateStats->TargetModified += pMasterStats->TargetModified;
pOperateStats->TargetAdded += pMasterStats->TargetAdded;
pOperateStats->TargetDeleted += pMasterStats->TargetDeleted;
pOperateStats->ApiCount += pMasterStats->ApiCount;
ShowInformation((L"\nUpdate Statistics: Number of Apis %d\n",
pOperateStats->ApiCount));
ShowInformation((L"Links: Added %d Deleted %d Modified %d\n",
pOperateStats->LinkAdded,
pOperateStats->LinkDeleted,
pOperateStats->LinkModified));
ShowInformation((L"Targets: Added %d Deleted %d Modified %d\n",
pOperateStats->TargetAdded,
pOperateStats->TargetDeleted,
pOperateStats->TargetModified));
}
return Status;
}
DFSSTATUS
SetDfsRoots(
DfsRoot *pOperateRoot,
DfsRoot *pMasterRoot,
HANDLE BackupHandle,
BOOLEAN NoBackup )
{
DFSSTATUS Status;
PUNICODE_STRING pRootToUpdate = pOperateRoot->GetLinkNameCountedString();
if (NoBackup == FALSE)
{
Status = DfsGenerateBackupFile(pOperateRoot, BackupHandle);
if (Status != ERROR_SUCCESS)
{
return Status;
}
}
pOperateRoot->SetRootApiName(pRootToUpdate);
pOperateRoot->SetRootWriteable();
pOperateRoot->MarkForDelete();
pMasterRoot->MarkForAddition();
Status = DfsUpdate( pOperateRoot,
pMasterRoot );
if (Status == ERROR_SUCCESS)
{
Status = pOperateRoot->UpdateMetadata();
}
if (Status == ERROR_SUCCESS)
{
(VOID) ReSynchronizeRootTargets(pOperateRoot->GetLinkNameString());
}
return Status;
}
DFSSTATUS
MergeDfsRoots(
DfsRoot *pOperateRoot,
DfsRoot *pMasterRoot,
HANDLE BackupHandle,
BOOLEAN NoBackup )
{
DFSSTATUS Status;
PUNICODE_STRING pRootToUpdate = pOperateRoot->GetLinkNameCountedString();
if (NoBackup == FALSE)
{
Status = DfsGenerateBackupFile(pOperateRoot, BackupHandle);
if (Status != ERROR_SUCCESS)
{
return Status;
}
}
pOperateRoot->SetRootApiName(pRootToUpdate);
pOperateRoot->SetRootWriteable();
pMasterRoot->MarkForAddition();
Status = DfsUpdate( pOperateRoot,
pMasterRoot );
if (Status == ERROR_SUCCESS)
{
Status = pOperateRoot->UpdateMetadata();
}
if (Status == ERROR_SUCCESS)
{
(VOID) ReSynchronizeRootTargets(pOperateRoot->GetLinkNameString());
}
return Status;
}
ULONG
DfsShowVerifyInformation(
LPWSTR RootName,
DfsRoot *pOperateRoot)
{
DfsLink *pLink;
DfsTarget *pTarget;
ULONG Errors = 0;
for (pLink = pOperateRoot->GetFirstLink();
pLink != NULL;
pLink = pLink->GetNextLink())
{
if (pLink->MarkedForDelete())
{
ShowInformation((L"%wS\\%wS, link additional\n",
RootName,
pLink->GetLinkNameString()));
Errors++;
}
if (pLink->MarkedForAddition())
{
ShowInformation((L"%wS\\%wS, link missing\n",
RootName,
pLink->GetLinkNameString()));
Errors++;
}
if (pLink->MarkedForCommentUpdate())
{
ShowInformation((L"%wS\\%wS, link Comment mismatch\n",
RootName,
pLink->GetLinkNameString()));
Errors++;
}
if (pLink->MarkedForStateUpdate())
{
ShowInformation((L"%wS\\%wS, link State mismatch\n",
RootName,
pLink->GetLinkNameString()));
Errors++;
}
if (pLink->MarkedForTimeoutUpdate())
{
ShowInformation((L"%wS\\%wS, link Timeout mismatch\n",
RootName,
pLink->GetLinkNameString()));
Errors++;
}
for (pTarget = pLink->GetFirstTarget();
(pTarget != NULL);
pTarget = pTarget->GetNextTarget())
{
if (pTarget->MarkedForDelete())
{
ShowInformation((L"%wS\\%wS, Target (Server %wS, Folder %wS) Additional\n",
RootName,
pLink->GetLinkNameString(),
pTarget->GetTargetServerString(),
pTarget->GetTargetFolderString()));
Errors++;
}
if (pTarget->MarkedForAddition())
{
ShowInformation((L"%wS\\%wS, Target (Server %wS, Folder %wS) Missing\n",
RootName,
pLink->GetLinkNameString(),
pTarget->GetTargetServerString(),
pTarget->GetTargetFolderString()));
Errors++;
}
if (pTarget->MarkedForStateUpdate())
{
ShowInformation((L"%wS\\%wS, Target (Server %wS, Folder %wS) State mismatch\n",
RootName,
pLink->GetLinkNameString(),
pTarget->GetTargetServerString(),
pTarget->GetTargetFolderString()));
Errors++;
}
}
}
return Errors;
}
DFSSTATUS
VerifyDfsRoots(
DfsRoot *pOperateRoot,
DfsRoot *pMasterRoot )
{
DFSSTATUS Status;
ULONG Errors = 0;
pOperateRoot->MarkForDelete();
pMasterRoot->MarkForAddition();
Status = DfsProcessRoots( pOperateRoot,
pMasterRoot );
if (Status == ERROR_SUCCESS)
{
Errors = DfsShowVerifyInformation(
pOperateRoot->GetLinkNameString(),
pOperateRoot);
Errors += DfsShowVerifyInformation(
pOperateRoot->GetLinkNameString(),
pMasterRoot);
}
if (Errors == 0)
{
ShowInformation((L"\n\nVerification successful for Namespace %wS\n\n",
pOperateRoot->GetLinkNameString()));
}
else
{
ShowInformation((L"\n\nVerification detected %d inconsistencies for Namespace %wS\n\n",
Errors,
pOperateRoot->GetLinkNameString()));
}
return Status;
}