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 /* FUNCTIONS ******************************************************************/
17 NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue
)
21 ASSERT(DataQueue
->QueueState
== Empty
);
23 RtlZeroMemory(DataQueue
, sizeof(*DataQueue
));
24 return STATUS_SUCCESS
;
29 NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue
,
34 DataQueue
->BytesInQueue
= 0;
35 DataQueue
->EntriesInQueue
= 0;
36 DataQueue
->QuotaUsed
= 0;
37 DataQueue
->ByteOffset
= 0;
38 DataQueue
->QueueState
= Empty
;
39 DataQueue
->Quota
= Quota
;
40 InitializeListHead(&DataQueue
->Queue
);
41 return STATUS_SUCCESS
;
46 NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue
,
49 ULONG QuotaLeft
, ByteOffset
, DataLeft
, NewQuotaLeft
;
50 PNP_DATA_QUEUE_ENTRY DataQueueEntry
;
52 PLIST_ENTRY NextEntry
;
54 QuotaLeft
= DataQueue
->Quota
- DataQueue
->QuotaUsed
;
55 ByteOffset
= DataQueue
->ByteOffset
;
57 NextEntry
= DataQueue
->Queue
.Flink
;
58 while (NextEntry
!= &DataQueue
->Queue
)
60 if (!QuotaLeft
) break;
62 DataQueueEntry
= CONTAINING_RECORD(NextEntry
, NP_DATA_QUEUE_ENTRY
, Irp
);
64 Irp
= DataQueueEntry
->Irp
;
66 if ((DataQueueEntry
->DataEntryType
== 0) && (Irp
))
68 DataLeft
= DataQueueEntry
->DataSize
- ByteOffset
;
70 if (DataQueueEntry
->QuotaInEntry
< DataLeft
)
72 NewQuotaLeft
= DataLeft
- DataQueueEntry
->QuotaInEntry
;
73 if (NewQuotaLeft
> QuotaLeft
) NewQuotaLeft
= QuotaLeft
;
75 QuotaLeft
-= NewQuotaLeft
;
76 DataQueueEntry
->QuotaInEntry
+= NewQuotaLeft
;
78 if (DataQueueEntry
->QuotaInEntry
== DataLeft
&&
79 IoSetCancelRoutine(Irp
, NULL
))
81 DataQueueEntry
->Irp
= NULL
;
83 Irp
->IoStatus
.Status
= 0;
84 Irp
->IoStatus
.Information
= DataQueueEntry
->DataSize
;
86 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
91 NextEntry
= NextEntry
->Flink
;
95 DataQueue
->QuotaUsed
= DataQueue
->Quota
- QuotaLeft
;
100 NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue
,
105 PNP_DATA_QUEUE_ENTRY QueueEntry
;
108 if (DataQueue
->QueueState
== Empty
)
111 ASSERT(IsListEmpty(&DataQueue
->Queue
));
112 ASSERT(DataQueue
->EntriesInQueue
== 0);
113 ASSERT(DataQueue
->BytesInQueue
== 0);
114 ASSERT(DataQueue
->QuotaUsed
== 0);
118 QueueEntry
= CONTAINING_RECORD(RemoveHeadList(&DataQueue
->Queue
),
122 DataQueue
->BytesInQueue
-= QueueEntry
->DataSize
;
123 --DataQueue
->EntriesInQueue
;
126 if (!DataQueue
->QueueState
!= WriteEntries
|| DataQueue
->QuotaUsed
< DataQueue
->Quota
|| !QueueEntry
->QuotaInEntry
)
131 DataQueue
->QuotaUsed
-= QueueEntry
->QuotaInEntry
;
133 if (DataQueue
->Queue
.Flink
== &DataQueue
->Queue
)
135 DataQueue
->QueueState
= Empty
;
139 Irp
= QueueEntry
->Irp
;
140 NpFreeClientSecurityContext(QueueEntry
->ClientSecurityContext
);
142 if (Irp
&& IoSetCancelRoutine(Irp
, NULL
))
144 Irp
->Tail
.Overlay
.DriverContext
[3] = NULL
;
147 ExFreePool(QueueEntry
);
151 NpGetNextRealDataQueueEntry(DataQueue
, List
);
156 NpCompleteStalledWrites(DataQueue
, List
);
160 DataQueue
->ByteOffset
= 0;
166 NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue
,
169 PNP_DATA_QUEUE_ENTRY DataEntry
;
172 PLIST_ENTRY NextEntry
;
177 NextEntry
= DataQueue
->Queue
.Flink
;
178 while (NextEntry
!= &DataQueue
->Queue
)
180 DataEntry
= CONTAINING_RECORD(NextEntry
, NP_DATA_QUEUE_ENTRY
, QueueEntry
);
182 Type
= DataEntry
->DataEntryType
;
183 if (Type
== Buffered
|| Type
== Unbuffered
) break;
185 Irp
= NpRemoveDataQueueEntry(DataQueue
, FALSE
, List
);
188 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
189 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
198 NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject
,
201 PNP_DATA_QUEUE DataQueue
;
202 PNP_DATA_QUEUE_ENTRY DataEntry
;
203 LIST_ENTRY DeferredList
;
204 PSECURITY_CLIENT_CONTEXT ClientSecurityContext
;
205 BOOLEAN CompleteWrites
, FirstEntry
;
207 if (DeviceObject
) IoReleaseCancelSpinLock(Irp
->CancelIrql
);
209 InitializeListHead(&DeferredList
);
211 DataQueue
= (PNP_DATA_QUEUE
)Irp
->Tail
.Overlay
.DriverContext
[2];
212 ClientSecurityContext
= NULL
;
216 FsRtlEnterFileSystem();
217 NpAcquireExclusiveVcb();
220 DataEntry
= (PNP_DATA_QUEUE_ENTRY
)Irp
->Tail
.Overlay
.DriverContext
[3];
223 if (DataEntry
->QueueEntry
.Blink
== &DataQueue
->Queue
)
225 DataQueue
->ByteOffset
= 0;
233 RemoveEntryList(&DataEntry
->QueueEntry
);
235 ClientSecurityContext
= DataEntry
->ClientSecurityContext
;
238 if (!DataQueue
->QueueState
!= WriteEntries
|| DataQueue
->QuotaUsed
< DataQueue
->Quota
|| !DataEntry
->QuotaInEntry
)
243 DataQueue
->BytesInQueue
-= DataEntry
->DataSize
;
244 DataQueue
->QuotaUsed
-= DataEntry
->QuotaInEntry
;
245 --DataQueue
->EntriesInQueue
;
247 if (DataQueue
->Queue
.Flink
== &DataQueue
->Queue
)
249 DataQueue
->QueueState
= Empty
;
250 ASSERT(DataQueue
->BytesInQueue
== 0);
251 ASSERT(DataQueue
->EntriesInQueue
== 0);
252 ASSERT(DataQueue
->QuotaUsed
== 0);
258 NpGetNextRealDataQueueEntry(DataQueue
, &DeferredList
);
262 NpCompleteStalledWrites(DataQueue
, &DeferredList
);
270 FsRtlExitFileSystem();
273 if (DataEntry
) ExFreePool(DataEntry
);
275 NpFreeClientSecurityContext(ClientSecurityContext
);
276 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
277 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
279 NpCompleteDeferredIrps(&DeferredList
);
284 NpAddDataQueueEntry(IN ULONG NamedPipeEnd
,
286 IN PNP_DATA_QUEUE DataQueue
,
295 PNP_DATA_QUEUE_ENTRY DataEntry
;
298 PSECURITY_CLIENT_CONTEXT ClientContext
;
301 ClientContext
= NULL
;
302 ASSERT((DataQueue
->QueueState
== Empty
) || (DataQueue
->QueueState
== Who
));
304 Status
= STATUS_SUCCESS
;
306 if ((Type
!= 2) && (Who
== WriteEntries
))
308 Status
= NpGetClientSecurityContext(NamedPipeEnd
,
310 Irp
? Irp
->Tail
.Overlay
.Thread
:
311 PsGetCurrentThread(),
313 if (!NT_SUCCESS(Status
))
326 DataEntry
= ExAllocatePoolWithQuotaTag(NonPagedPool
,
328 NPFS_DATA_ENTRY_TAG
);
331 NpFreeClientSecurityContext(ClientContext
);
332 return STATUS_INSUFFICIENT_RESOURCES
;
335 DataEntry
->DataEntryType
= Type
;
336 DataEntry
->QuotaInEntry
= 0;
337 DataEntry
->Irp
= Irp
;
338 DataEntry
->DataSize
= DataSize
;
339 DataEntry
->ClientSecurityContext
= ClientContext
;
340 ASSERT((DataQueue
->QueueState
== Empty
) || (DataQueue
->QueueState
== Who
));
341 Status
= STATUS_PENDING
;
346 EntrySize
= sizeof(*DataEntry
);
347 if (Who
!= ReadEntries
)
349 EntrySize
+= DataSize
;
350 if (EntrySize
< DataSize
)
352 NpFreeClientSecurityContext(ClientContext
);
353 return STATUS_INVALID_PARAMETER
;
357 QuotaInEntry
= DataSize
- ByteOffset
;
358 if (DataQueue
->Quota
- DataQueue
->QuotaUsed
< QuotaInEntry
)
360 QuotaInEntry
= DataQueue
->Quota
- DataQueue
->QuotaUsed
;
368 DataEntry
= ExAllocatePoolWithQuotaTag(NonPagedPool
,
370 NPFS_DATA_ENTRY_TAG
);
373 NpFreeClientSecurityContext(ClientContext
);
374 return STATUS_INSUFFICIENT_RESOURCES
;
377 DataEntry
->QuotaInEntry
= QuotaInEntry
;
378 DataEntry
->Irp
= Irp
;
379 DataEntry
->DataEntryType
= Buffered
;
380 DataEntry
->ClientSecurityContext
= ClientContext
;
381 DataEntry
->DataSize
= DataSize
;
383 if (Who
== ReadEntries
)
387 Status
= STATUS_PENDING
;
388 ASSERT((DataQueue
->QueueState
== Empty
) ||
389 (DataQueue
->QueueState
== Who
));
395 RtlCopyMemory(DataEntry
+ 1,
396 Irp
? Irp
->UserBuffer
: Buffer
,
399 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
401 NpFreeClientSecurityContext(ClientContext
);
402 return _SEH2_GetExceptionCode();
408 Status
= STATUS_PENDING
;
412 DataEntry
->Irp
= NULL
;
413 Status
= STATUS_SUCCESS
;
416 ASSERT((DataQueue
->QueueState
== Empty
) ||
417 (DataQueue
->QueueState
== Who
));
423 NpFreeClientSecurityContext(ClientContext
);
424 return STATUS_INVALID_PARAMETER
;
427 ASSERT((DataQueue
->QueueState
== Empty
) || (DataQueue
->QueueState
== Who
));
428 if (DataQueue
->QueueState
== Empty
)
430 ASSERT(DataQueue
->BytesInQueue
== 0);
431 ASSERT(DataQueue
->EntriesInQueue
== 0);
432 ASSERT(IsListEmpty (&DataQueue
->Queue
));
436 ASSERT(DataQueue
->QueueState
== Who
);
437 ASSERT(DataQueue
->QueueState
!= Empty
);
438 ASSERT(DataQueue
->EntriesInQueue
!= 0);
441 DataQueue
->QuotaUsed
+= DataEntry
->QuotaInEntry
;
442 DataQueue
->QueueState
= Who
;
443 DataQueue
->BytesInQueue
+= DataEntry
->DataSize
;
444 DataQueue
->EntriesInQueue
++;
448 DataQueue
->ByteOffset
= ByteOffset
;
449 ASSERT(Who
== WriteEntries
);
450 ASSERT(ByteOffset
< DataEntry
->DataSize
);
451 ASSERT(DataQueue
->EntriesInQueue
== 1);
454 InsertTailList(&DataQueue
->Queue
, &DataEntry
->QueueEntry
);
456 if (Status
== STATUS_PENDING
)
458 IoMarkIrpPending(Irp
);
459 Irp
->Tail
.Overlay
.DriverContext
[2] = DataQueue
;
460 Irp
->Tail
.Overlay
.DriverContext
[3] = DataEntry
;
462 IoSetCancelRoutine(Irp
, NpCancelDataQueueIrp
);
464 if ((Irp
->Cancel
) && (IoSetCancelRoutine(Irp
, NULL
)))
466 NpCancelDataQueueIrp(NULL
, Irp
);