2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/datasup.c
5 * PURPOSE: Data Queues Support
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_DATASUP)
16 /* FUNCTIONS ******************************************************************/
20 NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue
)
24 ASSERT(DataQueue
->QueueState
== Empty
);
26 RtlZeroMemory(DataQueue
, sizeof(*DataQueue
));
27 return STATUS_SUCCESS
;
32 NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue
,
37 DataQueue
->BytesInQueue
= 0;
38 DataQueue
->EntriesInQueue
= 0;
39 DataQueue
->QuotaUsed
= 0;
40 DataQueue
->ByteOffset
= 0;
41 DataQueue
->QueueState
= Empty
;
42 DataQueue
->Quota
= Quota
;
43 InitializeListHead(&DataQueue
->Queue
);
44 return STATUS_SUCCESS
;
49 NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue
,
52 ULONG QuotaLeft
, ByteOffset
, DataLeft
, NewQuotaLeft
;
53 PNP_DATA_QUEUE_ENTRY DataQueueEntry
;
55 PLIST_ENTRY NextEntry
;
57 QuotaLeft
= DataQueue
->Quota
- DataQueue
->QuotaUsed
;
58 ByteOffset
= DataQueue
->ByteOffset
;
60 NextEntry
= DataQueue
->Queue
.Flink
;
61 while (NextEntry
!= &DataQueue
->Queue
)
63 if (!QuotaLeft
) break;
65 DataQueueEntry
= CONTAINING_RECORD(NextEntry
, NP_DATA_QUEUE_ENTRY
, Irp
);
67 Irp
= DataQueueEntry
->Irp
;
69 if ((DataQueueEntry
->DataEntryType
== 0) && (Irp
))
71 DataLeft
= DataQueueEntry
->DataSize
- ByteOffset
;
73 if (DataQueueEntry
->QuotaInEntry
< DataLeft
)
75 NewQuotaLeft
= DataLeft
- DataQueueEntry
->QuotaInEntry
;
76 if (NewQuotaLeft
> QuotaLeft
) NewQuotaLeft
= QuotaLeft
;
78 QuotaLeft
-= NewQuotaLeft
;
79 DataQueueEntry
->QuotaInEntry
+= NewQuotaLeft
;
81 if (DataQueueEntry
->QuotaInEntry
== DataLeft
&&
82 IoSetCancelRoutine(Irp
, NULL
))
84 DataQueueEntry
->Irp
= NULL
;
86 Irp
->IoStatus
.Status
= 0;
87 Irp
->IoStatus
.Information
= DataQueueEntry
->DataSize
;
89 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
94 NextEntry
= NextEntry
->Flink
;
98 DataQueue
->QuotaUsed
= DataQueue
->Quota
- QuotaLeft
;
103 NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue
,
108 PNP_DATA_QUEUE_ENTRY QueueEntry
;
111 if (DataQueue
->QueueState
== Empty
)
114 ASSERT(IsListEmpty(&DataQueue
->Queue
));
115 ASSERT(DataQueue
->EntriesInQueue
== 0);
116 ASSERT(DataQueue
->BytesInQueue
== 0);
117 ASSERT(DataQueue
->QuotaUsed
== 0);
121 QueueEntry
= CONTAINING_RECORD(RemoveHeadList(&DataQueue
->Queue
),
125 DataQueue
->BytesInQueue
-= QueueEntry
->DataSize
;
126 --DataQueue
->EntriesInQueue
;
129 if (!DataQueue
->QueueState
!= WriteEntries
|| DataQueue
->QuotaUsed
< DataQueue
->Quota
|| !QueueEntry
->QuotaInEntry
)
134 DataQueue
->QuotaUsed
-= QueueEntry
->QuotaInEntry
;
136 if (DataQueue
->Queue
.Flink
== &DataQueue
->Queue
)
138 DataQueue
->QueueState
= Empty
;
142 Irp
= QueueEntry
->Irp
;
143 NpFreeClientSecurityContext(QueueEntry
->ClientSecurityContext
);
145 if (Irp
&& IoSetCancelRoutine(Irp
, NULL
))
147 Irp
->Tail
.Overlay
.DriverContext
[3] = NULL
;
150 ExFreePool(QueueEntry
);
154 NpGetNextRealDataQueueEntry(DataQueue
, List
);
159 NpCompleteStalledWrites(DataQueue
, List
);
163 DataQueue
->ByteOffset
= 0;
169 NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue
,
172 PNP_DATA_QUEUE_ENTRY DataEntry
;
175 PLIST_ENTRY NextEntry
;
180 NextEntry
= DataQueue
->Queue
.Flink
;
181 while (NextEntry
!= &DataQueue
->Queue
)
183 DataEntry
= CONTAINING_RECORD(NextEntry
, NP_DATA_QUEUE_ENTRY
, QueueEntry
);
185 Type
= DataEntry
->DataEntryType
;
186 if (Type
== Buffered
|| Type
== Unbuffered
) break;
188 Irp
= NpRemoveDataQueueEntry(DataQueue
, FALSE
, List
);
191 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
192 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
201 NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject
,
204 PNP_DATA_QUEUE DataQueue
;
205 PNP_DATA_QUEUE_ENTRY DataEntry
;
206 LIST_ENTRY DeferredList
;
207 PSECURITY_CLIENT_CONTEXT ClientSecurityContext
;
208 BOOLEAN CompleteWrites
, FirstEntry
;
210 if (DeviceObject
) IoReleaseCancelSpinLock(Irp
->CancelIrql
);
212 InitializeListHead(&DeferredList
);
214 DataQueue
= (PNP_DATA_QUEUE
)Irp
->Tail
.Overlay
.DriverContext
[2];
215 ClientSecurityContext
= NULL
;
219 FsRtlEnterFileSystem();
220 NpAcquireExclusiveVcb();
223 DataEntry
= (PNP_DATA_QUEUE_ENTRY
)Irp
->Tail
.Overlay
.DriverContext
[3];
226 if (DataEntry
->QueueEntry
.Blink
== &DataQueue
->Queue
)
228 DataQueue
->ByteOffset
= 0;
236 RemoveEntryList(&DataEntry
->QueueEntry
);
238 ClientSecurityContext
= DataEntry
->ClientSecurityContext
;
241 if (!DataQueue
->QueueState
!= WriteEntries
|| DataQueue
->QuotaUsed
< DataQueue
->Quota
|| !DataEntry
->QuotaInEntry
)
246 DataQueue
->BytesInQueue
-= DataEntry
->DataSize
;
247 DataQueue
->QuotaUsed
-= DataEntry
->QuotaInEntry
;
248 --DataQueue
->EntriesInQueue
;
250 if (DataQueue
->Queue
.Flink
== &DataQueue
->Queue
)
252 DataQueue
->QueueState
= Empty
;
253 ASSERT(DataQueue
->BytesInQueue
== 0);
254 ASSERT(DataQueue
->EntriesInQueue
== 0);
255 ASSERT(DataQueue
->QuotaUsed
== 0);
261 NpGetNextRealDataQueueEntry(DataQueue
, &DeferredList
);
265 NpCompleteStalledWrites(DataQueue
, &DeferredList
);
273 FsRtlExitFileSystem();
276 if (DataEntry
) ExFreePool(DataEntry
);
278 NpFreeClientSecurityContext(ClientSecurityContext
);
279 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
280 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
282 NpCompleteDeferredIrps(&DeferredList
);
287 NpAddDataQueueEntry(IN ULONG NamedPipeEnd
,
289 IN PNP_DATA_QUEUE DataQueue
,
298 PNP_DATA_QUEUE_ENTRY DataEntry
;
301 PSECURITY_CLIENT_CONTEXT ClientContext
;
304 ClientContext
= NULL
;
305 ASSERT((DataQueue
->QueueState
== Empty
) || (DataQueue
->QueueState
== Who
));
307 Status
= STATUS_SUCCESS
;
309 if ((Type
!= 2) && (Who
== WriteEntries
))
311 Status
= NpGetClientSecurityContext(NamedPipeEnd
,
313 Irp
? Irp
->Tail
.Overlay
.Thread
:
314 PsGetCurrentThread(),
316 if (!NT_SUCCESS(Status
))
329 DataEntry
= ExAllocatePoolWithQuotaTag(NonPagedPool
,
331 NPFS_DATA_ENTRY_TAG
);
334 NpFreeClientSecurityContext(ClientContext
);
335 return STATUS_INSUFFICIENT_RESOURCES
;
338 DataEntry
->DataEntryType
= Type
;
339 DataEntry
->QuotaInEntry
= 0;
340 DataEntry
->Irp
= Irp
;
341 DataEntry
->DataSize
= DataSize
;
342 DataEntry
->ClientSecurityContext
= ClientContext
;
343 ASSERT((DataQueue
->QueueState
== Empty
) || (DataQueue
->QueueState
== Who
));
344 Status
= STATUS_PENDING
;
349 EntrySize
= sizeof(*DataEntry
);
350 if (Who
!= ReadEntries
)
352 EntrySize
+= DataSize
;
353 if (EntrySize
< DataSize
)
355 NpFreeClientSecurityContext(ClientContext
);
356 return STATUS_INVALID_PARAMETER
;
360 QuotaInEntry
= DataSize
- ByteOffset
;
361 if (DataQueue
->Quota
- DataQueue
->QuotaUsed
< QuotaInEntry
)
363 QuotaInEntry
= DataQueue
->Quota
- DataQueue
->QuotaUsed
;
371 DataEntry
= ExAllocatePoolWithQuotaTag(NonPagedPool
,
373 NPFS_DATA_ENTRY_TAG
);
376 NpFreeClientSecurityContext(ClientContext
);
377 return STATUS_INSUFFICIENT_RESOURCES
;
380 DataEntry
->QuotaInEntry
= QuotaInEntry
;
381 DataEntry
->Irp
= Irp
;
382 DataEntry
->DataEntryType
= Buffered
;
383 DataEntry
->ClientSecurityContext
= ClientContext
;
384 DataEntry
->DataSize
= DataSize
;
386 if (Who
== ReadEntries
)
390 Status
= STATUS_PENDING
;
391 ASSERT((DataQueue
->QueueState
== Empty
) ||
392 (DataQueue
->QueueState
== Who
));
398 RtlCopyMemory(DataEntry
+ 1,
399 Irp
? Irp
->UserBuffer
: Buffer
,
402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
404 NpFreeClientSecurityContext(ClientContext
);
405 return _SEH2_GetExceptionCode();
411 Status
= STATUS_PENDING
;
415 DataEntry
->Irp
= NULL
;
416 Status
= STATUS_SUCCESS
;
419 ASSERT((DataQueue
->QueueState
== Empty
) ||
420 (DataQueue
->QueueState
== Who
));
426 NpFreeClientSecurityContext(ClientContext
);
427 return STATUS_INVALID_PARAMETER
;
430 ASSERT((DataQueue
->QueueState
== Empty
) || (DataQueue
->QueueState
== Who
));
431 if (DataQueue
->QueueState
== Empty
)
433 ASSERT(DataQueue
->BytesInQueue
== 0);
434 ASSERT(DataQueue
->EntriesInQueue
== 0);
435 ASSERT(IsListEmpty (&DataQueue
->Queue
));
439 ASSERT(DataQueue
->QueueState
== Who
);
440 ASSERT(DataQueue
->QueueState
!= Empty
);
441 ASSERT(DataQueue
->EntriesInQueue
!= 0);
444 DataQueue
->QuotaUsed
+= DataEntry
->QuotaInEntry
;
445 DataQueue
->QueueState
= Who
;
446 DataQueue
->BytesInQueue
+= DataEntry
->DataSize
;
447 DataQueue
->EntriesInQueue
++;
451 DataQueue
->ByteOffset
= ByteOffset
;
452 ASSERT(Who
== WriteEntries
);
453 ASSERT(ByteOffset
< DataEntry
->DataSize
);
454 ASSERT(DataQueue
->EntriesInQueue
== 1);
457 InsertTailList(&DataQueue
->Queue
, &DataEntry
->QueueEntry
);
459 if (Status
== STATUS_PENDING
)
461 IoMarkIrpPending(Irp
);
462 Irp
->Tail
.Overlay
.DriverContext
[2] = DataQueue
;
463 Irp
->Tail
.Overlay
.DriverContext
[3] = DataEntry
;
465 IoSetCancelRoutine(Irp
, NpCancelDataQueueIrp
);
467 if ((Irp
->Cancel
) && (IoSetCancelRoutine(Irp
, NULL
)))
469 NpCancelDataQueueIrp(NULL
, Irp
);