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