Reverted latest changes.
[reactos.git] / reactos / drivers / fs / np / create.c
1 /* $Id: create.c,v 1.14 2002/09/08 10:22:11 chorns 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 DPRINT1("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 ? FILE_PIPE_MESSAGE_TYPE : FILE_PIPE_BYTE_STREAM_TYPE;
255 Pipe->PipeWriteMode = Buffer->WriteModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
256 Pipe->PipeReadMode = Buffer->ReadModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
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 PLIST_ENTRY CurrentEntry;
343 PNPFS_PIPE_DATA Current;
344
345
346 DPRINT1("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
347
348 IoStack = IoGetCurrentIrpStackLocation(Irp);
349 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
350 FileObject = IoStack->FileObject;
351 Fcb = FileObject->FsContext;
352
353 if (Fcb == NULL)
354 {
355 Irp->IoStatus.Status = STATUS_SUCCESS;
356 Irp->IoStatus.Information = 0;
357
358 IoCompleteRequest(Irp, IO_NO_INCREMENT);
359
360 return(STATUS_SUCCESS);
361 }
362
363 DPRINT("Fcb %x\n", Fcb);
364 Pipe = Fcb->Pipe;
365
366 DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);
367
368 KeLockMutex(&DeviceExt->PipeListLock);
369
370
371 if (Fcb->PipeEnd == FILE_PIPE_SERVER_END)
372 {
373 /* FIXME: Clean up existing connections here ?? */
374 DPRINT("Server\n");
375 Pipe->CurrentInstances--;
376 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
377 {
378 if (Fcb->OtherSide)
379 {
380 Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE;
381 }
382 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
383 }
384 }
385 Pipe->ReferenceCount--;
386
387 if (Fcb->PipeEnd == FILE_PIPE_CLIENT_END)
388 {
389 DPRINT("Client\n");
390 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
391 {
392 if (Fcb->OtherSide)
393 {
394 Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE;
395
396 /* Signaling the read event. If is possible that an other
397 * thread waits of read data.
398 */
399 KeSetEvent(&Fcb->OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
400 }
401 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
402 }
403 }
404
405 FileObject->FsContext = NULL;
406
407 if (Pipe->ReferenceCount == 0)
408 {
409 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
410 if (Fcb->OtherSide)
411 {
412 RemoveEntryList(&Fcb->OtherSide->FcbListEntry);
413 }
414 RemoveEntryList(&Fcb->FcbListEntry);
415 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
416 if (Fcb->OtherSide)
417 {
418 KeAcquireSpinLock(&Fcb->OtherSide->DataListLock, &oldIrql);
419 while (!IsListEmpty(&Fcb->OtherSide->DataListHead))
420 {
421 CurrentEntry = RemoveHeadList(&Fcb->OtherSide->DataListHead);
422 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
423
424 NpfsFreePipeData(Current);
425 }
426 KeReleaseSpinLock(&Fcb->OtherSide->DataListLock, oldIrql);
427 ExFreePool(Fcb->OtherSide);
428 }
429
430 KeAcquireSpinLock(&Fcb->DataListLock, &oldIrql);
431 while (!IsListEmpty(&Fcb->DataListHead))
432 {
433 CurrentEntry = RemoveHeadList(&Fcb->DataListHead);
434 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
435 NpfsFreePipeData(Current);
436 }
437 KeReleaseSpinLock(&Fcb->DataListLock, oldIrql);
438 ExFreePool(Fcb);
439 RtlFreeUnicodeString(&Pipe->PipeName);
440 RemoveEntryList(&Pipe->PipeListEntry);
441 ExFreePool(Pipe);
442 }
443
444 KeUnlockMutex(&DeviceExt->PipeListLock);
445
446 Irp->IoStatus.Status = STATUS_SUCCESS;
447 Irp->IoStatus.Information = 0;
448
449 IoCompleteRequest(Irp, IO_NO_INCREMENT);
450
451 return(STATUS_SUCCESS);
452 }
453
454 /* EOF */