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>
10 /* INCLUDES ******************************************************************/
12 #include <ddk/ntddk.h>
20 /* GLOBALS *******************************************************************/
23 /* FUNCTIONS *****************************************************************/
26 NpfsCreate(PDEVICE_OBJECT DeviceObject,
29 PIO_STACK_LOCATION IoStack;
30 PFILE_OBJECT FileObject;
35 PLIST_ENTRY current_entry;
36 PNPFS_DEVICE_EXTENSION DeviceExt;
40 DPRINT1("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
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);
49 ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
50 if (ClientFcb == NULL)
52 Irp->IoStatus.Status = STATUS_NO_MEMORY;
53 Irp->IoStatus.Information = 0;
55 IoCompleteRequest(Irp, IO_NO_INCREMENT);
56 DPRINT("No memory!\n");
58 return(STATUS_NO_MEMORY);
61 KeLockMutex(&DeviceExt->PipeListLock);
62 current_entry = DeviceExt->PipeListHead.Flink;
63 while (current_entry != &DeviceExt->PipeListHead)
65 current = CONTAINING_RECORD(current_entry,
69 if (RtlCompareUnicodeString(&FileObject->FileName,
76 current_entry = current_entry->Flink;
79 if (current_entry == &DeviceExt->PipeListHead)
81 ExFreePool(ClientFcb);
82 KeUnlockMutex(&DeviceExt->PipeListLock);
84 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
85 Irp->IoStatus.Information = 0;
87 IoCompleteRequest(Irp, IO_NO_INCREMENT);
88 DPRINT("No pipe found!\n");
90 return(STATUS_OBJECT_NAME_NOT_FOUND);
95 ClientFcb->Pipe = Pipe;
96 ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END;
97 ClientFcb->OtherSide = NULL;
98 ClientFcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
100 /* initialize data list */
101 InitializeListHead(&ClientFcb->DataListHead);
102 KeInitializeSpinLock(&ClientFcb->DataListLock);
104 KeInitializeEvent(&ClientFcb->ConnectEvent,
105 SynchronizationEvent,
108 KeInitializeEvent(&ClientFcb->ReadEvent,
109 SynchronizationEvent,
112 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
113 InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry);
114 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
116 Pipe->ReferenceCount++;
118 KeUnlockMutex(&DeviceExt->PipeListLock);
121 if (Disposition == OPEN_EXISTING)
123 /* do not connect to listening servers */
124 FileObject->FsContext = ClientFcb;
126 Irp->IoStatus.Status = STATUS_SUCCESS;
127 Irp->IoStatus.Information = 0;
129 IoCompleteRequest(Irp, IO_NO_INCREMENT);
130 DPRINT("Success!\n");
132 return(STATUS_SUCCESS);
136 /* search for disconnected or listening server fcb */
137 current_entry = Pipe->ServerFcbListHead.Flink;
138 while (current_entry != &Pipe->ServerFcbListHead)
140 ServerFcb = CONTAINING_RECORD(current_entry,
143 if ((ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE)
144 || (ServerFcb->PipeState == FILE_PIPE_DISCONNECTED_STATE))
146 DPRINT("Server found! Fcb %p\n", ServerFcb);
149 current_entry = current_entry->Flink;
152 if (current_entry == &Pipe->ServerFcbListHead)
154 DPRINT("No server fcb found!\n");
156 FileObject->FsContext = ClientFcb;
158 Irp->IoStatus.Status = STATUS_SUCCESS;
159 Irp->IoStatus.Information = 0;
161 IoCompleteRequest(Irp, IO_NO_INCREMENT);
163 return(STATUS_SUCCESS);
166 ClientFcb->OtherSide = ServerFcb;
167 ServerFcb->OtherSide = ClientFcb;
168 ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
169 ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
171 /* FIXME: create data queue(s) */
173 /* wake server thread */
174 KeSetEvent(&ServerFcb->ConnectEvent, 0, FALSE);
176 FileObject->FsContext = ClientFcb;
178 Irp->IoStatus.Status = STATUS_SUCCESS;
179 Irp->IoStatus.Information = 0;
181 IoCompleteRequest(Irp, IO_NO_INCREMENT);
182 DPRINT("Success!\n");
184 return(STATUS_SUCCESS);
189 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
192 PIO_STACK_LOCATION IoStack;
193 PFILE_OBJECT FileObject;
194 PNPFS_DEVICE_EXTENSION DeviceExt;
198 PLIST_ENTRY current_entry;
200 PIO_PIPE_CREATE_BUFFER Buffer;
202 DPRINT1("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
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);
210 Buffer = (PIO_PIPE_CREATE_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
212 Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE));
215 Irp->IoStatus.Status = STATUS_NO_MEMORY;
216 Irp->IoStatus.Information = 0;
218 IoCompleteRequest(Irp, IO_NO_INCREMENT);
220 return(STATUS_NO_MEMORY);
223 Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
228 Irp->IoStatus.Status = STATUS_NO_MEMORY;
229 Irp->IoStatus.Information = 0;
231 IoCompleteRequest(Irp, IO_NO_INCREMENT);
233 return(STATUS_NO_MEMORY);
236 if (RtlCreateUnicodeString(&Pipe->PipeName, FileObject->FileName.Buffer) == 0)
241 Irp->IoStatus.Status = STATUS_NO_MEMORY;
242 Irp->IoStatus.Information = 0;
244 IoCompleteRequest(Irp, IO_NO_INCREMENT);
246 return(STATUS_NO_MEMORY);
249 Pipe->ReferenceCount = 0;
250 InitializeListHead(&Pipe->ServerFcbListHead);
251 InitializeListHead(&Pipe->ClientFcbListHead);
252 KeInitializeSpinLock(&Pipe->FcbListLock);
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;
265 KeLockMutex(&DeviceExt->PipeListLock);
266 current_entry = DeviceExt->PipeListHead.Flink;
267 while (current_entry != &DeviceExt->PipeListHead)
269 current = CONTAINING_RECORD(current_entry,
273 if (RtlCompareUnicodeString(&Pipe->PipeName, ¤t->PipeName, TRUE) == 0)
278 current_entry = current_entry->Flink;
281 if (current_entry != &DeviceExt->PipeListHead)
283 RtlFreeUnicodeString(&Pipe->PipeName);
290 InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
292 Pipe->ReferenceCount++;
293 Pipe->CurrentInstances++;
295 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
296 InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
297 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
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;
306 /* initialize data list */
307 InitializeListHead(&Fcb->DataListHead);
308 KeInitializeSpinLock(&Fcb->DataListLock);
310 KeInitializeEvent(&Fcb->ConnectEvent,
311 SynchronizationEvent,
314 KeInitializeEvent(&Fcb->ReadEvent,
315 SynchronizationEvent,
319 KeUnlockMutex(&DeviceExt->PipeListLock);
321 FileObject->FsContext = Fcb;
323 Irp->IoStatus.Status = STATUS_SUCCESS;
324 Irp->IoStatus.Information = 0;
326 IoCompleteRequest(Irp, IO_NO_INCREMENT);
328 return(STATUS_SUCCESS);
333 NpfsClose(PDEVICE_OBJECT DeviceObject,
336 PNPFS_DEVICE_EXTENSION DeviceExt;
337 PIO_STACK_LOCATION IoStack;
338 PFILE_OBJECT FileObject;
342 PLIST_ENTRY CurrentEntry;
343 PNPFS_PIPE_DATA Current;
346 DPRINT1("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
348 IoStack = IoGetCurrentIrpStackLocation(Irp);
349 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
350 FileObject = IoStack->FileObject;
351 Fcb = FileObject->FsContext;
355 Irp->IoStatus.Status = STATUS_SUCCESS;
356 Irp->IoStatus.Information = 0;
358 IoCompleteRequest(Irp, IO_NO_INCREMENT);
360 return(STATUS_SUCCESS);
363 DPRINT("Fcb %x\n", Fcb);
366 DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);
368 KeLockMutex(&DeviceExt->PipeListLock);
371 if (Fcb->PipeEnd == FILE_PIPE_SERVER_END)
373 /* FIXME: Clean up existing connections here ?? */
375 Pipe->CurrentInstances--;
376 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
380 Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE;
382 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
385 Pipe->ReferenceCount--;
387 if (Fcb->PipeEnd == FILE_PIPE_CLIENT_END)
390 if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
394 Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE;
396 /* Signaling the read event. If is possible that an other
397 * thread waits of read data.
399 KeSetEvent(&Fcb->OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
401 Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
405 FileObject->FsContext = NULL;
407 if (Pipe->ReferenceCount == 0)
409 KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
412 RemoveEntryList(&Fcb->OtherSide->FcbListEntry);
414 RemoveEntryList(&Fcb->FcbListEntry);
415 KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
418 KeAcquireSpinLock(&Fcb->OtherSide->DataListLock, &oldIrql);
419 while (!IsListEmpty(&Fcb->OtherSide->DataListHead))
421 CurrentEntry = RemoveHeadList(&Fcb->OtherSide->DataListHead);
422 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
424 NpfsFreePipeData(Current);
426 KeReleaseSpinLock(&Fcb->OtherSide->DataListLock, oldIrql);
427 ExFreePool(Fcb->OtherSide);
430 KeAcquireSpinLock(&Fcb->DataListLock, &oldIrql);
431 while (!IsListEmpty(&Fcb->DataListHead))
433 CurrentEntry = RemoveHeadList(&Fcb->DataListHead);
434 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
435 NpfsFreePipeData(Current);
437 KeReleaseSpinLock(&Fcb->DataListLock, oldIrql);
439 RtlFreeUnicodeString(&Pipe->PipeName);
440 RemoveEntryList(&Pipe->PipeListEntry);
444 KeUnlockMutex(&DeviceExt->PipeListLock);
446 Irp->IoStatus.Status = STATUS_SUCCESS;
447 Irp->IoStatus.Information = 0;
449 IoCompleteRequest(Irp, IO_NO_INCREMENT);
451 return(STATUS_SUCCESS);