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 OldIrql
= KfAcquireSpinLock(&WaitQueue
->WaitLock
);
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 KfReleaseSpinLock(&WaitQueue
->WaitLock
, OldIrql
);
48 ObfDereferenceObject(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 OldIrql
= KfAcquireSpinLock(&WaitEntry
->WaitQueue
->WaitLock
);
72 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
73 if (!IoSetCancelRoutine(Irp
, NULL
))
75 Irp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
79 KfReleaseSpinLock(&WaitEntry
->WaitQueue
->WaitLock
, OldIrql
);
82 Irp
->IoStatus
.Status
= STATUS_IO_TIMEOUT
;
83 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
85 ObfDereferenceObject(WaitEntry
->FileObject
);
86 ExFreePool(WaitEntry
);
91 NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue
)
93 InitializeListHead(&WaitQueue
->WaitList
);
94 KeInitializeSpinLock(&WaitQueue
->WaitLock
);
99 NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue
,
100 IN PUNICODE_STRING PipeName
,
102 IN PLIST_ENTRY ListEntry
)
104 UNICODE_STRING DestinationString
;
108 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PipeName
->Length
, NPFS_WAIT_BLOCK_TAG
);
109 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
111 RtlInitEmptyUnicodeString(&DestinationString
, Buffer
, PipeName
->Length
);
112 RtlUpcaseUnicodeString(&DestinationString
, PipeName
, FALSE
);
114 OldIrql
= KfAcquireSpinLock(&WaitQueue
->WaitLock
);
116 ASSERT(IsListEmpty(&WaitQueue
->WaitList
) == TRUE
);
118 KfReleaseSpinLock(&WaitQueue
->WaitLock
, OldIrql
);
119 ExFreePool(DestinationString
.Buffer
);
120 return STATUS_SUCCESS
;
125 NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue
,
126 IN LARGE_INTEGER WaitTime
,
128 IN PUNICODE_STRING Name
)
130 PIO_STACK_LOCATION IoStack
;
133 PNP_WAIT_QUEUE_ENTRY WaitEntry
;
134 PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer
;
135 LARGE_INTEGER DueTime
;
138 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
140 WaitEntry
= ExAllocatePoolWithQuotaTag(NonPagedPool
, sizeof(*WaitEntry
), NPFS_WRITE_BLOCK_TAG
);
143 KeInitializeDpc(&WaitEntry
->Dpc
, NpTimerDispatch
, WaitEntry
);
144 KeInitializeTimer(&WaitEntry
->Timer
);
148 WaitEntry
->String
= *Name
;
152 WaitEntry
->String
.Length
= 0;
153 WaitEntry
->String
.Buffer
= 0;
156 WaitEntry
->WaitQueue
= WaitQueue
;
157 WaitEntry
->Irp
= Irp
;
159 WaitBuffer
= (PFILE_PIPE_WAIT_FOR_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
160 if (WaitBuffer
->TimeoutSpecified
)
162 DueTime
= WaitBuffer
->Timeout
;
169 for (i
= 0; i
< WaitBuffer
->NameLength
/ sizeof(WCHAR
); i
++)
171 WaitBuffer
->Name
[i
] = RtlUpcaseUnicodeChar(WaitBuffer
->Name
[i
]);
174 Irp
->Tail
.Overlay
.DriverContext
[0] = WaitQueue
;
175 Irp
->Tail
.Overlay
.DriverContext
[1] = WaitEntry
;
176 OldIrql
= KfAcquireSpinLock(&WaitQueue
->WaitLock
);
178 IoSetCancelRoutine(Irp
, NpCancelWaitQueueIrp
);
180 if (Irp
->Cancel
&& IoSetCancelRoutine(Irp
, NULL
))
182 Status
= STATUS_CANCELLED
;
186 InsertTailList(&WaitQueue
->WaitList
, &Irp
->Tail
.Overlay
.ListEntry
);
188 IoMarkIrpPending(Irp
);
189 Status
= STATUS_PENDING
;
191 WaitEntry
->FileObject
= IoStack
->FileObject
;
192 ObfReferenceObject(WaitEntry
->FileObject
);
194 KeSetTimer(&WaitEntry
->Timer
, DueTime
, &WaitEntry
->Dpc
);
198 KfReleaseSpinLock(&WaitQueue
->WaitLock
, OldIrql
);
199 if (WaitEntry
) ExFreePool(WaitEntry
);
203 Status
= STATUS_INSUFFICIENT_RESOURCES
;