|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
fscontrl.c
Abstract:
This module implements the file system control routines for the MUP called by the dispatch driver.
Author:
Manny Weiser (mannyw) 26-Dec-1991
Revision History:
--*/
#include "mup.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_FSCONTROL)
//
// local procedure prototypes
//
NTSTATUS RegisterUncProvider ( IN PMUP_DEVICE_OBJECT MupDeviceObject, IN PIRP Irp );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, MupFsControl )
#pragma alloc_text( PAGE, RegisterUncProvider )
#endif
NTSTATUS MupFsControl ( IN PMUP_DEVICE_OBJECT MupDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the the File System Control IRP.
Arguments:
MupDeviceObject - Supplies the device object to use.
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The status for the Irp
--*/
{ NTSTATUS status; PIO_STACK_LOCATION irpSp; PFILE_OBJECT FileObject;
PAGED_CODE(); irpSp = IoGetCurrentIrpStackLocation( Irp ); FileObject = irpSp->FileObject;
DebugTrace(+1, Dbg, "MupFsControl\n", 0); MUP_TRACE_HIGH(TRACE_IRP, MupFsControl_Entry, LOGPTR(MupDeviceObject) LOGPTR(Irp) LOGPTR(FileObject));
//
// Reference our input parameters to make things easier
//
DebugTrace(+1, Dbg, "MupFileSystemControl\n", 0); DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp); DebugTrace( 0, Dbg, "OutputBufferLength = %08lx\n", irpSp->Parameters.FileSystemControl.OutputBufferLength); DebugTrace( 0, Dbg, "InputBufferLength = %08lx\n", irpSp->Parameters.FileSystemControl.InputBufferLength); DebugTrace( 0, Dbg, "FsControlCode = %08lx\n", irpSp->Parameters.FileSystemControl.FsControlCode);
try { //
// Decide how to handle this IRP. Call the appropriate worker function.
//
switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
case FSCTL_MUP_REGISTER_UNC_PROVIDER:
if( Irp->RequestorMode != KernelMode ) { status = STATUS_ACCESS_DENIED; MupCompleteRequest(Irp, STATUS_ACCESS_DENIED); return STATUS_ACCESS_DENIED; }
status = RegisterUncProvider( MupDeviceObject, Irp ); break;
default:
if (MupEnableDfs) { status = DfsFsdFileSystemControl( (PDEVICE_OBJECT) MupDeviceObject, Irp); } else { status = STATUS_INVALID_PARAMETER; MupCompleteRequest(Irp, STATUS_INVALID_PARAMETER); }
}
} except ( EXCEPTION_EXECUTE_HANDLER ) { NOTHING; }
//
// Return to the caller.
//
MUP_TRACE_HIGH(TRACE_IRP, MupFsControl_Exit, LOGSTATUS(status) LOGPTR(MupDeviceObject) LOGPTR(FileObject) LOGPTR(Irp)); DebugTrace(-1, Dbg, "MupFsControl -> %08lx\n", status); return status; }
NTSTATUS RegisterUncProvider ( IN PMUP_DEVICE_OBJECT MupDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This function handles registration of a UNC provider. The provider is added to the list of available providers.
Arguments:
MupDeviceObject - A pointer to the file system device object.
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{ NTSTATUS status; PVCB vcb; PVOID fsContext2; PIO_STACK_LOCATION irpSp;
PREDIRECTOR_REGISTRATION paramBuffer; ULONG paramLength; BLOCK_TYPE blockType;
PUNC_PROVIDER uncProvider = NULL; PUNC_PROVIDER provider; PLIST_ENTRY listEntry; PVOID dataBuffer;
OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; OBJECT_HANDLE_INFORMATION handleInformation; BOOLEAN InsertInProviderList = FALSE;
MupDeviceObject;
PAGED_CODE(); irpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "RegisterUncProvider\n", 0);
//
// Get MUP ordering information, if we haven't already.
//
MupAcquireGlobalLock();
if ( !MupOrderInitialized ) { MupOrderInitialized = TRUE; MupReleaseGlobalLock(); MupGetProviderInformation(); } else { MupReleaseGlobalLock(); }
//
// Make local copies of the input parameters to make things easier.
//
paramLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; paramBuffer = Irp->AssociatedIrp.SystemBuffer;
//
// Decode the file object. If it is the file system VCB, it will be
// referenced.
//
blockType = MupDecodeFileObject( irpSp->FileObject, (PVOID *)&vcb, &fsContext2 );
if ( blockType != BlockTypeVcb ) {
DebugTrace(0, Dbg, "File is disconnected from us\n", 0);
MupCompleteRequest( Irp, STATUS_INVALID_HANDLE ); status = STATUS_INVALID_HANDLE;
DebugTrace(-1, Dbg, "RegisterUncProvider -> %08lx\n", status ); return status; }
try {
UNICODE_STRING deviceName;
deviceName.Length = (USHORT)paramBuffer->DeviceNameLength; deviceName.MaximumLength = (USHORT)paramBuffer->DeviceNameLength; deviceName.Buffer = (PWCH)((PCHAR)paramBuffer + paramBuffer->DeviceNameOffset);
//
// Do the work
//
uncProvider = MupCheckForUnregisteredProvider( &deviceName );
if ( uncProvider == NULL) {
InsertInProviderList = TRUE; uncProvider = MupAllocateUncProvider( paramBuffer->DeviceNameLength);
if (uncProvider != NULL) {
//
// Copy the data from the IRP.
//
dataBuffer = uncProvider + 1; uncProvider->DeviceName = deviceName; uncProvider->DeviceName.Buffer = dataBuffer; uncProvider->Priority = 0x7FFFFFFF; RtlMoveMemory( uncProvider->DeviceName.Buffer, (PCHAR)paramBuffer + paramBuffer->DeviceNameOffset, paramBuffer->DeviceNameLength);
} else {
status = STATUS_INVALID_USER_BUFFER; try_return( NOTHING );
}
}
dataBuffer = (PCHAR)dataBuffer + uncProvider->DeviceName.MaximumLength;
uncProvider->MailslotsSupported = paramBuffer->MailslotsSupported;
//
// Reference the unc provider
//
MupReferenceBlock( uncProvider );
//
// Get a handle to the provider.
//
InitializeObjectAttributes( &objectAttributes, &uncProvider->DeviceName, OBJ_CASE_INSENSITIVE, // Attributes
0, // Root Directory
NULL // Security
);
status = NtOpenFile( &uncProvider->Handle, FILE_TRAVERSE, &objectAttributes, &ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
if ( NT_SUCCESS( status ) ) { status = ioStatusBlock.Status; }
if ( NT_SUCCESS( status ) ) { //
// Use the file object, to keep a pointer to the uncProvider
//
irpSp->FileObject->FsContext2 = uncProvider; //
// 426184, need to check return code for errors.
//
status = ObReferenceObjectByHandle( uncProvider->Handle, 0, NULL, KernelMode, (PVOID *)&uncProvider->FileObject, &handleInformation );
if (!NT_SUCCESS( status)) { NtClose(uncProvider->Handle); } }
if ( !NT_SUCCESS( status ) ) { MupDereferenceUncProvider(uncProvider); } else { uncProvider->DeviceObject = IoGetRelatedDeviceObject( uncProvider->FileObject );
MupAcquireGlobalLock();
MupProviderCount++;
if(InsertInProviderList) { //
// We need to make sure we put the providers in the list in order of priority.
//
listEntry = MupProviderList.Flink; while ( listEntry != &MupProviderList ) {
provider = CONTAINING_RECORD( listEntry, UNC_PROVIDER, ListEntry );
if( uncProvider->Priority < provider->Priority ) { break; } listEntry = listEntry->Flink; }
InsertTailList(listEntry, &uncProvider->ListEntry); } uncProvider->Registered = TRUE; MupReleaseGlobalLock();
//
// !!! What do we do with the handle? It is useless.
//
//
// Finish up the fs control IRP.
//
status = STATUS_SUCCESS; }
try_exit: NOTHING; } finally {
if ( AbnormalTermination() ) { status = STATUS_INVALID_USER_BUFFER; }
//
// Release the reference to the VCB.
//
MupDereferenceVcb( vcb );
DebugTrace(-1, Dbg, "MupRegisterUncProvider -> %08lx\n", status); }
MupCompleteRequest( Irp, status );
return status; }
|