[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 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 if (Fcb->MessageCount > 0)
66 {
67 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
68 Entry = RemoveHeadList(&Fcb->MessageListHead);
69 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
70
71 /* copy current message into buffer */
72 Message = CONTAINING_RECORD(Entry, MSFS_MESSAGE, MessageListEntry);
73 memcpy(Buffer, &Message->Buffer, min(Message->Size,Length));
74 LengthRead = Message->Size;
75
76 ExFreePoolWithTag(Message, 'rFsM');
77 Fcb->MessageCount--;
78 if (Fcb->MessageCount == 0)
79 {
80 KeClearEvent(&Fcb->MessageEvent);
81 }
82
83 Irp->IoStatus.Status = STATUS_SUCCESS;
84 Irp->IoStatus.Information = LengthRead;
85 IoCompleteRequest(Irp, IO_NO_INCREMENT);
86
87 return STATUS_SUCCESS;
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 IoCsqInsertIrp(&Fcb->CancelSafeQueue, Irp, &Context->CsqContext);
111 Timer = &Context->Timer;
112 Dpc = &Context->Dpc;
113 Context->Csq = &Fcb->CancelSafeQueue;
114
115 /* No timer for INFINITY_WAIT */
116 if (Timeout.QuadPart != -1)
117 {
118 KeInitializeTimer(Timer);
119 KeInitializeDpc(Dpc, MsfsTimeout, (PVOID)Context);
120 KeSetTimer(Timer, Timeout, Dpc);
121 }
122
123 Fcb->WaitCount++;
124 IoMarkIrpPending(Irp);
125
126 return STATUS_PENDING;
127 }
128
129
130 NTSTATUS DEFAULTAPI
131 MsfsWrite(PDEVICE_OBJECT DeviceObject,
132 PIRP Irp)
133 {
134 PIO_STACK_LOCATION IoStack;
135 PFILE_OBJECT FileObject;
136 PMSFS_FCB Fcb;
137 PMSFS_CCB Ccb;
138 PMSFS_MESSAGE Message;
139 KIRQL oldIrql;
140 ULONG Length;
141 PVOID Buffer;
142 PIRP CsqIrp;
143
144 DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
145
146 IoStack = IoGetCurrentIrpStackLocation (Irp);
147 FileObject = IoStack->FileObject;
148 Fcb = (PMSFS_FCB)FileObject->FsContext;
149 Ccb = (PMSFS_CCB)FileObject->FsContext2;
150
151 DPRINT("MailslotName: %wZ\n", &Fcb->Name);
152
153 /* writing is not permitted on server side */
154 if (Fcb->ServerCcb == Ccb)
155 {
156 Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
157 Irp->IoStatus.Information = 0;
158
159 IoCompleteRequest(Irp, IO_NO_INCREMENT);
160
161 return STATUS_ACCESS_DENIED;
162 }
163
164 Length = IoStack->Parameters.Write.Length;
165 if (Irp->MdlAddress)
166 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
167 else
168 Buffer = Irp->UserBuffer;
169
170 DPRINT("Length: %lu Message: %s\n", Length, (PUCHAR)Buffer);
171
172 /* Allocate new message */
173 Message = ExAllocatePoolWithTag(NonPagedPool,
174 sizeof(MSFS_MESSAGE) + Length,
175 'rFsM');
176 if (Message == NULL)
177 {
178 Irp->IoStatus.Status = STATUS_NO_MEMORY;
179 Irp->IoStatus.Information = 0;
180
181 IoCompleteRequest(Irp, IO_NO_INCREMENT);
182
183 return STATUS_NO_MEMORY;
184 }
185
186 Message->Size = Length;
187 memcpy(&Message->Buffer, Buffer, Length);
188
189 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
190 InsertTailList(&Fcb->MessageListHead, &Message->MessageListEntry);
191 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
192
193 Fcb->MessageCount++;
194 if (Fcb->MessageCount == 1)
195 {
196 KeSetEvent(&Fcb->MessageEvent,
197 0,
198 FALSE);
199 }
200
201 if (Fcb->WaitCount > 0)
202 {
203 CsqIrp = IoCsqRemoveNextIrp(&Fcb->CancelSafeQueue, NULL);
204 /* FIXME: It is necessary to reset the timers. */
205 MsfsRead(DeviceObject, CsqIrp);
206 Fcb->WaitCount--;
207 }
208
209 Irp->IoStatus.Status = STATUS_SUCCESS;
210 Irp->IoStatus.Information = Length;
211
212 IoCompleteRequest(Irp, IO_NO_INCREMENT);
213
214 return STATUS_SUCCESS;
215 }
216
217 /* EOF */