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
9 /* INCLUDES *******************************************************************/
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_WAITSUP)
16 /* FUNCTIONS ******************************************************************/
20 NpCancelWaitQueueIrp(IN PDEVICE_OBJECT DeviceObject
,
24 PNP_WAIT_QUEUE_ENTRY WaitEntry
;
25 PNP_WAIT_QUEUE WaitQueue
;
27 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
29 WaitQueue
= (PNP_WAIT_QUEUE
)Irp
->Tail
.Overlay
.DriverContext
[0];
31 KeAcquireSpinLock(&WaitQueue
->WaitLock
, &OldIrql
);
33 WaitEntry
= (PNP_WAIT_QUEUE_ENTRY
)Irp
->Tail
.Overlay
.DriverContext
[1];
36 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
37 if (!KeCancelTimer(&WaitEntry
->Timer
))
39 WaitEntry
->Irp
= NULL
;
44 KeReleaseSpinLock(&WaitQueue
->WaitLock
, OldIrql
);
48 ObDereferenceObject(WaitEntry
->FileObject
);
49 ExFreePool(WaitEntry
);
52 Irp
->IoStatus
.Information
= 0;
53 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
54 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
59 NpTimerDispatch(IN PKDPC Dpc
,
66 PNP_WAIT_QUEUE_ENTRY WaitEntry
= Context
;
68 KeAcquireSpinLock(&WaitEntry
->WaitQueue
->WaitLock
, &OldIrql
);
73 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
75 if (!IoSetCancelRoutine(Irp
, NULL
))
77 Irp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
82 KeReleaseSpinLock(&WaitEntry
->WaitQueue
->WaitLock
, OldIrql
);
86 Irp
->IoStatus
.Status
= STATUS_IO_TIMEOUT
;
87 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
90 ObDereferenceObject(WaitEntry
->FileObject
);
91 ExFreePool(WaitEntry
);
96 NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue
)
98 InitializeListHead(&WaitQueue
->WaitList
);
99 KeInitializeSpinLock(&WaitQueue
->WaitLock
);
104 NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue
,
105 IN PUNICODE_STRING PipeName
,
109 UNICODE_STRING DestinationString
;
112 PLIST_ENTRY NextEntry
;
113 PNP_WAIT_QUEUE_ENTRY WaitEntry
, Linkage
;
115 PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer
;
120 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
122 NPFS_WAIT_BLOCK_TAG
);
123 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
125 RtlInitEmptyUnicodeString(&DestinationString
, Buffer
, PipeName
->Length
);
126 RtlUpcaseUnicodeString(&DestinationString
, PipeName
, FALSE
);
128 KeAcquireSpinLock(&WaitQueue
->WaitLock
, &OldIrql
);
130 for (NextEntry
= WaitQueue
->WaitList
.Flink
;
131 NextEntry
!= &WaitQueue
->WaitList
;
132 NextEntry
= NextEntry
->Flink
)
134 WaitIrp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
135 WaitEntry
= WaitIrp
->Tail
.Overlay
.DriverContext
[1];
137 if (WaitEntry
->AliasName
.Length
)
140 if (DestinationString
.Length
== WaitEntry
->AliasName
.Length
)
142 if (RtlCompareMemory(WaitEntry
->AliasName
.Buffer
,
143 DestinationString
.Buffer
,
144 DestinationString
.Length
) ==
145 DestinationString
.Length
)
148 RemoveEntryList(&WaitIrp
->Tail
.Overlay
.ListEntry
);
149 if (KeCancelTimer(&WaitEntry
->Timer
))
151 WaitEntry
->WaitQueue
= (PNP_WAIT_QUEUE
)Linkage
;
156 WaitEntry
->Irp
= NULL
;
157 WaitIrp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
160 if (IoSetCancelRoutine(WaitIrp
, NULL
))
162 WaitIrp
->IoStatus
.Information
= 0;
163 WaitIrp
->IoStatus
.Status
= Status
;
164 InsertTailList(List
, &WaitIrp
->Tail
.Overlay
.ListEntry
);
168 WaitIrp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
175 WaitBuffer
= WaitIrp
->AssociatedIrp
.SystemBuffer
;
177 if (WaitBuffer
->NameLength
+ sizeof(WCHAR
) == DestinationString
.Length
)
179 NameLength
= WaitBuffer
->NameLength
/ sizeof(WCHAR
);
180 for (i
= 0; i
< NameLength
; i
++)
182 if (WaitBuffer
->Name
[i
] != DestinationString
.Buffer
[i
+ 1]) break;
185 if (i
>= NameLength
) goto CancelWait
;
190 KeReleaseSpinLock(&WaitQueue
->WaitLock
, OldIrql
);
192 ExFreePool(DestinationString
.Buffer
);
197 Linkage
= (PNP_WAIT_QUEUE_ENTRY
)Linkage
->WaitQueue
;
198 ObDereferenceObject(WaitEntry
->FileObject
);
199 ExFreePool(WaitEntry
);
202 return STATUS_SUCCESS
;
207 NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue
,
208 IN LARGE_INTEGER WaitTime
,
210 IN PUNICODE_STRING AliasName
)
212 PIO_STACK_LOCATION IoStack
;
215 PNP_WAIT_QUEUE_ENTRY WaitEntry
;
216 PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer
;
217 LARGE_INTEGER DueTime
;
220 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
222 WaitEntry
= ExAllocatePoolWithQuotaTag(NonPagedPool
| POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
,
224 NPFS_WRITE_BLOCK_TAG
);
227 return STATUS_INSUFFICIENT_RESOURCES
;
230 KeInitializeDpc(&WaitEntry
->Dpc
, NpTimerDispatch
, WaitEntry
);
231 KeInitializeTimer(&WaitEntry
->Timer
);
235 WaitEntry
->AliasName
= *AliasName
;
239 WaitEntry
->AliasName
.Length
= 0;
240 WaitEntry
->AliasName
.Buffer
= NULL
;
243 WaitEntry
->WaitQueue
= WaitQueue
;
244 WaitEntry
->Irp
= Irp
;
246 WaitBuffer
= (PFILE_PIPE_WAIT_FOR_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
247 if (WaitBuffer
->TimeoutSpecified
)
249 DueTime
= WaitBuffer
->Timeout
;
256 for (i
= 0; i
< WaitBuffer
->NameLength
/ sizeof(WCHAR
); i
++)
258 WaitBuffer
->Name
[i
] = RtlUpcaseUnicodeChar(WaitBuffer
->Name
[i
]);
261 Irp
->Tail
.Overlay
.DriverContext
[0] = WaitQueue
;
262 Irp
->Tail
.Overlay
.DriverContext
[1] = WaitEntry
;
264 KeAcquireSpinLock(&WaitQueue
->WaitLock
, &OldIrql
);
266 IoSetCancelRoutine(Irp
, NpCancelWaitQueueIrp
);
268 if (Irp
->Cancel
&& IoSetCancelRoutine(Irp
, NULL
))
270 Status
= STATUS_CANCELLED
;
274 InsertTailList(&WaitQueue
->WaitList
, &Irp
->Tail
.Overlay
.ListEntry
);
276 IoMarkIrpPending(Irp
);
277 Status
= STATUS_PENDING
;
279 WaitEntry
->FileObject
= IoStack
->FileObject
;
280 ObReferenceObject(WaitEntry
->FileObject
);
282 KeSetTimer(&WaitEntry
->Timer
, DueTime
, &WaitEntry
->Dpc
);
287 KeReleaseSpinLock(&WaitQueue
->WaitLock
, OldIrql
);
288 if (WaitEntry
) ExFreePool(WaitEntry
);