ReactOS  0.4.13-dev-100-gc8611ae
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 
19 NTAPI
21 {
22  PAGED_CODE();
23 
24  ASSERT(DataQueue->QueueState == Empty);
25 
26  RtlZeroMemory(DataQueue, sizeof(*DataQueue));
27  return STATUS_SUCCESS;
28 }
29 
31 NTAPI
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 
47 VOID
48 NTAPI
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 
103 PIRP
104 NTAPI
106  IN BOOLEAN Flag,
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  {
159  NpGetNextRealDataQueueEntry(DataQueue, List);
160  }
161 
162  if (HasWrites)
163  {
164  NpCompleteStalledWrites(DataQueue, List);
165  }
166  }
167 
168  DataQueue->ByteOffset = 0;
169  return Irp;
170 }
171 
173 NTAPI
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 
205 VOID
206 NTAPI
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 
293 NTSTATUS
294 NTAPI
296  IN PNP_CCB Ccb,
297  IN PNP_DATA_QUEUE DataQueue,
298  IN ULONG Who,
299  IN ULONG Type,
300  IN ULONG DataSize,
301  IN PIRP Irp,
302  IN PVOID Buffer,
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 :
323  &ClientContext);
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  {
360  EntrySize += DataSize;
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  {
404  _SEH2_TRY
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 */
VOID NTAPI NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: datasup.c:207
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI NpGetClientSecurityContext(IN ULONG NamedPipeEnd, IN PNP_CCB Ccb, IN PETHREAD Thread, IN PSECURITY_CLIENT_CONTEXT *Context)
Definition: secursup.c:129
#define FsRtlEnterFileSystem
PVOID NTAPI ExAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:2939
Type
Definition: Type.h:6
PLIST_ENTRY NTAPI NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, IN PLIST_ENTRY List)
Definition: datasup.c:174
#define NPFS_DATA_ENTRY_TAG
Definition: npfs.h:61
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define FsRtlExitFileSystem
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
LIST_ENTRY QueueEntry
Definition: npfs.h:150
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue, IN ULONG Quota)
Definition: datasup.c:32
ULONG Quota
Definition: npfs.h:144
Definition: npfs.h:131
#define InsertTailList(ListHead, Entry)
IoSetCancelRoutine(Irp, CancelRoutine)
_In_ UCHAR EntrySize
Definition: iofuncs.h:640
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
ULONG EntriesInQueue
Definition: npfs.h:141
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
Definition: npfs.h:258
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID NTAPI NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext)
Definition: secursup.c:40
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
ULONG QuotaUsed
Definition: npfs.h:142
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
Definition: bufpool.h:45
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
ULONG QueueState
Definition: npfs.h:139
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
PIRP NTAPI NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, IN BOOLEAN Flag, IN PLIST_ENTRY List)
Definition: datasup.c:105
ULONG DataSize
Definition: npfs.h:155
ULONG BytesInQueue
Definition: npfs.h:140
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
LIST_ENTRY List
Definition: psmgr.c:57
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
_In_ PVOID ClientContext
Definition: netioddk.h:55
Definition: xml2sdb.h:79
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
ULONG ByteOffset
Definition: npfs.h:143
#define IO_NAMED_PIPE_INCREMENT
Definition: iotypes.h:571
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue, IN PLIST_ENTRY List)
Definition: datasup.c:49
Definition: npfs.h:148
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
Definition: typedefs.h:117
NTSTATUS NTAPI NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue)
Definition: datasup.c:20
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
ULONG_PTR SIZE_T
Definition: typedefs.h:78
_SEH2_END
Definition: create.c:4424
PSECURITY_CLIENT_CONTEXT ClientSecurityContext
Definition: npfs.h:154
LIST_ENTRY Queue
Definition: npfs.h:138
FORCEINLINE VOID NpReleaseVcb(VOID)
Definition: npfs.h:344
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
ULONG DataEntryType
Definition: npfs.h:151
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
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
FORCEINLINE VOID NpAcquireExclusiveVcb(VOID)
Definition: npfs.h:336
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:2725
IoMarkIrpPending(Irp)
ULONG QuotaInEntry
Definition: npfs.h:153
FORCEINLINE VOID NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList)
Definition: npfs.h:356
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4733
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
Definition: npfs.h:125
PIRP Irp
Definition: npfs.h:152