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 fsctrl.c
msfs.c msfs.c
rw.c rw.c
msfssup.c
msfs.h) msfs.h)
add_library(msfs SHARED ${SOURCE} msfs.rc) add_library(msfs SHARED ${SOURCE} msfs.rc)

View file

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

View file

@ -4,12 +4,14 @@
* FILE: drivers/filesystems/msfs/msfs.h * FILE: drivers/filesystems/msfs/msfs.h
* PURPOSE: Mailslot filesystem * PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl * PROGRAMMER: Eric Kohl
* Nikita Pechenkin (n.pechenkin@mail.ru)
*/ */
#ifndef __DRIVERS_FS_MS_MSFS_H #ifndef __DRIVERS_FS_MS_MSFS_H
#define __DRIVERS_FS_MS_MSFS_H #define __DRIVERS_FS_MS_MSFS_H
#include <ntifs.h> #include <ntifs.h>
#include <wdm.h>
#define DEFAULTAPI NTAPI #define DEFAULTAPI NTAPI
@ -35,9 +37,22 @@ typedef struct _MSFS_FCB
ULONG MessageCount; ULONG MessageCount;
KSPIN_LOCK MessageListLock; KSPIN_LOCK MessageListLock;
LIST_ENTRY MessageListHead; LIST_ENTRY MessageListHead;
IO_CSQ CancelSafeQueue;
KSPIN_LOCK QueueLock;
LIST_ENTRY PendingIrpQueue;
ULONG WaitCount;
} MSFS_FCB, *PMSFS_FCB; } 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 typedef struct _MSFS_CCB
{ {
LIST_ENTRY CcbListEntry; LIST_ENTRY CcbListEntry;
@ -89,4 +104,35 @@ NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject, DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath); 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 */ #endif /* __DRIVERS_FS_MS_MSFS_H */

View file

@ -4,6 +4,7 @@
* FILE: drivers/filesystems/msfs/rw.c * FILE: drivers/filesystems/msfs/rw.c
* PURPOSE: Mailslot filesystem * PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl * PROGRAMMER: Eric Kohl
* Nikita Pechenkin (n.pechenkin@mail.ru)
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
@ -28,8 +29,10 @@ MsfsRead(PDEVICE_OBJECT DeviceObject,
ULONG Length; ULONG Length;
ULONG LengthRead = 0; ULONG LengthRead = 0;
PVOID Buffer; PVOID Buffer;
NTSTATUS Status; LARGE_INTEGER Timeout;
PLARGE_INTEGER Timeout; PKTIMER Timer;
PMSFS_DPC_CTX Context;
PKDPC Dpc;
DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp); DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
@ -57,18 +60,7 @@ MsfsRead(PDEVICE_OBJECT DeviceObject,
else else
Buffer = Irp->UserBuffer; 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 */ /* copy current message into buffer */
@ -89,20 +81,53 @@ MsfsRead(PDEVICE_OBJECT DeviceObject,
{ {
KeClearEvent(&Fcb->MessageEvent); KeClearEvent(&Fcb->MessageEvent);
} }
}
else
{
/* No message found after waiting */
Status = STATUS_IO_TIMEOUT;
}
}
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = LengthRead; Irp->IoStatus.Information = LengthRead;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status; return STATUS_SUCCESS;
}
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; KIRQL oldIrql;
ULONG Length; ULONG Length;
PVOID Buffer; PVOID Buffer;
PIRP CsqIrp;
DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp); DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
@ -176,6 +202,14 @@ MsfsWrite(PDEVICE_OBJECT DeviceObject,
FALSE); 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.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length; Irp->IoStatus.Information = Length;