[MSFS]
[reactos.git] / reactos / drivers / filesystems / msfs / rw.c
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
37 DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
38
39 IoStack = IoGetCurrentIrpStackLocation (Irp);
40 FileObject = IoStack->FileObject;
41 Fcb = (PMSFS_FCB)FileObject->FsContext;
42 Ccb = (PMSFS_CCB)FileObject->FsContext2;
43
44 DPRINT("MailslotName: %wZ\n", &Fcb->Name);
45
46 /* reading is not permitted on client side */
47 if (Fcb->ServerCcb != Ccb)
48 {
49 Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
50 Irp->IoStatus.Information = 0;
51
52 IoCompleteRequest(Irp, IO_NO_INCREMENT);
53
54 return STATUS_ACCESS_DENIED;
55 }
56
57 Length = IoStack->Parameters.Read.Length;
58 if (Irp->MdlAddress)
59 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
60 else
61 Buffer = Irp->UserBuffer;
62
63
64 if (Fcb->MessageCount > 0)
65 {
66 /* copy current message into buffer */
67 Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
68 MSFS_MESSAGE,
69 MessageListEntry);
70
71 memcpy(Buffer, &Message->Buffer, min(Message->Size,Length));
72 LengthRead = Message->Size;
73
74 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
75 RemoveHeadList(&Fcb->MessageListHead);
76 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
77
78 ExFreePoolWithTag(Message, 'rFsM');
79 Fcb->MessageCount--;
80 if (Fcb->MessageCount == 0)
81 {
82 KeClearEvent(&Fcb->MessageEvent);
83 }
84
85 Irp->IoStatus.Status = STATUS_SUCCESS;
86 Irp->IoStatus.Information = LengthRead;
87 IoCompleteRequest(Irp, IO_NO_INCREMENT);
88
89 return STATUS_SUCCESS;
90 }
91
92 Timeout = Fcb->TimeOut;
93 if (Timeout.HighPart == 0 && Timeout.LowPart == 0)
94 {
95 Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
96 Irp->IoStatus.Information = 0;
97 IoCompleteRequest(Irp, IO_NO_INCREMENT);
98
99 return STATUS_IO_TIMEOUT;
100 }
101
102 Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_DPC_CTX), 'NFsM');
103 if (Context == NULL)
104 {
105 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
106 Irp->IoStatus.Information = 0;
107 IoCompleteRequest(Irp, IO_NO_INCREMENT);
108
109 return STATUS_INSUFFICIENT_RESOURCES;
110 }
111
112 IoCsqInsertIrp(&Fcb->CancelSafeQueue, Irp, &Context->CsqContext);
113 Timer = &Context->Timer;
114 Dpc = &Context->Dpc;
115 Context->Csq = &Fcb->CancelSafeQueue;
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 Fcb->WaitCount++;
126 Irp->IoStatus.Status = STATUS_PENDING;
127 Irp->IoStatus.Information = 0;
128 IoMarkIrpPending(Irp);
129
130 return STATUS_PENDING;
131 }
132
133
134 NTSTATUS DEFAULTAPI
135 MsfsWrite(PDEVICE_OBJECT DeviceObject,
136 PIRP Irp)
137 {
138 PIO_STACK_LOCATION IoStack;
139 PFILE_OBJECT FileObject;
140 PMSFS_FCB Fcb;
141 PMSFS_CCB Ccb;
142 PMSFS_MESSAGE Message;
143 KIRQL oldIrql;
144 ULONG Length;
145 PVOID Buffer;
146 PIRP CsqIrp;
147
148 DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
149
150 IoStack = IoGetCurrentIrpStackLocation (Irp);
151 FileObject = IoStack->FileObject;
152 Fcb = (PMSFS_FCB)FileObject->FsContext;
153 Ccb = (PMSFS_CCB)FileObject->FsContext2;
154
155 DPRINT("MailslotName: %wZ\n", &Fcb->Name);
156
157 /* writing is not permitted on server side */
158 if (Fcb->ServerCcb == Ccb)
159 {
160 Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
161 Irp->IoStatus.Information = 0;
162
163 IoCompleteRequest(Irp, IO_NO_INCREMENT);
164
165 return STATUS_ACCESS_DENIED;
166 }
167
168 Length = IoStack->Parameters.Write.Length;
169 if (Irp->MdlAddress)
170 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
171 else
172 Buffer = Irp->UserBuffer;
173
174 DPRINT("Length: %lu Message: %s\n", Length, (PUCHAR)Buffer);
175
176 /* Allocate new message */
177 Message = ExAllocatePoolWithTag(NonPagedPool,
178 sizeof(MSFS_MESSAGE) + Length,
179 'rFsM');
180 if (Message == NULL)
181 {
182 Irp->IoStatus.Status = STATUS_NO_MEMORY;
183 Irp->IoStatus.Information = 0;
184
185 IoCompleteRequest(Irp, IO_NO_INCREMENT);
186
187 return STATUS_NO_MEMORY;
188 }
189
190 Message->Size = Length;
191 memcpy(&Message->Buffer, Buffer, Length);
192
193 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
194 InsertTailList(&Fcb->MessageListHead, &Message->MessageListEntry);
195 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
196
197 Fcb->MessageCount++;
198 if (Fcb->MessageCount == 1)
199 {
200 KeSetEvent(&Fcb->MessageEvent,
201 0,
202 FALSE);
203 }
204
205 if (Fcb->WaitCount > 0)
206 {
207 CsqIrp = IoCsqRemoveNextIrp(&Fcb->CancelSafeQueue, NULL);
208 /* FIXME: It is necessary to reset the timers. */
209 MsfsRead(DeviceObject, CsqIrp);
210 Fcb->WaitCount--;
211 }
212
213 Irp->IoStatus.Status = STATUS_SUCCESS;
214 Irp->IoStatus.Information = Length;
215
216 IoCompleteRequest(Irp, IO_NO_INCREMENT);
217
218 return STATUS_SUCCESS;
219 }
220
221 /* EOF */