IN PIRP Irp)
{
PNPFS_CONTEXT Context;
- PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
+ PNPFS_VCB Vcb;
PNPFS_CCB Ccb;
- BOOLEAN Complete = FALSE;
+ PLIST_ENTRY ListEntry;
+ PNPFS_THREAD_CONTEXT ThreadContext;
+ ULONG i;
DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
IoReleaseCancelSpinLock(Irp->CancelIrql);
Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
- DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
Ccb = IoStack->FileObject->FsContext2;
- KeLockMutex(&DeviceExt->PipeListLock);
+ KeLockMutex(&Vcb->PipeListLock);
ExAcquireFastMutex(&Ccb->DataListLock);
switch(IoStack->MajorFunction)
{
case IRP_MJ_READ:
- if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
- {
- /* we are not the first in the list, remove an complete us */
- RemoveEntryList(&Context->ListEntry);
- Complete = TRUE;
- }
- else
+ ListEntry = Vcb->ThreadListHead.Flink;
+ while (ListEntry != &Vcb->ThreadListHead)
{
- KeSetEvent(&Ccb->ReadEvent, IO_NO_INCREMENT, FALSE);
+ ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT, ListEntry);
+ /* Real events start at index 1 */
+ for (i = 1; i < ThreadContext->Count; i++)
+ {
+ if (ThreadContext->WaitIrpArray[i] == Irp)
+ {
+ ASSERT(ThreadContext->WaitObjectArray[i] == Context->WaitEvent);
+
+ ThreadContext->WaitIrpArray[i] = NULL;
+
+ RemoveEntryList(&Context->ListEntry);
+
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ Irp->IoStatus.Information = 0;
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE);
+
+ ExReleaseFastMutex(&Ccb->DataListLock);
+ KeUnlockMutex(&Vcb->PipeListLock);
+
+ return;
+ }
+ }
+ ListEntry = ListEntry->Flink;
}
- break;
- default:
- ASSERT(FALSE);
- }
- ExReleaseFastMutex(&Ccb->DataListLock);
- KeUnlockMutex(&DeviceExt->PipeListLock);
- if (Complete)
- {
+
+ RemoveEntryList(&Context->ListEntry);
+
+ ExReleaseFastMutex(&Ccb->DataListLock);
+ KeUnlockMutex(&Vcb->PipeListLock);
+
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
+
IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ break;
+ default:
+ ASSERT(FALSE);
}
}
{
PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
ULONG CurrentCount;
- ULONG Count = 0;
+ ULONG Count = 0, i;
PIRP Irp = NULL;
- PIRP NextIrp;
NTSTATUS Status;
- BOOLEAN Terminate = FALSE;
- BOOLEAN Cancel = FALSE;
PIO_STACK_LOCATION IoStack = NULL;
- PNPFS_CONTEXT Context;
- PNPFS_CONTEXT NextContext;
- PNPFS_CCB Ccb;
+ KIRQL OldIrql;
- KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
+ KeLockMutex(&ThreadContext->Vcb->PipeListLock);
while (1)
{
CurrentCount = ThreadContext->Count;
- KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock);
- if (Irp)
+ KeUnlockMutex(&ThreadContext->Vcb->PipeListLock);
+ IoAcquireCancelSpinLock(&OldIrql);
+ if (Irp && IoSetCancelRoutine(Irp, NULL) != NULL)
{
- if (Cancel)
- {
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- }
- else
+ IoReleaseCancelSpinLock(OldIrql);
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ switch (IoStack->MajorFunction)
{
- switch (IoStack->MajorFunction)
- {
case IRP_MJ_READ:
NpfsRead(IoStack->DeviceObject, Irp);
break;
default:
ASSERT(FALSE);
- }
}
}
- if (Terminate)
+ else
{
- break;
+ IoReleaseCancelSpinLock(OldIrql);
}
Status = KeWaitForMultipleObjects(CurrentCount,
ThreadContext->WaitObjectArray,
{
ASSERT(FALSE);
}
- KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
- Count = Status - STATUS_SUCCESS;
+ KeLockMutex(&ThreadContext->Vcb->PipeListLock);
+ Count = Status - STATUS_WAIT_0;
ASSERT (Count < CurrentCount);
if (Count > 0)
{
Irp = ThreadContext->WaitIrpArray[Count];
ThreadContext->Count--;
- ThreadContext->DeviceExt->EmptyWaiterCount++;
+ ThreadContext->Vcb->EmptyWaiterCount++;
ThreadContext->WaitObjectArray[Count] = ThreadContext->WaitObjectArray[ThreadContext->Count];
ThreadContext->WaitIrpArray[Count] = ThreadContext->WaitIrpArray[ThreadContext->Count];
+ }
+ else
+ {
+ /* someone has add a new wait request or cancelled an old one */
+ Irp = NULL;
- Cancel = (NULL == IoSetCancelRoutine(Irp, NULL));
- Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- if (Cancel)
+ /* Look for cancelled requests */
+ for (i = 1; i < ThreadContext->Count; i++)
{
- Ccb = IoStack->FileObject->FsContext2;
- ExAcquireFastMutex(&Ccb->DataListLock);
- RemoveEntryList(&Context->ListEntry);
- switch (IoStack->MajorFunction)
+ if (ThreadContext->WaitIrpArray[i] == NULL)
{
- case IRP_MJ_READ:
- if (!IsListEmpty(&Ccb->ReadRequestListHead))
- {
- /* put the next request on the wait list */
- NextContext = CONTAINING_RECORD(Ccb->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:
- ASSERT(FALSE);
+ ThreadContext->Count--;
+ ThreadContext->Vcb->EmptyWaiterCount++;
+ ThreadContext->WaitObjectArray[i] = ThreadContext->WaitObjectArray[ThreadContext->Count];
+ ThreadContext->WaitIrpArray[i] = ThreadContext->WaitIrpArray[ThreadContext->Count];
}
- ExReleaseFastMutex(&Ccb->DataListLock);
}
}
- else
- {
- /* someone has add a new wait request */
- Irp = NULL;
- }
- if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
+ if (ThreadContext->Count == 1 && ThreadContext->Vcb->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
{
/* it exist an other thread with empty wait slots, we can remove our thread from the list */
RemoveEntryList(&ThreadContext->ListEntry);
- ThreadContext->DeviceExt->EmptyWaiterCount -= MAXIMUM_WAIT_OBJECTS - 1;
- Terminate = TRUE;
+ ThreadContext->Vcb->EmptyWaiterCount -= MAXIMUM_WAIT_OBJECTS - 1;
+ KeUnlockMutex(&ThreadContext->Vcb->PipeListLock);
+ break;
}
}
ExFreePool(ThreadContext);
{
PLIST_ENTRY ListEntry;
PNPFS_THREAD_CONTEXT ThreadContext = NULL;
- NTSTATUS Status;
+ PNPFS_CONTEXT Context;
HANDLE hThread;
+ PNPFS_VCB Vcb;
KIRQL oldIrql;
+ NTSTATUS Status;
- PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
- PNPFS_DEVICE_EXTENSION DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
+ Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
- KeLockMutex(&DeviceExt->PipeListLock);
+ KeLockMutex(&Vcb->PipeListLock);
- ListEntry = DeviceExt->ThreadListHead.Flink;
- while (ListEntry != &DeviceExt->ThreadListHead)
+ ListEntry = Vcb->ThreadListHead.Flink;
+ while (ListEntry != &Vcb->ThreadListHead)
{
ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT, ListEntry);
if (ThreadContext->Count < MAXIMUM_WAIT_OBJECTS)
}
ListEntry = ListEntry->Flink;
}
- if (ListEntry == &DeviceExt->ThreadListHead)
+
+ if (ListEntry == &Vcb->ThreadListHead)
{
ThreadContext = ExAllocatePool(NonPagedPool, sizeof(NPFS_THREAD_CONTEXT));
if (ThreadContext == NULL)
{
- KeUnlockMutex(&DeviceExt->PipeListLock);
+ KeUnlockMutex(&Vcb->PipeListLock);
return STATUS_NO_MEMORY;
}
- ThreadContext->DeviceExt = DeviceExt;
+
+ ThreadContext->Vcb = Vcb;
KeInitializeEvent(&ThreadContext->Event, SynchronizationEvent, FALSE);
ThreadContext->Count = 1;
ThreadContext->WaitObjectArray[0] = &ThreadContext->Event;
-
DPRINT("Creating a new system thread for waiting read/write requests\n");
Status = PsCreateSystemThread(&hThread,
if (!NT_SUCCESS(Status))
{
ExFreePool(ThreadContext);
- KeUnlockMutex(&DeviceExt->PipeListLock);
+ KeUnlockMutex(&Vcb->PipeListLock);
return Status;
}
- InsertHeadList(&DeviceExt->ThreadListHead, &ThreadContext->ListEntry);
- DeviceExt->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1;
+
+ InsertHeadList(&Vcb->ThreadListHead, &ThreadContext->ListEntry);
+ Vcb->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1;
}
IoMarkIrpPending(Irp);
ThreadContext->WaitObjectArray[ThreadContext->Count] = Context->WaitEvent;
ThreadContext->WaitIrpArray[ThreadContext->Count] = Irp;
ThreadContext->Count++;
- DeviceExt->EmptyWaiterCount--;
+ Vcb->EmptyWaiterCount--;
KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE);
Status = STATUS_SUCCESS;
}
- KeUnlockMutex(&DeviceExt->PipeListLock);
+ KeUnlockMutex(&Vcb->PipeListLock);
return Status;
}
if ((Ccb->OtherSide == NULL) && (Ccb->ReadDataAvailable == 0))
{
if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
- {
- DPRINT("File pipe broken\n");
Status = STATUS_PIPE_BROKEN;
- }
else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
Status = STATUS_PIPE_LISTENING;
else if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
{
break;
}
- if ((Ccb->PipeState != FILE_PIPE_CONNECTED_STATE) && (Ccb->ReadDataAvailable == 0))
+ if (((Ccb->PipeState != FILE_PIPE_CONNECTED_STATE) || (!Ccb->OtherSide)) && (Ccb->ReadDataAvailable == 0))
{
DPRINT("PipeState: %x\n", Ccb->PipeState);
Status = STATUS_PIPE_BROKEN;
}
Status = STATUS_SUCCESS;
- Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
+ Buffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, NormalPagePriority);
+
+ if (!Buffer)
+ {
+ DPRINT("MmGetSystemAddressForMdlSafe failed\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ Length = 0;
+ goto done;
+
+ }
ExAcquireFastMutex(&ReaderCcb->DataListLock);
{
if ((ReaderCcb->WriteQuotaAvailable == 0))
{
- KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE);
- if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE)
+ if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE || !Ccb->OtherSide)
{
Status = STATUS_PIPE_BROKEN;
ExReleaseFastMutex(&ReaderCcb->DataListLock);
goto done;
}
+ KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE);
ExReleaseFastMutex(&ReaderCcb->DataListLock);
DPRINT("Write Waiting for buffer space (%S)\n", Fcb->PipeName.Buffer);
* It's possible that the event was signaled because the
* other side of pipe was closed.
*/
- if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE)
+ if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE || !Ccb->OtherSide)
{
DPRINT("PipeState: %x\n", Ccb->PipeState);
Status = STATUS_PIPE_BROKEN;
goto done;
}
/* Check that the pipe has not been closed */
- if (ReaderCcb->PipeState != FILE_PIPE_CONNECTED_STATE)
+ if (ReaderCcb->PipeState != FILE_PIPE_CONNECTED_STATE || !ReaderCcb->OtherSide)
{
- /* If the other side is valid, fire event */
- if (Ccb)
- {
- KeResetEvent(&Ccb->WriteEvent);
- }
Status = STATUS_PIPE_BROKEN;
goto done;
}