summaryrefslogtreecommitdiffstats
path: root/private/ntos/mup/dfsinit.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/mup/dfsinit.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/mup/dfsinit.c')
-rw-r--r--private/ntos/mup/dfsinit.c522
1 files changed, 522 insertions, 0 deletions
diff --git a/private/ntos/mup/dfsinit.c b/private/ntos/mup/dfsinit.c
new file mode 100644
index 000000000..0a8819ddc
--- /dev/null
+++ b/private/ntos/mup/dfsinit.c
@@ -0,0 +1,522 @@
+//+----------------------------------------------------------------------------
+//
+// 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 "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
+DfsIoTimerRoutine(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ );
+
+VOID
+DfsDeleteDevices(
+ PDFS_TIMER_CONTEXT DfsTimerContext);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, DfsDriverEntry)
+#pragma alloc_text(PAGE, DfsDeleteDevices)
+
+//
+// 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;
+ HANDLE hTemp;
+ HANDLE DirHandle;
+ IO_STATUS_BLOCK iosb;
+
+ //
+ // 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 );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &UnicodeString,
+ OBJ_CASE_INSENSITIVE,
+ 0,
+ NULL);
+
+ Status = ZwCreateFile(
+ &hTemp,
+ SYNCHRONIZE,
+ &ObjectAttributes,
+ &iosb,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ NULL,
+ 0);
+
+ if (NT_SUCCESS(Status)) {
+ ZwClose( hTemp );
+ DfsDbgTrace(0, Dbg, "Dfs driver already loaded!\n", 0);
+ return( STATUS_UNSUCCESSFUL );
+ }
+
+ //
+ // Create the filesystem device object.
+ //
+
+ Status = IoCreateDevice( DriverObject,
+ 0,
+ &UnicodeString,
+ FILE_DEVICE_DFS_FILE_SYSTEM,
+ FILE_REMOTE_DEVICE,
+ 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,
+ OBJ_PERMANENT,
+ NULL,
+ NULL );
+
+ Status = ZwCreateDirectoryObject(
+ &DirHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes);
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ZwMakeTemporaryObject(DirHandle);
+
+ 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->FastIoDispatch = &FastIoDispatch;
+
+ //
+ // 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 );
+
+ InitializeListHead( &DfsData.Credentials );
+ InitializeListHead( &DfsData.DeletedCredentials );
+
+ DfsData.DriverObject = DriverObject;
+ DfsData.FileSysDeviceObject = DeviceObject;
+
+ DfsData.LogRootDevName = UnicodeString;
+
+ ExInitializeResource( &DfsData.Resource );
+ KeInitializeEvent( &DfsData.PktWritePending, NotificationEvent, TRUE );
+ KeInitializeSemaphore( &DfsData.PktReferralRequests, 1, 1 );
+
+ DfsData.MachineState = DFS_CLIENT;
+
+ //
+ // Allocate Provider structures.
+ //
+
+ DfsData.pProvider = ExAllocatePool( PagedPool,
+ sizeof ( PROVIDER_DEF ) * MAX_PROVIDERS);
+
+ 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;
+ ULONG ZoneSegmentSize;
+
+ 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);
+
+ //
+ // Now initialize the zone structures for allocating IRP context
+ // records. The size of the zone will depend upon the memory
+ // available in the system.
+ //
+
+ KeInitializeSpinLock( &DfsData.IrpContextSpinLock );
+
+ ZoneSegmentSize = (SystemSizeMultiplier *
+ QuadAlign(sizeof(IRP_CONTEXT))) +
+ sizeof(ZONE_SEGMENT_HEADER);
+
+ (VOID) ExInitializeZone( &DfsData.IrpContextZone,
+ QuadAlign(sizeof(IRP_CONTEXT)),
+ FsRtlAllocatePool( NonPagedPool,
+ ZoneSegmentSize ),
+ ZoneSegmentSize );
+
+ }
+
+ //
+ // Set up global pointer to the system process.
+ //
+
+ DfsData.OurProcess = PsGetCurrentProcess();
+
+ //
+ // Register the file system with the I/O system
+ //
+
+ IoRegisterFileSystem( DeviceObject );
+
+ //
+ // 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);
+
+ }
+
+ //
+ // Initialize the logical roots device objects. These are what form the
+ // link between the outside world and the Dfs driver.
+ //
+
+ Status = DfsInitializeLogicalRoot( DD_DFS_DEVICE_NAME, NULL, NULL, 0);
+
+ if (!NT_SUCCESS(Status)) {
+ DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "Failed creation of root logical root %08lx\n", Status);
+ return(Status);
+ }
+
+ //
+ // Let us start off the Timer Routine.
+ //
+
+ RtlZeroMemory(&DfsTimerContext, sizeof(DFS_TIMER_CONTEXT));
+ DfsTimerContext.InUse = FALSE;
+ DfsTimerContext.TickCount = 0;
+ IoInitializeTimer(DeviceObject, DfsIoTimerRoutine, &DfsTimerContext);
+ DfsDbgTrace(0, Dbg, "Initialized the Timer routine\n", 0);
+
+ //
+ // Let us start the timer now.
+ //
+
+ IoStartTimer(DeviceObject);
+
+ return STATUS_SUCCESS;
+}
+
+//+----------------------------------------------------------------------------
+//
+// 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);
+
+ ExAcquireResourceExclusive(&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", Vcb->OpenFileCount);
+
+ DfsDbgTrace(0, Dbg,
+ "DirectAccessOpens = %d\n", Vcb->DirectAccessOpenCount);
+
+ DfsDbgTrace(0, Dbg,
+ "DeviceObject Reference count = %d\n",
+ DeletedObject->DeviceObject.ReferenceCount);
+
+ }
+
+ }
+
+ ExReleaseResource(&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);
+
+}
+