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.
373 lines
9.4 KiB
373 lines
9.4 KiB
#include <DfsGeneric.hxx>
|
|
#include "DfsInit.hxx"
|
|
#include "lm.h"
|
|
#include "lmdfs.h"
|
|
|
|
#include "DfsSynchronizeRoots.tmh"
|
|
|
|
DWORD
|
|
DfsRootSyncThread(LPVOID TData);
|
|
|
|
typedef struct _DFS_ROOT_SYNCHRONIZE_HEADER
|
|
{
|
|
HANDLE hTimer;
|
|
HANDLE SyncEvent;
|
|
CRITICAL_SECTION DataLock;
|
|
LIST_ENTRY Entries;
|
|
} DFS_ROOT_SYNCHRONIZE_HEADER, *PDFS_ROOT_SYNCHRONIZE_HEADER;
|
|
|
|
|
|
typedef struct _DFS_ROOT_SYNCRHONIZE_INFO
|
|
{
|
|
UNICODE_STRING Target;
|
|
LIST_ENTRY ListEntry;
|
|
} DFS_ROOT_SYNCHRONIZE_INFO, *PDFS_ROOT_SYNCHRONIZE_INFO;
|
|
|
|
DFS_ROOT_SYNCHRONIZE_HEADER DfsRootSyncHeader;
|
|
|
|
BOOL SyncCritSectionInit = FALSE;
|
|
|
|
DFSSTATUS
|
|
DfsRootSynchronizeInit()
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
|
|
InitializeListHead(&DfsRootSyncHeader.Entries);
|
|
|
|
SyncCritSectionInit = InitializeCriticalSectionAndSpinCount( &DfsRootSyncHeader.DataLock, DFS_CRIT_SPIN_COUNT );
|
|
if(!SyncCritSectionInit)
|
|
{
|
|
Status = GetLastError();
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
DfsRootSyncHeader.SyncEvent = CreateEvent( NULL,
|
|
TRUE, // manual reset
|
|
FALSE, // initially reset.
|
|
NULL );
|
|
if (DfsRootSyncHeader.SyncEvent == NULL)
|
|
{
|
|
Status = GetLastError();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
// Create a waitable timer.
|
|
DfsRootSyncHeader.hTimer = CreateWaitableTimer(NULL,
|
|
FALSE, // not manual reset.
|
|
NULL );
|
|
if (DfsRootSyncHeader.hTimer == NULL)
|
|
{
|
|
Status = GetLastError();
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
HANDLE THandle;
|
|
DWORD Tid;
|
|
|
|
THandle = CreateThread (
|
|
NULL,
|
|
0,
|
|
DfsRootSyncThread,
|
|
0,
|
|
0,
|
|
&Tid);
|
|
|
|
if (THandle != NULL) {
|
|
CloseHandle(THandle);
|
|
DFS_TRACE_HIGH(REFERRAL_SERVER, "Created Scavenge Thread (%d) Tid\n", Tid);
|
|
}
|
|
else {
|
|
Status = GetLastError();
|
|
DFS_TRACE_HIGH(REFERRAL_SERVER, "Failed Scavenge Thread creation, Status %x\n", Status);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
DFSSTATUS
|
|
AddToSyncList (
|
|
PUNICODE_STRING pTarget)
|
|
{
|
|
PDFS_ROOT_SYNCHRONIZE_INFO pRootSync;
|
|
ULONG TotalSize;
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
|
|
TotalSize = sizeof(DFS_ROOT_SYNCHRONIZE_INFO) + pTarget->Length + sizeof(WCHAR);
|
|
pRootSync = (PDFS_ROOT_SYNCHRONIZE_INFO)new BYTE[TotalSize];
|
|
if (pRootSync != NULL)
|
|
{
|
|
pRootSync->Target.Buffer = (LPWSTR)(pRootSync + 1);
|
|
RtlCopyMemory( pRootSync->Target.Buffer,
|
|
pTarget->Buffer,
|
|
pTarget->Length );
|
|
pRootSync->Target.Length = pRootSync->Target.MaximumLength = pTarget->Length;
|
|
pRootSync->Target.Buffer[pRootSync->Target.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
InsertTailList( &DfsRootSyncHeader.Entries, &pRootSync->ListEntry);
|
|
|
|
SetEvent(DfsRootSyncHeader.SyncEvent);
|
|
}
|
|
else
|
|
{
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
DFS_TRACE_HIGH(REFERRAL_SERVER, "Adding %wZ to sync list, Status %x\n",
|
|
pTarget, Status);
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
DeleteSyncRoot(
|
|
PDFS_ROOT_SYNCHRONIZE_INFO pDeleteEntry )
|
|
{
|
|
delete [] (PBYTE)pDeleteEntry;
|
|
}
|
|
|
|
|
|
DFSSTATUS
|
|
AddRootToSyncrhonize(
|
|
PUNICODE_STRING pName )
|
|
{
|
|
DFSSTATUS Status;
|
|
PLIST_ENTRY pNext;
|
|
PDFS_ROOT_SYNCHRONIZE_INFO pRootSync;
|
|
BOOLEAN Found = FALSE;
|
|
|
|
Status = DfsAcquireWriteLock(&DfsRootSyncHeader.DataLock);
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
pNext = DfsRootSyncHeader.Entries.Flink;
|
|
while (pNext != &DfsRootSyncHeader.Entries)
|
|
{
|
|
pRootSync = CONTAINING_RECORD( pNext,
|
|
DFS_ROOT_SYNCHRONIZE_INFO,
|
|
ListEntry );
|
|
if (RtlCompareUnicodeString(&pRootSync->Target,
|
|
pName,
|
|
TRUE) == 0)
|
|
{
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
pNext = pNext->Flink;
|
|
}
|
|
|
|
if (!Found)
|
|
{
|
|
Status = AddToSyncList( pName );
|
|
}
|
|
|
|
DfsReleaseLock(&DfsRootSyncHeader.DataLock);
|
|
|
|
DFS_TRACE_HIGH(REFERRAL_SERVER, "AddRootToSync %wZ, Found? %d, Status %x\n",
|
|
pName, Found, Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DFSSTATUS
|
|
SynchronizeRoots()
|
|
{
|
|
BOOLEAN RootSync = TRUE;
|
|
PLIST_ENTRY pNext;
|
|
PDFS_ROOT_SYNCHRONIZE_INFO pRootSync;
|
|
BOOLEAN WorkToDo = TRUE;
|
|
DFSSTATUS Status;
|
|
|
|
while (WorkToDo)
|
|
{
|
|
Status = DfsAcquireWriteLock(&DfsRootSyncHeader.DataLock);
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
WorkToDo = FALSE;
|
|
pRootSync = NULL;
|
|
|
|
if (!IsListEmpty( &DfsRootSyncHeader.Entries ))
|
|
{
|
|
pNext = RemoveHeadList( &DfsRootSyncHeader.Entries );
|
|
pRootSync = CONTAINING_RECORD( pNext,
|
|
DFS_ROOT_SYNCHRONIZE_INFO,
|
|
ListEntry );
|
|
WorkToDo = TRUE;
|
|
}
|
|
|
|
DfsReleaseLock(&DfsRootSyncHeader.DataLock);
|
|
|
|
if (pRootSync != NULL)
|
|
{
|
|
DFS_INFO_101 DfsState;
|
|
DFSSTATUS ApiStatus;
|
|
|
|
DfsState.State = DFS_VOLUME_STATE_RESYNCHRONIZE;
|
|
//
|
|
// Ignore the api status.
|
|
//
|
|
|
|
ApiStatus = NetDfsSetInfo( pRootSync->Target.Buffer,
|
|
NULL,
|
|
NULL,
|
|
101,
|
|
(LPBYTE)&DfsState);
|
|
|
|
DFS_TRACE_NORM(REFERRAL_SERVER, "Syncrhonized %wZ, Status %x\n",
|
|
&pRootSync->Target, ApiStatus);
|
|
|
|
DeleteSyncRoot( pRootSync );
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DfsRootSyncThread(LPVOID TData)
|
|
{
|
|
UNREFERENCED_PARAMETER(TData);
|
|
|
|
HANDLE WaitHandles[2];
|
|
LARGE_INTEGER liDueTime;
|
|
DFSSTATUS Status;
|
|
|
|
liDueTime.QuadPart=-1000000000;
|
|
|
|
WaitHandles[0] = DfsRootSyncHeader.SyncEvent;
|
|
WaitHandles[1] = DfsRootSyncHeader.hTimer;
|
|
|
|
while (TRUE)
|
|
{
|
|
DFSSTATUS WaitStatus;
|
|
|
|
if (!ResetEvent(DfsRootSyncHeader.SyncEvent))
|
|
{
|
|
// Log this error.
|
|
Status = GetLastError();
|
|
}
|
|
if (!SetWaitableTimer( DfsRootSyncHeader.hTimer,
|
|
&liDueTime,
|
|
0, NULL, NULL, 0))
|
|
{
|
|
//
|
|
// log this error.
|
|
//
|
|
Status = GetLastError();
|
|
}
|
|
|
|
// dfsdev: use status here.
|
|
|
|
WaitStatus = WaitForMultipleObjects( 2,
|
|
WaitHandles,
|
|
TRUE,
|
|
INFINITE );
|
|
|
|
DFS_TRACE_LOW(REFERRAL_SERVER, "Sync thread, waking up %x\n", WaitStatus);
|
|
|
|
|
|
if (DfsIsShuttingDown())
|
|
{
|
|
break;
|
|
}
|
|
|
|
SynchronizeRoots();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DFSSTATUS
|
|
ClearSynchronizeRootsQueue(void)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
PLIST_ENTRY pNext =NULL;
|
|
PDFS_ROOT_SYNCHRONIZE_INFO pRootSync = NULL;
|
|
|
|
Status = DfsAcquireWriteLock(&DfsRootSyncHeader.DataLock);
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
if (!IsListEmpty( &DfsRootSyncHeader.Entries ))
|
|
{
|
|
pNext = RemoveHeadList( &DfsRootSyncHeader.Entries );
|
|
pRootSync = CONTAINING_RECORD( pNext,
|
|
DFS_ROOT_SYNCHRONIZE_INFO,
|
|
ListEntry );
|
|
DeleteSyncRoot( pRootSync );
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
DfsReleaseLock(&DfsRootSyncHeader.DataLock);
|
|
return Status;
|
|
}
|
|
|
|
void
|
|
DfsRootSynchronizeShutdown(void)
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
LARGE_INTEGER liDueTime;
|
|
|
|
liDueTime.QuadPart=0000000000;
|
|
|
|
if(DfsRootSyncHeader.hTimer != NULL)
|
|
{
|
|
if (!SetWaitableTimer( DfsRootSyncHeader.hTimer,
|
|
&liDueTime,
|
|
0, NULL, NULL, 0))
|
|
{
|
|
//
|
|
// log this error.
|
|
//
|
|
Status = GetLastError();
|
|
}
|
|
}
|
|
|
|
if(DfsRootSyncHeader.SyncEvent != NULL)
|
|
{
|
|
SetEvent(DfsRootSyncHeader.SyncEvent);
|
|
}
|
|
|
|
ClearSynchronizeRootsQueue();
|
|
|
|
if(SyncCritSectionInit == TRUE)
|
|
{
|
|
DeleteCriticalSection( &DfsRootSyncHeader.DataLock );
|
|
SyncCritSectionInit = FALSE;
|
|
}
|
|
|
|
|
|
if(DfsRootSyncHeader.hTimer != NULL)
|
|
{
|
|
CloseHandle(DfsRootSyncHeader.hTimer);
|
|
DfsRootSyncHeader.hTimer = NULL;
|
|
}
|
|
|
|
if(DfsRootSyncHeader.SyncEvent != NULL)
|
|
{
|
|
CloseHandle(DfsRootSyncHeader.SyncEvent);
|
|
DfsRootSyncHeader.SyncEvent = NULL;
|
|
}
|
|
}
|
|
|