[FS_REC]
[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 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "msfs.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 NTSTATUS DEFAULTAPI
19 MsfsRead(PDEVICE_OBJECT DeviceObject,
20 PIRP Irp)
21 {
22 PIO_STACK_LOCATION IoStack;
23 PFILE_OBJECT FileObject;
24 PMSFS_FCB Fcb;
25 PMSFS_CCB Ccb;
26 PMSFS_MESSAGE Message;
27 KIRQL oldIrql;
28 ULONG Length;
29 ULONG LengthRead = 0;
30 PVOID Buffer;
31 NTSTATUS Status;
32
33 DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
34
35 IoStack = IoGetCurrentIrpStackLocation (Irp);
36 FileObject = IoStack->FileObject;
37 Fcb = (PMSFS_FCB)FileObject->FsContext;
38 Ccb = (PMSFS_CCB)FileObject->FsContext2;
39
40 DPRINT("MailslotName: %wZ\n", &Fcb->Name);
41
42 /* reading is not permitted on client side */
43 if (Fcb->ServerCcb != Ccb)
44 {
45 Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
46 Irp->IoStatus.Information = 0;
47
48 IoCompleteRequest(Irp, IO_NO_INCREMENT);
49
50 return STATUS_ACCESS_DENIED;
51 }
52
53 Length = IoStack->Parameters.Read.Length;
54 if (Irp->MdlAddress)
55 Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
56 else
57 Buffer = Irp->UserBuffer;
58
59 Status = KeWaitForSingleObject(&Fcb->MessageEvent,
60 UserRequest,
61 KernelMode,
62 FALSE,
63 &Fcb->TimeOut);
64 if (NT_SUCCESS(Status))
65 {
66 if (Fcb->MessageCount > 0)
67 {
68 /* copy current message into buffer */
69 Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
70 MSFS_MESSAGE,
71 MessageListEntry);
72
73 memcpy(Buffer, &Message->Buffer, min(Message->Size,Length));
74 LengthRead = Message->Size;
75
76 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
77 RemoveHeadList(&Fcb->MessageListHead);
78 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
79
80 ExFreePool(Message);
81 Fcb->MessageCount--;
82 if (Fcb->MessageCount == 0)
83 {
84 KeClearEvent(&Fcb->MessageEvent);
85 }
86 }
87 else if (Fcb->TimeOut.QuadPart != 0LL)
88 {
89 /* No message found after waiting */
90 Status = STATUS_IO_TIMEOUT;
91 }
92 }
93
94 Irp->IoStatus.Status = Status;
95 Irp->IoStatus.Information = LengthRead;
96
97 IoCompleteRequest(Irp, IO_NO_INCREMENT);
98
99 return Status;
100 }
101
102
103 NTSTATUS DEFAULTAPI
104 MsfsWrite(PDEVICE_OBJECT DeviceObject,
105 PIRP Irp)
106 {
107 PIO_STACK_LOCATION IoStack;
108 PFILE_OBJECT FileObject;
109 PMSFS_FCB Fcb;
110 PMSFS_CCB Ccb;
111 PMSFS_MESSAGE Message;
112 KIRQL oldIrql;
113 ULONG Length;
114 PVOID Buffer;
115
116 DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
117
118 IoStack = IoGetCurrentIrpStackLocation (Irp);
119 FileObject = IoStack->FileObject;
120 Fcb = (PMSFS_FCB)FileObject->FsContext;
121 Ccb = (PMSFS_CCB)FileObject->FsContext2;
122
123 DPRINT("MailslotName: %wZ\n", &Fcb->Name);
124
125 /* writing is not permitted on server side */
126 if (Fcb->ServerCcb == Ccb)
127 {
128 Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
129 Irp->IoStatus.Information = 0;
130
131 IoCompleteRequest(Irp, IO_NO_INCREMENT);
132
133 return STATUS_ACCESS_DENIED;
134 }
135
136 Length = IoStack->Parameters.Write.Length;
137 if (Irp->MdlAddress)
138 Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
139 else
140 Buffer = Irp->UserBuffer;
141
142 DPRINT("Length: %lu Message: %s\n", Length, (PUCHAR)Buffer);
143
144 /* Allocate new message */
145 Message = ExAllocatePool(NonPagedPool,
146 sizeof(MSFS_MESSAGE) + Length);
147 if (Message == NULL)
148 {
149 Irp->IoStatus.Status = STATUS_NO_MEMORY;
150 Irp->IoStatus.Information = 0;
151
152 IoCompleteRequest(Irp, IO_NO_INCREMENT);
153
154 return STATUS_NO_MEMORY;
155 }
156
157 Message->Size = Length;
158 memcpy(&Message->Buffer, Buffer, Length);
159
160 KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
161 InsertTailList(&Fcb->MessageListHead, &Message->MessageListEntry);
162 KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
163
164 Fcb->MessageCount++;
165 if (Fcb->MessageCount == 1)
166 {
167 KeSetEvent(&Fcb->MessageEvent,
168 0,
169 FALSE);
170 }
171
172 Irp->IoStatus.Status = STATUS_SUCCESS;
173 Irp->IoStatus.Information = Length;
174
175 IoCompleteRequest(Irp, IO_NO_INCREMENT);
176
177 return STATUS_SUCCESS;
178 }
179
180 /* EOF */