Implement asynchronous reading from mailslot.
Patch by Nikita Pechenkin

Adjustements, style fixing by myself.

CORE-10245 #resolve #comment Modified patch committed with r69475. I have tested kernel32:mailslot and your provided test, both are passing 100%. Thanks!

svn path=/trunk/; revision=69475
This commit is contained in:
Pierre Schweitzer 2015-10-10 08:29:05 +00:00
parent 8cd50ca0ee
commit ead10526aa
4 changed files with 134 additions and 41 deletions

View file

@ -5,6 +5,7 @@ list(APPEND SOURCE
fsctrl.c
msfs.c
rw.c
msfssup.c
msfs.h)
add_library(msfs SHARED ${SOURCE} msfs.rc)

View file

@ -4,6 +4,7 @@
* FILE: drivers/filesystems/msfs/create.c
* PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl
* Nikita Pechenkin (n.pechenkin@mail.ru)
*/
/* INCLUDES ******************************************************************/
@ -183,6 +184,17 @@ MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject,
InitializeListHead(&Fcb->MessageListHead);
KeInitializeSpinLock(&Fcb->MessageListLock);
Fcb->WaitCount = 0;
KeInitializeSpinLock(&Fcb->QueueLock);
InitializeListHead(&Fcb->PendingIrpQueue);
IoCsqInitialize(&Fcb->CancelSafeQueue,
MsfsInsertIrp,
MsfsRemoveIrp,
MsfsPeekNextIrp,
MsfsAcquireLock,
MsfsReleaseLock,
MsfsCompleteCanceledIrp);
KeLockMutex(&DeviceExtension->FcbListLock);
current_entry = DeviceExtension->FcbListHead.Flink;
while (current_entry != &DeviceExtension->FcbListHead)

View file

@ -4,12 +4,14 @@
* FILE: drivers/filesystems/msfs/msfs.h
* PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl
* Nikita Pechenkin (n.pechenkin@mail.ru)
*/
#ifndef __DRIVERS_FS_MS_MSFS_H
#define __DRIVERS_FS_MS_MSFS_H
#include <ntifs.h>
#include <wdm.h>
#define DEFAULTAPI NTAPI
@ -35,9 +37,22 @@ typedef struct _MSFS_FCB
ULONG MessageCount;
KSPIN_LOCK MessageListLock;
LIST_ENTRY MessageListHead;
IO_CSQ CancelSafeQueue;
KSPIN_LOCK QueueLock;
LIST_ENTRY PendingIrpQueue;
ULONG WaitCount;
} MSFS_FCB, *PMSFS_FCB;
typedef struct _MSFS_DPC_CTX
{
KTIMER Timer;
KDPC Dpc;
PIO_CSQ Csq;
IO_CSQ_IRP_CONTEXT CsqContext;
} MSFS_DPC_CTX, *PMSFS_DPC_CTX;
typedef struct _MSFS_CCB
{
LIST_ENTRY CcbListEntry;
@ -89,4 +104,35 @@ NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath);
IO_CSQ_INSERT_IRP MsfsInsertIrp;
VOID NTAPI
MsfsInsertIrp(PIO_CSQ Csq, PIRP Irp);
IO_CSQ_REMOVE_IRP MsfsRemoveIrp;
VOID NTAPI
MsfsRemoveIrp(PIO_CSQ Csq, PIRP Irp);
IO_CSQ_PEEK_NEXT_IRP MsfsPeekNextIrp;
PIRP NTAPI
MsfsPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext);
IO_CSQ_ACQUIRE_LOCK MsfsAcquireLock;
VOID NTAPI
MsfsAcquireLock(PIO_CSQ Csq, PKIRQL Irql);
IO_CSQ_RELEASE_LOCK MsfsReleaseLock;
VOID NTAPI
MsfsReleaseLock(PIO_CSQ Csq, KIRQL Irql);
IO_CSQ_COMPLETE_CANCELED_IRP MsfsCompleteCanceledIrp;
VOID NTAPI
MsfsCompleteCanceledIrp(PIO_CSQ pCsq, PIRP Irp);
KDEFERRED_ROUTINE MsfsTimeout;
VOID NTAPI
MsfsTimeout(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2);
#endif /* __DRIVERS_FS_MS_MSFS_H */

View file

@ -4,6 +4,7 @@
* FILE: drivers/filesystems/msfs/rw.c
* PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl
* Nikita Pechenkin (n.pechenkin@mail.ru)
*/
/* INCLUDES ******************************************************************/
@ -28,8 +29,10 @@ MsfsRead(PDEVICE_OBJECT DeviceObject,
ULONG Length;
ULONG LengthRead = 0;
PVOID Buffer;
NTSTATUS Status;
PLARGE_INTEGER Timeout;
LARGE_INTEGER Timeout;
PKTIMER Timer;
PMSFS_DPC_CTX Context;
PKDPC Dpc;
DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
@ -57,52 +60,74 @@ MsfsRead(PDEVICE_OBJECT DeviceObject,
else
Buffer = Irp->UserBuffer;
if (Fcb->TimeOut.QuadPart == -1LL)
Timeout = NULL;
else
Timeout = &Fcb->TimeOut;
Status = KeWaitForSingleObject(&Fcb->MessageEvent,
UserRequest,
UserMode,
FALSE,
Timeout);
if (Status != STATUS_USER_APC)
if (Fcb->MessageCount > 0)
{
if (Fcb->MessageCount > 0)
/* copy current message into buffer */
Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
MSFS_MESSAGE,
MessageListEntry);
memcpy(Buffer, &Message->Buffer, min(Message->Size,Length));
LengthRead = Message->Size;
KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
RemoveHeadList(&Fcb->MessageListHead);
KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
ExFreePoolWithTag(Message, 'rFsM');
Fcb->MessageCount--;
if (Fcb->MessageCount == 0)
{
/* copy current message into buffer */
Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
MSFS_MESSAGE,
MessageListEntry);
memcpy(Buffer, &Message->Buffer, min(Message->Size,Length));
LengthRead = Message->Size;
KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
RemoveHeadList(&Fcb->MessageListHead);
KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
ExFreePoolWithTag(Message, 'rFsM');
Fcb->MessageCount--;
if (Fcb->MessageCount == 0)
{
KeClearEvent(&Fcb->MessageEvent);
}
KeClearEvent(&Fcb->MessageEvent);
}
else
{
/* No message found after waiting */
Status = STATUS_IO_TIMEOUT;
}
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = LengthRead;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = LengthRead;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
return Status;
Timeout = Fcb->TimeOut;
if (Timeout.HighPart == 0 && Timeout.LowPart == 0)
{
Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_IO_TIMEOUT;
}
Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_DPC_CTX), 'NFsM');
if (Context == NULL)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
IoCsqInsertIrp(&Fcb->CancelSafeQueue, Irp, &Context->CsqContext);
Timer = &Context->Timer;
Dpc = &Context->Dpc;
Context->Csq = &Fcb->CancelSafeQueue;
/* No timer for INFINITY_WAIT */
if (Timeout.QuadPart != -1)
{
KeInitializeTimer(Timer);
KeInitializeDpc(Dpc, MsfsTimeout, (PVOID)Context);
KeSetTimer(Timer, Timeout, Dpc);
}
Fcb->WaitCount++;
Irp->IoStatus.Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
@ -118,6 +143,7 @@ MsfsWrite(PDEVICE_OBJECT DeviceObject,
KIRQL oldIrql;
ULONG Length;
PVOID Buffer;
PIRP CsqIrp;
DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
@ -176,6 +202,14 @@ MsfsWrite(PDEVICE_OBJECT DeviceObject,
FALSE);
}
if (Fcb->WaitCount > 0)
{
CsqIrp = IoCsqRemoveNextIrp(&Fcb->CancelSafeQueue, NULL);
/* FIXME: It is necessary to reset the timers. */
MsfsRead(DeviceObject, CsqIrp);
Fcb->WaitCount--;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length;