reactos/drivers/filesystems/npfs/writesup.c

176 lines
5.3 KiB
C

/*
* PROJECT: ReactOS Named Pipe FileSystem
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/filesystems/npfs/writesup.c
* PURPOSE: Pipes Writing Support
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include "npfs.h"
// File ID number for NPFS bugchecking support
#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_WRITESUP)
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
IN ULONG Mode,
IN PVOID OutBuffer,
IN ULONG OutBufferSize,
IN ULONG PipeType,
OUT PULONG BytesNotWritten,
IN PNP_CCB Ccb,
IN ULONG NamedPipeEnd,
IN PETHREAD Thread,
IN PLIST_ENTRY List)
{
BOOLEAN HaveContext = FALSE, MoreProcessing, AllocatedBuffer;
PNP_DATA_QUEUE_ENTRY DataEntry;
ULONG DataSize, BufferSize;
PIRP WriteIrp;
PIO_STACK_LOCATION IoStack;
PVOID Buffer;
NTSTATUS Status;
PSECURITY_CLIENT_CONTEXT ClientContext;
PAGED_CODE();
*BytesNotWritten = OutBufferSize;
MoreProcessing = TRUE;
if ((PipeType != FILE_PIPE_MESSAGE_MODE) || (OutBufferSize))
{
MoreProcessing = FALSE;
}
for (DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(WriteQueue, List),
NP_DATA_QUEUE_ENTRY,
QueueEntry);
((WriteQueue->QueueState == ReadEntries) &&
((*BytesNotWritten > 0) || (MoreProcessing)));
DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(WriteQueue, List),
NP_DATA_QUEUE_ENTRY,
QueueEntry))
{
DataSize = DataEntry->DataSize;
IoStack = IoGetCurrentIrpStackLocation(DataEntry->Irp);
if (IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
IoStack->Parameters.FileSystemControl.FsControlCode == FSCTL_PIPE_INTERNAL_READ_OVFLOW &&
(DataSize < OutBufferSize || MoreProcessing))
{
WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
if (WriteIrp)
{
WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
}
continue;
}
if (DataEntry->DataEntryType == Unbuffered)
{
DataEntry->Irp->Overlay.AllocationSize.QuadPart = 0;
}
BufferSize = *BytesNotWritten;
if (BufferSize >= DataSize) BufferSize = DataSize;
if (DataEntry->DataEntryType != Unbuffered && BufferSize)
{
Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, NPFS_DATA_ENTRY_TAG);
if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
AllocatedBuffer = TRUE;
}
else
{
Buffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
AllocatedBuffer = FALSE;
}
_SEH2_TRY
{
RtlCopyMemory(Buffer,
(PVOID)((ULONG_PTR)OutBuffer + OutBufferSize - *BytesNotWritten),
BufferSize);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
if (AllocatedBuffer) ExFreePool(Buffer);
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
if (!HaveContext)
{
HaveContext = TRUE;
Status = NpGetClientSecurityContext(NamedPipeEnd, Ccb, Thread, &ClientContext);
if (!NT_SUCCESS(Status))
{
if (AllocatedBuffer) ExFreePool(Buffer);
return Status;
}
if (ClientContext)
{
NpFreeClientSecurityContext(Ccb->ClientContext);
Ccb->ClientContext = ClientContext;
}
}
WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
if (WriteIrp)
{
*BytesNotWritten -= BufferSize;
WriteIrp->IoStatus.Information = BufferSize;
if (AllocatedBuffer)
{
WriteIrp->AssociatedIrp.SystemBuffer = Buffer;
WriteIrp->Flags |= IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
}
if (!*BytesNotWritten)
{
MoreProcessing = FALSE;
WriteIrp->IoStatus.Status = STATUS_SUCCESS;
InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
continue;
}
if (Mode == FILE_PIPE_MESSAGE_MODE)
{
WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
}
else
{
WriteIrp->IoStatus.Status = STATUS_SUCCESS;
}
InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
}
else if (AllocatedBuffer)
{
ExFreePool(Buffer);
}
}
if (*BytesNotWritten > 0 || MoreProcessing)
{
ASSERT(WriteQueue->QueueState != ReadEntries);
Status = STATUS_MORE_PROCESSING_REQUIRED;
}
else
{
Status = STATUS_SUCCESS;
}
return Status;
}
/* EOF */