mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
255 lines
7.1 KiB
C
255 lines
7.1 KiB
C
/*
|
|
* PROJECT: ReactOS Named Pipe FileSystem
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
* FILE: drivers/filesystems/npfs/write.c
|
|
* PURPOSE: Pipes Writing
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include "npfs.h"
|
|
|
|
// File ID number for NPFS bugchecking support
|
|
#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_WRITE)
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
LONG NpSlowWriteCalls;
|
|
ULONG NpFastWriteTrue;
|
|
ULONG NpFastWriteFalse;
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
NpCommonWrite(IN PFILE_OBJECT FileObject,
|
|
IN PVOID Buffer,
|
|
IN ULONG DataSize,
|
|
IN PETHREAD Thread,
|
|
IN PIO_STATUS_BLOCK IoStatus,
|
|
IN PIRP Irp,
|
|
IN PLIST_ENTRY List)
|
|
{
|
|
NODE_TYPE_CODE NodeType;
|
|
BOOLEAN WriteOk;
|
|
PNP_CCB Ccb;
|
|
PNP_NONPAGED_CCB NonPagedCcb;
|
|
PNP_DATA_QUEUE WriteQueue;
|
|
NTSTATUS Status;
|
|
PNP_EVENT_BUFFER EventBuffer;
|
|
ULONG BytesWritten, NamedPipeEnd, ReadMode;
|
|
PAGED_CODE();
|
|
|
|
IoStatus->Information = 0;
|
|
NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd);
|
|
|
|
if (!NodeType)
|
|
{
|
|
IoStatus->Status = STATUS_PIPE_DISCONNECTED;
|
|
return TRUE;
|
|
}
|
|
|
|
if (NodeType != NPFS_NTC_CCB)
|
|
{
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return TRUE;
|
|
}
|
|
|
|
NonPagedCcb = Ccb->NonPagedCcb;
|
|
ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
|
|
|
|
if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
|
|
{
|
|
if (Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE)
|
|
{
|
|
IoStatus->Status = STATUS_PIPE_DISCONNECTED;
|
|
}
|
|
else if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE)
|
|
{
|
|
IoStatus->Status = STATUS_PIPE_LISTENING;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE);
|
|
IoStatus->Status = STATUS_PIPE_CLOSING;
|
|
}
|
|
|
|
WriteOk = TRUE;
|
|
goto Quickie;
|
|
}
|
|
|
|
if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND) ||
|
|
(NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND))
|
|
{
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
WriteOk = TRUE;
|
|
goto Quickie;
|
|
}
|
|
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
IoStatus->Information = DataSize;
|
|
|
|
if (NamedPipeEnd == FILE_PIPE_SERVER_END)
|
|
{
|
|
WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
|
|
ReadMode = Ccb->ReadMode[FILE_PIPE_CLIENT_END];
|
|
}
|
|
else
|
|
{
|
|
WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
|
|
ReadMode = Ccb->ReadMode[FILE_PIPE_SERVER_END];
|
|
}
|
|
|
|
EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
|
|
|
|
if ((WriteQueue->QueueState == ReadEntries &&
|
|
WriteQueue->BytesInQueue < DataSize &&
|
|
WriteQueue->Quota < DataSize - WriteQueue->BytesInQueue) ||
|
|
(WriteQueue->QueueState != ReadEntries &&
|
|
WriteQueue->Quota - WriteQueue->QuotaUsed < DataSize))
|
|
{
|
|
if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE &&
|
|
Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION)
|
|
{
|
|
IoStatus->Information = 0;
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
WriteOk = TRUE;
|
|
goto Quickie;
|
|
}
|
|
|
|
if (!Irp)
|
|
{
|
|
WriteOk = FALSE;
|
|
goto Quickie;
|
|
}
|
|
}
|
|
|
|
Status = NpWriteDataQueue(WriteQueue,
|
|
ReadMode,
|
|
Buffer,
|
|
DataSize,
|
|
Ccb->Fcb->NamedPipeType,
|
|
&BytesWritten,
|
|
Ccb,
|
|
NamedPipeEnd,
|
|
Thread,
|
|
List);
|
|
IoStatus->Status = Status;
|
|
|
|
if (Status == STATUS_MORE_PROCESSING_REQUIRED)
|
|
{
|
|
ASSERT(WriteQueue->QueueState != ReadEntries);
|
|
if ((Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION || !Irp) &&
|
|
((WriteQueue->Quota - WriteQueue->QuotaUsed) < BytesWritten))
|
|
{
|
|
IoStatus->Information = DataSize - BytesWritten;
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(WriteQueue->QueueState != ReadEntries);
|
|
|
|
IoStatus->Status = NpAddDataQueueEntry(NamedPipeEnd,
|
|
Ccb,
|
|
WriteQueue,
|
|
WriteEntries,
|
|
Buffered,
|
|
DataSize,
|
|
Irp,
|
|
Buffer,
|
|
DataSize - BytesWritten);
|
|
}
|
|
}
|
|
|
|
if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
|
|
WriteOk = TRUE;
|
|
|
|
Quickie:
|
|
ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
|
|
return WriteOk;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
LIST_ENTRY DeferredList;
|
|
PAGED_CODE();
|
|
NpSlowWriteCalls++;
|
|
|
|
InitializeListHead(&DeferredList);
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FsRtlEnterFileSystem();
|
|
NpAcquireSharedVcb();
|
|
|
|
NpCommonWrite(IoStack->FileObject,
|
|
Irp->UserBuffer,
|
|
IoStack->Parameters.Write.Length,
|
|
Irp->Tail.Overlay.Thread,
|
|
&IoStatus,
|
|
Irp,
|
|
&DeferredList);
|
|
|
|
NpReleaseVcb();
|
|
NpCompleteDeferredIrps(&DeferredList);
|
|
FsRtlExitFileSystem();
|
|
|
|
if (IoStatus.Status != STATUS_PENDING)
|
|
{
|
|
Irp->IoStatus.Information = IoStatus.Information;
|
|
Irp->IoStatus.Status = IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
|
|
}
|
|
|
|
return IoStatus.Status;
|
|
}
|
|
|
|
|
|
_Function_class_(FAST_IO_WRITE)
|
|
_IRQL_requires_same_
|
|
BOOLEAN
|
|
NTAPI
|
|
NpFastWrite(
|
|
_In_ PFILE_OBJECT FileObject,
|
|
_In_ PLARGE_INTEGER FileOffset,
|
|
_In_ ULONG Length,
|
|
_In_ BOOLEAN Wait,
|
|
_In_ ULONG LockKey,
|
|
_In_ PVOID Buffer,
|
|
_Out_ PIO_STATUS_BLOCK IoStatus,
|
|
_In_ PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
LIST_ENTRY DeferredList;
|
|
BOOLEAN Result;
|
|
PAGED_CODE();
|
|
|
|
InitializeListHead(&DeferredList);
|
|
|
|
FsRtlEnterFileSystem();
|
|
NpAcquireSharedVcb();
|
|
|
|
Result = NpCommonWrite(FileObject,
|
|
Buffer,
|
|
Length,
|
|
PsGetCurrentThread(),
|
|
IoStatus,
|
|
NULL,
|
|
&DeferredList);
|
|
if (Result)
|
|
++NpFastWriteTrue;
|
|
else
|
|
++NpFastWriteFalse;
|
|
|
|
NpReleaseVcb();
|
|
NpCompleteDeferredIrps(&DeferredList);
|
|
FsRtlExitFileSystem();
|
|
|
|
return Result;
|
|
}
|
|
|
|
/* EOF */
|