1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: drivers/filesystems/msfs/rw.c 5 * PURPOSE: Mailslot filesystem 6 * PROGRAMMER: Eric Kohl 7 * Nikita Pechenkin (n.pechenkin@mail.ru) 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include "msfs.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* FUNCTIONS *****************************************************************/ 18 19 NTSTATUS DEFAULTAPI 20 MsfsRead(PDEVICE_OBJECT DeviceObject, 21 PIRP Irp) 22 { 23 PIO_STACK_LOCATION IoStack; 24 PFILE_OBJECT FileObject; 25 PMSFS_FCB Fcb; 26 PMSFS_CCB Ccb; 27 PMSFS_MESSAGE Message; 28 KIRQL oldIrql; 29 ULONG Length; 30 ULONG LengthRead = 0; 31 PVOID Buffer; 32 LARGE_INTEGER Timeout; 33 PKTIMER Timer; 34 PMSFS_DPC_CTX Context; 35 PKDPC Dpc; 36 PLIST_ENTRY Entry; 37 38 DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp); 39 40 IoStack = IoGetCurrentIrpStackLocation (Irp); 41 FileObject = IoStack->FileObject; 42 Fcb = (PMSFS_FCB)FileObject->FsContext; 43 Ccb = (PMSFS_CCB)FileObject->FsContext2; 44 45 DPRINT("MailslotName: %wZ\n", &Fcb->Name); 46 47 /* reading is not permitted on client side */ 48 if (Fcb->ServerCcb != Ccb) 49 { 50 Irp->IoStatus.Status = STATUS_ACCESS_DENIED; 51 Irp->IoStatus.Information = 0; 52 53 IoCompleteRequest(Irp, IO_NO_INCREMENT); 54 55 return STATUS_ACCESS_DENIED; 56 } 57 58 Length = IoStack->Parameters.Read.Length; 59 if (Irp->MdlAddress) 60 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 61 else 62 Buffer = Irp->UserBuffer; 63 64 65 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql); 66 if (Fcb->MessageCount > 0) 67 { 68 Entry = RemoveHeadList(&Fcb->MessageListHead); 69 Fcb->MessageCount--; 70 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql); 71 72 /* copy current message into buffer */ 73 Message = CONTAINING_RECORD(Entry, MSFS_MESSAGE, MessageListEntry); 74 memcpy(Buffer, &Message->Buffer, min(Message->Size,Length)); 75 LengthRead = Message->Size; 76 77 ExFreePoolWithTag(Message, 'rFsM'); 78 79 Irp->IoStatus.Status = STATUS_SUCCESS; 80 Irp->IoStatus.Information = LengthRead; 81 IoCompleteRequest(Irp, IO_NO_INCREMENT); 82 83 return STATUS_SUCCESS; 84 } 85 else 86 { 87 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql); 88 } 89 90 Timeout = Fcb->TimeOut; 91 if (Timeout.HighPart == 0 && Timeout.LowPart == 0) 92 { 93 Irp->IoStatus.Status = STATUS_IO_TIMEOUT; 94 Irp->IoStatus.Information = 0; 95 IoCompleteRequest(Irp, IO_NO_INCREMENT); 96 97 return STATUS_IO_TIMEOUT; 98 } 99 100 Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_DPC_CTX), 'NFsM'); 101 if (Context == NULL) 102 { 103 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 104 Irp->IoStatus.Information = 0; 105 IoCompleteRequest(Irp, IO_NO_INCREMENT); 106 107 return STATUS_INSUFFICIENT_RESOURCES; 108 } 109 110 KeInitializeEvent(&Context->Event, SynchronizationEvent, FALSE); 111 IoCsqInsertIrp(&Fcb->CancelSafeQueue, Irp, &Context->CsqContext); 112 Timer = &Context->Timer; 113 Dpc = &Context->Dpc; 114 Context->Csq = &Fcb->CancelSafeQueue; 115 Irp->Tail.Overlay.DriverContext[0] = Context; 116 117 /* No timer for INFINITY_WAIT */ 118 if (Timeout.QuadPart != -1) 119 { 120 KeInitializeTimer(Timer); 121 KeInitializeDpc(Dpc, MsfsTimeout, (PVOID)Context); 122 KeSetTimer(Timer, Timeout, Dpc); 123 } 124 125 IoMarkIrpPending(Irp); 126 127 return STATUS_PENDING; 128 } 129 130 131 NTSTATUS DEFAULTAPI 132 MsfsWrite(PDEVICE_OBJECT DeviceObject, 133 PIRP Irp) 134 { 135 PIO_STACK_LOCATION IoStack; 136 PFILE_OBJECT FileObject; 137 PMSFS_FCB Fcb; 138 PMSFS_CCB Ccb; 139 PMSFS_MESSAGE Message; 140 KIRQL oldIrql; 141 ULONG Length; 142 PVOID Buffer; 143 PIRP CsqIrp; 144 PMSFS_DPC_CTX Context; 145 146 DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp); 147 148 IoStack = IoGetCurrentIrpStackLocation (Irp); 149 FileObject = IoStack->FileObject; 150 Fcb = (PMSFS_FCB)FileObject->FsContext; 151 Ccb = (PMSFS_CCB)FileObject->FsContext2; 152 153 DPRINT("MailslotName: %wZ\n", &Fcb->Name); 154 155 /* writing is not permitted on server side */ 156 if (Fcb->ServerCcb == Ccb) 157 { 158 Irp->IoStatus.Status = STATUS_ACCESS_DENIED; 159 Irp->IoStatus.Information = 0; 160 161 IoCompleteRequest(Irp, IO_NO_INCREMENT); 162 163 return STATUS_ACCESS_DENIED; 164 } 165 166 Length = IoStack->Parameters.Write.Length; 167 if (Irp->MdlAddress) 168 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 169 else 170 Buffer = Irp->UserBuffer; 171 172 DPRINT("Length: %lu Message: %s\n", Length, (PUCHAR)Buffer); 173 174 /* Allocate new message */ 175 Message = ExAllocatePoolWithTag(NonPagedPool, 176 sizeof(MSFS_MESSAGE) + Length, 177 'rFsM'); 178 if (Message == NULL) 179 { 180 Irp->IoStatus.Status = STATUS_NO_MEMORY; 181 Irp->IoStatus.Information = 0; 182 183 IoCompleteRequest(Irp, IO_NO_INCREMENT); 184 185 return STATUS_NO_MEMORY; 186 } 187 188 Message->Size = Length; 189 memcpy(&Message->Buffer, Buffer, Length); 190 191 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql); 192 InsertTailList(&Fcb->MessageListHead, &Message->MessageListEntry); 193 Fcb->MessageCount++; 194 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql); 195 196 CsqIrp = IoCsqRemoveNextIrp(&Fcb->CancelSafeQueue, NULL); 197 if (CsqIrp != NULL) 198 { 199 /* Get the context */ 200 Context = CsqIrp->Tail.Overlay.DriverContext[0]; 201 /* DPC was queued, wait for it to fail (IRP is ours) */ 202 if (Fcb->TimeOut.QuadPart != -1 && !KeCancelTimer(&Context->Timer)) 203 { 204 KeWaitForSingleObject(&Context->Event, Executive, KernelMode, FALSE, NULL); 205 } 206 207 /* Free context & attempt read */ 208 ExFreePoolWithTag(Context, 'NFsM'); 209 MsfsRead(DeviceObject, CsqIrp); 210 } 211 212 Irp->IoStatus.Status = STATUS_SUCCESS; 213 Irp->IoStatus.Information = Length; 214 215 IoCompleteRequest(Irp, IO_NO_INCREMENT); 216 217 return STATUS_SUCCESS; 218 } 219 220 /* EOF */ 221