ReactOS 0.4.15-dev-7788-g1ad9096
datasup.c
Go to the documentation of this file.
1/*
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
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include "npfs.h"
12
13// File ID number for NPFS bugchecking support
14#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_DATASUP)
15
16/* FUNCTIONS ******************************************************************/
17
21{
22 PAGED_CODE();
23
24 ASSERT(DataQueue->QueueState == Empty);
25
26 RtlZeroMemory(DataQueue, sizeof(*DataQueue));
27 return STATUS_SUCCESS;
28}
29
33 IN ULONG Quota)
34{
35 PAGED_CODE();
36
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;
45}
46
47VOID
51{
52 ULONG QuotaLeft, ByteOffset, DataLeft, NewQuotaLeft;
53 PNP_DATA_QUEUE_ENTRY DataQueueEntry;
54 PIRP Irp;
55 PLIST_ENTRY NextEntry;
56
57 QuotaLeft = DataQueue->Quota - DataQueue->QuotaUsed;
58 ByteOffset = DataQueue->ByteOffset;
59
60 NextEntry = DataQueue->Queue.Flink;
61 while (NextEntry != &DataQueue->Queue)
62 {
63 if (!QuotaLeft) break;
64
65 DataQueueEntry = CONTAINING_RECORD(NextEntry,
67 QueueEntry);
68
69 Irp = DataQueueEntry->Irp;
70
71 if ((DataQueueEntry->DataEntryType == Buffered) && (Irp))
72 {
73 DataLeft = DataQueueEntry->DataSize - ByteOffset;
74
75 if (DataQueueEntry->QuotaInEntry < DataLeft)
76 {
77 NewQuotaLeft = DataLeft - DataQueueEntry->QuotaInEntry;
78 if (NewQuotaLeft > QuotaLeft) NewQuotaLeft = QuotaLeft;
79
80 QuotaLeft -= NewQuotaLeft;
81 DataQueueEntry->QuotaInEntry += NewQuotaLeft;
82
83 if (DataQueueEntry->QuotaInEntry == DataLeft &&
85 {
86 DataQueueEntry->Irp = NULL;
87
88 Irp->IoStatus.Status = STATUS_SUCCESS;
89 Irp->IoStatus.Information = DataQueueEntry->DataSize;
90
91 InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
92 }
93 }
94 }
95
96 NextEntry = NextEntry->Flink;
97 ByteOffset = 0;
98 }
99
100 DataQueue->QuotaUsed = DataQueue->Quota - QuotaLeft;
101}
102
103PIRP
104NTAPI
108{
109 PIRP Irp;
110 PNP_DATA_QUEUE_ENTRY QueueEntry;
111 BOOLEAN HasWrites;
112
113 if (DataQueue->QueueState == Empty)
114 {
115 Irp = NULL;
116 ASSERT(IsListEmpty(&DataQueue->Queue));
117 ASSERT(DataQueue->EntriesInQueue == 0);
118 ASSERT(DataQueue->BytesInQueue == 0);
119 ASSERT(DataQueue->QuotaUsed == 0);
120 }
121 else
122 {
123 QueueEntry = CONTAINING_RECORD(RemoveHeadList(&DataQueue->Queue),
125 QueueEntry);
126
127 DataQueue->BytesInQueue -= QueueEntry->DataSize;
128 --DataQueue->EntriesInQueue;
129
130 HasWrites = TRUE;
131 if (DataQueue->QueueState != WriteEntries ||
132 DataQueue->QuotaUsed < DataQueue->Quota ||
133 !QueueEntry->QuotaInEntry)
134 {
135 HasWrites = FALSE;
136 }
137
138 DataQueue->QuotaUsed -= QueueEntry->QuotaInEntry;
139
140 if (IsListEmpty(&DataQueue->Queue))
141 {
142 DataQueue->QueueState = Empty;
143 HasWrites = FALSE;
144 }
145
146 Irp = QueueEntry->Irp;
148
149 if (Irp && !IoSetCancelRoutine(Irp, NULL))
150 {
151 Irp->Tail.Overlay.DriverContext[3] = NULL;
152 Irp = NULL;
153 }
154
155 ExFreePool(QueueEntry);
156
157 if (Flag)
158 {
160 }
161
162 if (HasWrites)
163 {
164 NpCompleteStalledWrites(DataQueue, List);
165 }
166 }
167
168 DataQueue->ByteOffset = 0;
169 return Irp;
170}
171
173NTAPI
176{
177 PNP_DATA_QUEUE_ENTRY DataEntry;
178 ULONG Type;
179 PIRP Irp;
180 PLIST_ENTRY NextEntry;
181 PAGED_CODE();
182
183 for (NextEntry = DataQueue->Queue.Flink;
184 NextEntry != &DataQueue->Queue;
185 NextEntry = DataQueue->Queue.Flink)
186 {
187 DataEntry = CONTAINING_RECORD(NextEntry,
189 QueueEntry);
190
191 Type = DataEntry->DataEntryType;
192 if (Type == Buffered || Type == Unbuffered) break;
193
194 Irp = NpRemoveDataQueueEntry(DataQueue, FALSE, List);
195 if (Irp)
196 {
197 Irp->IoStatus.Status = STATUS_SUCCESS;
198 InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
199 }
200 }
201
202 return NextEntry;
203}
204
205VOID
206NTAPI
208 IN PIRP Irp)
209{
210 PNP_DATA_QUEUE DataQueue;
211 PNP_DATA_QUEUE_ENTRY DataEntry;
212 LIST_ENTRY DeferredList;
213 PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
214 BOOLEAN CompleteWrites, FirstEntry;
215
216 if (DeviceObject) IoReleaseCancelSpinLock(Irp->CancelIrql);
217
218 InitializeListHead(&DeferredList);
219
220 DataQueue = Irp->Tail.Overlay.DriverContext[2];
221 ClientSecurityContext = NULL;
222
223 if (DeviceObject)
224 {
227 }
228
229 DataEntry = Irp->Tail.Overlay.DriverContext[3];
230 if (DataEntry)
231 {
232 if (DataEntry->QueueEntry.Blink == &DataQueue->Queue)
233 {
234 DataQueue->ByteOffset = 0;
235 FirstEntry = TRUE;
236 }
237 else
238 {
239 FirstEntry = FALSE;
240 }
241
242 RemoveEntryList(&DataEntry->QueueEntry);
243
244 ClientSecurityContext = DataEntry->ClientSecurityContext;
245
246 CompleteWrites = TRUE;
247 if (DataQueue->QueueState != WriteEntries ||
248 DataQueue->QuotaUsed < DataQueue->Quota ||
249 !DataEntry->QuotaInEntry)
250 {
251 CompleteWrites = FALSE;
252 }
253
254 DataQueue->BytesInQueue -= DataEntry->DataSize;
255 DataQueue->QuotaUsed -= DataEntry->QuotaInEntry;
256 --DataQueue->EntriesInQueue;
257
258 if (IsListEmpty(&DataQueue->Queue))
259 {
260 DataQueue->QueueState = Empty;
261 ASSERT(DataQueue->BytesInQueue == 0);
262 ASSERT(DataQueue->EntriesInQueue == 0);
263 ASSERT(DataQueue->QuotaUsed == 0);
264 }
265 else
266 {
267 if (FirstEntry)
268 {
269 NpGetNextRealDataQueueEntry(DataQueue, &DeferredList);
270 }
271 if (CompleteWrites)
272 {
273 NpCompleteStalledWrites(DataQueue, &DeferredList);
274 }
275 }
276 }
277
278 if (DeviceObject)
279 {
280 NpReleaseVcb();
282 }
283
284 if (DataEntry) ExFreePool(DataEntry);
285
286 NpFreeClientSecurityContext(ClientSecurityContext);
287 Irp->IoStatus.Status = STATUS_CANCELLED;
289
290 NpCompleteDeferredIrps(&DeferredList);
291}
292
294NTAPI
296 IN PNP_CCB Ccb,
297 IN PNP_DATA_QUEUE DataQueue,
298 IN ULONG Who,
299 IN ULONG Type,
301 IN PIRP Irp,
304{
306 PNP_DATA_QUEUE_ENTRY DataEntry;
308 ULONG QuotaInEntry;
310 BOOLEAN HasSpace;
311
313 ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
314
316
317 if ((Type != 2) && (Who == WriteEntries))
318 {
319 Status = NpGetClientSecurityContext(NamedPipeEnd,
320 Ccb,
321 Irp ? Irp->Tail.Overlay.Thread :
324 if (!NT_SUCCESS(Status))
325 {
326 return Status;
327 }
328 }
329
330 switch (Type)
331 {
332 case Unbuffered:
333 case 2:
334 case 3:
335
336 ASSERT(Irp != NULL);
338 sizeof(*DataEntry),
340 if (!DataEntry)
341 {
344 }
345
346 DataEntry->DataEntryType = Type;
347 DataEntry->QuotaInEntry = 0;
348 DataEntry->Irp = Irp;
349 DataEntry->DataSize = DataSize;
351 ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
353 break;
354
355 case Buffered:
356
357 EntrySize = sizeof(*DataEntry);
358 if (Who != ReadEntries)
359 {
361 if (EntrySize < DataSize)
362 {
365 }
366 }
367
368 QuotaInEntry = DataSize - ByteOffset;
369 if (DataQueue->Quota - DataQueue->QuotaUsed < QuotaInEntry)
370 {
371 QuotaInEntry = DataQueue->Quota - DataQueue->QuotaUsed;
372 HasSpace = TRUE;
373 }
374 else
375 {
376 HasSpace = FALSE;
377 }
378
380 EntrySize,
382 if (!DataEntry)
383 {
386 }
387
388 DataEntry->QuotaInEntry = QuotaInEntry;
389 DataEntry->Irp = Irp;
390 DataEntry->DataEntryType = Buffered;
392 DataEntry->DataSize = DataSize;
393
394 if (Who == ReadEntries)
395 {
396 ASSERT(Irp);
397
399 ASSERT((DataQueue->QueueState == Empty) ||
400 (DataQueue->QueueState == Who));
401 }
402 else
403 {
405 {
406 RtlCopyMemory(DataEntry + 1,
407 Irp ? Irp->UserBuffer: Buffer,
408 DataSize);
409 }
411 {
414 }
415 _SEH2_END;
416
417 if (HasSpace && Irp)
418 {
420 }
421 else
422 {
423 DataEntry->Irp = NULL;
425 }
426
427 ASSERT((DataQueue->QueueState == Empty) ||
428 (DataQueue->QueueState == Who));
429 }
430 break;
431
432 default:
433 ASSERT(FALSE);
436 }
437
438 ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
439 if (DataQueue->QueueState == Empty)
440 {
441 ASSERT(DataQueue->BytesInQueue == 0);
442 ASSERT(DataQueue->EntriesInQueue == 0);
443 ASSERT(IsListEmpty(&DataQueue->Queue));
444 }
445 else
446 {
447 ASSERT(DataQueue->QueueState == Who);
448 ASSERT(DataQueue->QueueState != Empty);
449 ASSERT(DataQueue->EntriesInQueue != 0);
450 }
451
452 DataQueue->QuotaUsed += DataEntry->QuotaInEntry;
453 DataQueue->QueueState = Who;
454 DataQueue->BytesInQueue += DataEntry->DataSize;
455 DataQueue->EntriesInQueue++;
456
457 if (ByteOffset)
458 {
459 DataQueue->ByteOffset = ByteOffset;
460 ASSERT(Who == WriteEntries);
461 ASSERT(ByteOffset < DataEntry->DataSize);
462 ASSERT(DataQueue->EntriesInQueue == 1);
463 }
464
465 InsertTailList(&DataQueue->Queue, &DataEntry->QueueEntry);
466
467 if (Status == STATUS_PENDING)
468 {
470 Irp->Tail.Overlay.DriverContext[2] = DataQueue;
471 Irp->Tail.Overlay.DriverContext[3] = DataEntry;
472
474
475 if ((Irp->Cancel) && (IoSetCancelRoutine(Irp, NULL)))
476 {
478 }
479 }
480
481 return Status;
482}
483
484/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
Type
Definition: Type.h:7
LONG NTSTATUS
Definition: precomp.h:26
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
PIRP NTAPI NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, IN BOOLEAN Flag, IN PLIST_ENTRY List)
Definition: datasup.c:105
NTSTATUS NTAPI NpAddDataQueueEntry(IN ULONG NamedPipeEnd, IN PNP_CCB Ccb, IN PNP_DATA_QUEUE DataQueue, IN ULONG Who, IN ULONG Type, IN ULONG DataSize, IN PIRP Irp, IN PVOID Buffer, IN ULONG ByteOffset)
Definition: datasup.c:295
NTSTATUS NTAPI NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue)
Definition: datasup.c:20
VOID NTAPI NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue, IN PLIST_ENTRY List)
Definition: datasup.c:49
PLIST_ENTRY NTAPI NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, IN PLIST_ENTRY List)
Definition: datasup.c:174
VOID NTAPI NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: datasup.c:207
NTSTATUS NTAPI NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue, IN ULONG Quota)
Definition: datasup.c:32
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
FORCEINLINE VOID NpAcquireExclusiveVcb(VOID)
Definition: npfs.h:336
FORCEINLINE VOID NpReleaseVcb(VOID)
Definition: npfs.h:344
@ Buffered
Definition: npfs.h:131
@ Unbuffered
Definition: npfs.h:132
@ ReadEntries
Definition: npfs.h:123
@ Empty
Definition: npfs.h:125
@ WriteEntries
Definition: npfs.h:124
NTSTATUS NTAPI NpGetClientSecurityContext(IN ULONG NamedPipeEnd, IN PNP_CCB Ccb, IN PETHREAD Thread, IN PSECURITY_CLIENT_CONTEXT *Context)
Definition: secursup.c:129
FORCEINLINE VOID NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList)
Definition: npfs.h:356
#define NPFS_DATA_ENTRY_TAG
Definition: npfs.h:61
VOID NTAPI NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext)
Definition: secursup.c:40
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
#define ASSERT(a)
Definition: mode.c:44
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_In_ PVOID ClientContext
Definition: netioddk.h:55
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define STATUS_PENDING
Definition: ntstatus.h:82
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: xml2sdb.h:80
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: npfs.h:259
Definition: npfs.h:149
ULONG DataSize
Definition: npfs.h:155
PSECURITY_CLIENT_CONTEXT ClientSecurityContext
Definition: npfs.h:154
ULONG QuotaInEntry
Definition: npfs.h:153
ULONG DataEntryType
Definition: npfs.h:151
LIST_ENTRY QueueEntry
Definition: npfs.h:150
PIRP Irp
Definition: npfs.h:152
ULONG Quota
Definition: npfs.h:144
ULONG EntriesInQueue
Definition: npfs.h:141
LIST_ENTRY Queue
Definition: npfs.h:138
ULONG QueueState
Definition: npfs.h:139
ULONG QuotaUsed
Definition: npfs.h:142
ULONG BytesInQueue
Definition: npfs.h:140
ULONG ByteOffset
Definition: npfs.h:143
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define ExAllocatePoolWithQuotaTag(a, b, c)
Definition: exfuncs.h:530
_In_ UCHAR EntrySize
Definition: iofuncs.h:642
#define IO_NAMED_PIPE_INCREMENT
Definition: iotypes.h:604
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE