274 lines
5.8 KiB
C
274 lines
5.8 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
write.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the file write routines for MSFS called by the
|
||
dispatch driver.
|
||
|
||
Author:
|
||
|
||
Manny Weiser (mannyw) 16-Jan-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "mailslot.h"
|
||
|
||
//
|
||
// The debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_WRITE)
|
||
|
||
//
|
||
// local procedure prototypes.
|
||
//
|
||
|
||
NTSTATUS
|
||
MsCommonWrite (
|
||
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text( PAGE, MsCommonWrite )
|
||
#pragma alloc_text( PAGE, MsFsdWrite )
|
||
#endif
|
||
|
||
NTSTATUS
|
||
MsFsdWrite (
|
||
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the FSD part of the NtWriteFile API call.
|
||
|
||
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, "MsFsdWrite\n", 0);
|
||
|
||
FsRtlEnterFileSystem();
|
||
|
||
status = MsCommonWrite( MsfsDeviceObject, Irp );
|
||
|
||
FsRtlExitFileSystem();
|
||
|
||
//
|
||
// Return to the caller.
|
||
//
|
||
|
||
DebugTrace(-1, Dbg, "MsFsdWrite -> %08lx\n", status );
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
MsCommonWrite (
|
||
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the common routine for writing to a mailslot file.
|
||
|
||
Arguments:
|
||
|
||
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;
|
||
PCCB ccb;
|
||
PFCB fcb;
|
||
PVOID fsContext2;
|
||
|
||
PIRP writeIrp;
|
||
PUCHAR writeBuffer;
|
||
ULONG writeLength;
|
||
PDATA_QUEUE writeQueue;
|
||
|
||
PAGED_CODE();
|
||
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
||
|
||
DebugTrace(+1, Dbg, "MsCommonWrite\n", 0);
|
||
DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject);
|
||
DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp);
|
||
DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)irpSp->FileObject);
|
||
|
||
//
|
||
// Get the CCB and make sure it isn't closing.
|
||
//
|
||
|
||
if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject,
|
||
(PVOID *)&ccb,
|
||
&fsContext2 )) == NTC_UNDEFINED) {
|
||
|
||
DebugTrace(0, Dbg, "The mailslot is disconnected\n", 0);
|
||
|
||
MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED );
|
||
status = STATUS_FILE_FORCED_CLOSED;
|
||
|
||
DebugTrace(-1, Dbg, "MsCommonWrite -> %08lx\n", status );
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Allow write operations only to the client side of the mailslot.
|
||
//
|
||
|
||
if (nodeTypeCode != MSFS_NTC_CCB) {
|
||
|
||
DebugTrace(0, Dbg, "FileObject is not the correct type", 0);
|
||
MsDereferenceNode( &ccb->Header );
|
||
|
||
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
|
||
status = STATUS_INVALID_PARAMETER;
|
||
|
||
DebugTrace(-1, Dbg, "MsCommonWrite -> %08lx\n", status );
|
||
return status;
|
||
|
||
}
|
||
|
||
//
|
||
// Get a pointer to the FCB for this CCB
|
||
//
|
||
|
||
fcb = ccb->Fcb;
|
||
|
||
//
|
||
// Make local copies of the input parameters to make things easier, and
|
||
// initialize the main variables that describe the write command.
|
||
//
|
||
|
||
writeIrp = Irp;
|
||
writeBuffer = Irp->UserBuffer;
|
||
writeLength = irpSp->Parameters.Write.Length;
|
||
|
||
writeIrp->IoStatus.Information = 0;
|
||
writeQueue = &fcb->DataQueue;
|
||
|
||
//
|
||
// Make sure the write does not exceed the stated maximum. If max is
|
||
// zero, this means don't enforce.
|
||
//
|
||
|
||
if ( (writeQueue->MaximumMessageSize != 0) &&
|
||
(writeLength > writeQueue->MaximumMessageSize) ) {
|
||
|
||
DebugTrace(0, Dbg, "Write exceeds maximum message size", 0);
|
||
MsDereferenceCcb( ccb );
|
||
|
||
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
|
||
status = STATUS_INVALID_PARAMETER;
|
||
|
||
DebugTrace(-1, Dbg, "MsCommonWrite -> %08lx\n", status );
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Now acquire exclusive access to the FCB.
|
||
//
|
||
|
||
MsAcquireExclusiveFcb( fcb );
|
||
|
||
|
||
//
|
||
// Ensure that this CCB still belongs to an active open mailslot.
|
||
//
|
||
|
||
status = MsVerifyCcb( ccb );
|
||
if (NT_SUCCESS (status)) {
|
||
|
||
//
|
||
// Now we'll call our common write data queue routine to
|
||
// transfer data out of our write buffer into the data queue.
|
||
// If the result of the call is FALSE then there were no queued
|
||
// read operations and we must queue this write.
|
||
//
|
||
|
||
status = MsWriteDataQueue( writeQueue,
|
||
writeBuffer,
|
||
writeLength );
|
||
|
||
|
||
if (status == STATUS_MORE_PROCESSING_REQUIRED) {
|
||
|
||
ASSERT( !MsIsDataQueueReaders( writeQueue ));
|
||
|
||
DebugTrace(0, Dbg, "Add write to data queue\n", 0);
|
||
|
||
//
|
||
// Add this write request to the write queue
|
||
//
|
||
|
||
status = MsAddDataQueueEntry( writeQueue,
|
||
WriteEntries,
|
||
writeLength,
|
||
Irp,
|
||
NULL );
|
||
|
||
} else {
|
||
|
||
DebugTrace(0, Dbg, "Complete the Write Irp\n", 0);
|
||
|
||
|
||
//
|
||
// Update the FCB last modification time.
|
||
//
|
||
if (NT_SUCCESS (status)) {
|
||
writeIrp->IoStatus.Information = writeLength;
|
||
KeQuerySystemTime( &fcb->Specific.Fcb.LastModificationTime );
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
MsReleaseFcb( fcb );
|
||
|
||
MsDereferenceCcb( ccb );
|
||
|
||
MsCompleteRequest( writeIrp, status );
|
||
|
||
DebugTrace(-1, Dbg, "MsCommonWrite -> %08lx\n", status);
|
||
|
||
return status;
|
||
}
|
||
|
||
|