mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
[MSFS]
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:
parent
8cd50ca0ee
commit
ead10526aa
|
@ -5,6 +5,7 @@ list(APPEND SOURCE
|
|||
fsctrl.c
|
||||
msfs.c
|
||||
rw.c
|
||||
msfssup.c
|
||||
msfs.h)
|
||||
|
||||
add_library(msfs SHARED ${SOURCE} msfs.rc)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue