xref: /reactos/drivers/filesystems/msfs/rw.c (revision 69931a4a)
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