* 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
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;
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 */
* FILE: drivers/filesystems/msfs/rw.c
* PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl
+ * Nikita Pechenkin (n.pechenkin@mail.ru)
*/
/* INCLUDES ******************************************************************/
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);
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)
- {
- KeClearEvent(&Fcb->MessageEvent);
- }
- }
- else
+ /* 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)
{
- /* No message found after waiting */
- Status = STATUS_IO_TIMEOUT;
+ KeClearEvent(&Fcb->MessageEvent);
}
- }
- 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;
+ }
+
+ 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;
- return Status;
+ /* 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;
}
KIRQL oldIrql;
ULONG Length;
PVOID Buffer;
+ PIRP CsqIrp;
DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
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;