windows-nt/Source/XPSP1/NT/base/fs/mailslot/write.c

274 lines
5.8 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}