1 /* $Id: create.c,v 1.18 2004/04/12 14:46:02 navaraf Exp $
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>
19 /* FUNCTIONS *****************************************************************/
22 NpfsCreate(PDEVICE_OBJECT DeviceObject
,
25 PIO_STACK_LOCATION IoStack
;
26 PFILE_OBJECT FileObject
;
31 PLIST_ENTRY current_entry
;
32 PNPFS_DEVICE_EXTENSION DeviceExt
;
36 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
38 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
39 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
40 FileObject
= IoStack
->FileObject
;
41 Disposition
= ((IoStack
->Parameters
.Create
.Options
>> 24) & 0xff);
42 DPRINT("FileObject %p\n", FileObject
);
43 DPRINT("FileName %wZ\n", &FileObject
->FileName
);
45 ClientFcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
46 if (ClientFcb
== NULL
)
48 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
49 Irp
->IoStatus
.Information
= 0;
51 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
52 DPRINT("No memory!\n");
54 return(STATUS_NO_MEMORY
);
57 KeLockMutex(&DeviceExt
->PipeListLock
);
58 current_entry
= DeviceExt
->PipeListHead
.Flink
;
59 while (current_entry
!= &DeviceExt
->PipeListHead
)
61 current
= CONTAINING_RECORD(current_entry
,
65 if (RtlCompareUnicodeString(&FileObject
->FileName
,
72 current_entry
= current_entry
->Flink
;
75 if (current_entry
== &DeviceExt
->PipeListHead
)
77 ExFreePool(ClientFcb
);
78 KeUnlockMutex(&DeviceExt
->PipeListLock
);
80 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
81 Irp
->IoStatus
.Information
= 0;
83 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
84 DPRINT("No pipe found!\n");
86 return(STATUS_OBJECT_NAME_NOT_FOUND
);
91 ClientFcb
->Pipe
= Pipe
;
92 ClientFcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
93 ClientFcb
->OtherSide
= NULL
;
94 ClientFcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
96 /* initialize data list */
97 if (Pipe
->InboundQuota
)
99 ClientFcb
->Data
= ExAllocatePool(NonPagedPool
, Pipe
->InboundQuota
);
100 if (ClientFcb
->Data
== NULL
)
102 ExFreePool(ClientFcb
);
103 KeUnlockMutex(&DeviceExt
->PipeListLock
);
105 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
106 Irp
->IoStatus
.Information
= 0;
108 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
109 DPRINT("No memory!\n");
111 return(STATUS_NO_MEMORY
);
116 ClientFcb
->Data
= NULL
;
118 ClientFcb
->ReadPtr
= ClientFcb
->Data
;
119 ClientFcb
->WritePtr
= ClientFcb
->Data
;
120 ClientFcb
->ReadDataAvailable
= 0;
121 ClientFcb
->WriteQuotaAvailable
= Pipe
->InboundQuota
;
122 ClientFcb
->MaxDataLength
= Pipe
->InboundQuota
;
123 KeInitializeSpinLock(&ClientFcb
->DataListLock
);
125 KeInitializeEvent(&ClientFcb
->ConnectEvent
,
126 SynchronizationEvent
,
129 KeInitializeEvent(&ClientFcb
->Event
,
130 SynchronizationEvent
,
133 KeAcquireSpinLock(&Pipe
->FcbListLock
, &oldIrql
);
134 InsertTailList(&Pipe
->ClientFcbListHead
, &ClientFcb
->FcbListEntry
);
135 KeReleaseSpinLock(&Pipe
->FcbListLock
, oldIrql
);
137 Pipe
->ReferenceCount
++;
139 KeUnlockMutex(&DeviceExt
->PipeListLock
);
141 /* search for listening server fcb */
142 current_entry
= Pipe
->ServerFcbListHead
.Flink
;
143 while (current_entry
!= &Pipe
->ServerFcbListHead
)
145 ServerFcb
= CONTAINING_RECORD(current_entry
,
148 if (ServerFcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
150 DPRINT("Server found! Fcb %p\n", ServerFcb
);
153 current_entry
= current_entry
->Flink
;
156 if (current_entry
== &Pipe
->ServerFcbListHead
)
158 DPRINT("No server fcb found!\n");
160 FileObject
->FsContext
= ClientFcb
;
162 if (Disposition
== FILE_OPEN
)
164 Irp
->IoStatus
.Status
= STATUS_PIPE_BUSY
;
165 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
166 return STATUS_PIPE_BUSY
;
170 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
171 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
172 return STATUS_SUCCESS
;
176 ClientFcb
->OtherSide
= ServerFcb
;
177 ServerFcb
->OtherSide
= ClientFcb
;
178 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
179 ServerFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
181 /* FIXME: create data queue(s) */
183 /* wake server thread */
184 KeSetEvent(&ServerFcb
->ConnectEvent
, 0, FALSE
);
186 FileObject
->FsContext
= ClientFcb
;
188 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
189 Irp
->IoStatus
.Information
= 0;
191 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
192 DPRINT("Success!\n");
194 return(STATUS_SUCCESS
);
199 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
202 PIO_STACK_LOCATION IoStack
;
203 PFILE_OBJECT FileObject
;
204 PNPFS_DEVICE_EXTENSION DeviceExt
;
208 PLIST_ENTRY current_entry
;
210 PIO_PIPE_CREATE_BUFFER Buffer
;
212 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
214 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
215 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
216 FileObject
= IoStack
->FileObject
;
217 DPRINT("FileObject %p\n", FileObject
);
218 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
220 Buffer
= (PIO_PIPE_CREATE_BUFFER
)Irp
->Tail
.Overlay
.AuxiliaryBuffer
;
222 Irp
->IoStatus
.Information
= 0;
224 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
227 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
228 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
229 return STATUS_NO_MEMORY
;
232 KeLockMutex(&DeviceExt
->PipeListLock
);
235 * First search for existing Pipe with the same name.
238 current_entry
= DeviceExt
->PipeListHead
.Flink
;
239 while (current_entry
!= &DeviceExt
->PipeListHead
)
241 current
= CONTAINING_RECORD(current_entry
,
245 if (RtlCompareUnicodeString(&FileObject
->FileName
, ¤t
->PipeName
, TRUE
) == 0)
250 current_entry
= current_entry
->Flink
;
253 if (current_entry
!= &DeviceExt
->PipeListHead
)
256 * Found Pipe with the same name. Check if we are
261 KeUnlockMutex(&DeviceExt
->PipeListLock
);
263 if (Pipe
->CurrentInstances
>= Pipe
->MaximumInstances
)
266 Irp
->IoStatus
.Status
= STATUS_PIPE_BUSY
;
267 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
268 return STATUS_PIPE_BUSY
;
271 /* FIXME: Check pipe modes also! */
272 if (Pipe
->MaximumInstances
!= Buffer
->MaxInstances
||
273 Pipe
->TimeOut
.QuadPart
!= Buffer
->TimeOut
.QuadPart
)
276 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
277 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
278 return STATUS_ACCESS_DENIED
;
283 Pipe
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_PIPE
));
286 KeUnlockMutex(&DeviceExt
->PipeListLock
);
287 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
288 Irp
->IoStatus
.Information
= 0;
289 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
290 return STATUS_NO_MEMORY
;
293 if (RtlCreateUnicodeString(&Pipe
->PipeName
, FileObject
->FileName
.Buffer
) == 0)
295 KeUnlockMutex(&DeviceExt
->PipeListLock
);
298 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
299 Irp
->IoStatus
.Information
= 0;
300 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
301 return(STATUS_NO_MEMORY
);
304 Pipe
->ReferenceCount
= 0;
305 InitializeListHead(&Pipe
->ServerFcbListHead
);
306 InitializeListHead(&Pipe
->ClientFcbListHead
);
307 KeInitializeSpinLock(&Pipe
->FcbListLock
);
309 Pipe
->PipeType
= Buffer
->WriteModeMessage
? FILE_PIPE_MESSAGE_TYPE
: FILE_PIPE_BYTE_STREAM_TYPE
;
310 Pipe
->PipeWriteMode
= Buffer
->WriteModeMessage
? FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
311 Pipe
->PipeReadMode
= Buffer
->ReadModeMessage
? FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
312 Pipe
->PipeBlockMode
= Buffer
->NonBlocking
;
313 Pipe
->PipeConfiguration
= IoStack
->Parameters
.Create
.Options
& 0x3;
314 Pipe
->MaximumInstances
= Buffer
->MaxInstances
;
315 Pipe
->CurrentInstances
= 0;
316 Pipe
->TimeOut
= Buffer
->TimeOut
;
317 if (!(IoStack
->Parameters
.Create
.Options
& FILE_PIPE_OUTBOUND
) ||
318 IoStack
->Parameters
.Create
.Options
& FILE_PIPE_FULL_DUPLEX
)
320 if (Buffer
->InBufferSize
== 0)
322 Pipe
->InboundQuota
= DeviceExt
->DefaultQuota
;
326 Pipe
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InBufferSize
);
327 if (Pipe
->InboundQuota
< DeviceExt
->MinQuota
)
329 Pipe
->InboundQuota
= DeviceExt
->MinQuota
;
331 else if (Pipe
->InboundQuota
> DeviceExt
->MaxQuota
)
333 Pipe
->InboundQuota
= DeviceExt
->MaxQuota
;
339 Pipe
->InboundQuota
= 0;
341 if (IoStack
->Parameters
.Create
.Options
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
343 if (Buffer
->OutBufferSize
== 0)
345 Pipe
->OutboundQuota
= DeviceExt
->DefaultQuota
;
349 Pipe
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutBufferSize
);
350 if (Pipe
->OutboundQuota
< DeviceExt
->MinQuota
)
352 Pipe
->OutboundQuota
= DeviceExt
->MinQuota
;
354 else if (Pipe
->OutboundQuota
> DeviceExt
->MaxQuota
)
356 Pipe
->OutboundQuota
= DeviceExt
->MaxQuota
;
362 Pipe
->OutboundQuota
= 0;
365 InsertTailList(&DeviceExt
->PipeListHead
, &Pipe
->PipeListEntry
);
366 KeUnlockMutex(&DeviceExt
->PipeListLock
);
369 if (Pipe
->OutboundQuota
)
371 Fcb
->Data
= ExAllocatePool(NonPagedPool
, Pipe
->OutboundQuota
);
372 if (Fcb
->Data
== NULL
)
378 RtlFreeUnicodeString(&Pipe
->PipeName
);
382 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
383 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
384 return STATUS_NO_MEMORY
;
392 Fcb
->ReadPtr
= Fcb
->Data
;
393 Fcb
->WritePtr
= Fcb
->Data
;
394 Fcb
->ReadDataAvailable
= 0;
395 Fcb
->WriteQuotaAvailable
= Pipe
->OutboundQuota
;
396 Fcb
->MaxDataLength
= Pipe
->OutboundQuota
;
397 KeInitializeSpinLock(&Fcb
->DataListLock
);
399 Pipe
->ReferenceCount
++;
400 Pipe
->CurrentInstances
++;
402 KeAcquireSpinLock(&Pipe
->FcbListLock
, &oldIrql
);
403 InsertTailList(&Pipe
->ServerFcbListHead
, &Fcb
->FcbListEntry
);
404 KeReleaseSpinLock(&Pipe
->FcbListLock
, oldIrql
);
407 Fcb
->PipeEnd
= FILE_PIPE_SERVER_END
;
408 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
409 Fcb
->OtherSide
= NULL
;
411 KeInitializeEvent(&Fcb
->ConnectEvent
,
412 SynchronizationEvent
,
415 KeInitializeEvent(&Fcb
->Event
,
416 SynchronizationEvent
,
419 FileObject
->FsContext
= Fcb
;
421 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
422 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
424 return(STATUS_SUCCESS
);
429 NpfsClose(PDEVICE_OBJECT DeviceObject
,
432 PNPFS_DEVICE_EXTENSION DeviceExt
;
433 PIO_STACK_LOCATION IoStack
;
434 PFILE_OBJECT FileObject
;
439 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
441 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
442 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
443 FileObject
= IoStack
->FileObject
;
444 Fcb
= FileObject
->FsContext
;
448 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
449 Irp
->IoStatus
.Information
= 0;
451 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
453 return(STATUS_SUCCESS
);
456 DPRINT("Fcb %x\n", Fcb
);
459 DPRINT("Closing pipe %wZ\n", &Pipe
->PipeName
);
461 KeLockMutex(&DeviceExt
->PipeListLock
);
463 if (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
)
465 /* FIXME: Clean up existing connections here ?? */
467 Pipe
->CurrentInstances
--;
468 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
472 Fcb
->OtherSide
->PipeState
= FILE_PIPE_CLOSING_STATE
;
473 /* Signaling the write event. If is possible that an other
474 * thread waits of an empty buffer.
476 KeSetEvent(&Fcb
->OtherSide
->Event
, IO_NO_INCREMENT
, FALSE
);
482 Pipe
->ReferenceCount
--;
484 if (Fcb
->PipeEnd
== FILE_PIPE_CLIENT_END
)
487 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
491 Fcb
->OtherSide
->PipeState
= FILE_PIPE_CLOSING_STATE
;
493 /* Signaling the read event. If is possible that an other
494 * thread waits of read data.
496 KeSetEvent(&Fcb
->OtherSide
->Event
, IO_NO_INCREMENT
, FALSE
);
502 FileObject
->FsContext
= NULL
;
505 DPRINT("%x\n", Pipe
->ReferenceCount
);
506 if (Pipe
->ReferenceCount
== 0)
508 if (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
&&
509 Fcb
->Pipe
->CurrentInstances
== 0)
512 KeAcquireSpinLock(&Pipe
->FcbListLock
, &oldIrql
);
515 RemoveEntryList(&Fcb
->OtherSide
->FcbListEntry
);
517 RemoveEntryList(&Fcb
->FcbListEntry
);
518 KeReleaseSpinLock(&Pipe
->FcbListLock
, oldIrql
);
521 if (Fcb
->OtherSide
->Data
)
523 ExFreePool(Fcb
->OtherSide
->Data
);
525 ExFreePool(Fcb
->OtherSide
);
529 ExFreePool(Fcb
->Data
);
532 RtlFreeUnicodeString(&Pipe
->PipeName
);
533 RemoveEntryList(&Pipe
->PipeListEntry
);
537 KeUnlockMutex(&DeviceExt
->PipeListLock
);
539 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
540 Irp
->IoStatus
.Information
= 0;
542 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
544 return(STATUS_SUCCESS
);