/* * 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 /* 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 */