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