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