415 lines
9.6 KiB
C
415 lines
9.6 KiB
C
/*++
|
||
|
||
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;
|
||
}
|