767 lines
22 KiB
C
767 lines
22 KiB
C
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Copyright (C) 1992, Microsoft Corporation.
|
|||
|
//
|
|||
|
// File: dfsinit.c
|
|||
|
//
|
|||
|
// Contents: This module implements the DRIVER_INITIALIZATION routine
|
|||
|
// for the Dfs file system driver.
|
|||
|
//
|
|||
|
// Functions: DfsDriverEntry - Main entry point for driver initialization
|
|||
|
// DfsIoTimerRoutine - Main entry point for scavenger thread
|
|||
|
// DfsDeleteDevices - Routine to scavenge deleted net uses
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "align.h"
|
|||
|
|
|||
|
#include "dfsprocs.h"
|
|||
|
#include "fastio.h"
|
|||
|
#include "fcbsup.h"
|
|||
|
|
|||
|
//
|
|||
|
// The following are includes for init modules, which will get discarded when
|
|||
|
// the driver has finished loading.
|
|||
|
//
|
|||
|
|
|||
|
#include "provider.h"
|
|||
|
|
|||
|
//
|
|||
|
// The debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_INIT)
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MupGetDebugFlags(VOID);
|
|||
|
|
|||
|
VOID
|
|||
|
DfsGetEventLogValue(VOID);
|
|||
|
|
|||
|
VOID
|
|||
|
DfsIoTimerRoutine(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PVOID Context
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
DfsDeleteDevices(
|
|||
|
PDFS_TIMER_CONTEXT DfsTimerContext);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfsShutdown (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
DfsCheckLUIDDeviceMapsEnabled(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Globals
|
|||
|
//
|
|||
|
HANDLE DfsDirHandle = NULL;
|
|||
|
BOOL DfsLUIDDeviceMapsEnabled = FALSE;
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(INIT, DfsDriverEntry)
|
|||
|
#pragma alloc_text(PAGE, DfsDeleteDevices)
|
|||
|
#pragma alloc_text(PAGE, DfsUnload)
|
|||
|
#pragma alloc_text(PAGE, DfsShutdown)
|
|||
|
|
|||
|
//
|
|||
|
// The following routine should not be pageable, because it gets called by
|
|||
|
// the NT timer routine frequently. We don't want to thrash.
|
|||
|
//
|
|||
|
// DfsIoTimerRoutine
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
#endif // ALLOC_PRAGMA
|
|||
|
|
|||
|
//
|
|||
|
// This macro takes a pointer (or ulong) and returns its rounded up quadword
|
|||
|
// value
|
|||
|
//
|
|||
|
|
|||
|
#define QuadAlign(Ptr) ( \
|
|||
|
((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//+-------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsDriverEntry, main entry point
|
|||
|
//
|
|||
|
// Synopsis: This is the initialization routine for the Dfs file system
|
|||
|
// device driver. This routine creates the device object for
|
|||
|
// the FileSystem device and performs all other driver
|
|||
|
// initialization.
|
|||
|
//
|
|||
|
// Arguments: [DriverObject] -- Pointer to driver object created by the
|
|||
|
// system.
|
|||
|
// [RegistryPath] -- Path to section in registry describing
|
|||
|
// this driver's configuration.
|
|||
|
//
|
|||
|
// Returns: [NTSTATUS] - The function value is the final status from
|
|||
|
// the initialization operation.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfsDriverEntry(
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
) {
|
|||
|
NTSTATUS Status;
|
|||
|
UNICODE_STRING UnicodeString;
|
|||
|
PDEVICE_OBJECT DeviceObject;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
PWSTR p;
|
|||
|
int i;
|
|||
|
IO_STATUS_BLOCK iosb;
|
|||
|
LUID LogonID = SYSTEM_LUID;
|
|||
|
|
|||
|
#if DBG
|
|||
|
//
|
|||
|
// If debug, get debug flags
|
|||
|
//
|
|||
|
MupGetDebugFlags();
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Get the event logging level
|
|||
|
//
|
|||
|
DfsGetEventLogValue();
|
|||
|
|
|||
|
//
|
|||
|
// See if someone else has already created a File System Device object
|
|||
|
// with the name we intend to use. If so, we bail.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString( &UnicodeString, DFS_DRIVER_NAME );
|
|||
|
|
|||
|
//
|
|||
|
// Create the filesystem device object.
|
|||
|
//
|
|||
|
|
|||
|
Status = IoCreateDevice( DriverObject,
|
|||
|
0,
|
|||
|
&UnicodeString,
|
|||
|
FILE_DEVICE_DFS_FILE_SYSTEM,
|
|||
|
FILE_REMOTE_DEVICE | FILE_DEVICE_SECURE_OPEN,
|
|||
|
FALSE,
|
|||
|
&DeviceObject );
|
|||
|
if ( !NT_SUCCESS( Status ) ) {
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create a permanent object directory in which the logical root
|
|||
|
// device objects will reside. Make the directory temporary, so
|
|||
|
// we can just close the handle to make it go away.
|
|||
|
//
|
|||
|
|
|||
|
UnicodeString.Buffer = p = LogicalRootDevPath;
|
|||
|
UnicodeString.Length = 0;
|
|||
|
UnicodeString.MaximumLength = MAX_LOGICAL_ROOT_LEN;
|
|||
|
while (*p++ != UNICODE_NULL)
|
|||
|
UnicodeString.Length += sizeof (WCHAR);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&UnicodeString,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL );
|
|||
|
|
|||
|
Status = ZwCreateDirectoryObject(
|
|||
|
&DfsDirHandle,
|
|||
|
DIRECTORY_ALL_ACCESS,
|
|||
|
&ObjectAttributes);
|
|||
|
|
|||
|
if ( !NT_SUCCESS( Status ) ) {
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
p[-1] = UNICODE_PATH_SEP;
|
|||
|
UnicodeString.Length += sizeof (WCHAR);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the driver object with this driver's entry points.
|
|||
|
// Most are simply passed through to some other device driver.
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|||
|
DriverObject->MajorFunction[i] = DfsVolumePassThrough;
|
|||
|
}
|
|||
|
|
|||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)DfsFsdCreate;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)DfsFsdClose;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)DfsFsdCleanup;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdQueryInformation;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdSetInformation;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)DfsFsdFileSystemControl;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdQueryVolumeInformation;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdSetVolumeInformation;
|
|||
|
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DfsShutdown;
|
|||
|
|
|||
|
DriverObject->FastIoDispatch = &FastIoDispatch;
|
|||
|
|
|||
|
Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject, &FsFilterCallbacks );
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
goto ErrorOut;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the global data structures
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
RtlZeroMemory(&DfsData, sizeof (DFS_DATA));
|
|||
|
|
|||
|
DfsData.NodeTypeCode = DSFS_NTC_DATA_HEADER;
|
|||
|
DfsData.NodeByteSize = sizeof( DFS_DATA );
|
|||
|
|
|||
|
InitializeListHead( &DfsData.VcbQueue );
|
|||
|
InitializeListHead( &DfsData.DeletedVcbQueue );
|
|||
|
|
|||
|
// Initialize the devless root queue: this holds all the device less
|
|||
|
// net uses.
|
|||
|
InitializeListHead( &DfsData.DrtQueue );
|
|||
|
|
|||
|
InitializeListHead( &DfsData.Credentials );
|
|||
|
InitializeListHead( &DfsData.DeletedCredentials );
|
|||
|
|
|||
|
InitializeListHead( &DfsData.OfflineRoots );
|
|||
|
|
|||
|
DfsData.DriverObject = DriverObject;
|
|||
|
DfsData.FileSysDeviceObject = DeviceObject;
|
|||
|
|
|||
|
DfsData.LogRootDevName = UnicodeString;
|
|||
|
|
|||
|
ExInitializeResourceLite( &DfsData.Resource );
|
|||
|
KeInitializeEvent( &DfsData.PktWritePending, NotificationEvent, TRUE );
|
|||
|
KeInitializeSemaphore( &DfsData.PktReferralRequests, 1, 1 );
|
|||
|
|
|||
|
DfsData.MachineState = DFS_CLIENT;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate Provider structures.
|
|||
|
//
|
|||
|
|
|||
|
DfsData.pProvider = ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
sizeof ( PROVIDER_DEF ) * MAX_PROVIDERS,
|
|||
|
' puM');
|
|||
|
|
|||
|
if (DfsData.pProvider == NULL) {
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto ErrorOut;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < MAX_PROVIDERS; i++) {
|
|||
|
DfsData.pProvider[i].NodeTypeCode = DSFS_NTC_PROVIDER;
|
|||
|
DfsData.pProvider[i].NodeByteSize = sizeof ( PROVIDER_DEF );
|
|||
|
}
|
|||
|
|
|||
|
DfsData.cProvider = 0;
|
|||
|
DfsData.maxProvider = MAX_PROVIDERS;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the system wide PKT
|
|||
|
//
|
|||
|
|
|||
|
PktInitialize(&DfsData.Pkt);
|
|||
|
|
|||
|
{
|
|||
|
ULONG SystemSizeMultiplier;
|
|||
|
|
|||
|
switch (MmQuerySystemSize()) {
|
|||
|
default:
|
|||
|
case MmSmallSystem:
|
|||
|
SystemSizeMultiplier = 4;
|
|||
|
break;
|
|||
|
case MmMediumSystem:
|
|||
|
SystemSizeMultiplier = 8;
|
|||
|
break;
|
|||
|
|
|||
|
case MmLargeSystem:
|
|||
|
SystemSizeMultiplier = 16;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate the DFS_FCB hash table structure. The number of
|
|||
|
// hash buckets will depend upon the memory size of the system.
|
|||
|
//
|
|||
|
|
|||
|
Status = DfsInitFcbs(SystemSizeMultiplier * 2);
|
|||
|
if (!NT_SUCCESS (Status)) {
|
|||
|
PktUninitialize(&DfsData.Pkt);
|
|||
|
ExFreePool (DfsData.pProvider);
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
goto ErrorOut;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create a lookaside for the IRP contexts
|
|||
|
//
|
|||
|
|
|||
|
ExInitializeNPagedLookasideList (&DfsData.IrpContextLookaside,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
sizeof(IRP_CONTEXT),
|
|||
|
'IpuM',
|
|||
|
10 // unused
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set up global pointer to the system process.
|
|||
|
//
|
|||
|
|
|||
|
DfsData.OurProcess = PsGetCurrentProcess();
|
|||
|
|
|||
|
//
|
|||
|
// Set up the global pointers for the EA buffers to be used to differentiate
|
|||
|
// CSC agent opens from non CSC agent opens. This is a read only buffer used
|
|||
|
// to distinguish the CSC agent requests
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
{
|
|||
|
UCHAR EaNameCSCAgentSize = (UCHAR) (ROUND_UP_COUNT(
|
|||
|
strlen(EA_NAME_CSCAGENT) + sizeof(CHAR),
|
|||
|
ALIGN_DWORD
|
|||
|
) - sizeof(CHAR));
|
|||
|
|
|||
|
DfsData.CSCEaBufferLength = ROUND_UP_COUNT(
|
|||
|
FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
|
|||
|
EaNameCSCAgentSize + sizeof(CHAR),
|
|||
|
ALIGN_DWORD
|
|||
|
);
|
|||
|
|
|||
|
DfsData.CSCEaBuffer = ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
DfsData.CSCEaBufferLength,
|
|||
|
' puM');
|
|||
|
|
|||
|
if (DfsData.CSCEaBuffer != NULL) {
|
|||
|
|
|||
|
// clear the buffer, otherwise so we don't get any spurious
|
|||
|
// failure due to IO manager checks
|
|||
|
memset(DfsData.CSCEaBuffer, 0, DfsData.CSCEaBufferLength);
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
(LPSTR)DfsData.CSCEaBuffer->EaName,
|
|||
|
EA_NAME_CSCAGENT,
|
|||
|
EaNameCSCAgentSize);
|
|||
|
|
|||
|
DfsData.CSCEaBuffer->EaNameLength = EaNameCSCAgentSize;
|
|||
|
|
|||
|
DfsData.CSCEaBuffer->EaValueLength = 0;
|
|||
|
|
|||
|
DfsData.CSCEaBuffer->NextEntryOffset = 0;
|
|||
|
} else {
|
|||
|
ExDeleteNPagedLookasideList (&DfsData.IrpContextLookaside);
|
|||
|
DfsUninitFcbs ();
|
|||
|
PktUninitialize(&DfsData.Pkt);
|
|||
|
ExFreePool (DfsData.pProvider);
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "Failed to allocate CSC ea buffer %08lx\n", ULongToPtr(Status) );
|
|||
|
return Status;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Register the file system with the I/O system. We don't need to invert this as its never registered.
|
|||
|
//
|
|||
|
|
|||
|
IoRegisterFileSystem( DeviceObject );
|
|||
|
|
|||
|
Status = IoRegisterShutdownNotification (DeviceObject); // This is automaticaly removed when IoDeleteDevice is called
|
|||
|
if (!NT_SUCCESS (Status)) {
|
|||
|
ExFreePool (DfsData.CSCEaBuffer);
|
|||
|
ExDeleteNPagedLookasideList (&DfsData.IrpContextLookaside);
|
|||
|
DfsUninitFcbs ();
|
|||
|
PktUninitialize(&DfsData.Pkt);
|
|||
|
ExFreePool (DfsData.pProvider);
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
return Status;
|
|||
|
}
|
|||
|
//
|
|||
|
// Initialize the provider definitions from the registry.
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS( ProviderInit() )) {
|
|||
|
|
|||
|
DfsDbgTrace(0,DEBUG_TRACE_ERROR,
|
|||
|
"Could not initialize some or all providers!\n", 0);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check if LUID device maps are enabled
|
|||
|
//
|
|||
|
DfsLUIDDeviceMapsEnabled = DfsCheckLUIDDeviceMapsEnabled();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the logical roots device objects. These are what form the
|
|||
|
// link between the outside world and the Dfs driver.
|
|||
|
//
|
|||
|
|
|||
|
#ifdef TERMSRV
|
|||
|
Status = DfsInitializeLogicalRoot( DD_DFS_DEVICE_NAME, NULL, NULL, 0, INVALID_SESSIONID, &LogonID);
|
|||
|
#else // TERMSRV
|
|||
|
Status = DfsInitializeLogicalRoot( DD_DFS_DEVICE_NAME, NULL, NULL, 0, &LogonID);
|
|||
|
#endif // TERMSRV
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "Failed creation of root logical root %08lx\n", ULongToPtr(Status) );
|
|||
|
|
|||
|
ExDeleteNPagedLookasideList (&DfsData.IrpContextLookaside);
|
|||
|
DfsUninitFcbs ();
|
|||
|
PktUninitialize(&DfsData.Pkt);
|
|||
|
ExFreePool (DfsData.pProvider);
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Let us start off the Timer Routine.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory(&DfsTimerContext, sizeof(DFS_TIMER_CONTEXT));
|
|||
|
DfsTimerContext.InUse = FALSE;
|
|||
|
DfsTimerContext.TickCount = 0;
|
|||
|
|
|||
|
//
|
|||
|
// 375929, io initialize timer, check return status.
|
|||
|
//
|
|||
|
Status = IoInitializeTimer( DeviceObject,
|
|||
|
DfsIoTimerRoutine,
|
|||
|
&DfsTimerContext );
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
#ifdef TERMSRV
|
|||
|
DfsDeleteLogicalRoot (DD_DFS_DEVICE_NAME, FALSE, INVALID_SESSIONID, &LogonID);
|
|||
|
#else
|
|||
|
DfsDeleteLogicalRoot (DD_DFS_DEVICE_NAME, FALSE, &LogonID);
|
|||
|
#endif
|
|||
|
ExDeleteNPagedLookasideList (&DfsData.IrpContextLookaside);
|
|||
|
DfsUninitFcbs ();
|
|||
|
PktUninitialize(&DfsData.Pkt);
|
|||
|
ExFreePool (DfsData.pProvider);
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DeviceObject);
|
|||
|
goto ErrorOut;
|
|||
|
}
|
|||
|
DfsDbgTrace(0, Dbg, "Initialized the Timer routine\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Let us start the timer now.
|
|||
|
//
|
|||
|
|
|||
|
IoStartTimer(DeviceObject);
|
|||
|
|
|||
|
DfsDbgTrace(-1, Dbg, "DfsDriverEntry exit STATUS_SUCCESS\n", 0);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
ErrorOut:
|
|||
|
|
|||
|
DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "DfsDriverEntry exit %08lx\n", ULongToPtr(Status) );
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DfsShutdown (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
{
|
|||
|
//
|
|||
|
// Unregister the file system object so we can unload
|
|||
|
//
|
|||
|
IoUnregisterFileSystem (DeviceObject);
|
|||
|
|
|||
|
DfsCompleteRequest( NULL, Irp, STATUS_SUCCESS );
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsUnload
|
|||
|
//
|
|||
|
// Synopsis: Routine called at unload time to free resources
|
|||
|
//
|
|||
|
// Arguments: [DriverObject] -- Driver object of MUP
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
DfsUnload(
|
|||
|
IN PDRIVER_OBJECT DriverObject
|
|||
|
)
|
|||
|
{
|
|||
|
LUID LogonID = SYSTEM_LUID;
|
|||
|
|
|||
|
IoStopTimer(DfsData.FileSysDeviceObject);
|
|||
|
#ifdef TERMSRV
|
|||
|
DfsDeleteLogicalRoot (DD_DFS_DEVICE_NAME, FALSE, INVALID_SESSIONID, &LogonID);
|
|||
|
#else
|
|||
|
DfsDeleteLogicalRoot (DD_DFS_DEVICE_NAME, FALSE, &LogonID);
|
|||
|
#endif
|
|||
|
ExFreePool (DfsData.CSCEaBuffer);
|
|||
|
ExDeleteNPagedLookasideList (&DfsData.IrpContextLookaside);
|
|||
|
DfsUninitFcbs ();
|
|||
|
PktUninitialize(&DfsData.Pkt);
|
|||
|
ExFreePool (DfsData.pProvider);
|
|||
|
ExDeleteResourceLite( &DfsData.Resource );
|
|||
|
ZwClose (DfsDirHandle);
|
|||
|
IoDeleteDevice (DfsData.FileSysDeviceObject);
|
|||
|
}
|
|||
|
|
|||
|
//+----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsDeleteDevices
|
|||
|
//
|
|||
|
// Synopsis: Routine to scavenge deleted devices (net uses).
|
|||
|
//
|
|||
|
// Arguments: [pDfsTimerContext] -- Timer Context
|
|||
|
//
|
|||
|
// Returns: Nothing - this routine is meant to be queued to a worker
|
|||
|
// thread.
|
|||
|
//
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
DfsDeleteDevices(
|
|||
|
PDFS_TIMER_CONTEXT DfsTimerContext)
|
|||
|
{
|
|||
|
PLIST_ENTRY plink;
|
|||
|
PDFS_VCB Vcb;
|
|||
|
PLOGICAL_ROOT_DEVICE_OBJECT DeletedObject;
|
|||
|
|
|||
|
if (DfsData.DeletedVcbQueue.Flink != &DfsData.DeletedVcbQueue) {
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg, "Examining Deleted Vcbs...\n", 0);
|
|||
|
|
|||
|
ExAcquireResourceExclusiveLite(&DfsData.Resource, TRUE);
|
|||
|
|
|||
|
for (plink = DfsData.DeletedVcbQueue.Flink;
|
|||
|
plink != &DfsData.DeletedVcbQueue;
|
|||
|
NOTHING) {
|
|||
|
|
|||
|
Vcb = CONTAINING_RECORD(
|
|||
|
plink,
|
|||
|
DFS_VCB,
|
|||
|
VcbLinks);
|
|||
|
|
|||
|
plink = plink->Flink;
|
|||
|
|
|||
|
DeletedObject = CONTAINING_RECORD(
|
|||
|
Vcb,
|
|||
|
LOGICAL_ROOT_DEVICE_OBJECT,
|
|||
|
Vcb);
|
|||
|
|
|||
|
if (Vcb->OpenFileCount == 0 &&
|
|||
|
Vcb->DirectAccessOpenCount == 0 &&
|
|||
|
DeletedObject->DeviceObject.ReferenceCount == 0) {
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg, "Deleting Vcb@%08lx\n", Vcb);
|
|||
|
|
|||
|
if (Vcb->LogRootPrefix.Buffer != NULL)
|
|||
|
ExFreePool(Vcb->LogRootPrefix.Buffer);
|
|||
|
|
|||
|
if (Vcb->LogicalRoot.Buffer != NULL)
|
|||
|
ExFreePool(Vcb->LogicalRoot.Buffer);
|
|||
|
|
|||
|
RemoveEntryList(&Vcb->VcbLinks);
|
|||
|
|
|||
|
ObDereferenceObject((PVOID) DeletedObject);
|
|||
|
|
|||
|
IoDeleteDevice( &DeletedObject->DeviceObject );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg, "Not deleting Vcb@%08lx\n", Vcb);
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg,
|
|||
|
"OpenFileCount = %d\n", ULongToPtr(Vcb->OpenFileCount) );
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg,
|
|||
|
"DirectAccessOpens = %d\n", ULongToPtr(Vcb->DirectAccessOpenCount) );
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg,
|
|||
|
"DeviceObject Reference count = %d\n",
|
|||
|
ULongToPtr(DeletedObject->DeviceObject.ReferenceCount) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ExReleaseResourceLite(&DfsData.Resource);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DfsTimerContext->InUse = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsIoTimerRoutine
|
|||
|
//
|
|||
|
// Synopsis: This function gets called by IO Subsystem once every second.
|
|||
|
// This can be used for various purposes in the driver. For now,
|
|||
|
// it periodically posts a request to a system thread to age Pkt
|
|||
|
// Entries.
|
|||
|
//
|
|||
|
// Arguments: [Context] -- This is the context information. It is actually
|
|||
|
// a pointer to a DFS_TIMER_CONTEXT.
|
|||
|
// [DeviceObject] -- Pointer to the Device object for DFS. We dont
|
|||
|
// really use this here.
|
|||
|
//
|
|||
|
// Returns: Nothing
|
|||
|
//
|
|||
|
// Notes: The Context which we get here is assumed to have all the
|
|||
|
// required fields setup properly.
|
|||
|
//
|
|||
|
// History: 04/24/93 SudK Created.
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
VOID
|
|||
|
DfsIoTimerRoutine(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
PDFS_TIMER_CONTEXT pDfsTimerContext = (PDFS_TIMER_CONTEXT) Context;
|
|||
|
|
|||
|
DfsDbgTrace(+1, Dbg, "DfsIoTimerRoutine: Entered\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// If the DfsTimerContext is in USE then we just return blindly. Due to
|
|||
|
// this action we might actually lose some ticks. But then we really are
|
|||
|
// not very particular about this and hence dont care.
|
|||
|
//
|
|||
|
|
|||
|
if (pDfsTimerContext->InUse == TRUE) {
|
|||
|
|
|||
|
DfsDbgTrace(-1, Dbg, "DfsIoTimerRoutine: TimerContext in use\n", 0);
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// First let us increment the count in the DFS_TIMER_CONTEXT. If it has
|
|||
|
// reached a bound value then we have to go ahead and schedule the
|
|||
|
// necessary work items.
|
|||
|
//
|
|||
|
|
|||
|
pDfsTimerContext->TickCount++;
|
|||
|
|
|||
|
if (pDfsTimerContext->TickCount == DFS_MAX_TICKS) {
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg, "Queuing Pkt Entry Scavenger\n", 0);
|
|||
|
|
|||
|
pDfsTimerContext->InUse = TRUE;
|
|||
|
|
|||
|
ExInitializeWorkItem(
|
|||
|
&pDfsTimerContext->WorkQueueItem,
|
|||
|
DfsAgePktEntries,
|
|||
|
pDfsTimerContext);
|
|||
|
|
|||
|
ExQueueWorkItem( &pDfsTimerContext->WorkQueueItem, DelayedWorkQueue);
|
|||
|
|
|||
|
} else if (DfsData.DeletedVcbQueue.Flink != &DfsData.DeletedVcbQueue) {
|
|||
|
|
|||
|
DfsDbgTrace(0, Dbg, "Queueing Deleted Vcb Scavenger\n", 0);
|
|||
|
|
|||
|
pDfsTimerContext->InUse = TRUE;
|
|||
|
|
|||
|
ExInitializeWorkItem(
|
|||
|
&pDfsTimerContext->DeleteQueueItem,
|
|||
|
DfsDeleteDevices,
|
|||
|
pDfsTimerContext);
|
|||
|
|
|||
|
ExQueueWorkItem(&pDfsTimerContext->DeleteQueueItem, DelayedWorkQueue);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DfsDbgTrace(-1, Dbg, "DfsIoTimerRoutine: Exiting\n", 0);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//+-------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: DfsCheckLUIDDeviceMapsEnabled
|
|||
|
//
|
|||
|
// Synopsis: This function calls ZwQueryInformationProcess to determine if
|
|||
|
// LUID device maps are enabled/disabled
|
|||
|
//
|
|||
|
// Arguments: NONE
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// TRUE - LUID device maps are enabled
|
|||
|
//
|
|||
|
// FALSE - LUID device maps are disabled
|
|||
|
//
|
|||
|
//--------------------------------------------------------------------------
|
|||
|
BOOL
|
|||
|
DfsCheckLUIDDeviceMapsEnabled(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG LUIDDeviceMapsEnabled;
|
|||
|
BOOL Result;
|
|||
|
|
|||
|
Status = ZwQueryInformationProcess( NtCurrentProcess(),
|
|||
|
ProcessLUIDDeviceMapsEnabled,
|
|||
|
&LUIDDeviceMapsEnabled,
|
|||
|
sizeof(LUIDDeviceMapsEnabled),
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DfsDbgTrace(
|
|||
|
-1,
|
|||
|
DEBUG_TRACE_ERROR,
|
|||
|
"DfsCheckLUIDDeviceMapsEnabled to failed to check if LUID device maps enabled, status = %08lx\n",
|
|||
|
ULongToPtr(Status));
|
|||
|
Result = FALSE;
|
|||
|
}
|
|||
|
else {
|
|||
|
Result = (LUIDDeviceMapsEnabled != 0);
|
|||
|
}
|
|||
|
|
|||
|
return( Result );
|
|||
|
}
|