- Put the wait entry into the DriverContext of the irp instead to allocated it from pool.

- Lock the data list on both ends of the pipe, if we disconnect the pipe.    
- Implemented a read and a write event on each end of the pipe.  
- Implemented a list for read requests to deliver the requests in the correct sequence.  
- Do not end a read request if the pipe was connected and if the buffer wasn't filled completely.

svn path=/trunk/; revision=14372
This commit is contained in:
Hartmut Birr 2005-03-28 18:42:53 +00:00
parent 9b5646acd0
commit a48a01798c
5 changed files with 514 additions and 310 deletions

View file

@ -50,20 +50,21 @@ NpfsFindListeningServerInstance(PNPFS_PIPE Pipe)
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PNPFS_WAITER_ENTRY Waiter; PNPFS_WAITER_ENTRY Waiter;
KIRQL oldIrql; KIRQL oldIrql;
PIRP Irp;
CurrentEntry = Pipe->WaiterListHead.Flink; CurrentEntry = Pipe->WaiterListHead.Flink;
while (CurrentEntry != &Pipe->WaiterListHead) while (CurrentEntry != &Pipe->WaiterListHead)
{ {
Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry); Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
if (Waiter->Fcb->PipeState == FILE_PIPE_LISTENING_STATE && Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
!Waiter->Irp->Cancel) if (Waiter->Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{ {
DPRINT("Server found! Fcb %p\n", Waiter->Fcb); DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
IoAcquireCancelSpinLock(&oldIrql); IoAcquireCancelSpinLock(&oldIrql);
if (!Waiter->Irp->Cancel) if (!Irp->Cancel)
{ {
IoSetCancelRoutine(Waiter->Irp, NULL); IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(oldIrql); IoReleaseCancelSpinLock(oldIrql);
return Waiter->Fcb; return Waiter->Fcb;
} }
@ -83,6 +84,7 @@ NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
{ {
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PNPFS_WAITER_ENTRY Waiter; PNPFS_WAITER_ENTRY Waiter;
PIRP Irp;
CurrentEntry = Pipe->WaiterListHead.Flink; CurrentEntry = Pipe->WaiterListHead.Flink;
while (CurrentEntry != &Pipe->WaiterListHead) while (CurrentEntry != &Pipe->WaiterListHead)
@ -92,13 +94,12 @@ NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
{ {
DPRINT("Server found! Fcb %p\n", Waiter->Fcb); DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
Waiter->Irp->IoStatus.Status = STATUS_PIPE_CONNECTED;
Waiter->Irp->IoStatus.Information = 0;
IoCompleteRequest(Waiter->Irp, IO_NO_INCREMENT);
RemoveEntryList(&Waiter->Entry); RemoveEntryList(&Waiter->Entry);
ExFreePool(Waiter); Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
return; Irp->IoStatus.Status = STATUS_PIPE_CONNECTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
} }
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
} }
@ -175,6 +176,9 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END; ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END;
ClientFcb->OtherSide = NULL; ClientFcb->OtherSide = NULL;
ClientFcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE; ClientFcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
InitializeListHead(&ClientFcb->ReadRequestListHead);
DPRINT("Fcb: %x\n", ClientFcb);
/* Initialize data list. */ /* Initialize data list. */
if (Pipe->OutboundQuota) if (Pipe->OutboundQuota)
@ -202,7 +206,9 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
ClientFcb->MaxDataLength = Pipe->OutboundQuota; ClientFcb->MaxDataLength = Pipe->OutboundQuota;
ExInitializeFastMutex(&ClientFcb->DataListLock); ExInitializeFastMutex(&ClientFcb->DataListLock);
KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientFcb->Event, SynchronizationEvent, FALSE); KeInitializeEvent(&ClientFcb->ReadEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientFcb->WriteEvent, SynchronizationEvent, FALSE);
/* /*
* Step 3. Search for listening server FCB. * Step 3. Search for listening server FCB.
@ -489,6 +495,7 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
Fcb->ReadDataAvailable = 0; Fcb->ReadDataAvailable = 0;
Fcb->WriteQuotaAvailable = Pipe->InboundQuota; Fcb->WriteQuotaAvailable = Pipe->InboundQuota;
Fcb->MaxDataLength = Pipe->InboundQuota; Fcb->MaxDataLength = Pipe->InboundQuota;
InitializeListHead(&Fcb->ReadRequestListHead);
ExInitializeFastMutex(&Fcb->DataListLock); ExInitializeFastMutex(&Fcb->DataListLock);
Pipe->CurrentInstances++; Pipe->CurrentInstances++;
@ -498,13 +505,11 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
Fcb->PipeState = FILE_PIPE_LISTENING_STATE; Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
Fcb->OtherSide = NULL; Fcb->OtherSide = NULL;
KeInitializeEvent(&Fcb->ConnectEvent, DPRINT("Fcb: %x\n", Fcb);
SynchronizationEvent,
FALSE);
KeInitializeEvent(&Fcb->Event, KeInitializeEvent(&Fcb->ConnectEvent, SynchronizationEvent, FALSE);
SynchronizationEvent, KeInitializeEvent(&Fcb->ReadEvent, SynchronizationEvent, FALSE);
FALSE); KeInitializeEvent(&Fcb->WriteEvent, SynchronizationEvent, FALSE);
KeLockMutex(&Pipe->FcbListLock); KeLockMutex(&Pipe->FcbListLock);
InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry); InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
@ -528,7 +533,7 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
PNPFS_DEVICE_EXTENSION DeviceExt; PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PNPFS_FCB Fcb; PNPFS_FCB Fcb, OtherSide;
PNPFS_PIPE Pipe; PNPFS_PIPE Pipe;
BOOL Server; BOOL Server;
@ -566,18 +571,37 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
{ {
DPRINT("Client\n"); DPRINT("Client\n");
} }
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{ {
if (Fcb->OtherSide) OtherSide = Fcb->OtherSide;
/* Lock the server first */
if (Server)
{ {
Fcb->OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE; ExAcquireFastMutex(&Fcb->DataListLock);
Fcb->OtherSide->OtherSide = NULL; ExAcquireFastMutex(&OtherSide->DataListLock);
}
else
{
ExAcquireFastMutex(&OtherSide->DataListLock);
ExAcquireFastMutex(&Fcb->DataListLock);
}
OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
OtherSide->OtherSide = NULL;
/* /*
* Signaling the write event. If is possible that an other * Signaling the write event. If is possible that an other
* thread waits for an empty buffer. * thread waits for an empty buffer.
*/ */
KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
if (Server)
{
ExReleaseFastMutex(&Fcb->DataListLock);
ExReleaseFastMutex(&OtherSide->DataListLock);
}
else
{
ExReleaseFastMutex(&OtherSide->DataListLock);
ExReleaseFastMutex(&Fcb->DataListLock);
} }
} }
else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE) else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
@ -586,6 +610,7 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
PNPFS_WAITER_ENTRY WaitEntry = NULL; PNPFS_WAITER_ENTRY WaitEntry = NULL;
BOOLEAN Complete = FALSE; BOOLEAN Complete = FALSE;
KIRQL oldIrql; KIRQL oldIrql;
PIRP tmpIrp;
Entry = Fcb->Pipe->WaiterListHead.Flink; Entry = Fcb->Pipe->WaiterListHead.Flink;
while (Entry != &Fcb->Pipe->WaiterListHead) while (Entry != &Fcb->Pipe->WaiterListHead)
@ -594,28 +619,25 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
if (WaitEntry->Fcb == Fcb) if (WaitEntry->Fcb == Fcb)
{ {
RemoveEntryList(Entry); RemoveEntryList(Entry);
tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
IoAcquireCancelSpinLock(&oldIrql); IoAcquireCancelSpinLock(&oldIrql);
if (!Irp->Cancel) if (!tmpIrp->Cancel)
{ {
IoSetCancelRoutine(WaitEntry->Irp, NULL); IoSetCancelRoutine(tmpIrp, NULL);
Complete = TRUE; Complete = TRUE;
} }
IoReleaseCancelSpinLock(oldIrql); IoReleaseCancelSpinLock(oldIrql);
if (Complete)
{
tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
tmpIrp->IoStatus.Information = 0;
IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
}
break; break;
} }
Entry = Entry->Flink; Entry = Entry->Flink;
} }
if (Entry != &Fcb->Pipe->WaiterListHead)
{
if (Complete)
{
WaitEntry->Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
WaitEntry->Irp->IoStatus.Information = 0;
IoCompleteRequest(WaitEntry->Irp, IO_NO_INCREMENT);
}
ExFreePool(WaitEntry);
}
} }
Fcb->PipeState = FILE_PIPE_CLOSING_STATE; Fcb->PipeState = FILE_PIPE_CLOSING_STATE;

View file

@ -26,18 +26,18 @@ NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
DPRINT1("NpfsListeningCancelRoutine() called\n"); DPRINT1("NpfsListeningCancelRoutine() called\n");
Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
IoReleaseCancelSpinLock(Irp->CancelIrql); IoReleaseCancelSpinLock(Irp->CancelIrql);
Waiter = Irp->Tail.Overlay.DriverContext[0];
KeLockMutex(&Waiter->Pipe->FcbListLock); KeLockMutex(&Waiter->Fcb->Pipe->FcbListLock);
RemoveEntryList(&Waiter->Entry); RemoveEntryList(&Waiter->Entry);
KeUnlockMutex(&Waiter->Pipe->FcbListLock); KeUnlockMutex(&Waiter->Fcb->Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
ExFreePool(Waiter);
} }
@ -48,18 +48,13 @@ NpfsAddListeningServerInstance(PIRP Irp,
PNPFS_WAITER_ENTRY Entry; PNPFS_WAITER_ENTRY Entry;
KIRQL oldIrql; KIRQL oldIrql;
Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY)); Entry = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
if (Entry == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
Entry->Irp = Irp;
Entry->Fcb = Fcb; Entry->Fcb = Fcb;
Entry->Pipe = Fcb->Pipe;
KeLockMutex(&Fcb->Pipe->FcbListLock); KeLockMutex(&Fcb->Pipe->FcbListLock);
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
Irp->Tail.Overlay.DriverContext[0] = Entry;
InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry); InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
IoAcquireCancelSpinLock(&oldIrql); IoAcquireCancelSpinLock(&oldIrql);
@ -78,7 +73,6 @@ NpfsAddListeningServerInstance(PIRP Irp,
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeUnlockMutex(&Fcb->Pipe->FcbListLock); KeUnlockMutex(&Fcb->Pipe->FcbListLock);
ExFreePool(Entry);
return STATUS_CANCELLED; return STATUS_CANCELLED;
} }
@ -173,38 +167,100 @@ NpfsConnectPipe(PIRP Irp,
static NTSTATUS static NTSTATUS
NpfsDisconnectPipe(PNPFS_FCB Fcb) NpfsDisconnectPipe(PNPFS_FCB Fcb)
{ {
NTSTATUS Status;
PNPFS_FCB OtherSide;
PNPFS_PIPE Pipe;
BOOL Server;
DPRINT("NpfsDisconnectPipe()\n"); DPRINT("NpfsDisconnectPipe()\n");
Pipe = Fcb->Pipe;
KeLockMutex(&Pipe->FcbListLock);
if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE) if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
return STATUS_SUCCESS;
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{ {
Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; DPRINT("Pipe is already disconnected\n");
/* FIXME: Shouldn't this be FILE_PIPE_CLOSING_STATE? */ Status = STATUS_SUCCESS;
Fcb->OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE; }
else if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
/* FIXME: remove data queue(s) */ {
Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
Fcb->OtherSide->OtherSide = NULL; OtherSide = Fcb->OtherSide;
Fcb->OtherSide = NULL; Fcb->OtherSide = NULL;
/* Lock the server first */
if (Server)
{
ExAcquireFastMutex(&Fcb->DataListLock);
ExAcquireFastMutex(&OtherSide->DataListLock);
}
else
{
ExAcquireFastMutex(&OtherSide->DataListLock);
ExAcquireFastMutex(&Fcb->DataListLock);
}
OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
OtherSide->OtherSide = NULL;
/*
* Signaling the write event. If is possible that an other
* thread waits for an empty buffer.
*/
KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
if (Server)
{
ExReleaseFastMutex(&Fcb->DataListLock);
ExReleaseFastMutex(&OtherSide->DataListLock);
}
else
{
ExReleaseFastMutex(&OtherSide->DataListLock);
ExReleaseFastMutex(&OtherSide->DataListLock);
}
Status = STATUS_SUCCESS;
}
else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{
PLIST_ENTRY Entry;
PNPFS_WAITER_ENTRY WaitEntry = NULL;
BOOLEAN Complete = FALSE;
PIRP Irp = NULL;
DPRINT("Pipe disconnected\n"); Entry = Fcb->Pipe->WaiterListHead.Flink;
return STATUS_SUCCESS; while (Entry != &Fcb->Pipe->WaiterListHead)
{
WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
if (WaitEntry->Fcb == Fcb)
{
RemoveEntryList(Entry);
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext);
Complete = (NULL == IoSetCancelRoutine(Irp, NULL));
break;
}
Entry = Entry->Flink;
} }
if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE) if (Irp)
{ {
Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; if (Complete)
Fcb->OtherSide = NULL; {
Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
/* FIXME: remove data queue(s) */ Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT("Pipe disconnected\n");
return STATUS_SUCCESS;
} }
}
return STATUS_UNSUCCESSFUL; Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
Status = STATUS_SUCCESS;
}
else if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
{
Status = STATUS_PIPE_CLOSING;
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
KeUnlockMutex(&Pipe->FcbListLock);
return Status;
} }

View file

@ -28,6 +28,9 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
DPRINT("Named Pipe FSD 0.0.2\n"); DPRINT("Named Pipe FSD 0.0.2\n");
ASSERT (sizeof(NPFS_CONTEXT) <= sizeof (((PIRP)NULL)->Tail.Overlay.DriverContext));
ASSERT (sizeof(NPFS_WAITER_ENTRY) <= sizeof(((PIRP)NULL)->Tail.Overlay.DriverContext));
DriverObject->MajorFunction[IRP_MJ_CREATE] = NpfsCreate; DriverObject->MajorFunction[IRP_MJ_CREATE] = NpfsCreate;
DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] =
NpfsCreateNamedPipe; NpfsCreateNamedPipe;
@ -74,8 +77,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
DeviceExtension = DeviceObject->DeviceExtension; DeviceExtension = DeviceObject->DeviceExtension;
InitializeListHead(&DeviceExtension->PipeListHead); InitializeListHead(&DeviceExtension->PipeListHead);
InitializeListHead(&DeviceExtension->ThreadListHead); InitializeListHead(&DeviceExtension->ThreadListHead);
KeInitializeMutex(&DeviceExtension->PipeListLock, KeInitializeMutex(&DeviceExtension->PipeListLock, 0);
0);
DeviceExtension->EmptyWaiterCount = 0; DeviceExtension->EmptyWaiterCount = 0;
/* set the size quotas */ /* set the size quotas */

View file

@ -42,12 +42,15 @@ typedef struct _NPFS_FCB
struct ETHREAD *Thread; struct ETHREAD *Thread;
PNPFS_PIPE Pipe; PNPFS_PIPE Pipe;
KEVENT ConnectEvent; KEVENT ConnectEvent;
KEVENT Event; KEVENT ReadEvent;
KEVENT WriteEvent;
ULONG PipeEnd; ULONG PipeEnd;
ULONG PipeState; ULONG PipeState;
ULONG ReadDataAvailable; ULONG ReadDataAvailable;
ULONG WriteQuotaAvailable; ULONG WriteQuotaAvailable;
LIST_ENTRY ReadRequestListHead;
PVOID Data; PVOID Data;
PVOID ReadPtr; PVOID ReadPtr;
PVOID WritePtr; PVOID WritePtr;
@ -58,11 +61,8 @@ typedef struct _NPFS_FCB
typedef struct _NPFS_CONTEXT typedef struct _NPFS_CONTEXT
{ {
PDEVICE_OBJECT DeviceObject; LIST_ENTRY ListEntry;
PIRP Irp; PKEVENT WaitEvent;
PNPFS_FCB Fcb;
UCHAR MajorFunction;
BOOLEAN AllocatedFromPool;
} NPFS_CONTEXT, *PNPFS_CONTEXT; } NPFS_CONTEXT, *PNPFS_CONTEXT;
typedef struct _NPFS_THREAD_CONTEXT typedef struct _NPFS_THREAD_CONTEXT
@ -73,14 +73,12 @@ typedef struct _NPFS_THREAD_CONTEXT
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
PVOID WaitObjectArray[MAXIMUM_WAIT_OBJECTS]; PVOID WaitObjectArray[MAXIMUM_WAIT_OBJECTS];
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS]; KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
PNPFS_CONTEXT WaitContextArray[MAXIMUM_WAIT_OBJECTS]; PIRP WaitIrpArray[MAXIMUM_WAIT_OBJECTS];
} NPFS_THREAD_CONTEXT, *PNPFS_THREAD_CONTEXT; } NPFS_THREAD_CONTEXT, *PNPFS_THREAD_CONTEXT;
typedef struct _NPFS_WAITER_ENTRY typedef struct _NPFS_WAITER_ENTRY
{ {
LIST_ENTRY Entry; LIST_ENTRY Entry;
PIRP Irp;
PNPFS_PIPE Pipe;
PNPFS_FCB Fcb; PNPFS_FCB Fcb;
} NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY; } NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY;

View file

@ -46,61 +46,90 @@ VOID HexDump(PUCHAR Buffer, ULONG Length)
} }
#endif #endif
static NTSTATUS
NpfsReadFromPipe(PNPFS_CONTEXT Context);
static VOID STDCALL static VOID STDCALL
NpfsWaitingCancelRoutine(IN PDEVICE_OBJECT DeviceObject, NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PNPFS_CONTEXT Context; PNPFS_CONTEXT Context;
PNPFS_DEVICE_EXTENSION DeviceExt; PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
PNPFS_FCB Fcb;
BOOLEAN Complete = FALSE;
DPRINT1("NpfsWaitingCancelRoutine() called\n"); DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
IoReleaseCancelSpinLock(Irp->CancelIrql); IoReleaseCancelSpinLock(Irp->CancelIrql);
Context = Irp->Tail.Overlay.DriverContext[0]; Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
DeviceExt = Context->DeviceObject->DeviceExtension; DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
Fcb = IoStack->FileObject->FsContext;
KeLockMutex(&DeviceExt->PipeListLock); KeLockMutex(&DeviceExt->PipeListLock);
KeSetEvent(&Context->Fcb->Event, IO_NO_INCREMENT, FALSE); ExAcquireFastMutex(&Fcb->DataListLock);
switch(IoStack->MajorFunction)
{
case IRP_MJ_READ:
if (Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
/* we are not the first in the list, remove an complete us */
RemoveEntryList(&Context->ListEntry);
Complete = TRUE;
}
else
{
KeSetEvent(&Fcb->ReadEvent, IO_NO_INCREMENT, FALSE);
}
break;
default:
KEBUGCHECK(0);
}
ExReleaseFastMutex(&Fcb->DataListLock);
KeUnlockMutex(&DeviceExt->PipeListLock); KeUnlockMutex(&DeviceExt->PipeListLock);
if (Complete)
{
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
} }
static VOID STDCALL static VOID STDCALL
NpfsWaiterThread(PVOID Context) NpfsWaiterThread(PVOID InitContext)
{ {
PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) Context; PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
ULONG CurrentCount, Count = 0; ULONG CurrentCount;
PNPFS_CONTEXT WaitContext = NULL; ULONG Count = 0;
PIRP Irp = NULL;
PIRP NextIrp;
NTSTATUS Status; NTSTATUS Status;
BOOLEAN Terminate = FALSE; BOOLEAN Terminate = FALSE;
BOOLEAN Cancel = FALSE; BOOLEAN Cancel = FALSE;
KIRQL oldIrql; PIO_STACK_LOCATION IoStack = NULL;
PNPFS_CONTEXT Context;
PNPFS_CONTEXT NextContext;
PNPFS_FCB Fcb;
KeLockMutex(&ThreadContext->DeviceExt->PipeListLock); KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
while (1) while (1)
{ {
CurrentCount = ThreadContext->Count; CurrentCount = ThreadContext->Count;
KeResetEvent(&ThreadContext->Event);
KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock); KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock);
if (WaitContext) if (Irp)
{ {
if (Cancel) if (Cancel)
{ {
WaitContext->Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Status = STATUS_CANCELLED;
WaitContext->Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoCompleteRequest(WaitContext->Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
ExFreePool(WaitContext);
} }
else else
{ {
switch (WaitContext->MajorFunction) switch (IoStack->MajorFunction)
{ {
case IRP_MJ_READ: case IRP_MJ_READ:
NpfsReadFromPipe(WaitContext); NpfsRead(IoStack->DeviceObject, Irp);
break; break;
default: default:
KEBUGCHECK(0); KEBUGCHECK(0);
@ -119,28 +148,54 @@ NpfsWaiterThread(PVOID Context)
FALSE, FALSE,
NULL, NULL,
ThreadContext->WaitBlockArray); ThreadContext->WaitBlockArray);
KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
KEBUGCHECK(0); KEBUGCHECK(0);
} }
KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
Count = Status - STATUS_SUCCESS; Count = Status - STATUS_SUCCESS;
ASSERT (Count <= CurrentCount); ASSERT (Count < CurrentCount);
if (Count > 0) if (Count > 0)
{ {
WaitContext = ThreadContext->WaitContextArray[Count]; Irp = ThreadContext->WaitIrpArray[Count];
ThreadContext->Count--; ThreadContext->Count--;
ThreadContext->DeviceExt->EmptyWaiterCount++; ThreadContext->DeviceExt->EmptyWaiterCount++;
ThreadContext->WaitObjectArray[Count] = ThreadContext->WaitObjectArray[ThreadContext->Count]; ThreadContext->WaitObjectArray[Count] = ThreadContext->WaitObjectArray[ThreadContext->Count];
ThreadContext->WaitContextArray[Count] = ThreadContext->WaitContextArray[ThreadContext->Count]; ThreadContext->WaitIrpArray[Count] = ThreadContext->WaitIrpArray[ThreadContext->Count];
IoAcquireCancelSpinLock(&oldIrql);
Cancel = NULL == IoSetCancelRoutine(WaitContext->Irp, NULL); Cancel = (NULL == IoSetCancelRoutine(Irp, NULL));
IoReleaseCancelSpinLock(oldIrql); Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (Cancel)
{
Fcb = IoStack->FileObject->FsContext;
ExAcquireFastMutex(&Fcb->DataListLock);
RemoveEntryList(&Context->ListEntry);
switch (IoStack->MajorFunction)
{
case IRP_MJ_READ:
if (!IsListEmpty(&Fcb->ReadRequestListHead))
{
/* put the next request on the wait list */
NextContext = CONTAINING_RECORD(Fcb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
ThreadContext->WaitObjectArray[ThreadContext->Count] = NextContext->WaitEvent;
NextIrp = CONTAINING_RECORD(NextContext, IRP, Tail.Overlay.DriverContext);
ThreadContext->WaitIrpArray[ThreadContext->Count] = NextIrp;
ThreadContext->Count++;
ThreadContext->DeviceExt->EmptyWaiterCount--;
}
break;
default:
KEBUGCHECK(0);
}
ExReleaseFastMutex(&Fcb->DataListLock);
}
} }
else else
{ {
/* someone has add a new wait request */ /* someone has add a new wait request */
WaitContext = NULL; Irp = NULL;
} }
if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS) if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
{ {
@ -155,14 +210,20 @@ NpfsWaiterThread(PVOID Context)
} }
static NTSTATUS static NTSTATUS
NpfsAddWaitingReader(PNPFS_DEVICE_EXTENSION DeviceExt, PNPFS_CONTEXT Context, PNPFS_FCB Fcb) NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{ {
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
PNPFS_THREAD_CONTEXT ThreadContext; PNPFS_THREAD_CONTEXT ThreadContext = NULL;
NTSTATUS Status; NTSTATUS Status;
HANDLE hThread; HANDLE hThread;
KIRQL oldIrql; KIRQL oldIrql;
PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
PNPFS_DEVICE_EXTENSION DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;;
DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
KeLockMutex(&DeviceExt->PipeListLock); KeLockMutex(&DeviceExt->PipeListLock);
ListEntry = DeviceExt->ThreadListHead.Flink; ListEntry = DeviceExt->ThreadListHead.Flink;
@ -184,12 +245,12 @@ NpfsAddWaitingReader(PNPFS_DEVICE_EXTENSION DeviceExt, PNPFS_CONTEXT Context, PN
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
ThreadContext->DeviceExt = DeviceExt; ThreadContext->DeviceExt = DeviceExt;
KeInitializeEvent(&ThreadContext->Event, NotificationEvent, FALSE); KeInitializeEvent(&ThreadContext->Event, SynchronizationEvent, FALSE);
ThreadContext->Count = 1; ThreadContext->Count = 1;
ThreadContext->WaitObjectArray[0] = &ThreadContext->Event; ThreadContext->WaitObjectArray[0] = &ThreadContext->Event;
DPRINT("Creating a new system thread for waiting read requests\n"); DPRINT("Creating a new system thread for waiting read/write requests\n");
Status = PsCreateSystemThread(&hThread, Status = PsCreateSystemThread(&hThread,
THREAD_ALL_ACCESS, THREAD_ALL_ACCESS,
@ -207,21 +268,20 @@ NpfsAddWaitingReader(PNPFS_DEVICE_EXTENSION DeviceExt, PNPFS_CONTEXT Context, PN
InsertHeadList(&DeviceExt->ThreadListHead, &ThreadContext->ListEntry); InsertHeadList(&DeviceExt->ThreadListHead, &ThreadContext->ListEntry);
DeviceExt->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1; DeviceExt->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1;
} }
IoMarkIrpPending(Context->Irp); IoMarkIrpPending(Irp);
Context->Irp->Tail.Overlay.DriverContext[0] = Context;
IoAcquireCancelSpinLock(&oldIrql); IoAcquireCancelSpinLock(&oldIrql);
if (Context->Irp->Cancel) if (Irp->Cancel)
{ {
IoReleaseCancelSpinLock(oldIrql); IoReleaseCancelSpinLock(oldIrql);
Status = STATUS_CANCELLED; Status = STATUS_CANCELLED;
} }
else else
{ {
IoSetCancelRoutine(Context->Irp, NpfsWaitingCancelRoutine); IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine);
IoReleaseCancelSpinLock(oldIrql); IoReleaseCancelSpinLock(oldIrql);
ThreadContext->WaitObjectArray[ThreadContext->Count] = &Fcb->Event; ThreadContext->WaitObjectArray[ThreadContext->Count] = Context->WaitEvent;
ThreadContext->WaitContextArray[ThreadContext->Count] = Context; ThreadContext->WaitIrpArray[ThreadContext->Count] = Irp;
ThreadContext->Count++; ThreadContext->Count++;
DeviceExt->EmptyWaiterCount--; DeviceExt->EmptyWaiterCount--;
KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE);
@ -231,108 +291,160 @@ NpfsAddWaitingReader(PNPFS_DEVICE_EXTENSION DeviceExt, PNPFS_CONTEXT Context, PN
return Status; return Status;
} }
static NTSTATUS NTSTATUS STDCALL
NpfsReadFromPipe(PNPFS_CONTEXT Context) NpfsRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{ {
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
NTSTATUS Status; NTSTATUS Status;
ULONG Information; NTSTATUS OriginalStatus = STATUS_SUCCESS;
PNPFS_FCB Fcb; PNPFS_FCB Fcb;
PNPFS_FCB WriterFcb; PNPFS_CONTEXT Context;
PNPFS_PIPE Pipe; KEVENT Event;
ULONG Length; ULONG Length;
PVOID Buffer; ULONG Information;
ULONG CopyLength; ULONG CopyLength;
ULONG TempLength; ULONG TempLength;
BOOLEAN IsOriginalRequest = TRUE;
PVOID Buffer;
DPRINT("NpfsReadFromPipe(Context %p)\n", Context); DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
IoStack = IoGetCurrentIrpStackLocation(Context->Irp); if (Irp->MdlAddress == NULL)
FileObject = IoStack->FileObject;
Fcb = FileObject->FsContext;
Pipe = Fcb->Pipe;
WriterFcb = Fcb->OtherSide;
if (Fcb->Data == NULL)
{ {
DPRINT("Pipe is NOT readable!\n"); DPRINT("Irp->MdlAddress == NULL\n");
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
Information = 0; Irp->IoStatus.Information = 0;
goto done; goto done;
} }
Status = STATUS_SUCCESS; FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
Length = IoStack->Parameters.Read.Length; Fcb = FileObject->FsContext;
Information = 0; Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
if (Fcb->Data == NULL)
{
DPRINT1("Pipe is NOT readable!\n");
Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
goto done;
}
Buffer = MmGetSystemAddressForMdl(Context->Irp->MdlAddress);
ExAcquireFastMutex(&Fcb->DataListLock); ExAcquireFastMutex(&Fcb->DataListLock);
if (IoIsOperationSynchronous(Irp))
{
InsertTailList(&Fcb->ReadRequestListHead, &Context->ListEntry);
if (Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Context->WaitEvent = &Event;
ExReleaseFastMutex(&Fcb->DataListLock);
Status = KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
ExAcquireFastMutex(&Fcb->DataListLock);
}
Irp->IoStatus.Information = 0;
}
else
{
KIRQL oldIrql;
if (IsListEmpty(&Fcb->ReadRequestListHead) ||
Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
/* this is a new request */
Irp->IoStatus.Information = 0;
Context->WaitEvent = &Fcb->ReadEvent;
InsertTailList(&Fcb->ReadRequestListHead, &Context->ListEntry);
if (Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
/* there was already a request on the list */
IoAcquireCancelSpinLock(&oldIrql);
if (Irp->Cancel)
{
IoReleaseCancelSpinLock(oldIrql);
RemoveEntryList(&Context->ListEntry);
ExReleaseFastMutex(&Fcb->DataListLock);
Status = STATUS_CANCELLED;
goto done;
}
IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine);
IoReleaseCancelSpinLock(oldIrql);
ExReleaseFastMutex(&Fcb->DataListLock);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
goto done;
}
}
}
while (1)
{
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Information = Irp->IoStatus.Information;
Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
ASSERT (Information <= Length);
Buffer += Information;
Length -= Information;
Status = STATUS_SUCCESS;
while (1) while (1)
{ {
if (Fcb->ReadDataAvailable == 0) if (Fcb->ReadDataAvailable == 0)
{ {
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{ {
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&Fcb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
} }
ExReleaseFastMutex(&Fcb->DataListLock); if (Information > 0 &&
if (Information > 0) (Fcb->Pipe->ReadMode != FILE_PIPE_BYTE_STREAM_MODE ||
Fcb->PipeState != FILE_PIPE_CONNECTED_STATE))
{ {
Status = STATUS_SUCCESS; break;
goto done;
} }
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE) if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
{ {
DPRINT("PipeState: %x\n", Fcb->PipeState); DPRINT("PipeState: %x\n", Fcb->PipeState);
Status = STATUS_PIPE_BROKEN; Status = STATUS_PIPE_BROKEN;
goto done; break;
} }
ExReleaseFastMutex(&Fcb->DataListLock);
if (IoIsOperationSynchronous(Context->Irp)) if (IoIsOperationSynchronous(Irp))
{ {
/* Wait for ReadEvent to become signaled */ /* Wait for ReadEvent to become signaled */
DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer);
Status = KeWaitForSingleObject(&Fcb->Event, DPRINT("Waiting for readable data (%wZ)\n", &Fcb->Pipe->PipeName);
Status = KeWaitForSingleObject(&Fcb->ReadEvent,
UserRequest, UserRequest,
KernelMode, KernelMode,
FALSE, FALSE,
NULL); NULL);
DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status); DPRINT("Finished waiting (%wZ)! Status: %x\n", &Fcb->Pipe->PipeName, Status);
ExAcquireFastMutex(&Fcb->DataListLock);
} }
else else
{ {
PNPFS_CONTEXT NewContext; PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
NewContext = ExAllocatePool(NonPagedPool, sizeof(NPFS_CONTEXT)); Context->WaitEvent = &Fcb->ReadEvent;
if (NewContext == NULL) Status = NpfsAddWaitingReadWriteRequest(DeviceObject, Irp);
{
Status = STATUS_NO_MEMORY;
goto done;
}
memcpy(NewContext, Context, sizeof(NPFS_CONTEXT));
NewContext->AllocatedFromPool = TRUE;
NewContext->Fcb = Fcb;
NewContext->MajorFunction = IRP_MJ_READ;
Status = NpfsAddWaitingReader(Context->DeviceObject->DeviceExtension, NewContext, Fcb);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = STATUS_PENDING; Status = STATUS_PENDING;
} }
else
{
ExFreePool(NewContext);
}
goto done;
}
ExAcquireFastMutex(&Fcb->DataListLock); ExAcquireFastMutex(&Fcb->DataListLock);
break;
} }
}
if (Pipe->ReadMode == FILE_PIPE_BYTE_STREAM_MODE) if (Fcb->Pipe->ReadMode == FILE_PIPE_BYTE_STREAM_MODE)
{ {
DPRINT("Byte stream mode\n"); DPRINT("Byte stream mode\n");
/* Byte stream mode */ /* Byte stream mode */
@ -368,9 +480,9 @@ NpfsReadFromPipe(PNPFS_CONTEXT Context)
{ {
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{ {
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&Fcb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
} }
KeResetEvent(&Fcb->Event); KeResetEvent(&Fcb->ReadEvent);
break; break;
} }
} }
@ -401,10 +513,10 @@ NpfsReadFromPipe(PNPFS_CONTEXT Context)
} }
else else
{ {
KeResetEvent(&Fcb->Event); KeResetEvent(&Fcb->ReadEvent);
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{ {
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&Fcb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
} }
Fcb->ReadDataAvailable = 0; Fcb->ReadDataAvailable = 0;
Fcb->WriteQuotaAvailable = Fcb->MaxDataLength; Fcb->WriteQuotaAvailable = Fcb->MaxDataLength;
@ -417,49 +529,61 @@ NpfsReadFromPipe(PNPFS_CONTEXT Context)
} }
} }
} }
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
if (IoIsOperationSynchronous(Irp))
{
RemoveEntryList(&Context->ListEntry);
if (!IsListEmpty(&Fcb->ReadRequestListHead))
{
Context = CONTAINING_RECORD(Fcb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
KeSetEvent(Context->WaitEvent, IO_NO_INCREMENT, FALSE);
}
ExReleaseFastMutex(&Fcb->DataListLock); ExReleaseFastMutex(&Fcb->DataListLock);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT("NpfsRead done (Status %lx)\n", Status);
return Status;
}
else
{
if (IsOriginalRequest)
{
IsOriginalRequest = FALSE;
OriginalStatus = Status;
}
if (Status == STATUS_PENDING)
{
ExReleaseFastMutex(&Fcb->DataListLock);
DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus);
return OriginalStatus;
}
RemoveEntryList(&Context->ListEntry);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (IsListEmpty(&Fcb->ReadRequestListHead))
{
ExReleaseFastMutex(&Fcb->DataListLock);
DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus);
return OriginalStatus;
}
Context = CONTAINING_RECORD(Fcb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
Irp = CONTAINING_RECORD(Context, IRP, Tail.Overlay.DriverContext);
}
}
done: done:
Context->Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
Context->Irp->IoStatus.Information = Information;
if (Status != STATUS_PENDING) if (Status != STATUS_PENDING)
{ {
IoCompleteRequest(Context->Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
if (Context->AllocatedFromPool)
{
ExFreePool(Context);
} }
DPRINT("NpfsRead done (Status %lx)\n", Status); DPRINT("NpfsRead done (Status %lx)\n", Status);
return Status; return Status;
} }
NTSTATUS STDCALL
NpfsRead(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
NPFS_CONTEXT Context;
Context.AllocatedFromPool = FALSE;
Context.DeviceObject = DeviceObject;
Context.Irp = Irp;
if (Irp->MdlAddress == NULL)
{
DPRINT("Irp->MdlAddress == NULL\n");
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
return NpfsReadFromPipe(&Context);
}
NTSTATUS STDCALL NTSTATUS STDCALL
NpfsWrite(PDEVICE_OBJECT DeviceObject, NpfsWrite(PDEVICE_OBJECT DeviceObject,
PIRP Irp) PIRP Irp)
@ -534,22 +658,24 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
{ {
if (ReaderFcb->WriteQuotaAvailable == 0) if (ReaderFcb->WriteQuotaAvailable == 0)
{ {
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&ReaderFcb->ReadEvent, IO_NO_INCREMENT, FALSE);
ExReleaseFastMutex(&ReaderFcb->DataListLock);
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE) if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
{ {
Status = STATUS_PIPE_BROKEN; Status = STATUS_PIPE_BROKEN;
ExReleaseFastMutex(&ReaderFcb->DataListLock);
goto done; goto done;
} }
ExReleaseFastMutex(&ReaderFcb->DataListLock);
DPRINT("Waiting for buffer space (%S)\n", Pipe->PipeName.Buffer); DPRINT("Waiting for buffer space (%S)\n", Pipe->PipeName.Buffer);
Status = KeWaitForSingleObject(&Fcb->Event, Status = KeWaitForSingleObject(&Fcb->WriteEvent,
UserRequest, UserRequest,
KernelMode, KernelMode,
FALSE, FALSE,
NULL); NULL);
DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status); DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
ExAcquireFastMutex(&ReaderFcb->DataListLock);
/* /*
* It's possible that the event was signaled because the * It's possible that the event was signaled because the
* other side of pipe was closed. * other side of pipe was closed.
@ -558,9 +684,9 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
{ {
DPRINT("PipeState: %x\n", Fcb->PipeState); DPRINT("PipeState: %x\n", Fcb->PipeState);
Status = STATUS_PIPE_BROKEN; Status = STATUS_PIPE_BROKEN;
ExReleaseFastMutex(&ReaderFcb->DataListLock);
goto done; goto done;
} }
ExAcquireFastMutex(&ReaderFcb->DataListLock);
} }
if (Pipe->WriteMode == FILE_PIPE_BYTE_STREAM_MODE) if (Pipe->WriteMode == FILE_PIPE_BYTE_STREAM_MODE)
@ -596,8 +722,8 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
if (Length == 0) if (Length == 0)
{ {
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&ReaderFcb->ReadEvent, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->Event); KeResetEvent(&Fcb->WriteEvent);
break; break;
} }
} }
@ -616,8 +742,8 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
if (Information > 0) if (Information > 0)
{ {
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&ReaderFcb->ReadEvent, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->Event); KeResetEvent(&Fcb->WriteEvent);
break; break;
} }
} }