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