1467 lines
40 KiB
C
1467 lines
40 KiB
C
//+----------------------------------------------------------------------------
|
||
//
|
||
// Copyright (C) 1992, Microsoft Corporation.
|
||
//
|
||
// File: PKTFSCTL.C
|
||
//
|
||
// Contents: This module contains the implementation for FS controls
|
||
// which manipulate the PKT.
|
||
//
|
||
// Functions: PktFsctrlGetRelationInfo -
|
||
// PktFsctrlSetRelationInfo -
|
||
// PktFsctrlIsChildnameLegal -
|
||
// PktFsctrlCreateEntry -
|
||
// PktFsctrlCreateSubordinateEntry -
|
||
// PktFsctrlDestroyEntry -
|
||
// PktFsctrlUpdateSiteCosts -
|
||
// DfsAgePktEntries - Flush PKT entries periodically
|
||
//
|
||
// Private Functions
|
||
//
|
||
// DfspCreateExitPathOnRoot
|
||
// PktpHashSiteCostList
|
||
// PktpLookupSiteCost
|
||
// PktpUpdateSiteCosts
|
||
//
|
||
// Debug Only Functions
|
||
//
|
||
// PktFsctrlFlushCache - Flush PKT entries on command
|
||
//
|
||
// History: 12 Jul 1993 Alanw Created from localvol.c.
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
#include "dfsprocs.h"
|
||
#include <dfserr.h>
|
||
#include <netevent.h>
|
||
#include "fsctrl.h"
|
||
#include "log.h"
|
||
#include "know.h"
|
||
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_LOCALVOL)
|
||
|
||
NTSTATUS
|
||
DfspCreateExitPathOnRoot(
|
||
PDFS_SERVICE service,
|
||
PUNICODE_STRING RemPath
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text( PAGE, PktFsctrlGetRelationInfo )
|
||
#pragma alloc_text( PAGE, PktFsctrlVerifyLocalVolumeKnowledge )
|
||
#pragma alloc_text( PAGE, PktFsctrlPruneLocalVolume )
|
||
#pragma alloc_text( PAGE, PktFsctrlCreateEntry )
|
||
#pragma alloc_text( PAGE, PktFsctrlCreateSubordinateEntry )
|
||
#pragma alloc_text( PAGE, PktFsctrlDestroyEntry )
|
||
#pragma alloc_text( PAGE, DfsAgePktEntries )
|
||
#pragma alloc_text( PAGE, DfspCreateExitPathOnRoot )
|
||
|
||
|
||
#if DBG
|
||
#pragma alloc_text( PAGE, PktFsctrlFlushCache )
|
||
#endif // DBG
|
||
|
||
#endif // ALLOC_PRAGMA
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: DfspCreateExitPathOnRoot
|
||
//
|
||
// Synopsis: This function creates an on disk exit path on the ORGROOT vol
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
DfspCreateExitPathOnRoot(
|
||
PDFS_SERVICE service,
|
||
PUNICODE_STRING RemPath
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
UNICODE_STRING ExitPath;
|
||
|
||
status = BuildLocalVolPath(&ExitPath, service, RemPath);
|
||
if (NT_SUCCESS(status)) {
|
||
//
|
||
// For now make sure that StorageId Exists. Dont worry about the
|
||
// actual exit pt bit on it. Fix when EXIT_PTs come along.
|
||
//
|
||
if (DfsFixExitPath(ExitPath.Buffer)) {
|
||
DebugTrace(0, Dbg, "Succeeded to Create ExitPth on Orgroot %wZ\n",
|
||
&ExitPath);
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
else {
|
||
DebugTrace(0, Dbg, "Failed to Create ExitPath on Orgroot %wZ\n",
|
||
&ExitPath);
|
||
status = DFS_STATUS_BAD_EXIT_POINT;
|
||
}
|
||
ExFreePool(ExitPath.Buffer);
|
||
}
|
||
else {
|
||
DebugTrace(0, Dbg, "Failed to create localvol path for %wZ \n",
|
||
RemPath);
|
||
}
|
||
|
||
return(status);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlGetRelationInfo, public
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: We only process this FSCTRL from the file system process,
|
||
// never from the driver.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PktFsctrlGetRelationInfo(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength,
|
||
IN PVOID OutputBuffer,
|
||
IN ULONG OutputBufferLength
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
DFS_PKT_ENTRY_ID EntryId;
|
||
DFS_PKT_RELATION_INFO relationInfo;
|
||
ULONG size = 0;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlGetRelationInfo, TRUE, TRUE );
|
||
|
||
//
|
||
// Unmarshal the argument...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
status = DfsRtlGet(&marshalBuffer, &MiPktEntryId, &EntryId);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PDFS_PKT pkt = _GetPkt();
|
||
status = PktRelationInfoConstruct(&relationInfo, pkt, &EntryId);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
DfsRtlSize(&MiPktRelationInfo, &relationInfo, &size);
|
||
if (size>OutputBufferLength) {
|
||
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
||
} else {
|
||
MarshalBufferInitialize(&marshalBuffer,
|
||
size,
|
||
OutputBuffer);
|
||
DfsRtlPut(&marshalBuffer,
|
||
&MiPktRelationInfo,
|
||
&relationInfo);
|
||
}
|
||
//
|
||
// Now we have to free up the relation info struct that we
|
||
// created above.
|
||
//
|
||
PktRelationInfoDestroy(&relationInfo, FALSE);
|
||
}
|
||
|
||
PktEntryIdDestroy(&EntryId, FALSE);
|
||
|
||
} else
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlGetRelationInfo: Unmarshalling Error!\n", 0);
|
||
|
||
Irp->IoStatus.Information = marshalBuffer.Current - marshalBuffer.First;
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg, "PktFsctrlGetRelationInfo: Exit -> %08lx\n", ULongToPtr( status ));
|
||
|
||
return(status);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlSetRelationInfo, public
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: We only process this FSCTRL from the file system process,
|
||
// never from the driver.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PktFsctrlSetRelationInfo(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
DFS_PKT_RELATION_INFO relationInfo;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlSetRelationInfo, TRUE, FALSE);
|
||
|
||
//
|
||
// Unmarshal the argument...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
status = DfsRtlGet(&marshalBuffer, &MiPktRelationInfo, &relationInfo);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PDFS_PKT pkt = _GetPkt();
|
||
|
||
status = PktSetRelationInfo(
|
||
pkt,
|
||
&relationInfo
|
||
);
|
||
|
||
//
|
||
// Need to deallocate the relationInfo...
|
||
//
|
||
|
||
PktRelationInfoDestroy(&relationInfo, FALSE);
|
||
} else
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlSetRelationInfo: Unmarshalling Error!\n", 0);
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg, "PktFsctrlSetRelationInfo: Exit -> %08lx\n", ULongToPtr( status ));
|
||
return status;
|
||
}
|
||
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlIsChildnameLegal, public
|
||
//
|
||
// Synopsis: Determines whether the given childname is a valid one for
|
||
// the given parent prefix.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- The childname is legal
|
||
//
|
||
// [STATUS_OBJECT_NAME_COLLISION] -- The childname conflicts with
|
||
// another child of the parent prefix.
|
||
//
|
||
// [STATUS_OBJECT_PATH_NOT_FOUND] -- The childname is not a
|
||
// hierarchically related to the parent
|
||
//
|
||
// [STATUS_INVALID_PARAMETER] -- The childname is bogus and
|
||
// doesn't start with a backslash
|
||
//
|
||
// [STATUS_DATA_ERROR] -- If the input buffer could not be
|
||
// unmarshalled.
|
||
//
|
||
// [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory unmarshalling
|
||
// input buffer.
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktFsctrlIsChildnameLegal(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength)
|
||
{
|
||
NTSTATUS status;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
DFS_PKT_ENTRY_ID idParent;
|
||
DFS_PKT_ENTRY_ID idChild;
|
||
UNICODE_STRING ustrRem;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlIsChildnameLegal, TRUE, FALSE);
|
||
|
||
MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
|
||
|
||
status = DfsRtlGet( &marshalBuffer, &MiPktEntryId, &idParent );
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
status = DfsRtlGet( &marshalBuffer, &MiPktEntryId, &idChild );
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PDFS_PKT pPkt = _GetPkt();
|
||
PDFS_PKT_ENTRY pPktEntry, pSuperiorEntry;
|
||
|
||
ustrRem.Length = ustrRem.MaximumLength = 0;
|
||
ustrRem.Buffer = NULL;
|
||
|
||
PktAcquireShared( pPkt, TRUE );
|
||
|
||
pPktEntry = PktLookupEntryByPrefix(
|
||
pPkt,
|
||
&idChild.Prefix,
|
||
&ustrRem);
|
||
|
||
if (pPktEntry != NULL) {
|
||
|
||
if (ustrRem.Length != 0) {
|
||
|
||
//
|
||
// There is no exact match for the child, so
|
||
// lets check to see if the match occured with the
|
||
// parent prefix.
|
||
//
|
||
|
||
if (RtlCompareUnicodeString(
|
||
&idParent.Prefix,
|
||
&pPktEntry->Id.Prefix,
|
||
FALSE) == 0) {
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
|
||
status = STATUS_OBJECT_NAME_COLLISION;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// This might be a legal child name. Check to see if the
|
||
// passed-in child guid matches the one in the pkt entry
|
||
// we found; if so, then this is a valid child name.
|
||
//
|
||
|
||
if (GuidEqual(&idChild.Uid, &pPktEntry->Id.Uid)) {
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
|
||
status = STATUS_OBJECT_NAME_COLLISION;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
status = STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
PktRelease( pPkt );
|
||
|
||
PktEntryIdDestroy(&idChild, FALSE);
|
||
|
||
}
|
||
|
||
PktEntryIdDestroy(&idParent, FALSE);
|
||
}
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg, "PktFsctrlIsChildnameLegal: Exit -> %08lx\n", ULongToPtr( status ));
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlCreateEntry, public
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: We only process this FSCTRL from the file system process,
|
||
// never from the driver.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PktFsctrlCreateEntry(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
DFS_PKT_CREATE_ENTRY_ARG arg;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlCreateEntry, TRUE, FALSE);
|
||
|
||
//
|
||
// Unmarshal the argument...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
status = DfsRtlGet(&marshalBuffer, &MiPktCreateEntryArg, &arg);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PDFS_PKT pkt = _GetPkt();
|
||
PDFS_PKT_ENTRY entry;
|
||
ULONG i;
|
||
|
||
PktAcquireExclusive(pkt, TRUE);
|
||
try {
|
||
status = PktCreateEntry(pkt,
|
||
arg.EntryType,
|
||
&arg.EntryId,
|
||
&arg.EntryInfo,
|
||
arg.CreateDisposition,
|
||
&entry);
|
||
} finally {
|
||
PktRelease(pkt);
|
||
}
|
||
|
||
//
|
||
// Need to deallocate the entry Id...
|
||
//
|
||
PktEntryIdDestroy(&arg.EntryId, FALSE);
|
||
PktEntryInfoDestroy(&arg.EntryInfo, FALSE);
|
||
} else
|
||
DebugTrace(0, Dbg, "PktFsctrlCreateEntry: Unmarshalling Error!\n", 0);
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg, "PktFsctrlCreateEntry: Exit -> %08lx\n", ULongToPtr( status ));
|
||
return status;
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlCreateSubordinateEntry, public
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: We only process this FSCTRL from the file system process,
|
||
// never from the driver.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PktFsctrlCreateSubordinateEntry(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
DFS_PKT_CREATE_SUBORDINATE_ENTRY_ARG arg;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlCreateSubordinateEntry, TRUE, FALSE);
|
||
|
||
//
|
||
// Unmarshal the argument...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
status = DfsRtlGet(&marshalBuffer, &MiPktCreateSubordinateEntryArg, &arg);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PDFS_PKT pkt = _GetPkt();
|
||
PDFS_PKT_ENTRY superior;
|
||
PDFS_PKT_ENTRY subEntry;
|
||
|
||
PktAcquireExclusive(pkt, TRUE);
|
||
try {
|
||
superior = PktLookupEntryById(pkt, &arg.EntryId);
|
||
if (superior != NULL) {
|
||
status = PktCreateSubordinateEntry(
|
||
pkt,
|
||
superior,
|
||
arg.SubEntryType,
|
||
&arg.SubEntryId,
|
||
&arg.SubEntryInfo,
|
||
arg.CreateDisposition,
|
||
&subEntry);
|
||
} else {
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlCreateSubordinateEntry: No Superior!\n", 0);
|
||
status = DFS_STATUS_NO_SUCH_ENTRY;
|
||
}
|
||
} finally {
|
||
PktRelease(pkt);
|
||
}
|
||
|
||
//
|
||
// Need to deallocate the entry Id...
|
||
//
|
||
PktEntryIdDestroy(&arg.EntryId, FALSE);
|
||
PktEntryIdDestroy(&arg.SubEntryId, FALSE);
|
||
PktEntryInfoDestroy(&arg.SubEntryInfo, FALSE);
|
||
} else {
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlCreateSubordinateEntry: Unmarshalling Error!\n", 0);
|
||
}
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg,
|
||
"PktFsctrlCreateSubordinateEntry: Exit -> %08lx\n", ULongToPtr( status ));
|
||
return status;
|
||
}
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlDestroyEntry, public
|
||
//
|
||
// Synopsis:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: We only process this FSCTRL from the file system process,
|
||
// never from the driver.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PktFsctrlDestroyEntry(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
DFS_PKT_ENTRY_ID Id;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
PDFS_PKT_ENTRY victim;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlDestroyEntry, TRUE, FALSE);
|
||
|
||
//
|
||
// Unmarshal the argument...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
status = DfsRtlGet(&marshalBuffer, &MiPktEntryId, &Id);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PDFS_PKT pkt = _GetPkt();
|
||
|
||
PktAcquireExclusive(pkt, TRUE);
|
||
|
||
victim = PktLookupEntryById(pkt, &Id);
|
||
|
||
if (victim != NULL) {
|
||
//
|
||
// If there is a local service we first need to delete this
|
||
// explicitly before we call PktEntryDestroy.
|
||
//
|
||
if (victim->LocalService) {
|
||
|
||
UNICODE_STRING a, b;
|
||
|
||
RtlInitUnicodeString(&b, L"\\");
|
||
BuildLocalVolPath(&a, victim->LocalService, &b);
|
||
PktEntryRemoveLocalService(pkt, victim, &a);
|
||
|
||
}
|
||
PktEntryDestroy( victim, pkt, (BOOLEAN) TRUE);
|
||
} else {
|
||
DebugTrace(0, Dbg, "PktFsctrlDestroyEntry: No Superior!\n", 0);
|
||
status = DFS_STATUS_NO_SUCH_ENTRY;
|
||
}
|
||
|
||
PktRelease(pkt);
|
||
|
||
//
|
||
// Need to deallocate the entry Id...
|
||
//
|
||
|
||
PktEntryIdDestroy(&Id, FALSE);
|
||
} else
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlDestroyEntry: Unmarshalling Error!\n", 0);
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg,
|
||
"PktFsctrlDestroyEntry: Exit -> %08lx\n", ULongToPtr(status) );
|
||
return status;
|
||
}
|
||
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktpPruneAllExtraVolumes
|
||
//
|
||
// Synopsis: Given a set of relation infos, this helper routine will
|
||
// prune all local volume entries in the pkt that are not present
|
||
// in the input set of relation infos.
|
||
//
|
||
// Arguments: [pPkt] -- The pkt to operate upon. Should be acquired
|
||
// exclusive
|
||
// [cInfo] -- The number of config infos in the set
|
||
// [pInfo] -- The set of config infos
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- No extra volumes were found.
|
||
//
|
||
// [STATUS_REGISTRY_RECOVERED] -- Extra volumes were found and
|
||
// were successfully recovered.
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- Extra volumes were found but could
|
||
// not be deleted. A detailed error was logged.
|
||
//
|
||
// Notes: Assumes Pkt has been acquired exclusive
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktpPruneAllExtraVolumes(
|
||
PDFS_PKT pPkt,
|
||
ULONG cInfo,
|
||
PDFS_LOCAL_VOLUME_CONFIG pInfo)
|
||
{
|
||
//
|
||
// 447479: init return status.
|
||
NTSTATUS status, returnStatus = STATUS_UNSUCCESSFUL;
|
||
PDFS_PKT_ENTRY pPktEntry;
|
||
ULONG i, j;
|
||
BOOLEAN fExtra;
|
||
|
||
//
|
||
// This is a pretty brute-force algorithm - for each Pkt entry that is
|
||
// local, we scan the entire set of infos looking for a match. If a
|
||
// match is not found, we delete the local volume.
|
||
//
|
||
|
||
pPktEntry = CONTAINING_RECORD(pPkt->EntryList.Flink, DFS_PKT_ENTRY, Link);
|
||
|
||
for (i = 0, status = STATUS_SUCCESS;
|
||
i < pPkt->EntryCount && NT_SUCCESS(status);
|
||
i++) {
|
||
|
||
for (j = 0, fExtra = TRUE; j < cInfo && fExtra; j++) {
|
||
|
||
if (GuidEqual( &pInfo[j].RelationInfo.EntryId.Uid, &pPktEntry->Id.Uid)) {
|
||
|
||
fExtra = FALSE;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
if (fExtra && !(pPktEntry->Type & PKT_ENTRY_TYPE_MACHINE)) {
|
||
|
||
DebugTrace(0, Dbg,
|
||
"Pruning Extra volume [%wZ]\n", &pPktEntry->Id.Prefix);
|
||
|
||
status = DfsInternalDeleteLocalVolume( &pPktEntry->Id );
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
UNICODE_STRING puStr[2];
|
||
|
||
puStr[0] = pPktEntry->Id.Prefix;
|
||
|
||
puStr[1].MaximumLength = sizeof(L"LocalMachine");
|
||
puStr[1].Length = puStr[1].MaximumLength - sizeof(WCHAR);
|
||
puStr[1].Buffer = L"LocalMachine";
|
||
|
||
LogWriteMessage(
|
||
EXTRA_VOLUME_NOT_DELETED,
|
||
status,
|
||
2,
|
||
puStr);
|
||
|
||
returnStatus = STATUS_UNSUCCESSFUL;
|
||
|
||
} else {
|
||
|
||
returnStatus = STATUS_REGISTRY_RECOVERED;
|
||
}
|
||
|
||
}
|
||
|
||
pPktEntry =
|
||
CONTAINING_RECORD(pPktEntry->Link.Flink, DFS_PKT_ENTRY, Link);
|
||
|
||
}
|
||
|
||
return( returnStatus );
|
||
|
||
}
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktpResetOneLocalVolume
|
||
//
|
||
// Synopsis: Given a relation info (as sent over by the DC), this routine
|
||
// will locate a pkt entry for the given volume. If such an
|
||
// entry is found, this routine will try to sync up the relation
|
||
// info to that of the passed in info.
|
||
//
|
||
// Arguments: [pPkt] -- The pkt to operate upon. Should be acquired
|
||
// exclusive
|
||
// [pRemoteInfo] -- The DFS_LOCAL_VOLUME_CONFIG_INFO sent by the
|
||
// DC.
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- Either there is no such local volume in
|
||
// the Pkt, or the local volume's relation info is in
|
||
// exact sync.
|
||
//
|
||
// [STATUS_REGISTRY_RECOVERED] -- Found a local volume, and
|
||
// steps were taken to bring it in sync with the
|
||
// passed in relation info.
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- Found a local volume, and in
|
||
// taking steps to bring it in sync, an error was
|
||
// encountered. A detailed message has been logged.
|
||
//
|
||
// History: April 6, 1995 Milans created
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktpResetOneLocalVolume(
|
||
PDFS_PKT pPkt,
|
||
PDFS_LOCAL_VOLUME_CONFIG pRemoteInfo)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PDFS_PKT_ENTRY pPktEntry;
|
||
UNICODE_STRING LocalMachStr;
|
||
|
||
LocalMachStr.MaximumLength = sizeof(L"LocalMachine");
|
||
LocalMachStr.Length = LocalMachStr.MaximumLength - sizeof(WCHAR);
|
||
LocalMachStr.Buffer = L"LocalMachine";
|
||
|
||
pPktEntry = PktLookupEntryByUid( pPkt, &pRemoteInfo->RelationInfo.EntryId.Uid );
|
||
|
||
if (pPktEntry != NULL) {
|
||
|
||
DFS_PKT_RELATION_INFO LocalInfo;
|
||
|
||
//
|
||
// We found a matching pkt entry in the local pkt. Lets see
|
||
// if it is in sync with the input relation info.
|
||
//
|
||
|
||
status = PktRelationInfoConstruct(
|
||
&LocalInfo,
|
||
pPkt,
|
||
&pPktEntry->Id);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
status = PktRelationInfoValidate(
|
||
&LocalInfo,
|
||
&pRemoteInfo->RelationInfo,
|
||
LocalMachStr);
|
||
|
||
if (status == DFS_STATUS_RESYNC_INFO) {
|
||
|
||
status = PktpFixupRelationInfo(
|
||
&LocalInfo,
|
||
&pRemoteInfo->RelationInfo);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
status = STATUS_REGISTRY_RECOVERED;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
status = DFS_STATUS_NOSUCH_LOCAL_VOLUME;
|
||
|
||
}
|
||
|
||
return( status );
|
||
|
||
}
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktpCreateIfMissing
|
||
//
|
||
// Synopsis: Given a relation info for a local volume, this routine
|
||
// will create a local volume matching the relation info if
|
||
// a volume with the given guid does not already exist.
|
||
//
|
||
// Arguments: [pPkt] -- The pkt to operate upon. Should be acquired
|
||
// exclusive
|
||
// [pInfo] -- The local volume config info required to recreate
|
||
// the local volume.
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- The local volume already exists. Doesn't
|
||
// guarantee that the relation info matches, just that
|
||
// there is already a pkt entry for the given guid.
|
||
//
|
||
// [STATUS_REGISTRY_RECOVERED] -- The local volume was missing
|
||
// and was successfully recreated.
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- The local volume is missing, and
|
||
// an error was encountered while recreating it; a
|
||
// more detailed error message has been logged.
|
||
//
|
||
// History: April 6, 1995 Milans created
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktpCreateIfMissing(
|
||
PDFS_PKT pPkt,
|
||
PDFS_LOCAL_VOLUME_CONFIG pInfo)
|
||
{
|
||
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PDFS_PKT_ENTRY pPktEntry;
|
||
|
||
pPktEntry = PktLookupEntryByUid( pPkt, &pInfo->RelationInfo.EntryId.Uid );
|
||
|
||
if (pPktEntry == NULL) {
|
||
|
||
//
|
||
// There is no local volume matching pInfo. We try to recreate it.
|
||
//
|
||
|
||
pInfo->EntryType = PKT_ENTRY_TYPE_CAIRO;
|
||
pInfo->ServiceType |= DFS_SERVICE_TYPE_MASTER;
|
||
|
||
status = DfsInternalCreateLocalPartition(
|
||
&pInfo->StgId,
|
||
TRUE,
|
||
pInfo);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
UNICODE_STRING puStr[2];
|
||
|
||
puStr[0] = pInfo->RelationInfo.EntryId.Prefix;
|
||
|
||
puStr[1].MaximumLength = sizeof(L"LocalMachine");
|
||
puStr[1].Length = puStr[1].MaximumLength - sizeof(WCHAR);
|
||
puStr[1].Buffer = L"LocalMachine";
|
||
|
||
LogWriteMessage(
|
||
MISSING_VOLUME_NOT_CREATED,
|
||
status,
|
||
2,
|
||
puStr);
|
||
|
||
status = STATUS_UNSUCCESSFUL;
|
||
|
||
} else {
|
||
|
||
status = STATUS_REGISTRY_RECOVERED;
|
||
}
|
||
|
||
}
|
||
|
||
return( status );
|
||
|
||
}
|
||
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktpResetLocalVolumes
|
||
//
|
||
// Synopsis: Given an array of relation infos for local volumes, this
|
||
// routine will set the pkt to match the entire set of infos.
|
||
// Local volumes in the pkt but not in the set of infos will
|
||
// be deleted. Local volumes in the pkt and in the set will
|
||
// be modified if needed to match the info in the set. Lastly,
|
||
// infos in the set but not in the pkt will result in a new
|
||
// local volume being created.
|
||
//
|
||
// Arguments: [cInfo] -- The number of config infos passed in.
|
||
// [pInfo] -- The array of DFS_LOCAL_VOLUME_CONFIG structs.
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- The pkt is already in sync with the
|
||
// passed in set of relation infos.
|
||
//
|
||
// [STATUS_REGISTRY_RECOVERED] -- The pkt was successfully
|
||
// brought in sync with the passed in infos; some
|
||
// needed changes were made and messages were logged.
|
||
// THIS IS AN NT INFORMATION STATUS CODE!
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- Unable to bring the pkt in sync;
|
||
// The problem was logged.
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktpResetLocalVolumes(
|
||
ULONG cInfo,
|
||
PDFS_LOCAL_VOLUME_CONFIG pInfo)
|
||
{
|
||
|
||
PDFS_PKT pPkt;
|
||
NTSTATUS status, returnStatus;
|
||
ULONG i;
|
||
|
||
pPkt = _GetPkt();
|
||
|
||
PktAcquireExclusive( pPkt, TRUE );
|
||
|
||
//
|
||
// First, we need to see if we have any extra volumes, and if so, we
|
||
// need to prune them
|
||
//
|
||
|
||
status = PktpPruneAllExtraVolumes( pPkt, cInfo, pInfo );
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
returnStatus = status;
|
||
|
||
//
|
||
// Next, we need to sync up all the local volumes which are
|
||
// out of sync
|
||
//
|
||
|
||
for (i = 0; i < cInfo && NT_SUCCESS(status); i++) {
|
||
|
||
status = PktpResetOneLocalVolume( pPkt, &pInfo[i] );
|
||
|
||
if (status == STATUS_REGISTRY_RECOVERED) {
|
||
|
||
returnStatus = status;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Lastly, we need to create any missing volumes
|
||
//
|
||
|
||
for (i = 0; i < cInfo && NT_SUCCESS(status); i++) {
|
||
|
||
status = PktpCreateIfMissing( pPkt, &pInfo[i] );
|
||
|
||
if (status == STATUS_REGISTRY_RECOVERED) {
|
||
|
||
returnStatus = status;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
PktRelease( pPkt );
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
returnStatus = STATUS_UNSUCCESSFUL;
|
||
|
||
}
|
||
|
||
return( returnStatus );
|
||
|
||
}
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlSetServerInfo
|
||
//
|
||
// Synopsis: During the course of Dfs admin operations, the DC might
|
||
// discover that a particular server's knowledge does not agree
|
||
// with its own. If that is the case, the DC will try to force
|
||
// the server to sync up to its knowledge.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- The pkt is already in sync with the
|
||
// passed in set of relation infos.
|
||
//
|
||
// [STATUS_REGISTRY_RECOVERED] -- The pkt was successfully
|
||
// brought in sync with the passed in infos; some
|
||
// needed changes were made and messages were logged.
|
||
// THIS IS AN NT INFORMATION STATUS CODE!
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- Unable to bring the pkt in sync;
|
||
// The problem was logged.
|
||
//
|
||
// [STATUS_INSUFFICIENT_RESOURCES] -- Unable to unmarshal
|
||
// arguments or otherwise out of memory
|
||
//
|
||
// [STATUS_INVALID_DOMAIN_ROLE] -- Can't set server info because
|
||
// this machine is a DC.
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktFsctrlSetServerInfo(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
ULONG i, cInfo;
|
||
PDFS_LOCAL_VOLUME_CONFIG pInfos = NULL;
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlSetServerInfo, TRUE, FALSE);
|
||
|
||
//
|
||
// First, check to see if this machine is a DC. If so, we should not
|
||
// muck with our Pkt!
|
||
//
|
||
|
||
if (DfsData.MachineState == DFS_ROOT_SERVER) {
|
||
|
||
DebugTrace(0, Dbg, "Ignoring SetServerInfo call on DC!\n", 0);
|
||
|
||
status = STATUS_INVALID_DOMAIN_ROLE;
|
||
|
||
} else {
|
||
|
||
MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
|
||
|
||
status = DfsRtlGetUlong( &marshalBuffer, &cInfo );
|
||
|
||
}
|
||
|
||
if (NT_SUCCESS(status) && cInfo > 0) {
|
||
|
||
//
|
||
// We want to get all the config infos first, and then fix up each
|
||
// instead of unmarshalling and fixing them one by one. This way,
|
||
// we won't get messeded up if we hit an unmarshalling error after
|
||
// having fixed up some of our local volumes.
|
||
//
|
||
|
||
ULONG cbSize;
|
||
|
||
cbSize = sizeof(DFS_LOCAL_VOLUME_CONFIG) * cInfo;
|
||
|
||
if ((cbSize / cInfo) == sizeof(DFS_LOCAL_VOLUME_CONFIG)) {
|
||
|
||
pInfos = ExAllocatePoolWithTag(PagedPool,cbSize, ' sfD');
|
||
|
||
if (pInfos != NULL) {
|
||
|
||
DebugTrace(0, Dbg, "Unmarshalling %d Config Infos\n", ULongToPtr( cInfo ));
|
||
|
||
for (i = 0; i < cInfo && NT_SUCCESS(status); i++) {
|
||
|
||
status = DfsRtlGet(
|
||
&marshalBuffer,
|
||
&MiLocalVolumeConfig,
|
||
&pInfos[i]);
|
||
|
||
}
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Unmarshalling error - cleanup
|
||
//
|
||
|
||
DebugTrace(0, Dbg, "Error %08lx unmarshalling ", ULongToPtr( status ));
|
||
DebugTrace(0, Dbg, "the %d th relation info", ULongToPtr( i ));
|
||
|
||
for ( ; i > 0; i--) {
|
||
|
||
LocalVolumeConfigInfoDestroy( &pInfos[i-1], FALSE );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
DebugTrace(0, Dbg, "Unable to allocate %d bytes\n", ULongToPtr( cbSize ));
|
||
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
DebugTrace(0, Dbg, "Interger overflow in %s\n", __FILE__);
|
||
|
||
status = STATUS_INVALID_PARAMETER;
|
||
|
||
}
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
DebugTrace(0, Dbg, "Successfully unmarshalled %d Infos\n", ULongToPtr( cInfo ));
|
||
|
||
status = PktpResetLocalVolumes( cInfo, pInfos );
|
||
|
||
for (i = 0; i < cInfo; i++) {
|
||
|
||
LocalVolumeConfigInfoDestroy( &pInfos[i], FALSE );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
DebugTrace(0, Dbg, "Error %08lx getting count\n", ULongToPtr( status ));
|
||
|
||
}
|
||
|
||
if (pInfos != NULL) {
|
||
|
||
ExFreePool( pInfos );
|
||
|
||
}
|
||
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1,Dbg, "PktFsctrlSetServerInfo: Exit -> %08lx\n", ULongToPtr( status ));
|
||
|
||
return(status);
|
||
|
||
}
|
||
|
||
|
||
//+------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlVerifyLocalVolumeKnowledge
|
||
//
|
||
// Synopsis: This method runs on a Dfs Server and validates the local
|
||
// volume knowledge with the one passed in.
|
||
//
|
||
// Arguments: [InputBuffer] -- Marshalled DFS_PKT_RELATION_INFO to compare
|
||
// with.
|
||
//
|
||
// [InputBufferLength] -- the length in bytes of InputBuffer
|
||
//
|
||
// Returns: [STATUS_SUCCESS] -- Verified that local volume knowledge was
|
||
// already in sync with passed in argument.
|
||
//
|
||
// [STATUS_REGISTRY_RECOVERED] -- Synced up local volume
|
||
// knowledge with passed in argument
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- Unable to fully sync up - a message
|
||
// was logged to the local event log.
|
||
//
|
||
// [STATUS_DATA_ERROR] -- Passed in argument could not be
|
||
// unmarshalled.
|
||
//
|
||
// [DFS_STATUS_NOSUCH_LOCAL_VOLUME] -- Local volume not found.
|
||
//
|
||
// [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory.
|
||
//
|
||
//-------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktFsctrlVerifyLocalVolumeKnowledge(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
DFS_LOCAL_VOLUME_CONFIG remoteInfo;
|
||
PDFS_PKT pkt = _GetPkt();
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlVerifyLocalVolumeKnowledge, TRUE, FALSE);
|
||
|
||
//
|
||
// unmarshal the arguments...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
|
||
RtlZeroMemory(&remoteInfo, sizeof(remoteInfo));
|
||
|
||
status = DfsRtlGet(
|
||
&marshalBuffer,
|
||
&MiPktRelationInfo,
|
||
&remoteInfo.RelationInfo);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PktAcquireExclusive(pkt, TRUE);
|
||
|
||
status = PktpResetOneLocalVolume(pkt, &remoteInfo);
|
||
|
||
PktRelease(pkt);
|
||
|
||
PktRelationInfoDestroy(&remoteInfo.RelationInfo, FALSE);
|
||
|
||
} else
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlVerifyLocalVolumeKnowledge: Unmarshalling Error\n",0);
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg, "DfsFsctrlVerifyLocalVolumeKnowledge: Exit -> %08lx\n",
|
||
ULongToPtr( status ));
|
||
return status;
|
||
}
|
||
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlPruneLocalVolume, public
|
||
//
|
||
// Synopsis: Prunes information about an extra local volume.
|
||
//
|
||
// Arguments: [InputBuffer] -- Marshalled EntryId of the local volume.
|
||
//
|
||
// [InputBufferLength] -- length of InputBuffer
|
||
//
|
||
// Returns: [STATUS_REGISTRY_RECOVERED] -- Volume pruned successfully.
|
||
//
|
||
// [STATUS_UNSUCCESSFUL] -- Unable to delete volume - proper
|
||
// event has been logged to eventlog
|
||
//
|
||
// [STATUS_DATA_ERROR] -- Unable to unmarshal input arguments
|
||
//
|
||
// [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
PktFsctrlPruneLocalVolume(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
DFS_PKT_ENTRY_ID EntryId;
|
||
PDFS_PKT pkt = _GetPkt();
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlPruneLocalVolume, TRUE, FALSE);
|
||
|
||
//
|
||
// unmarshal the arguments...
|
||
//
|
||
|
||
MarshalBufferInitialize(&marshalBuffer, InputBufferLength, InputBuffer);
|
||
|
||
status = DfsRtlGet(
|
||
&marshalBuffer,
|
||
&MiPktEntryId,
|
||
&EntryId);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
status = DfsInternalDeleteLocalVolume(&EntryId);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
UNICODE_STRING puStr[2];
|
||
|
||
puStr[0] = EntryId.Prefix;
|
||
|
||
puStr[1].MaximumLength = sizeof(L"LocalMachine");
|
||
puStr[1].Length = puStr[1].MaximumLength - sizeof(WCHAR);
|
||
puStr[1].Buffer = L"LocalMachine";
|
||
|
||
LogWriteMessage(
|
||
EXTRA_VOLUME_NOT_DELETED,
|
||
status,
|
||
2,
|
||
puStr);
|
||
|
||
status = STATUS_UNSUCCESSFUL;
|
||
|
||
} else {
|
||
|
||
status = STATUS_REGISTRY_RECOVERED;
|
||
|
||
}
|
||
|
||
PktEntryIdDestroy(&EntryId, FALSE);
|
||
|
||
} else
|
||
DebugTrace(0, Dbg,
|
||
"PktFsctrlPruneLocalVolume: Unmarshalling Error\n",0);
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1, Dbg, "DfsFsctrlPruneLocalVolume: Exit -> %08lx\n",
|
||
ULongToPtr( status ) );
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
#if DBG
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlFlushCache, public
|
||
//
|
||
// Synopsis: This function will flush all entries which have all the
|
||
// bits specified in the TYPE vairable set in their own Type field.
|
||
// However, this function will refuse to delete and Permanent
|
||
// entries of the PKT.
|
||
//
|
||
// Arguments: Type - Specifies which entries to delete.
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes: We only process this FSCTRL from the file system process,
|
||
// never from the driver.
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
PktFsctrlFlushCache(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength
|
||
)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
ULONG Type;
|
||
PDFS_PKT Pkt;
|
||
PDFS_PKT_ENTRY curEntry, nextEntry;
|
||
|
||
|
||
STD_FSCTRL_PROLOGUE(PktFsctrlFlushCache, TRUE, FALSE);
|
||
|
||
//
|
||
// Unmarshalling is very simple here. We only expect a ULONG.
|
||
//
|
||
|
||
Type = (*((ULONG *)InputBuffer));
|
||
|
||
Pkt = _GetPkt();
|
||
PktAcquireExclusive(Pkt, TRUE);
|
||
curEntry = PktFirstEntry(Pkt);
|
||
|
||
while (curEntry!=NULL) {
|
||
nextEntry = PktNextEntry(Pkt, curEntry);
|
||
|
||
if (((curEntry->Type & Type) == Type) &&
|
||
!(curEntry->Type & PKT_ENTRY_TYPE_LOCAL) &&
|
||
!(curEntry->Type & PKT_ENTRY_TYPE_LOCAL_XPOINT)) {
|
||
|
||
//
|
||
// Entry has all the Type bits specified in variable
|
||
// "Type" set and hence we can destroy this entry.
|
||
//
|
||
|
||
PktEntryDestroy(curEntry, Pkt, (BOOLEAN) TRUE);
|
||
|
||
}
|
||
curEntry = nextEntry;
|
||
}
|
||
PktRelease(Pkt);
|
||
|
||
DfsCompleteRequest( Irp, status );
|
||
|
||
DebugTrace(-1,Dbg, "PktFsctrlFlushCache: Exit -> %08lx\n", ULongToPtr( status ));
|
||
|
||
return(status);
|
||
}
|
||
|
||
|
||
//+----------------------------------------------------------------------------
|
||
//
|
||
// Function: PktFsctrlShufflePktEntry
|
||
//
|
||
// Synopsis: Shuffles a pkt entry. Useful for testing.
|
||
//
|
||
// Arguments: [Irp]
|
||
// [InputBuffer] -- Marshalled Pkt entry to shuffle.
|
||
// [InputBufferLength] -- size of InputBuffer.
|
||
//
|
||
// Returns:
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
VOID
|
||
PktShuffleServiceList(
|
||
PDFS_PKT_ENTRY_INFO pInfo);
|
||
|
||
NTSTATUS
|
||
PktFsctrlShufflePktEntry(
|
||
IN PIRP Irp,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputBufferLength)
|
||
{
|
||
NTSTATUS Status;
|
||
MARSHAL_BUFFER marshalBuffer;
|
||
DFS_PKT_ENTRY_ID PktEntryId;
|
||
PDFS_PKT_ENTRY pPktEntry;
|
||
UNICODE_STRING ustrRemaining;
|
||
|
||
MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
|
||
|
||
Status = DfsRtlGet( &marshalBuffer, &MiPktEntryId, &PktEntryId );
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
pPktEntry = PktLookupEntryByPrefix(
|
||
&DfsData.Pkt,
|
||
&PktEntryId.Prefix,
|
||
&ustrRemaining);
|
||
|
||
if (pPktEntry == NULL || ustrRemaining.Length != 0) {
|
||
|
||
DebugTrace(0, Dbg, "PktFsctrlShufflePktEntry : [%wZ] is not an entry\n", &PktEntryId.Prefix);
|
||
|
||
Status = STATUS_NOT_FOUND;
|
||
|
||
} else {
|
||
|
||
PktShuffleServiceList( &pPktEntry->Info );
|
||
|
||
}
|
||
|
||
PktEntryIdDestroy(&PktEntryId, FALSE);
|
||
|
||
} else {
|
||
|
||
DebugTrace(0, Dbg, "PktFsctrlShufflePktEntry : DfsRtlGet returned %08lx\n", ULongToPtr( Status ) );
|
||
|
||
}
|
||
|
||
DebugTrace(0, Dbg, "PktFsctrlShufflePktEntry - returning %08lx\n", ULongToPtr( Status ));
|
||
|
||
DfsCompleteRequest( Irp, Status );
|
||
|
||
return( Status );
|
||
|
||
}
|
||
|
||
#endif // DBG
|
||
|