193 lines
4.8 KiB
C
193 lines
4.8 KiB
C
/*++
|
||
|
||
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
|
||
|
||
NTSTATUS
|
||
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.
|
||
|
||
|
||
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:
|
||
|
||
STATUS_MORE_PROCESSING_REQUIRED if not all the data was written,
|
||
other status codes as appropriate.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
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.
|
||
//
|
||
|
||
status = STATUS_MORE_PROCESSING_REQUIRED;
|
||
|
||
for (listEntry = MsGetNextDataQueueEntry( WriteQueue );
|
||
|
||
(MsIsDataQueueReaders(WriteQueue) &&
|
||
status == STATUS_MORE_PROCESSING_REQUIRED);
|
||
|
||
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);
|
||
|
||
|
||
//
|
||
// 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. This may take an exception
|
||
// because its a raw user mode buffer
|
||
//
|
||
|
||
status = readStatus = STATUS_SUCCESS;
|
||
|
||
try {
|
||
|
||
RtlCopyMemory (readBuffer,
|
||
WriteBuffer,
|
||
WriteLength);
|
||
|
||
} except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
return GetExceptionCode ();
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// This read buffer was overflowed.
|
||
//
|
||
|
||
WriteLength = 0;
|
||
readStatus = STATUS_BUFFER_TOO_SMALL;
|
||
|
||
}
|
||
|
||
//
|
||
// We are about to complete a read IRP, so dequeue it.
|
||
//
|
||
|
||
readIrp = MsRemoveDataQueueEntry( WriteQueue, dataEntry );
|
||
if ( readIrp == NULL) {
|
||
//
|
||
// Cancel routine was already running for this IRP. Ignore it as it will be completed by
|
||
// cancel code. Force the loop for the next read irp if there is one.
|
||
//
|
||
status = STATUS_MORE_PROCESSING_REQUIRED;
|
||
continue;
|
||
}
|
||
//
|
||
// 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 );
|
||
}
|
||
|
||
readIrp->IoStatus.Information = WriteLength;
|
||
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 ( status == STATUS_MORE_PROCESSING_REQUIRED ) {
|
||
|
||
ASSERT( !MsIsDataQueueReaders( WriteQueue ));
|
||
}
|
||
|
||
DebugTrace(-1, Dbg, "MsWriteDataQueue -> %08lx\n", status);
|
||
return status;
|
||
|
||
}
|
||
|
||
|