Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

385 lines
8.2 KiB

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