list(APPEND SOURCE
+ cleanup.c
+ close.c
create.c
datasup.c
+ fileinfo.c
fileobsup.c
+ flushbuf.c
+ fsctrl.c
main.c
prefxsup.c
read.c
secursup.c
statesup.c
strucsup.c
- waitsup.c)
+ waitsup.c
+ write.c
+ writesup.c)
add_library(npfs_new SHARED ${SOURCE})
set_module_type(npfs_new kernelmodedriver)
--- /dev/null
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpCommonCleanup(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ NODE_TYPE_CODE NodeTypeCode;
+ LIST_ENTRY List;
+ PNP_FCB Fcb;
+ PNP_CCB Ccb;
+ BOOLEAN ServerSide;
+ PLIST_ENTRY ThisEntry, NextEntry;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ InitializeListHead(&List);
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+ (PVOID*)&Fcb,
+ &Ccb,
+ &ServerSide);
+ if (NodeTypeCode == NPFS_NTC_CCB )
+ {
+ if ( ServerSide == 1 )
+ {
+ ASSERT(Ccb->Fcb->ServerOpenCount != 0);
+ --Ccb->Fcb->ServerOpenCount;
+ }
+
+ NpSetClosingPipeState(Ccb, Irp, ServerSide, &List);
+ }
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+
+ NextEntry = List.Flink;
+ while (NextEntry != &List)
+ {
+ ThisEntry = NextEntry;
+ NextEntry = NextEntry->Flink;
+
+ Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ FsRtlEnterFileSystem();
+
+ Status = NpCommonCleanup(DeviceObject, Irp);
+
+ FsRtlExitFileSystem();
+
+ if ( Status != STATUS_PENDING )
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+
+ return Status;
+}
+
--- /dev/null
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpCommonClose(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ NODE_TYPE_CODE NodeTypeCode;
+ LIST_ENTRY List;
+ PNP_FCB Fcb;
+ PNP_CCB Ccb;
+ BOOLEAN ServerSide;
+ PLIST_ENTRY ThisEntry, NextEntry;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ InitializeListHead(&List);
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+ (PVOID*)&Fcb,
+ &Ccb,
+ &ServerSide);
+ if (NodeTypeCode == NPFS_NTC_ROOT_DCB)
+ {
+ --Fcb->CurrentInstances;
+ NpDeleteCcb(Ccb, &List);
+ }
+ else if (NodeTypeCode == NPFS_NTC_VCB)
+ {
+ --NpVcb->ReferenceCount;
+ }
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+
+ NextEntry = List.Flink;
+ while (NextEntry != &List)
+ {
+ ThisEntry = NextEntry;
+ NextEntry = NextEntry->Flink;
+
+ Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ }
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ FsRtlEnterFileSystem();
+
+ Status = NpCommonClose(DeviceObject, Irp);
+
+ FsRtlExitFileSystem();
+
+ return Status;
+}
+
--- /dev/null
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpSetBasicInfo(IN PNP_CCB Ccb,
+ IN PFILE_BASIC_INFORMATION Buffer)
+{
+ PAGED_CODE();
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpSetPipeInfo(IN PNP_FCB Fcb,
+ IN PNP_CCB Ccb,
+ IN PFILE_PIPE_INFORMATION Buffer,
+ IN ULONG ServerSide,
+ IN PLIST_ENTRY List)
+{
+ NTSTATUS Status;
+ PNP_DATA_QUEUE ReadQueue, WriteQueue;
+ ULONG CompletionMode;
+ PAGED_CODE();
+
+ if ( Buffer->ReadMode == FILE_PIPE_MESSAGE_MODE && Fcb->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE )
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ( ServerSide )
+ {
+ if ( ServerSide != 1 ) KeBugCheckEx(NPFS_FILE_SYSTEM, 0xA04EFu, ServerSide, 0, 0);
+ ReadQueue = &Ccb->InQueue;
+ WriteQueue = &Ccb->OutQueue;
+ CompletionMode = Ccb->ServerCompletionMode;
+ }
+ else
+ {
+ ReadQueue = &Ccb->OutQueue;
+ WriteQueue = &Ccb->InQueue;
+ CompletionMode = Ccb->ClientCompletionMode;
+ }
+
+ if ( Buffer->CompletionMode != FILE_PIPE_COMPLETE_OPERATION ||
+ CompletionMode == FILE_PIPE_COMPLETE_OPERATION ||
+ (ReadQueue->QueueState == ReadEntries &&
+ WriteQueue->QueueState != WriteEntries ))
+ {
+ if (ServerSide)
+ {
+ Ccb->ServerReadMode = Buffer->ReadMode & 0xFF;
+ Ccb->ServerCompletionMode = Buffer->CompletionMode & 0xFF;
+ }
+ else
+ {
+ Ccb->ClientReadMode = Buffer->ReadMode & 0xFF;
+ Ccb->ClientCompletionMode = Buffer->CompletionMode & 0xFF;
+ }
+
+ NpCheckForNotify(Fcb->ParentDcb, 0, List);
+ Status = 0;
+ }
+ else
+ {
+ Status = STATUS_PIPE_BUSY;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCommonSetInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ NODE_TYPE_CODE NodeTypeCode;
+ PIO_STACK_LOCATION IoStack;
+ ULONG InfoClass;
+ PVOID Buffer;
+ PNP_FCB Fcb;
+ PNP_CCB Ccb;
+ BOOLEAN ServerSide;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+ (PVOID*)&Fcb,
+ &Ccb,
+ &ServerSide);
+ if ( !NodeTypeCode ) return STATUS_PIPE_DISCONNECTED;
+ if ( NodeTypeCode != NPFS_NTC_CCB ) return STATUS_INVALID_PARAMETER;
+
+ InfoClass = IoStack->Parameters.QueryFile.FileInformationClass;
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+ if ( InfoClass == FileBasicInformation ) return NpSetBasicInfo(Ccb, Buffer);
+
+ if ( InfoClass != FilePipeInformation ) return STATUS_INVALID_PARAMETER;
+
+ return NpSetPipeInfo(Fcb, Ccb, Buffer, ServerSide, List);
+}
+
+NTSTATUS
+NTAPI
+NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ LIST_ENTRY List;
+ PLIST_ENTRY NextEntry, ThisEntry;
+ PAGED_CODE();
+
+ InitializeListHead(&List);
+
+ FsRtlEnterFileSystem();
+ ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+ Status = NpCommonSetInformation(DeviceObject, Irp, &List);
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+
+ NextEntry = List.Flink;
+ while (NextEntry != &List)
+ {
+ ThisEntry = NextEntry;
+ NextEntry = NextEntry->Flink;
+
+ Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ }
+
+ FsRtlExitFileSystem();
+
+ if ( Status != STATUS_PENDING )
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCommonQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ FsRtlEnterFileSystem();
+ ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+ Status = NpCommonQueryInformation(DeviceObject, Irp);
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+ FsRtlExitFileSystem();
+
+ if ( Status != STATUS_PENDING )
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+
+ return Status;
+}
+
--- /dev/null
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpCommonFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NODE_TYPE_CODE NodeTypeCode;
+ PNP_CCB Ccb;
+ BOOLEAN ServerSide;
+ NTSTATUS Status;
+ PNP_DATA_QUEUE FlushQueue;
+ PAGED_CODE();
+
+ NodeTypeCode = NpDecodeFileObject(IoGetCurrentIrpStackLocation(Irp)->FileObject,
+ NULL,
+ &Ccb,
+ &ServerSide);
+ if (NodeTypeCode != NPFS_NTC_CCB ) return STATUS_PIPE_DISCONNECTED;
+
+ ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+ //ms_exc.registration.TryLevel = 0;
+
+ FlushQueue = &Ccb->OutQueue;
+ if ( ServerSide != 1 ) FlushQueue = &Ccb->InQueue;
+
+ if ( FlushQueue->QueueState == WriteEntries)
+ {
+ Status = NpAddDataQueueEntry(ServerSide,
+ Ccb,
+ FlushQueue,
+ 1,
+ 2u,
+ 0,
+ Irp,
+ NULL,
+ 0);
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ // ms_exc.registration.TryLevel = -1;
+ ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ FsRtlEnterFileSystem();
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+
+ Status = NpCommonFlushBuffers(DeviceObject, Irp);
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+ FsRtlExitFileSystem();
+
+ return Status;
+}
+
--- /dev/null
+#include "npfs.h"
+
+IO_STATUS_BLOCK NpUserIoStatusBlock;
+
+NTSTATUS
+NTAPI
+NpInternalTransceive(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpInternalRead(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN BOOLEAN Overflow,
+ IN PLIST_ENTRY List)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpInternalWrite(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpAssignEvent(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpQueryEvent(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpImpersonate(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpDisconnect(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ BOOLEAN ServerSide;
+ PNP_CCB Ccb;
+ NTSTATUS Status;
+ NODE_TYPE_CODE NodeTypeCode;
+ PIO_STACK_LOCATION IoStack;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+ if (NodeTypeCode == NPFS_NTC_CCB)
+ {
+ if ( ServerSide == 1 )
+ {
+ ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+
+ Status = NpSetDisconnectedPipeState(Ccb, List);
+
+ NpUninitializeSecurity(Ccb);
+
+ ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+ }
+ else
+ {
+ Status = STATUS_ILLEGAL_FUNCTION;
+ }
+ }
+ else
+ {
+ Status = STATUS_PIPE_DISCONNECTED;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpListen(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ BOOLEAN ServerSide;
+ PNP_CCB Ccb;
+ NTSTATUS Status;
+ NODE_TYPE_CODE NodeTypeCode;
+ PIO_STACK_LOCATION IoStack;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+ if (NodeTypeCode == NPFS_NTC_CCB)
+ {
+ if ( ServerSide == 1 )
+ {
+ ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+
+ Status = NpSetListeningPipeState(Ccb, Irp, List);
+
+ NpUninitializeSecurity(Ccb);
+
+ ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+ }
+ else
+ {
+ Status = STATUS_ILLEGAL_FUNCTION;
+ }
+ }
+ else
+ {
+ Status = STATUS_ILLEGAL_FUNCTION;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpPeek(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ PIO_STACK_LOCATION IoStack;
+ NODE_TYPE_CODE Type;
+ ULONG InputLength;
+ BOOLEAN ServerSide;
+ PNP_CCB Ccb;
+ PFILE_PIPE_PEEK_BUFFER PeekBuffer;
+ PNP_DATA_QUEUE DataQueue;
+ ULONG BytesPeeked;
+ IO_STATUS_BLOCK IoStatus;
+ NTSTATUS Status;
+ PNP_DATA_QUEUE_ENTRY DataEntry;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ InputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
+ Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+ if (!Type) return STATUS_PIPE_DISCONNECTED;
+
+ if ((Type != NPFS_NTC_CCB) && (InputLength < sizeof(*PeekBuffer)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+ if ( ServerSide )
+ {
+ if ( ServerSide != 1 )
+ {
+ KeBugCheckEx(NPFS_FILE_SYSTEM, 0xD02E5, ServerSide, 0, 0);
+ }
+ DataQueue = &Ccb->InQueue;
+ }
+ else
+ {
+ DataQueue = &Ccb->OutQueue;
+ }
+
+ if ( Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE )
+ {
+ if ( Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE )
+ {
+ return STATUS_INVALID_PIPE_STATE;
+ }
+ if ( DataQueue->QueueState != WriteEntries)
+ {
+ return STATUS_PIPE_BROKEN;
+ }
+ }
+
+ PeekBuffer->NamedPipeState = 0;
+ PeekBuffer->ReadDataAvailable = 0;
+ PeekBuffer->NumberOfMessages = 0;
+ PeekBuffer->MessageLength = 0;
+ PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
+ BytesPeeked = sizeof(*PeekBuffer);
+
+ if ( DataQueue->QueueState == WriteEntries)
+ {
+ DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
+ NP_DATA_QUEUE_ENTRY,
+ QueueEntry);
+ ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered));
+
+ PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset;
+ if ( Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE)
+ {
+ PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
+ PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
+ }
+ if ( InputLength == sizeof(*PeekBuffer) )
+ {
+ Status = PeekBuffer->ReadDataAvailable != 0 ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
+ }
+ else
+ {
+ IoStatus = NpReadDataQueue(DataQueue,
+ TRUE,
+ FALSE,
+ PeekBuffer->Data,
+ InputLength - sizeof(*PeekBuffer),
+ Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
+ Ccb,
+ List);
+ Status = IoStatus.Status;
+ BytesPeeked = IoStatus.Information + sizeof(*PeekBuffer);
+ }
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ Irp->IoStatus.Information = BytesPeeked;
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ PAGED_CODE();
+
+ if ( Irp->AssociatedIrp.SystemBuffer )
+ {
+ ExFreePool(Irp->AssociatedIrp.SystemBuffer);
+ }
+
+ IoFreeIrp(Irp);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+NTAPI
+NpTransceive(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ PIO_STACK_LOCATION IoStack;
+ PVOID InBuffer, OutBuffer;
+ ULONG InLength, OutLength, ReadMode, BytesWritten;
+ NODE_TYPE_CODE NodeTypeCode;
+ PNP_CCB Ccb;
+ BOOLEAN ServerSide;
+ PNP_NONPAGED_CCB NonPagedCcb;
+ PNP_DATA_QUEUE ReadQueue, WriteQueue;
+ PNP_EVENT_BUFFER EventBuffer;
+ NTSTATUS Status;
+ PIRP NewIrp;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
+ InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer;
+ OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
+ OutBuffer = Irp->UserBuffer;
+
+ if ( Irp->RequestorMode == UserMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead(InBuffer, InLength, sizeof(CHAR));
+ ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ASSERT(FALSE);
+ }
+ _SEH2_END;
+ }
+
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+ if (NodeTypeCode != NPFS_NTC_CCB )
+ {
+ return STATUS_PIPE_DISCONNECTED;
+ }
+
+ NonPagedCcb = Ccb->NonPagedCcb;
+ ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
+
+ //ms_exc.registration.TryLevel = 1;
+ if ( Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE )
+ {
+ Status = STATUS_INVALID_PIPE_STATE;
+ goto Quickie;
+ }
+
+ if ( ServerSide )
+ {
+ if ( ServerSide != 1 ) KeBugCheckEx(NPFS_FILE_SYSTEM, 0xD0538, ServerSide, 0, 0);
+ ReadQueue = &Ccb->InQueue;
+ WriteQueue = &Ccb->OutQueue;
+ WriteQueue = &Ccb->OutQueue;
+ EventBuffer = NonPagedCcb->EventBufferServer;
+ ReadMode = Ccb->ServerReadMode;
+ }
+ else
+ {
+ ReadQueue = &Ccb->OutQueue;
+ WriteQueue = &Ccb->InQueue;
+ EventBuffer = NonPagedCcb->EventBufferClient;
+ ReadMode = Ccb->ClientReadMode;
+ WriteQueue = &Ccb->InQueue;
+ }
+
+ if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX ||
+ ReadMode != FILE_PIPE_MESSAGE_MODE )
+ {
+ Status = STATUS_INVALID_PIPE_STATE;
+ goto Quickie;
+ }
+
+ if ( ReadQueue->QueueState != Empty)
+ {
+ Status = STATUS_PIPE_BUSY;
+ goto Quickie;
+ }
+
+ Status = NpWriteDataQueue(WriteQueue,
+ 1,
+ InBuffer,
+ InLength,
+ Ccb->Fcb->NamedPipeType,
+ &BytesWritten,
+ Ccb,
+ ServerSide,
+ Irp->Tail.Overlay.Thread,
+ List);
+ if ( Status == STATUS_MORE_PROCESSING_REQUIRED )
+ {
+ ASSERT(WriteQueue->QueueState != ReadEntries);
+ NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+ if ( !NewIrp )
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
+
+ IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE);
+
+ if ( BytesWritten )
+ {
+ NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool, BytesWritten, 'wFpN');
+ if ( !NewIrp->AssociatedIrp.SystemBuffer )
+ {
+ IoFreeIrp(NewIrp);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
+
+ RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer,
+ (PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten),
+ BytesWritten);
+ //ms_exc.registration.TryLevel = 1;
+ }
+ else
+ {
+ NewIrp->AssociatedIrp.SystemBuffer = NULL;
+ }
+
+ IoStack = IoGetNextIrpStackLocation(NewIrp);
+ IoSetNextIrpStackLocation(NewIrp);
+
+ NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
+ NewIrp->IoStatus.Information = BytesWritten;
+
+ IoStack->Parameters.Read.Length = BytesWritten;
+ IoStack->MajorFunction = IRP_MJ_WRITE;
+
+ if ( BytesWritten > 0 ) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
+ NewIrp->UserIosb = &NpUserIoStatusBlock;
+
+ Status = NpAddDataQueueEntry(ServerSide,
+ Ccb,
+ WriteQueue,
+ WriteEntries,
+ 1,
+ BytesWritten,
+ NewIrp,
+ NULL,
+ 0);
+ if ( Status != STATUS_PENDING )
+ {
+ NewIrp->IoStatus.Status = Status;
+ InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ if (!NT_SUCCESS(Status)) goto Quickie;
+
+ if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+ ASSERT(ReadQueue->QueueState == Empty);
+ Status = NpAddDataQueueEntry(ServerSide,
+ Ccb,
+ ReadQueue,
+ ReadEntries,
+ 0,
+ OutLength,
+ Irp,
+ NULL,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+ }
+
+Quickie:
+ //ms_exc.registration.TryLevel = -1;
+ ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ ULONG InLength, NameLength;
+ UNICODE_STRING SourceString, Prefix;
+ BOOLEAN ServerSide;
+ PNP_CCB Ccb;
+ PFILE_PIPE_WAIT_FOR_BUFFER Buffer;
+ NTSTATUS Status;
+ NODE_TYPE_CODE NodeTypeCode;
+ PLIST_ENTRY NextEntry;
+ PNP_FCB Fcb;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ InLength = IoStack->Parameters.DeviceIoControl.InputBufferLength;
+
+ SourceString.Buffer = NULL;
+
+ //ms_exc.registration.TryLevel = 0;
+
+ if (NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide) != NPFS_NTC_ROOT_DCB )
+ {
+ Status = STATUS_ILLEGAL_FUNCTION;
+ goto Quickie;
+ }
+
+ Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+ if (InLength < sizeof(*Buffer))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
+
+ NameLength = Buffer->NameLength;
+ if ((NameLength > 0xFFFD) || ((NameLength + sizeof(*Buffer)) > InLength ))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
+
+ SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
+ SourceString.Buffer = ExAllocatePoolWithTag(PagedPool, SourceString.Length, 'WFpN');
+ if (!SourceString.Buffer )
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
+
+ SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
+ RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
+
+ Status = STATUS_SUCCESS;
+ //Status = NpTranslateAlias(&SourceString);
+ if (!NT_SUCCESS(Status)) goto Quickie;
+
+ Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix);
+ Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1);
+
+ NodeTypeCode = Fcb ? Fcb->NodeType : 0;
+ if ( NodeTypeCode != NPFS_NTC_FCB )
+ {
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto Quickie;
+ }
+
+ for (NextEntry = Fcb->CcbList.Flink;
+ NextEntry != &Fcb->CcbList;
+ NextEntry = NextEntry->Flink)
+ {
+ Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
+ if ( Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE ) break;
+ }
+
+ if ( NextEntry == &Fcb->CcbList )
+ {
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = NpAddWaiter(&NpVcb->WaitQueue,
+ Fcb->Timeout,
+ Irp,
+ &SourceString);
+ }
+
+Quickie:
+ //ms_exc.registration.TryLevel = -1;
+ if ( SourceString.Buffer ) ExFreePool(SourceString.Buffer);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ ULONG Fsctl;
+ BOOLEAN Overflow = FALSE;
+ LIST_ENTRY List;
+ PLIST_ENTRY NextEntry, ThisEntry;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ InitializeListHead(&List);
+ Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode;
+
+ switch (Fsctl)
+ {
+ case FSCTL_PIPE_PEEK:
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpPeek(DeviceObject, Irp, &List);
+ break;
+
+ case FSCTL_PIPE_INTERNAL_WRITE:
+ ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+ Status = NpInternalWrite(DeviceObject, Irp, &List);
+ break;
+
+ case FSCTL_PIPE_TRANSCEIVE:
+ ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+ Status = NpTransceive(DeviceObject, Irp, &List);
+ break;
+
+ case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
+ ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+ Status = NpInternalTransceive(DeviceObject, Irp, &List);
+ break;
+
+ case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
+ Overflow = TRUE;
+ // on purpose
+
+ case FSCTL_PIPE_INTERNAL_READ:
+ ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+ Status = NpInternalRead(DeviceObject, Irp, Overflow, &List);
+ break;
+
+ case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
+
+ ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+ Status = NpQueryClientProcess(DeviceObject, Irp);
+ break;
+
+ case FSCTL_PIPE_ASSIGN_EVENT:
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpAssignEvent(DeviceObject, Irp);
+ break;
+
+ case FSCTL_PIPE_DISCONNECT:
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpDisconnect(DeviceObject, Irp, &List);
+ break;
+
+ case FSCTL_PIPE_LISTEN:
+
+ ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+ Status = NpListen(DeviceObject, Irp, &List);
+ break;
+
+ case FSCTL_PIPE_QUERY_EVENT:
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpQueryEvent(DeviceObject, Irp);
+ break;
+
+ case FSCTL_PIPE_WAIT:
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpWaitForNamedPipe(DeviceObject, Irp);
+ break;
+
+ case FSCTL_PIPE_IMPERSONATE:
+
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpImpersonate(DeviceObject, Irp);
+ break;
+
+ case FSCTL_PIPE_SET_CLIENT_PROCESS:
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+ Status = NpSetClientProcess(DeviceObject, Irp);
+ break;
+
+ default:
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+
+ NextEntry = List.Flink;
+ while (NextEntry != &List)
+ {
+ ThisEntry = NextEntry;
+ NextEntry = NextEntry->Flink;
+
+ Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ FsRtlEnterFileSystem();
+
+ Status = NpCommonFileSystemControl(DeviceObject, Irp);
+
+ FsRtlExitFileSystem();
+
+ if ( Status != STATUS_PENDING )
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+
+ return Status;
+}
+
+
NTSTATUS
NTAPI
-NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- UNIMPLEMENTED;
-
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- UNIMPLEMENTED;
-
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+NpFsdSetSecurity(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
UNIMPLEMENTED;
NTSTATUS
NTAPI
-NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+NpFsdQuerySecurity(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS
-NTAPI
-NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- UNIMPLEMENTED;
-
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- UNIMPLEMENTED;
-
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
-}
-
NTSTATUS
NTAPI
NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS
-NTAPI
-NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- UNIMPLEMENTED;
-
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NOT_IMPLEMENTED;
-}
-
NTSTATUS
NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpFsdFlushBuffers;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = NpFsdDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = NpFsdFileSystemControl;
- // DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =
- // NpfsQuerySecurity;
- // DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] =
- // NpfsSetSecurity;
+ DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = NpFsdQuerySecurity;
+ DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = NpFsdSetSecurity;
DriverObject->DriverUnload = NULL;
- RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe");
+ RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe2");
Status = IoCreateDevice(DriverObject,
sizeof(NP_VCB),
&DeviceName,
KSPIN_LOCK WaitLock;
} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
+//
+// The Entries in the Queue above, one for each Waiter.
+//
+typedef struct _NP_WAIT_QUEUE_ENTRY
+{
+ PIRP Irp;
+ KDPC Dpc;
+ KTIMER Timer;
+ PNP_WAIT_QUEUE WaitQueue;
+ UNICODE_STRING String;
+ PFILE_OBJECT FileObject;
+} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY;
+
//
// The event buffer in the NonPaged CCB
//
extern PNP_VCB NpVcb;
+BOOLEAN
+NTAPI
+NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
+ IN PVOID Buffer);
+
VOID
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue);
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+NTSTATUS
+NTAPI
+NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+
+NTSTATUS
+NTAPI
+NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
NTSTATUS
NTAPI
NpSetConnectedPipeState(IN PNP_CCB Ccb,
IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List);
+NTSTATUS
+NTAPI
+NpSetListeningPipeState(IN PNP_CCB Ccb,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List);
+
+
+NTSTATUS
+NTAPI
+NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
+ IN PLIST_ENTRY List);
+
+NTSTATUS
+NTAPI
+NpSetClosingPipeState(IN PNP_CCB Ccb,
+ IN PIRP Irp,
+ IN ULONG NamedPipeEnd,
+ IN PLIST_ENTRY List);
+
VOID
NTAPI
NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext);
IN BOOLEAN SecondList,
IN PLIST_ENTRY List);
+NTSTATUS
+NTAPI
+NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
+ IN LARGE_INTEGER WaitTime,
+ IN PIRP Irp,
+ IN PUNICODE_STRING Name);
+
NTSTATUS
NTAPI
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN PNP_CCB Ccb,
IN PLIST_ENTRY List);
+
+NTSTATUS
+NTAPI
+NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
+ IN ULONG Mode,
+ IN PVOID OutBuffer,
+ IN ULONG OutBufferSize,
+ IN ULONG PipeType,
+ OUT PULONG BytesWritten,
+ IN PNP_CCB Ccb,
+ IN BOOLEAN ServerSide,
+ IN PETHREAD Thread,
+ IN PLIST_ENTRY List);
+
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
IN PLIST_ENTRY List)
{
NODE_TYPE_CODE NodeType;
- ULONG NamedPipeConfiguation;
PNP_DATA_QUEUE Queue;
PNP_EVENT_BUFFER EventBuffer;
NTSTATUS Status;
ASSERT((Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE) || (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE));
- NamedPipeConfiguation = Ccb->Fcb->NamedPipeConfiguration;
-
- if ((ServerSide == 1 && NamedPipeConfiguation == FILE_PIPE_OUTBOUND) ||
- (ServerSide == 0 && NamedPipeConfiguation == FILE_PIPE_INBOUND) )
+ if ((ServerSide == 1 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND) ||
+ (ServerSide == 0 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND ))
{
IoStatus->Status = STATUS_INVALID_PARAMETER;
ReadOk = TRUE;
goto Quickie;
}
- if ( Irp )
+ if ( !Irp )
{
- Status = NpAddDataQueueEntry(ServerSide,
- Ccb,
- Queue,
- 0,
- 0,
- BufferSize,
- Irp,
- 0,
- 0);
- IoStatus->Status = Status;
- if (!NT_SUCCESS(Status))
- {
- ReadOk = FALSE;
- goto Quickie;
- }
+ ReadOk = FALSE;
+ goto Quickie;
+ }
+ Status = NpAddDataQueueEntry(ServerSide,
+ Ccb,
+ Queue,
+ 0,
+ 0,
+ BufferSize,
+ Irp,
+ 0,
+ 0);
+ IoStatus->Status = Status;
+ if (!NT_SUCCESS(Status))
+ {
+ ReadOk = FALSE;
+ }
+ else
+ {
ReadOk = TRUE;
if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
- goto Quickie;
}
- ReadOk = FALSE;
Quickie:
//ms_exc.registration.TryLevel = -1;
ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
{
Irp->IoStatus.Information = IoStatus.Information;
Irp->IoStatus.Status = IoStatus.Status;
- IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
}
return IoStatus.Status;
#include "npfs.h"
+VOID
+NTAPI
+NpCancelListeningQueueIrp(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ FsRtlEnterFileSystem();
+ ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+ FsRtlExitFileSystem();
+ ExReleaseResourceLite(&NpVcb->Lock);
+
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+}
+
NTSTATUS
NTAPI
NpSetConnectedPipeState(IN PNP_CCB Ccb,
return STATUS_SUCCESS;
}
+
+NTSTATUS
+NTAPI
+NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
+ IN PLIST_ENTRY List)
+{
+ PIRP Irp;
+ PNP_NONPAGED_CCB NonPagedCcb;
+ NTSTATUS Status;
+ PLIST_ENTRY NextEntry;
+ PNP_EVENT_BUFFER EventBuffer;
+
+ NonPagedCcb = Ccb->NonPagedCcb;
+
+ switch (Ccb->NamedPipeState)
+ {
+ case FILE_PIPE_DISCONNECTED_STATE:
+ Status = STATUS_PIPE_DISCONNECTED;
+ break;
+
+ case FILE_PIPE_LISTENING_STATE:
+ while (!IsListEmpty(&Ccb->IrpList))
+ {
+ NextEntry = RemoveHeadList(&Ccb->IrpList);
+
+ Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
+
+ if (IoSetCancelRoutine(Irp, NULL))
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+ InsertTailList(List, NextEntry);
+ }
+ else
+ {
+ InitializeListHead(NextEntry);
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ case FILE_PIPE_CONNECTED_STATE:
+
+ EventBuffer = NonPagedCcb->EventBufferClient;
+ while (Ccb->InQueue.QueueState != Empty)
+ {
+ Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ while ( Ccb->OutQueue.QueueState != Empty)
+ {
+ Irp = NpRemoveDataQueueEntry(&Ccb->OutQueue, FALSE, List);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ case FILE_PIPE_CLOSING_STATE:
+
+ EventBuffer = NonPagedCcb->EventBufferClient;
+ while (Ccb->InQueue.QueueState != Empty)
+ {
+ Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ ASSERT(Ccb->OutQueue.QueueState == Empty);
+
+ NpDeleteEventTableEntry(&NpVcb->EventTable, EventBuffer);
+ NonPagedCcb->EventBufferClient = NULL;
+
+ NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+ Ccb->ClientFileObject = NULL;
+
+ NpUninitializeSecurity(Ccb);
+
+ if ( Ccb->ClientSession )
+ {
+ ExFreePool(Ccb->ClientSession);
+ Ccb->ClientSession = NULL;
+ }
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+ KeBugCheckEx(NPFS_FILE_SYSTEM, 0x1603DD, Ccb->NamedPipeState, 0, 0);
+ break;
+ }
+
+ Ccb->NamedPipeState = FILE_PIPE_DISCONNECTED_STATE;
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpSetListeningPipeState(IN PNP_CCB Ccb,
+ IN PIRP Irp,
+ IN PLIST_ENTRY List)
+{
+ NTSTATUS Status;
+
+ switch (Ccb->NamedPipeState)
+ {
+ case FILE_PIPE_DISCONNECTED_STATE:
+
+ Status = NpCancelWaiter(&NpVcb->WaitQueue,
+ &Ccb->Fcb->FullName,
+ STATUS_SUCCESS,
+ List);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ //
+ // Drop down on purpose
+ //
+
+ case FILE_PIPE_LISTENING_STATE:
+
+ if ( Ccb->ServerCompletionMode == FILE_PIPE_COMPLETE_OPERATION)
+ {
+ Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
+ return STATUS_PIPE_LISTENING;
+ }
+
+ IoSetCancelRoutine(Irp, NpCancelListeningQueueIrp);
+ if ( Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
+ {
+ return STATUS_CANCELLED;
+ }
+
+ Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
+ IoMarkIrpPending(Irp);
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ return STATUS_PENDING;
+
+ case FILE_PIPE_CONNECTED_STATE:
+ Status = STATUS_PIPE_CONNECTED;
+ break;
+
+ case FILE_PIPE_CLOSING_STATE:
+ Status = STATUS_PIPE_CLOSING;
+ break;
+
+ default:
+ KeBugCheckEx(NPFS_FILE_SYSTEM, 0x160133, Ccb->NamedPipeState, 0, 0);
+ break;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpSetClosingPipeState(IN PNP_CCB Ccb,
+ IN PIRP Irp,
+ IN ULONG NamedPipeEnd,
+ IN PLIST_ENTRY List)
+{
+ PNP_NONPAGED_CCB NonPagedCcb;
+ PNP_FCB Fcb;
+ PLIST_ENTRY NextEntry;
+ PNP_DATA_QUEUE ReadQueue, WriteQueue, DataQueue;
+ PNP_EVENT_BUFFER EventBuffer;
+
+ NonPagedCcb = Ccb->NonPagedCcb;
+ Fcb = Ccb->Fcb;
+
+ switch (Ccb->NamedPipeState)
+ {
+ case FILE_PIPE_LISTENING_STATE:
+
+ ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END);
+
+ while (!IsListEmpty(&Ccb->IrpList))
+ {
+ NextEntry = RemoveHeadList(&Ccb->IrpList);
+
+ Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
+
+ if (IoSetCancelRoutine(Irp, NULL))
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+ InsertTailList(List, NextEntry);
+ }
+ else
+ {
+ InitializeListHead(NextEntry);
+ }
+ }
+
+ // Drop on purpose
+
+ case FILE_PIPE_DISCONNECTED_STATE:
+
+ ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END);
+
+ NpSetFileObject(Ccb->ServerFileObject, NULL, NULL, TRUE);
+ Ccb->ServerFileObject = NULL;
+
+ NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+ Ccb->ClientFileObject = NULL;
+
+ NpDeleteCcb(Ccb, List);
+ if ( !Fcb->CurrentInstances ) NpDeleteFcb(Fcb, List);
+ break;
+
+ case FILE_PIPE_CLOSING_STATE:
+
+ if ( NamedPipeEnd == FILE_PIPE_SERVER_END)
+ {
+ DataQueue = &Ccb->InQueue;
+ }
+ else
+ {
+ DataQueue = &Ccb->OutQueue;
+ }
+
+ NpSetFileObject(Ccb->ServerFileObject, NULL, NULL, TRUE);
+ Ccb->ServerFileObject = NULL;
+
+ NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+ Ccb->ClientFileObject = NULL;
+
+ while (Ccb->InQueue.QueueState != Empty)
+ {
+ Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ NpUninitializeSecurity(Ccb);
+
+ if ( Ccb->ClientSession )
+ {
+ ExFreePool(Ccb->ClientSession);
+ Ccb->ClientSession = 0;
+ }
+
+ NpDeleteCcb(Ccb, List);
+ if ( !Fcb->CurrentInstances ) NpDeleteFcb(Fcb, List);
+ break;
+
+ case FILE_PIPE_CONNECTED_STATE:
+ if ( NamedPipeEnd == FILE_PIPE_SERVER_END)
+ {
+ ReadQueue = &Ccb->InQueue;
+ WriteQueue = &Ccb->OutQueue;
+ EventBuffer = NonPagedCcb->EventBufferServer;
+
+ NpSetFileObject(Ccb->ServerFileObject, NULL, NULL, TRUE);
+ Ccb->ServerFileObject = 0;
+ }
+ else
+ {
+ ReadQueue = &Ccb->OutQueue;
+ WriteQueue = &Ccb->InQueue;
+ EventBuffer = NonPagedCcb->EventBufferClient;
+
+ NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+ Ccb->ClientFileObject = 0;
+ }
+
+ Ccb->NamedPipeState = FILE_PIPE_CLOSING_STATE;
+
+ while (Ccb->InQueue.QueueState != Empty)
+ {
+ Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ while (WriteQueue->QueueState == WriteEntries)
+ {
+ Irp = NpRemoveDataQueueEntry(WriteQueue, FALSE, List);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+ InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+ }
+ }
+
+ if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+ break;
+
+ default:
+ KeBugCheckEx(0x25u, 0x1602F9, Ccb->NamedPipeState, 0, 0);
+ break;
+ }
+ return STATUS_SUCCESS;
+}
+
NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer)
{
- UNIMPLEMENTED;
- return FALSE;
+ if (!Buffer) return FALSE;
+
+ ObfDereferenceObject(((PNP_EVENT_BUFFER)Buffer)->Event);
+ return RtlDeleteElementGenericTable(Table, Buffer);
}
VOID
#include "npfs.h"
+VOID
+NTAPI
+NpCancelWaitQueueIrp(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ KIRQL OldIrql;
+ PNP_WAIT_QUEUE_ENTRY WaitEntry;
+ PNP_WAIT_QUEUE WaitQueue;
+
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ WaitQueue = (PNP_WAIT_QUEUE)Irp->Tail.Overlay.DriverContext[0];
+
+ OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
+
+ WaitEntry = (PNP_WAIT_QUEUE_ENTRY)Irp->Tail.Overlay.DriverContext[1];
+ if ( WaitEntry )
+ {
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+ if ( !KeCancelTimer(&WaitEntry->Timer) )
+ {
+ WaitEntry->Irp = NULL;
+ WaitEntry = NULL;
+ }
+ }
+
+ KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
+
+ if ( WaitEntry )
+ {
+ ObfDereferenceObject(WaitEntry->FileObject);
+ ExFreePool(WaitEntry);
+ }
+
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+}
+
+VOID
+NTAPI
+NpTimerDispatch(IN PKDPC Dpc,
+ IN PVOID Context,
+ IN PVOID Argument1,
+ IN PVOID Argument2)
+{
+ PIRP Irp;
+ KIRQL OldIrql;
+ PNP_WAIT_QUEUE_ENTRY WaitEntry = Context;
+
+ OldIrql = KfAcquireSpinLock(&WaitEntry->WaitQueue->WaitLock);
+ Irp = WaitEntry->Irp;
+ if ( Irp);
+ {
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+ if ( !IoSetCancelRoutine(Irp, NULL))
+ {
+ Irp->Tail.Overlay.DriverContext[1] = NULL;
+ Irp = NULL;
+ }
+ }
+ KfReleaseSpinLock(&WaitEntry->WaitQueue->WaitLock, OldIrql);
+ if ( Irp )
+ {
+ Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
+ IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+ ObfDereferenceObject(WaitEntry->FileObject);
+ ExFreePoolWithTag(WaitEntry, 0);
+}
+
VOID
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue)
ExFreePool(DestinationString.Buffer);
return STATUS_SUCCESS;
}
+
+NTSTATUS
+NTAPI
+NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
+ IN LARGE_INTEGER WaitTime,
+ IN PIRP Irp,
+ IN PUNICODE_STRING Name)
+{
+ PIO_STACK_LOCATION IoStack;
+ KIRQL OldIrql;
+ NTSTATUS Status;
+ PNP_WAIT_QUEUE_ENTRY WaitEntry;
+ PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer;
+ LARGE_INTEGER DueTime;
+ ULONG i;
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ WaitEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(*WaitEntry), 'wFpN');
+ if ( WaitEntry )
+ {
+ KeInitializeDpc(&WaitEntry->Dpc, NpTimerDispatch, WaitEntry);
+ KeInitializeTimer(&WaitEntry->Timer);
+
+ if ( Name )
+ {
+ WaitEntry->String = *Name;
+ }
+ else
+ {
+ WaitEntry->String.Length = 0;
+ WaitEntry->String.Buffer = 0;
+ }
+
+ WaitEntry->WaitQueue = WaitQueue;
+ WaitEntry->Irp = Irp;
+
+ WaitBuffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+ if ( WaitBuffer->TimeoutSpecified )
+ {
+ DueTime = WaitBuffer->Timeout;
+ }
+ else
+ {
+ DueTime = WaitTime;
+ }
+
+ for (i = 0; i < WaitBuffer->NameLength / sizeof(WCHAR); i++)
+ {
+ WaitBuffer->Name[i] = RtlUpcaseUnicodeChar(WaitBuffer->Name[i]);
+ }
+
+ Irp->Tail.Overlay.DriverContext[0] = WaitQueue;
+ Irp->Tail.Overlay.DriverContext[1] = WaitEntry;
+ OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
+
+ IoSetCancelRoutine(Irp, NpCancelWaitQueueIrp);
+
+ if ( Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
+ {
+ Status = STATUS_CANCELLED;
+ }
+ else
+ {
+ InsertTailList(&WaitQueue->WaitList, &Irp->Tail.Overlay.ListEntry);
+
+ IoMarkIrpPending(Irp);
+ Status = STATUS_PENDING;
+
+ WaitEntry->FileObject = IoStack->FileObject;
+ ObfReferenceObject(WaitEntry->FileObject);
+
+ KeSetTimer(&WaitEntry->Timer, DueTime, &WaitEntry->Dpc);
+ WaitEntry = NULL;
+
+ }
+ KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
+ if ( WaitEntry ) ExFreePool(WaitEntry);
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ return Status;
+}
--- /dev/null
+#include "npfs.h"
+
+LONG NpSlowWriteCalls;
+
+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, ServerSide;
+ PNP_CCB Ccb;
+ PNP_NONPAGED_CCB NonPagedCcb;
+ PNP_DATA_QUEUE WriteQueue;
+ NTSTATUS Status;
+ PNP_EVENT_BUFFER EventBuffer;
+ ULONG BytesWritten;
+ PAGED_CODE();
+
+ IoStatus->Information = 0;
+ NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &ServerSide);
+
+ 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);
+
+ // ms_exc.registration.TryLevel = 0;
+
+ if ( Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE )
+ {
+ IoStatus->Status = STATUS_PIPE_DISCONNECTED;
+ WriteOk = TRUE;
+ goto Quickie;
+ }
+
+ if ( Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE || Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE )
+ {
+ IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_LISTENING_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_CLOSING;
+ WriteOk = TRUE;
+ goto Quickie;
+ }
+
+ ASSERT(Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE);
+
+ if ((ServerSide == 1 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND) ||
+ (ServerSide == 0 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND))
+ {
+ IoStatus->Status = STATUS_INVALID_PARAMETER;
+ WriteOk = TRUE;
+ goto Quickie;
+ }
+
+ IoStatus->Status = 0;
+ IoStatus->Information = DataSize;
+
+ if ( ServerSide == 1 )
+ {
+ WriteQueue = &Ccb->OutQueue;
+ EventBuffer = NonPagedCcb->EventBufferClient;
+ }
+ else
+ {
+ WriteQueue = &Ccb->InQueue;
+ EventBuffer = NonPagedCcb->EventBufferServer;
+ }
+
+ if (WriteQueue->QueueState != ReadEntries ||
+ WriteQueue->BytesInQueue >= DataSize ||
+ WriteQueue->Quota >= DataSize - WriteQueue->BytesInQueue )
+ {
+ if (WriteQueue->QueueState != ReadEntries ||
+ WriteQueue->Quota - WriteQueue->QuotaUsed >= DataSize )
+ {
+ goto DoWrite;
+ }
+ }
+
+ if (Ccb->Fcb->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE &&
+ Ccb->ServerCompletionMode & FILE_PIPE_COMPLETE_OPERATION)
+ {
+ IoStatus->Information = 0;
+ IoStatus->Status = 0;
+ WriteOk = TRUE;
+ goto Quickie;
+ }
+
+ if (!Irp )
+ {
+ WriteOk = 0;
+ goto Quickie;
+ }
+
+DoWrite:
+ Status = NpWriteDataQueue(WriteQueue,
+ ServerSide ? Ccb->ClientReadMode : Ccb->ServerReadMode,
+ Buffer,
+ DataSize,
+ Ccb->Fcb->NamedPipeType,
+ &BytesWritten,
+ Ccb,
+ ServerSide,
+ Thread,
+ List);
+ IoStatus->Status = Status;
+ if ( Status == STATUS_MORE_PROCESSING_REQUIRED )
+ {
+ ASSERT(WriteQueue->QueueState != ReadEntries);
+ if ( (Ccb->ServerCompletionMode & FILE_PIPE_COMPLETE_OPERATION || !Irp)
+ && WriteQueue->Quota - WriteQueue->QuotaUsed < BytesWritten )
+ {
+ IoStatus->Information = DataSize - BytesWritten;
+ IoStatus->Status = 0;
+ }
+ else
+ {
+ ASSERT(WriteQueue->QueueState != ReadEntries);
+
+ IoStatus->Status = NpAddDataQueueEntry(ServerSide,
+ Ccb,
+ WriteQueue,
+ WriteEntries,
+ 0,
+ DataSize,
+ Irp,
+ Buffer,
+ DataSize - BytesWritten);
+ }
+ }
+
+ if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+ WriteOk = 1;
+
+Quickie:
+ //ms_exc.registration.TryLevel = -1;
+ 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 List;
+ PLIST_ENTRY NextEntry, ThisEntry;
+ PAGED_CODE();
+ NpSlowWriteCalls++;
+
+ InitializeListHead(&List);
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ FsRtlEnterFileSystem();
+ ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+ NpCommonWrite(IoStack->FileObject,
+ Irp->UserBuffer,
+ IoStack->Parameters.Write.Length,
+ Irp->Tail.Overlay.Thread,
+ &IoStatus,
+ Irp,
+ &List);
+
+ ExReleaseResourceLite(&NpVcb->Lock);
+
+ NextEntry = List.Flink;
+ while (NextEntry != &List)
+ {
+ ThisEntry = NextEntry;
+ NextEntry = NextEntry->Flink;
+
+ Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ }
+
+ 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;
+}
+
--- /dev/null
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
+ IN ULONG Mode,
+ IN PVOID OutBuffer,
+ IN ULONG OutBufferSize,
+ IN ULONG PipeType,
+ OUT PULONG BytesWritten,
+ IN PNP_CCB Ccb,
+ IN BOOLEAN ServerSide,
+ 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();
+
+ *BytesWritten = OutBufferSize;
+
+ MoreProcessing = 1;
+ if ( PipeType != FILE_PIPE_OUTBOUND || (OutBufferSize) ) MoreProcessing = 0;
+
+ for (DataEntry = NpGetNextRealDataQueueEntry(WriteQueue, List);
+ ((WriteQueue->QueueState == ReadEntries) &&
+ ((*BytesWritten > 0) || (MoreProcessing)));
+ DataEntry = NpGetNextRealDataQueueEntry(WriteQueue, List))
+ {
+ DataSize = DataEntry->DataSize;
+
+ IoStack = IoGetCurrentIrpStackLocation( DataEntry->Irp);
+
+ if ( IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
+ IoStack->Parameters.FileSystemControl.FsControlCode == FSCTL_PIPE_INTERNAL_WRITE &&
+ (DataSize < OutBufferSize || MoreProcessing) )
+ {
+ WriteIrp = NpRemoveDataQueueEntry(WriteQueue, 1, 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 = *BytesWritten;
+ if ( BufferSize >= DataSize ) BufferSize = DataSize;
+
+ if ( DataEntry->DataEntryType != Unbuffered && BufferSize )
+ {
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, 'RFpN');
+ if ( !Buffer ) return STATUS_INSUFFICIENT_RESOURCES;
+ AllocatedBuffer = 1;
+ }
+ else
+ {
+ Buffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
+ AllocatedBuffer = 0;
+ }
+
+ _SEH2_TRY
+ {
+ RtlCopyMemory(Buffer,
+ (PVOID)((ULONG_PTR)OutBuffer + OutBufferSize - *BytesWritten),
+ BufferSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ASSERT(FALSE);
+ }
+ _SEH2_END;
+
+ if ( !HaveContext )
+ {
+ HaveContext = 1;
+ Status = NpGetClientSecurityContext(ServerSide, Ccb, Thread, &ClientContext);
+ if (!NT_SUCCESS(Status))
+ {
+ if ( AllocatedBuffer ) ExFreePool(Buffer);
+ return Status;
+ }
+
+ if ( ClientContext )
+ {
+ NpFreeClientSecurityContext(Ccb->ClientContext);
+ Ccb->ClientContext = ClientContext;
+ }
+ }
+
+ WriteIrp = NpRemoveDataQueueEntry(WriteQueue, 1, List);
+ if ( WriteIrp )
+ {
+ *BytesWritten -= BufferSize;
+ WriteIrp->IoStatus.Information = BufferSize;
+
+ if ( AllocatedBuffer )
+ {
+ WriteIrp->AssociatedIrp.SystemBuffer = Buffer;
+ WriteIrp->Flags |= IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
+ }
+
+ if ( !*BytesWritten )
+ {
+ MoreProcessing = 0;
+ WriteIrp->IoStatus.Status = 0;
+ InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
+ continue;
+ }
+
+ if ( Mode == FILE_PIPE_MESSAGE_MODE )
+ {
+ WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ WriteIrp->IoStatus.Status = 0;
+ }
+
+ InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
+ }
+ else if ( AllocatedBuffer )
+ {
+ ExFreePool(Buffer);
+ }
+ }
+
+ if ( *BytesWritten > 0 || MoreProcessing )
+ {
+ ASSERT(WriteQueue->QueueState != ReadEntries);
+ Status = STATUS_MORE_PROCESSING_REQUIRED;
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ return Status;
+}
+