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;
|
|||
|
}
|