[NPFS-NEW]: Implement Close, Cleanup, Disconnect, Flush, Listen, Peek, SetInfo, Transceive, Wait, Write. Only QueryInfo remains as critical functionality to support the Kernel32 APIs. Code is WIP, untested, and ugly! But it is now 90% complete. r60000 should hopefully finalize the implementation. As long as I didn't forget a file :)

svn path=/trunk/; revision=59999
This commit is contained in:
Alex Ionescu 2013-09-10 02:23:32 +00:00
parent b5edd2ce20
commit 3dfdce74d8
14 changed files with 2057 additions and 106 deletions

View file

@ -1,8 +1,13 @@
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
@ -10,7 +15,9 @@ list(APPEND SOURCE
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)

View file

@ -0,0 +1,73 @@
#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;
}

View file

@ -0,0 +1,68 @@
#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;
}

View file

@ -0,0 +1,178 @@
#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;
}

View file

@ -0,0 +1,68 @@
#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;
}

View file

@ -0,0 +1,692 @@
#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;
}

View file

@ -4,8 +4,8 @@ PDEVICE_OBJECT NpfsDeviceObject;
NTSTATUS
NTAPI
NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
NpFsdSetSecurity(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
@ -18,36 +18,8 @@ NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
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)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
NpFsdQuerySecurity(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
@ -72,34 +44,6 @@ NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
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,
@ -114,20 +58,6 @@ 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,
@ -152,14 +82,12 @@ 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,

View file

@ -82,6 +82,19 @@ typedef struct _NP_WAIT_QUEUE
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
//
@ -225,6 +238,11 @@ typedef struct _NP_VCB
extern PNP_VCB NpVcb;
BOOLEAN
NTAPI
NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer);
VOID
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue);
@ -320,12 +338,47 @@ NTAPI
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);
@ -386,6 +439,13 @@ NpCheckForNotify(IN PNP_DCB Dcb,
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,
@ -405,8 +465,43 @@ NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
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);

View file

@ -12,7 +12,6 @@ NpCommonRead(IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List)
{
NODE_TYPE_CODE NodeType;
ULONG NamedPipeConfiguation;
PNP_DATA_QUEUE Queue;
PNP_EVENT_BUFFER EventBuffer;
NTSTATUS Status;
@ -51,10 +50,8 @@ NpCommonRead(IN PFILE_OBJECT FileObject,
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;
@ -109,30 +106,32 @@ NpCommonRead(IN PFILE_OBJECT FileObject,
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);
@ -182,7 +181,7 @@ NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
{
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;

View file

@ -1,5 +1,22 @@
#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,
@ -37,3 +54,316 @@ 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;
}

View file

@ -37,8 +37,10 @@ NTAPI
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

View file

@ -1,5 +1,76 @@
#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)
@ -33,3 +104,88 @@ NpCancelWaiter(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;
}

View file

@ -0,0 +1,204 @@
#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;
}

View file

@ -0,0 +1,151 @@
#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;
}