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