ReactOS  0.4.13-dev-66-gc714b7f
waitsup.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/waitsup.c
5  * PURPOSE: Pipes Waiting 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_WAITSUP)
15 
16 /* FUNCTIONS ******************************************************************/
17 
18 VOID
19 NTAPI
21  IN PIRP Irp)
22 {
23  KIRQL OldIrql;
24  PNP_WAIT_QUEUE_ENTRY WaitEntry;
25  PNP_WAIT_QUEUE WaitQueue;
26 
27  IoReleaseCancelSpinLock(Irp->CancelIrql);
28 
29  WaitQueue = Irp->Tail.Overlay.DriverContext[0];
30 
31  KeAcquireSpinLock(&WaitQueue->WaitLock, &OldIrql);
32 
33  WaitEntry = Irp->Tail.Overlay.DriverContext[1];
34  if (WaitEntry)
35  {
36  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
37  if (!KeCancelTimer(&WaitEntry->Timer))
38  {
39  WaitEntry->Irp = NULL;
40  WaitEntry = NULL;
41  }
42  }
43 
44  KeReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
45 
46  if (WaitEntry)
47  {
48  ObDereferenceObject(WaitEntry->FileObject);
49  ExFreePool(WaitEntry);
50  }
51 
52  Irp->IoStatus.Information = 0;
53  Irp->IoStatus.Status = STATUS_CANCELLED;
55 }
56 
57 VOID
58 NTAPI
63 {
64  PIRP Irp;
65  KIRQL OldIrql;
66  PNP_WAIT_QUEUE_ENTRY WaitEntry = Context;
67 
69 
70  Irp = WaitEntry->Irp;
71  if (Irp)
72  {
73  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
74 
76  {
77  Irp->Tail.Overlay.DriverContext[1] = NULL;
78  Irp = NULL;
79  }
80  }
81 
83 
84  if (Irp)
85  {
86  Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
88  }
89 
90  ObDereferenceObject(WaitEntry->FileObject);
91  ExFreePool(WaitEntry);
92 }
93 
94 VOID
95 NTAPI
97 {
98  InitializeListHead(&WaitQueue->WaitList);
99  KeInitializeSpinLock(&WaitQueue->WaitLock);
100 }
101 
102 static
103 BOOLEAN
106 {
107  SIZE_T EqualLength;
108 
109  if (String1->Length != String2->Length)
110  return FALSE;
111 
112  EqualLength = RtlCompareMemory(String1->Buffer,
113  String2->Buffer,
114  String1->Length);
115  return EqualLength == String1->Length;
116 }
117 
118 NTSTATUS
119 NTAPI
121  IN PUNICODE_STRING PipePath,
124 {
125  UNICODE_STRING PipePathUpper;
126  KIRQL OldIrql;
127  PWCHAR Buffer;
128  PLIST_ENTRY NextEntry;
129  PNP_WAIT_QUEUE_ENTRY WaitEntry, Linkage;
130  PIRP WaitIrp;
131  PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer;
132  UNICODE_STRING WaitName, PipeName;
133 
134  Linkage = NULL;
135 
137  PipePath->Length,
140 
141  RtlInitEmptyUnicodeString(&PipePathUpper, Buffer, PipePath->Length);
142  RtlUpcaseUnicodeString(&PipePathUpper, PipePath, FALSE);
143 
144  KeAcquireSpinLock(&WaitQueue->WaitLock, &OldIrql);
145 
146  NextEntry = WaitQueue->WaitList.Flink;
147  while (NextEntry != &WaitQueue->WaitList)
148  {
149  WaitIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
150  NextEntry = NextEntry->Flink;
151  WaitEntry = WaitIrp->Tail.Overlay.DriverContext[1];
152 
153  if (WaitEntry->AliasName.Length)
154  {
155  ASSERT(FALSE);
156  /* We have an alias. Use that for comparison */
157  WaitName = WaitEntry->AliasName;
158  PipeName = PipePathUpper;
159  }
160  else
161  {
162  /* Use the name from the wait buffer to compare */
163  WaitBuffer = WaitIrp->AssociatedIrp.SystemBuffer;
164  WaitName.Buffer = WaitBuffer->Name;
165  WaitName.Length = WaitBuffer->NameLength;
166  WaitName.MaximumLength = WaitName.Length;
167 
168  /* WaitName doesn't have a leading backslash,
169  * so skip the one in PipePathUpper for the comparison */
170  PipeName.Buffer = PipePathUpper.Buffer + 1;
171  PipeName.Length = PipePathUpper.Length - sizeof(WCHAR);
172  PipeName.MaximumLength = PipeName.Length;
173  }
174 
175  /* Can't use RtlEqualUnicodeString with a spinlock held */
176  if (NpEqualUnicodeString(&WaitName, &PipeName))
177  {
178  /* Found a matching wait. Cancel it */
179  RemoveEntryList(&WaitIrp->Tail.Overlay.ListEntry);
180  if (KeCancelTimer(&WaitEntry->Timer))
181  {
182  WaitEntry->WaitQueue = (PNP_WAIT_QUEUE)Linkage;
183  Linkage = WaitEntry;
184  }
185  else
186  {
187  WaitEntry->Irp = NULL;
188  WaitIrp->Tail.Overlay.DriverContext[1] = NULL;
189  }
190 
191  if (IoSetCancelRoutine(WaitIrp, NULL))
192  {
193  WaitIrp->IoStatus.Information = 0;
194  WaitIrp->IoStatus.Status = Status;
195  InsertTailList(List, &WaitIrp->Tail.Overlay.ListEntry);
196  }
197  else
198  {
199  WaitIrp->Tail.Overlay.DriverContext[1] = NULL;
200  }
201  }
202  }
203 
204  KeReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
205 
207 
208  while (Linkage)
209  {
210  WaitEntry = Linkage;
211  Linkage = (PNP_WAIT_QUEUE_ENTRY)Linkage->WaitQueue;
212  ObDereferenceObject(WaitEntry->FileObject);
213  ExFreePool(WaitEntry);
214  }
215 
216  return STATUS_SUCCESS;
217 }
218 
219 NTSTATUS
220 NTAPI
222  IN LARGE_INTEGER WaitTime,
223  IN PIRP Irp,
224  IN PUNICODE_STRING AliasName)
225 {
226  PIO_STACK_LOCATION IoStack;
227  KIRQL OldIrql;
229  PNP_WAIT_QUEUE_ENTRY WaitEntry;
230  PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer;
232  ULONG i;
233 
235 
237  sizeof(*WaitEntry),
239  if (!WaitEntry)
240  {
242  }
243 
244  KeInitializeDpc(&WaitEntry->Dpc, NpTimerDispatch, WaitEntry);
245  KeInitializeTimer(&WaitEntry->Timer);
246 
247  if (AliasName)
248  {
249  WaitEntry->AliasName = *AliasName;
250  }
251  else
252  {
253  WaitEntry->AliasName.Length = 0;
254  WaitEntry->AliasName.Buffer = NULL;
255  }
256 
257  WaitEntry->WaitQueue = WaitQueue;
258  WaitEntry->Irp = Irp;
259 
260  WaitBuffer = Irp->AssociatedIrp.SystemBuffer;
261  if (WaitBuffer->TimeoutSpecified)
262  {
263  DueTime = WaitBuffer->Timeout;
264  }
265  else
266  {
267  DueTime = WaitTime;
268  }
269 
270  for (i = 0; i < WaitBuffer->NameLength / sizeof(WCHAR); i++)
271  {
272  WaitBuffer->Name[i] = RtlUpcaseUnicodeChar(WaitBuffer->Name[i]);
273  }
274 
275  Irp->Tail.Overlay.DriverContext[0] = WaitQueue;
276  Irp->Tail.Overlay.DriverContext[1] = WaitEntry;
277 
278  KeAcquireSpinLock(&WaitQueue->WaitLock, &OldIrql);
279 
281 
282  if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
283  {
285  }
286  else
287  {
288  InsertTailList(&WaitQueue->WaitList, &Irp->Tail.Overlay.ListEntry);
289 
292 
293  WaitEntry->FileObject = IoStack->FileObject;
294  ObReferenceObject(WaitEntry->FileObject);
295 
296  KeSetTimer(&WaitEntry->Timer, DueTime, &WaitEntry->Dpc);
297  WaitEntry = NULL;
298  }
299 
300  KeReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
301  if (WaitEntry) ExFreePool(WaitEntry);
302 
303  return Status;
304 }
305 
306 /* EOF */
PNP_WAIT_QUEUE WaitQueue
Definition: npfs.h:171
LARGE_INTEGER Timeout
Definition: winioctl.h:457
#define IN
Definition: typedefs.h:38
#define NPFS_WAIT_BLOCK_TAG
Definition: npfs.h:63
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
PVOID NTAPI ExAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:2939
_IRQL_requires_same_ _In_opt_ PVOID Argument1
Definition: cmtypes.h:694
USHORT MaximumLength
Definition: env_spec_w32.h:370
_In_ PIRP Irp
Definition: csq.h:116
_In_ LARGE_INTEGER DueTime
Definition: kefuncs.h:524
PFILE_OBJECT FileObject
Definition: npfs.h:173
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue, IN PUNICODE_STRING PipePath, IN NTSTATUS Status, IN PLIST_ENTRY List)
Definition: waitsup.c:120
UNICODE_STRING AliasName
Definition: npfs.h:172
NTSTATUS NTAPI NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue, IN LARGE_INTEGER WaitTime, IN PIRP Irp, IN PUNICODE_STRING AliasName)
Definition: waitsup.c:221
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
IRP
Definition: iotypes.h:2462
uint16_t * PWCHAR
Definition: typedefs.h:54
#define InsertTailList(ListHead, Entry)
IoSetCancelRoutine(Irp, CancelRoutine)
NTSYSAPI WCHAR NTAPI RtlUpcaseUnicodeChar(WCHAR Source)
struct _NP_WAIT_QUEUE_ENTRY * PNP_WAIT_QUEUE_ENTRY
VOID NTAPI NpCancelWaitQueueIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: waitsup.c:20
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
Definition: bufpool.h:45
KTIMER Timer
Definition: npfs.h:170
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
_In_ PVOID Argument2
Definition: classpnp.h:680
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
LIST_ENTRY List
Definition: psmgr.c:57
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STATUS_PENDING
Definition: ntstatus.h:82
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
Definition: npfs.h:166
KSPIN_LOCK WaitLock
Definition: npfs.h:162
#define IO_NAMED_PIPE_INCREMENT
Definition: iotypes.h:571
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PIRP Irp
Definition: npfs.h:168
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: ketypes.h:687
Definition: typedefs.h:117
#define NPFS_WRITE_BLOCK_TAG
Definition: npfs.h:64
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
VOID NTAPI NpTimerDispatch(IN PKDPC Dpc, IN PVOID Context, IN PVOID Argument1, IN PVOID Argument2)
Definition: waitsup.c:59
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
ULONG_PTR SIZE_T
Definition: typedefs.h:78
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
struct _NP_WAIT_QUEUE * PNP_WAIT_QUEUE
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
_In_ const STRING * String2
Definition: rtlfuncs.h:2245
KDPC Dpc
Definition: npfs.h:169
#define ObReferenceObject
Definition: obfuncs.h:204
static BOOLEAN NpEqualUnicodeString(IN PCUNICODE_STRING String1, IN PCUNICODE_STRING String2)
Definition: waitsup.c:104
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2725
IoMarkIrpPending(Irp)
VOID NTAPI NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue)
Definition: waitsup.c:96
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465