Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

414 lines
10 KiB

/*++
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;
}