Implemented read/write.
[reactos.git] / reactos / drivers / fs / np / create.c
1 /* $Id: create.c,v 1.11 2001/11/20 20:34:29 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/np/create.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13
14 #include "npfs.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19
20 /* GLOBALS *******************************************************************/
21
22
23 /* FUNCTIONS *****************************************************************/
24
25 NTSTATUS STDCALL
26 NpfsCreate(PDEVICE_OBJECT DeviceObject,
27 PIRP Irp)
28 {
29 PIO_STACK_LOCATION IoStack;
30 PFILE_OBJECT FileObject;
31 PNPFS_PIPE Pipe;
32 PNPFS_FCB ClientFcb;
33 PNPFS_FCB ServerFcb;
34 PNPFS_PIPE current;
35 PLIST_ENTRY current_entry;
36 PNPFS_DEVICE_EXTENSION DeviceExt;
37 KIRQL oldIrql;
38 ULONG Disposition;
39
40 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
41
42 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
43 IoStack = IoGetCurrentIrpStackLocation(Irp);
44 FileObject = IoStack->FileObject;
45 Disposition = ((IoStack->Parameters.Create.Options >> 24) & 0xff);
46 DPRINT("FileObject %p\n", FileObject);
47 DPRINT("FileName %wZ\n", &FileObject->FileName);
48
49 ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
50 if (ClientFcb == NULL)
51 {
52 Irp->IoStatus.Status = STATUS_NO_MEMORY;
53 Irp->IoStatus.Information = 0;
54
55 IoCompleteRequest(Irp, IO_NO_INCREMENT);
56 DPRINT("No memory!\n");
57
58 return(STATUS_NO_MEMORY);
59 }
60
61 KeLockMutex(&DeviceExt->PipeListLock);
62 current_entry = DeviceExt->PipeListHead.Flink;
63 while (current_entry != &DeviceExt->PipeListHead)
64 {
65 current = CONTAINING_RECORD(current_entry,
66 NPFS_PIPE,
67 PipeListEntry);
68
69 if (RtlCompareUnicodeString(&FileObject->FileName,
70 &current->PipeName,
71 TRUE) == 0)
72 {
73 break;
74 }
75
76 current_entry = current_entry->Flink;
77 }
78
79 if (current_entry == &DeviceExt->PipeListHead)
80 {
81 ExFreePool(ClientFcb);
82 KeUnlockMutex(&DeviceExt->PipeListLock);
83
84 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
85 Irp->IoStatus.Information = 0;
86
87 IoCompleteRequest(Irp, IO_NO_INCREMENT);
88 DPRINT("No pipe found!\n");
89
90 return(STATUS_OBJECT_NAME_NOT_FOUND);
91 }
92
93 Pipe = current;
94
95 ClientFcb->Pipe = Pipe;
96 ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END;
97 ClientFcb->OtherSide = NULL;
98 ClientFcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
99
100 /* initialize data list */
101 InitializeListHead(&ClientFcb->DataListHead);
102 KeInitializeSpinLock(&ClientFcb->DataListLock);
103
104 KeInitializeEvent(&ClientFcb->ConnectEvent,
105 SynchronizationEvent,
106 FALSE);
107
108 KeInitializeEvent(&ClientFcb->ReadEvent,
109 SynchronizationEvent,
110 FALSE);
111
112 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
113 InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry);
114 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
115
116 Pipe->ReferenceCount++;
117
118 KeUnlockMutex(&DeviceExt->PipeListLock);
119
120 #if 0
121 if (Disposition == OPEN_EXISTING)
122 {
123 /* do not connect to listening servers */
124 FileObject->FsContext = ClientFcb;
125
126 Irp->IoStatus.Status = STATUS_SUCCESS;
127 Irp->IoStatus.Information = 0;
128
129 IoCompleteRequest(Irp, IO_NO_INCREMENT);
130 DPRINT("Success!\n");
131
132 return(STATUS_SUCCESS);
133 }
134 #endif
135
136 /* search for disconnected or listening server fcb */
137 current_entry = Pipe->ServerFcbListHead.Flink;
138 while (current_entry != &Pipe->ServerFcbListHead)
139 {
140 ServerFcb = CONTAINING_RECORD(current_entry,
141 NPFS_FCB,
142 FcbListEntry);
143 if ((ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE)
144 || (ServerFcb->PipeState == FILE_PIPE_DISCONNECTED_STATE))
145 {
146 DPRINT("Server found! Fcb %p\n", ServerFcb);
147 break;
148 }
149 current_entry = current_entry->Flink;
150 }
151
152 if (current_entry == &Pipe->ServerFcbListHead)
153 {
154 DPRINT("No server fcb found!\n");
155
156 FileObject->FsContext = ClientFcb;
157
158 Irp->IoStatus.Status = STATUS_SUCCESS;
159 Irp->IoStatus.Information = 0;
160
161 IoCompleteRequest(Irp, IO_NO_INCREMENT);
162
163 return(STATUS_SUCCESS);
164 }
165
166 ClientFcb->OtherSide = ServerFcb;
167 ServerFcb->OtherSide = ClientFcb;
168 ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
169 ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
170
171 /* FIXME: create data queue(s) */
172
173 /* wake server thread */
174 KeSetEvent(&ServerFcb->ConnectEvent, 0, FALSE);
175
176 FileObject->FsContext = ClientFcb;
177
178 Irp->IoStatus.Status = STATUS_SUCCESS;
179 Irp->IoStatus.Information = 0;
180
181 IoCompleteRequest(Irp, IO_NO_INCREMENT);
182 DPRINT("Success!\n");
183
184 return(STATUS_SUCCESS);
185 }
186
187
188 NTSTATUS STDCALL
189 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
190 PIRP Irp)
191 {
192 PIO_STACK_LOCATION IoStack;
193 PFILE_OBJECT FileObject;
194 PNPFS_DEVICE_EXTENSION DeviceExt;
195 PNPFS_PIPE Pipe;
196 PNPFS_FCB Fcb;
197 KIRQL oldIrql;
198 PLIST_ENTRY current_entry;
199 PNPFS_PIPE current;
200 PIO_PIPE_CREATE_BUFFER Buffer;
201
202 DPRINT1("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
203
204 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
205 IoStack = IoGetCurrentIrpStackLocation(Irp);
206 FileObject = IoStack->FileObject;
207 DPRINT("FileObject %p\n", FileObject);
208 DPRINT("Pipe name %wZ\n", &FileObject->FileName);
209
210 Buffer = (PIO_PIPE_CREATE_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
211
212 Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE));
213 if (Pipe == NULL)
214 {
215 Irp->IoStatus.Status = STATUS_NO_MEMORY;
216 Irp->IoStatus.Information = 0;
217
218 IoCompleteRequest(Irp, IO_NO_INCREMENT);
219
220 return(STATUS_NO_MEMORY);
221 }
222
223 Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
224 if (Fcb == NULL)
225 {
226 ExFreePool(Pipe);
227
228 Irp->IoStatus.Status = STATUS_NO_MEMORY;
229 Irp->IoStatus.Information = 0;
230
231 IoCompleteRequest(Irp, IO_NO_INCREMENT);
232
233 return(STATUS_NO_MEMORY);
234 }
235
236 if (RtlCreateUnicodeString(&Pipe->PipeName, FileObject->FileName.Buffer) == 0)
237 {
238 ExFreePool(Pipe);
239 ExFreePool(Fcb);
240
241 Irp->IoStatus.Status = STATUS_NO_MEMORY;
242 Irp->IoStatus.Information = 0;
243
244 IoCompleteRequest(Irp, IO_NO_INCREMENT);
245
246 return(STATUS_NO_MEMORY);
247 }
248
249 Pipe->ReferenceCount = 0;
250 InitializeListHead(&Pipe->ServerFcbListHead);
251 InitializeListHead(&Pipe->ClientFcbListHead);
252 KeInitializeSpinLock(&Pipe->FcbListLock);
253
254 Pipe->PipeType = Buffer->WriteModeMessage;
255 Pipe->PipeWriteMode = Buffer->WriteModeMessage;
256 Pipe->PipeReadMode = Buffer->ReadModeMessage;
257 Pipe->PipeBlockMode = Buffer->NonBlocking;
258 Pipe->PipeConfiguration = IoStack->Parameters.Create.Options & 0x3;
259 Pipe->MaximumInstances = Buffer->MaxInstances;
260 Pipe->CurrentInstances = 0;
261 Pipe->TimeOut = Buffer->TimeOut;
262 Pipe->InboundQuota = Buffer->InBufferSize;
263 Pipe->OutboundQuota = Buffer->OutBufferSize;
264
265 KeLockMutex(&DeviceExt->PipeListLock);
266 current_entry = DeviceExt->PipeListHead.Flink;
267 while (current_entry != &DeviceExt->PipeListHead)
268 {
269 current = CONTAINING_RECORD(current_entry,
270 NPFS_PIPE,
271 PipeListEntry);
272
273 if (RtlCompareUnicodeString(&Pipe->PipeName, &current->PipeName, TRUE) == 0)
274 {
275 break;
276 }
277
278 current_entry = current_entry->Flink;
279 }
280
281 if (current_entry != &DeviceExt->PipeListHead)
282 {
283 RtlFreeUnicodeString(&Pipe->PipeName);
284 ExFreePool(Pipe);
285
286 Pipe = current;
287 }
288 else
289 {
290 InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
291 }
292 Pipe->ReferenceCount++;
293 Pipe->CurrentInstances++;
294
295 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
296 InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
297 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
298
299 Fcb->Pipe = Pipe;
300 Fcb->PipeEnd = FILE_PIPE_SERVER_END;
301 Fcb->OtherSide = NULL;
302 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
303 Fcb->ReadDataAvailable = 0;
304 Fcb->WriteQuotaAvailable = 0;
305
306 /* initialize data list */
307 InitializeListHead(&Fcb->DataListHead);
308 KeInitializeSpinLock(&Fcb->DataListLock);
309
310 KeInitializeEvent(&Fcb->ConnectEvent,
311 SynchronizationEvent,
312 FALSE);
313
314 KeInitializeEvent(&Fcb->ReadEvent,
315 SynchronizationEvent,
316 FALSE);
317
318
319 KeUnlockMutex(&DeviceExt->PipeListLock);
320
321 FileObject->FsContext = Fcb;
322
323 Irp->IoStatus.Status = STATUS_SUCCESS;
324 Irp->IoStatus.Information = 0;
325
326 IoCompleteRequest(Irp, IO_NO_INCREMENT);
327
328 return(STATUS_SUCCESS);
329 }
330
331
332 NTSTATUS STDCALL
333 NpfsClose(PDEVICE_OBJECT DeviceObject,
334 PIRP Irp)
335 {
336 PNPFS_DEVICE_EXTENSION DeviceExt;
337 PIO_STACK_LOCATION IoStack;
338 PFILE_OBJECT FileObject;
339 PNPFS_FCB Fcb;
340 PNPFS_PIPE Pipe;
341 KIRQL oldIrql;
342
343 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
344
345 IoStack = IoGetCurrentIrpStackLocation(Irp);
346 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
347 FileObject = IoStack->FileObject;
348 Fcb = FileObject->FsContext;
349
350 if (Fcb == NULL)
351 {
352 Irp->IoStatus.Status = STATUS_SUCCESS;
353 Irp->IoStatus.Information = 0;
354
355 IoCompleteRequest(Irp, IO_NO_INCREMENT);
356
357 return(STATUS_SUCCESS);
358 }
359
360 DPRINT("Fcb %x\n", Fcb);
361 Pipe = Fcb->Pipe;
362
363 DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);
364
365 KeLockMutex(&DeviceExt->PipeListLock);
366
367
368 if (Fcb->PipeEnd == FILE_PIPE_SERVER_END)
369 {
370 /* FIXME: Clean up existing connections here ?? */
371 Pipe->CurrentInstances--;
372 }
373 Pipe->ReferenceCount--;
374
375 if ((Fcb->PipeEnd == FILE_PIPE_CLIENT_END)
376 && (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE))
377 {
378 Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE;
379 Fcb->OtherSide->OtherSide = NULL;
380 Fcb->OtherSide = NULL;
381 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
382 }
383
384 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
385 RemoveEntryList(&Fcb->FcbListEntry);
386 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
387
388 ExFreePool(Fcb);
389 FileObject->FsContext = NULL;
390
391 if (Pipe->ReferenceCount == 0)
392 {
393 RtlFreeUnicodeString(&Pipe->PipeName);
394 RemoveEntryList(&Pipe->PipeListEntry);
395 ExFreePool(Pipe);
396 }
397
398 KeUnlockMutex(&DeviceExt->PipeListLock);
399
400 Irp->IoStatus.Status = STATUS_SUCCESS;
401 Irp->IoStatus.Information = 0;
402
403 IoCompleteRequest(Irp, IO_NO_INCREMENT);
404
405 return(STATUS_SUCCESS);
406 }
407
408 /* EOF */