1 /* $Id: create.c,v 1.11 2001/11/20 20:34:29 ekohl 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>
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 DPRINT("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
;
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
;
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
;
343 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
345 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
346 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
347 FileObject
= IoStack
->FileObject
;
348 Fcb
= FileObject
->FsContext
;
352 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
353 Irp
->IoStatus
.Information
= 0;
355 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
357 return(STATUS_SUCCESS
);
360 DPRINT("Fcb %x\n", Fcb
);
363 DPRINT("Closing pipe %wZ\n", &Pipe
->PipeName
);
365 KeLockMutex(&DeviceExt
->PipeListLock
);
368 if (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
)
370 /* FIXME: Clean up existing connections here ?? */
371 Pipe
->CurrentInstances
--;
373 Pipe
->ReferenceCount
--;
375 if ((Fcb
->PipeEnd
== FILE_PIPE_CLIENT_END
)
376 && (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
))
378 Fcb
->OtherSide
->PipeState
= FILE_PIPE_CLOSING_STATE
;
379 Fcb
->OtherSide
->OtherSide
= NULL
;
380 Fcb
->OtherSide
= NULL
;
381 Fcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
384 KeAcquireSpinLock(&Pipe
->FcbListLock
, &oldIrql
);
385 RemoveEntryList(&Fcb
->FcbListEntry
);
386 KeReleaseSpinLock(&Pipe
->FcbListLock
, oldIrql
);
389 FileObject
->FsContext
= NULL
;
391 if (Pipe
->ReferenceCount
== 0)
393 RtlFreeUnicodeString(&Pipe
->PipeName
);
394 RemoveEntryList(&Pipe
->PipeListEntry
);
398 KeUnlockMutex(&DeviceExt
->PipeListLock
);
400 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
401 Irp
->IoStatus
.Information
= 0;
403 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
405 return(STATUS_SUCCESS
);