summaryrefslogtreecommitdiffstats
path: root/private/ntos/mailslot/writesup.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/mailslot/writesup.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/mailslot/writesup.c')
-rw-r--r--private/ntos/mailslot/writesup.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/private/ntos/mailslot/writesup.c b/private/ntos/mailslot/writesup.c
new file mode 100644
index 000000000..7b94adcd3
--- /dev/null
+++ b/private/ntos/mailslot/writesup.c
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ writesup.c
+
+Abstract:
+
+ This module implements the write support routine. This is a common
+ write function that is called by write and mailslot write.
+
+Author:
+
+ Manny Weiser (mannyw) 16-Jan-1991
+
+Revision History:
+
+--*/
+
+#include "mailslot.h"
+
+//
+// The debug trace level
+//
+
+#define Dbg (DEBUG_TRACE_WRITESUP)
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text( PAGE, MsWriteDataQueue )
+#endif
+
+BOOLEAN
+MsWriteDataQueue (
+ IN PDATA_QUEUE WriteQueue,
+ IN PUCHAR WriteBuffer,
+ IN ULONG WriteLength
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes data from the write buffer into read entries in
+ the write queue. It will also dequeue entries in the queue as necessary.
+
+ *** This function must be called from within a try statement.
+
+Arguments:
+
+ WriteQueue - Provides the write queue to process.
+
+ WriteBuffer - Provides the buffer from which to read the data.
+
+ WriteLength - Provides the length, in bytes, of WriteBuffer.
+
+Return Value:
+
+ BOOLEAN - TRUE if the operation wrote everything and FALSE otherwise.
+
+--*/
+
+{
+ BOOLEAN result;
+
+ PDATA_ENTRY dataEntry;
+ PLIST_ENTRY listEntry;
+ PFCB fcb;
+
+ PUCHAR readBuffer;
+ ULONG readLength;
+ PIRP readIrp;
+ NTSTATUS readStatus = STATUS_UNSUCCESSFUL;
+
+ PWORK_CONTEXT workContext;
+ PKTIMER timer;
+
+ PAGED_CODE();
+ DebugTrace(+1, Dbg, "MsWriteDataQueue\n", 0);
+ DebugTrace( 0, Dbg, "WriteQueue = %08lx\n", (ULONG)WriteQueue);
+ DebugTrace( 0, Dbg, "WriteBuffer = %08lx\n", (ULONG)WriteBuffer);
+ DebugTrace( 0, Dbg, "WriteLength = %08lx\n", WriteLength);
+
+ //
+ // Now while the write queue has some read entries in it and
+ // we have not successfully completed a read then we'll do the
+ // following main loop.
+ //
+
+ for (listEntry = MsGetNextDataQueueEntry( WriteQueue );
+
+ MsIsDataQueueReaders(WriteQueue) && !NT_SUCCESS(readStatus);
+
+ listEntry = MsGetNextDataQueueEntry( WriteQueue )) {
+
+ dataEntry = CONTAINING_RECORD( listEntry, DATA_ENTRY, ListEntry );
+ readBuffer = dataEntry->DataPointer;
+ readLength = dataEntry->DataSize;
+
+ DebugTrace(0, Dbg, "Top of write loop...\n", 0);
+ DebugTrace(0, Dbg, "ReadBuffer = %08lx\n", (ULONG)readBuffer);
+ DebugTrace(0, Dbg, "ReadLength = %08lx\n", readLength);
+
+ //
+ // We are about to complete a read IRP, so dequeue it.
+ //
+
+ readIrp = MsRemoveDataQueueEntry( WriteQueue, dataEntry );
+ ASSERT( readIrp != NULL );
+
+ //
+ // If the buffer for this read operation is large enough
+ // copy the data.
+ //
+
+ if ( readLength >= WriteLength ) {
+
+ //
+ // Copy the data from the write buffer to the read buffer.
+ //
+
+ RtlMoveMemory( readBuffer,
+ WriteBuffer,
+ WriteLength);
+
+ readIrp->IoStatus.Information = WriteLength;
+ readStatus = STATUS_SUCCESS;
+
+ } else {
+
+ //
+ // This read buffer was overflowed.
+ //
+
+ readIrp->IoStatus.Information = 0;
+ readStatus = STATUS_BUFFER_TOO_SMALL;
+
+ }
+
+ //
+ // Complete the read IRP.
+ //
+
+ workContext = dataEntry->TimeoutWorkContext;
+ if (workContext != NULL) {
+
+ DebugTrace( 0, Dbg, "Cancelling a timer\n", 0);
+
+ //
+ // There was a timer on this read operation. Attempt
+ // to cancel the operation. If the cancel operation
+ // is successful, then we must cleanup after the operation.
+ // If it was unsuccessful the timer DPC will run, and
+ // will eventually cleanup.
+ //
+
+ timer = &workContext->Timer;
+
+ if (KeCancelTimer( timer ) ) {
+
+ //
+ // Release the reference to the FCB.
+ //
+
+ MsDereferenceFcb( workContext->Fcb );
+
+ //
+ // Free the memory from the work context, the timer,
+ // and the DPC.
+ //
+
+ ExFreePool( workContext );
+
+ }
+
+ }
+
+ //
+ // Update the FCB last access time and complete the read request.
+ //
+
+ fcb = CONTAINING_RECORD( WriteQueue, FCB, DataQueue );
+ if ( NT_SUCCESS( readStatus ) ) {
+ KeQuerySystemTime( &fcb->Specific.Fcb.LastAccessTime );
+ }
+
+ MsCompleteRequest( readIrp, readStatus );
+
+ }
+
+ DebugTrace(0, Dbg, "Finished loop...\n", 0);
+
+ //
+ // At this point we've finished off all of the read entries in the
+ // queue and we might not have written the write data. If that
+ // is the case then we'll set our result to FALSE otherwise we're
+ // done so we'll return TRUE.
+ //
+
+ if ( !NT_SUCCESS( readStatus ) ) {
+
+ ASSERT( !MsIsDataQueueReaders( WriteQueue ));
+ result = FALSE;
+
+ } else {
+
+ result = TRUE;
+ }
+
+ DebugTrace(-1, Dbg, "MsWriteDataQueue -> %08lx\n", result);
+ return result;
+
+}
+