reactos/drivers/filesystems/msfs/rw.c

221 lines
6 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/msfs/rw.c
* PURPOSE: Mailslot filesystem
* PROGRAMMER: Eric Kohl
* Nikita Pechenkin (n.pechenkin@mail.ru)
*/
/* INCLUDES ******************************************************************/
#include "msfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
NTSTATUS DEFAULTAPI
MsfsRead(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PMSFS_FCB Fcb;
PMSFS_CCB Ccb;
PMSFS_MESSAGE Message;
KIRQL oldIrql;
ULONG Length;
ULONG LengthRead = 0;
PVOID Buffer;
LARGE_INTEGER Timeout;
PKTIMER Timer;
PMSFS_DPC_CTX Context;
PKDPC Dpc;
PLIST_ENTRY Entry;
DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
IoStack = IoGetCurrentIrpStackLocation (Irp);
FileObject = IoStack->FileObject;
Fcb = (PMSFS_FCB)FileObject->FsContext;
Ccb = (PMSFS_CCB)FileObject->FsContext2;
DPRINT("MailslotName: %wZ\n", &Fcb->Name);
/* reading is not permitted on client side */
if (Fcb->ServerCcb != Ccb)
{
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_ACCESS_DENIED;
}
Length = IoStack->Parameters.Read.Length;
if (Irp->MdlAddress)
Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
else
Buffer = Irp->UserBuffer;
KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
if (Fcb->MessageCount > 0)
{
Entry = RemoveHeadList(&Fcb->MessageListHead);
Fcb->MessageCount--;
KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
/* copy current message into buffer */
Message = CONTAINING_RECORD(Entry, MSFS_MESSAGE, MessageListEntry);
memcpy(Buffer, &Message->Buffer, min(Message->Size,Length));
LengthRead = Message->Size;
ExFreePoolWithTag(Message, 'rFsM');
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = LengthRead;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
else
{
KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
}
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;
}
KeInitializeEvent(&Context->Event, SynchronizationEvent, FALSE);
IoCsqInsertIrp(&Fcb->CancelSafeQueue, Irp, &Context->CsqContext);
Timer = &Context->Timer;
Dpc = &Context->Dpc;
Context->Csq = &Fcb->CancelSafeQueue;
Irp->Tail.Overlay.DriverContext[0] = Context;
/* No timer for INFINITY_WAIT */
if (Timeout.QuadPart != -1)
{
KeInitializeTimer(Timer);
KeInitializeDpc(Dpc, MsfsTimeout, (PVOID)Context);
KeSetTimer(Timer, Timeout, Dpc);
}
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
NTSTATUS DEFAULTAPI
MsfsWrite(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PMSFS_FCB Fcb;
PMSFS_CCB Ccb;
PMSFS_MESSAGE Message;
KIRQL oldIrql;
ULONG Length;
PVOID Buffer;
PIRP CsqIrp;
PMSFS_DPC_CTX Context;
DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
IoStack = IoGetCurrentIrpStackLocation (Irp);
FileObject = IoStack->FileObject;
Fcb = (PMSFS_FCB)FileObject->FsContext;
Ccb = (PMSFS_CCB)FileObject->FsContext2;
DPRINT("MailslotName: %wZ\n", &Fcb->Name);
/* writing is not permitted on server side */
if (Fcb->ServerCcb == Ccb)
{
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_ACCESS_DENIED;
}
Length = IoStack->Parameters.Write.Length;
if (Irp->MdlAddress)
Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
else
Buffer = Irp->UserBuffer;
DPRINT("Length: %lu Message: %s\n", Length, (PUCHAR)Buffer);
/* Allocate new message */
Message = ExAllocatePoolWithTag(NonPagedPool,
sizeof(MSFS_MESSAGE) + Length,
'rFsM');
if (Message == NULL)
{
Irp->IoStatus.Status = STATUS_NO_MEMORY;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
Message->Size = Length;
memcpy(&Message->Buffer, Buffer, Length);
KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
InsertTailList(&Fcb->MessageListHead, &Message->MessageListEntry);
Fcb->MessageCount++;
KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
CsqIrp = IoCsqRemoveNextIrp(&Fcb->CancelSafeQueue, NULL);
if (CsqIrp != NULL)
{
/* Get the context */
Context = CsqIrp->Tail.Overlay.DriverContext[0];
/* DPC was queued, wait for it to fail (IRP is ours) */
if (Fcb->TimeOut.QuadPart != -1 && !KeCancelTimer(&Context->Timer))
{
KeWaitForSingleObject(&Context->Event, Executive, KernelMode, FALSE, NULL);
}
/* Free context & attempt read */
ExFreePoolWithTag(Context, 'NFsM');
MsfsRead(DeviceObject, CsqIrp);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/* EOF */