|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
fscontrl.c
Abstract:
This module implements the file file system control routines for MSFS called by the dispatch driver.
Author:
Manny Weiser (mannyw) 25-Jan-1991
Revision History:
--*/
#include "mailslot.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_FSCONTROL)
//
// local procedure prototypes
//
NTSTATUS MsCommonFsControl ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp );
NTSTATUS MsPeek ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, MsCommonFsControl )
#pragma alloc_text( PAGE, MsFsdFsControl )
#pragma alloc_text( PAGE, MsPeek )
#endif
NTSTATUS MsFsdFsControl ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of the NtFsControlFile API calls.
Arguments:
MsfsDeviceObject - Supplies the device object to use.
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The Fsd status for the Irp
--*/
{ NTSTATUS status;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsFsdFsControl\n", 0);
//
// Call the common file system control function.
//
status = MsCommonFsControl( MsfsDeviceObject, Irp );
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsFsdFsControl -> %08lx\n", status );
return status; }
NTSTATUS MsCommonFsControl ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This is the common routine for handling a file system control call.
Arguments:
MsfsDeviceObject - A pointer to the mailslot file system device object.
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{ NTSTATUS status; PIO_STACK_LOCATION irpSp;
PAGED_CODE();
//
// Reference our input parameters to make things easier
//
irpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "MsCommonFileSystemControl\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);
//
// Decide how to handle this IRP. Call the appropriate worker function.
//
switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
case FSCTL_MAILSLOT_PEEK:
FsRtlEnterFileSystem();
status = MsPeek( MsfsDeviceObject, Irp );
FsRtlExitFileSystem();
break;
default:
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER ); status = STATUS_INVALID_PARAMETER;
}
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsCommonFsControl -> %08lx\n", status); return status; }
NTSTATUS MsPeek ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This function handles a mailslot peek call.
Arguments:
MsfsDeviceObject - A pointer to the mailslot file system device object.
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{ NTSTATUS status;
PIO_STACK_LOCATION irpSp;
NODE_TYPE_CODE nodeTypeCode; PFCB fcb; PVOID fsContext2;
PFILE_MAILSLOT_PEEK_BUFFER peekParamBuffer; ULONG peekParamLength;
PVOID peekDataBuffer; ULONG peekDataLength;
PDATA_QUEUE dataQueue; ULONG MessageLength;
PAGED_CODE(); irpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "MsPeek\n", 0);
//
// Make local copies of the input parameters to make things easier.
//
peekParamBuffer = irpSp->Parameters.FileSystemControl.Type3InputBuffer; peekParamLength = irpSp->Parameters.FileSystemControl.InputBufferLength;
peekDataBuffer = Irp->UserBuffer; peekDataLength = irpSp->Parameters.FileSystemControl.OutputBufferLength;
//
// Ensure that the supplied buffer is large enough for the peek
// parameters.
//
if (peekParamLength < sizeof( FILE_MAILSLOT_PEEK_BUFFER ) ) {
DebugTrace(0, Dbg, "Output buffer is too small\n", 0);
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER ); status = STATUS_INVALID_PARAMETER;
DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status ); return status; }
//
// If the requestor mode is user mode we need to probe the buffers.
// We do not need to have an exception handler here because our top
// level caller already has one that will complete the Irp with
// the appropriate status if we access violate.
//
if (Irp->RequestorMode != KernelMode) {
try {
ProbeForWrite( peekParamBuffer, peekParamLength, sizeof(UCHAR) ); ProbeForWrite( peekDataBuffer, peekDataLength, sizeof(UCHAR) ); peekParamBuffer->ReadDataAvailable = 0; peekParamBuffer->NumberOfMessages = 0; peekParamBuffer->MessageLength = 0;
} except(EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode (); MsCompleteRequest( Irp, status ); return status; }
}
//
// Decode the fil1e object. If it returns NTC_UNDEFINED, then the
// node is closing. Otherwise we obtain a referenced pointer to
// an FCB.
//
if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject, (PVOID *)&fcb, &fsContext2 )) == NTC_UNDEFINED) {
DebugTrace(0, Dbg, "Mailslot is disconnected from us\n", 0);
MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED ); status = STATUS_FILE_FORCED_CLOSED;
DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status ); return status; }
//
// Allow a peek operation only if this is a server side handle to
// a mailslot file (i.e. the node type is FCB).
//
if (nodeTypeCode != MSFS_NTC_FCB) {
DebugTrace(0, Dbg, "FileObject is not the correct type\n", 0);
MsDereferenceNode( &fcb->Header );
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER ); status = STATUS_INVALID_PARAMETER;
DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status ); return status; }
//
// Acquire exclusive access to the FCB.
//
MsAcquireExclusiveFcb( fcb );
//
// Ensure that this FCB still belongs to an active open mailslot.
//
status = MsVerifyFcb( fcb );
if (NT_SUCCESS (status)) {
//
// Look for write data in the mailslot.
//
dataQueue = &fcb->DataQueue;
if (!MsIsDataQueueWriters( dataQueue )) {
//
// There are no outstanding writes so leave all the zeros in there.
//
} else {
//
// There is write data for the peek. Fill in the peek output
// buffer.
//
Irp->IoStatus = MsReadDataQueue( dataQueue, Peek, peekDataBuffer, peekDataLength, &MessageLength );
status = Irp->IoStatus.Status;
if (NT_SUCCESS (status)) { try { peekParamBuffer->ReadDataAvailable = dataQueue->BytesInQueue; peekParamBuffer->NumberOfMessages = dataQueue->EntriesInQueue; peekParamBuffer->MessageLength = MessageLength;
} except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode (); } }
} }
MsReleaseFcb( fcb );
//
// Release the reference to the FCB.
//
MsDereferenceFcb( fcb ); //
// Finish up the fs control IRP.
//
MsCompleteRequest( Irp, status );
DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status);
return status; }
|