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