ReactOS 0.4.15-dev-5669-g09dde2c
wait.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/wait.c
5 * PURPOSE: CSR Server DLL Wait Implementation
6 * PROGRAMMERS: Emanuele Aliberti
7 * Alex Ionescu (alex@relsoft.net)
8 */
9
10/* INCLUDES *******************************************************************/
11
12#include "srv.h"
13
14#define NDEBUG
15#include <debug.h>
16
17/* DATA ***********************************************************************/
18
20
21/* PRIVATE FUNCTIONS **********************************************************/
22
23/*++
24 * @name CsrInitializeWait
25 *
26 * The CsrInitializeWait routine initializes a CSR Wait Object.
27 *
28 * @param WaitFunction
29 * Pointer to the function that will handle this wait.
30 *
31 * @param CsrWaitThread
32 * Pointer to the CSR Thread that will perform the wait.
33 *
34 * @param WaitApiMessage
35 * Pointer to the CSR API Message associated to this wait.
36 *
37 * @param WaitContext
38 * Pointer to a user-defined parameter associated to this wait.
39 *
40 * @param NewWaitBlock
41 * Pointed to the initialized CSR Wait Block for this wait.
42 *
43 * @return TRUE in case of success, FALSE otherwise.
44 *
45 * @remarks None.
46 *
47 *--*/
51 IN PCSR_THREAD CsrWaitThread,
52 IN OUT PCSR_API_MESSAGE WaitApiMessage,
53 IN PVOID WaitContext,
54 OUT PCSR_WAIT_BLOCK *NewWaitBlock)
55{
56 ULONG Size;
57 PCSR_WAIT_BLOCK WaitBlock;
58
59 /* Calculate the size of the wait block */
60 Size = sizeof(CSR_WAIT_BLOCK) -
61 sizeof(WaitBlock->WaitApiMessage) +
62 WaitApiMessage->Header.u1.s1.TotalLength;
63
64 /* Allocate the Wait Block */
66 if (!WaitBlock)
67 {
68 /* Fail */
69 WaitApiMessage->Status = STATUS_NO_MEMORY;
70 return FALSE;
71 }
72
73 /* Initialize it */
74 WaitBlock->Size = Size;
75 WaitBlock->WaitThread = CsrWaitThread;
76 WaitBlock->WaitContext = WaitContext;
77 WaitBlock->WaitFunction = WaitFunction;
78 WaitBlock->WaitList.Flink = NULL;
79 WaitBlock->WaitList.Blink = NULL;
80
81 /* Copy the message */
82 RtlCopyMemory(&WaitBlock->WaitApiMessage,
83 WaitApiMessage,
84 WaitApiMessage->Header.u1.s1.TotalLength);
85
86 /* Return the block */
87 *NewWaitBlock = WaitBlock;
88 return TRUE;
89}
90
91/*++
92 * @name CsrNotifyWaitBlock
93 *
94 * The CsrNotifyWaitBlock routine calls the wait function for a registered
95 * CSR Wait Block, and replies to the attached CSR API Message, if any.
96 *
97 * @param WaitBlock
98 * Pointer to the CSR Wait Block.
99 *
100 * @param WaitList
101 * Pointer to the wait list for this wait.
102 *
103 * @param WaitArgument[1-2]
104 * User-defined values to pass to the wait function.
105 *
106 * @param WaitFlags
107 * Wait flags for this wait.
108 *
109 * @param DereferenceThread
110 * Specifies whether the CSR Thread should be dereferenced at the
111 * end of this wait.
112 *
113 * @return TRUE in case of success, FALSE otherwise.
114 *
115 * @remarks After a wait block is notified, the wait function becomes invalid.
116 *
117 *--*/
119NTAPI
121 IN PLIST_ENTRY WaitList,
122 IN PVOID WaitArgument1,
123 IN PVOID WaitArgument2,
124 IN ULONG WaitFlags,
125 IN BOOLEAN DereferenceThread)
126{
127 /* Call the wait function */
128 if (WaitBlock->WaitFunction(WaitList,
129 WaitBlock->WaitThread,
130 &WaitBlock->WaitApiMessage,
131 WaitBlock->WaitContext,
132 WaitArgument1,
133 WaitArgument2,
134 WaitFlags))
135 {
136 /* The wait is done, clear the block */
137 WaitBlock->WaitThread->WaitBlock = NULL;
138
139 /* Check for captured arguments */
140 if (WaitBlock->WaitApiMessage.CsrCaptureData)
141 {
142 /* Release them */
143 CsrReleaseCapturedArguments(&WaitBlock->WaitApiMessage);
144 }
145
146 /* Reply to the port */
147 NtReplyPort(WaitBlock->WaitThread->Process->ClientPort,
148 &WaitBlock->WaitApiMessage.Header);
149
150 /* Check if we should dereference the thread */
151 if (DereferenceThread)
152 {
153 /* Remove it from the Wait List */
154 if (WaitBlock->WaitList.Flink)
155 {
156 RemoveEntryList(&WaitBlock->WaitList);
157 }
158
159 /* Dereference the thread */
160 CsrDereferenceThread(WaitBlock->WaitThread);
161
162 /* Free the wait block */
163 RtlFreeHeap(CsrHeap, 0, WaitBlock);
164 }
165 else
166 {
167 /* The wait is complete, but the thread is being kept alive */
168 WaitBlock->WaitFunction = NULL;
169 }
170
171 /* The wait succeeded */
172 return TRUE;
173 }
174
175 /* The wait failed */
176 return FALSE;
177}
178
179/* PUBLIC FUNCTIONS ***********************************************************/
180
181/*++
182 * @name CsrCreateWait
183 * @implemented NT4
184 *
185 * The CsrCreateWait routine creates a CSR Wait.
186 *
187 * @param WaitList
188 * Pointer to a wait list in which the wait will be added.
189 *
190 * @param WaitFunction
191 * Pointer to the function that will handle this wait.
192 *
193 * @param CsrWaitThread
194 * Pointer to the CSR Thread that will perform the wait.
195 *
196 * @param WaitApiMessage
197 * Pointer to the CSR API Message associated to this wait.
198 *
199 * @param WaitContext
200 * Pointer to a user-defined parameter associated to this wait.
201 *
202 * @return TRUE in case of success, FALSE otherwise.
203 *
204 * @remarks None.
205 *
206 *--*/
208NTAPI
210 IN CSR_WAIT_FUNCTION WaitFunction,
211 IN PCSR_THREAD CsrWaitThread,
212 IN OUT PCSR_API_MESSAGE WaitApiMessage,
213 IN PVOID WaitContext)
214{
215 PCSR_WAIT_BLOCK WaitBlock;
216
217 /* Initialize the wait */
218 if (!CsrInitializeWait(WaitFunction,
219 CsrWaitThread,
220 WaitApiMessage,
221 WaitContext,
222 &WaitBlock))
223 {
224 return FALSE;
225 }
226
227 /* Acquire the Wait Lock */
229
230 /* Make sure the thread wasn't destroyed */
231 if (CsrWaitThread->Flags & CsrThreadTerminated)
232 {
233 /* Fail the wait */
234 RtlFreeHeap(CsrHeap, 0, WaitBlock);
236 return FALSE;
237 }
238
239 /* Associate the newly created wait to the waiting thread */
240 CsrWaitThread->WaitBlock = WaitBlock;
241
242 /* Insert the wait in the queue */
243 InsertTailList(WaitList, &WaitBlock->WaitList);
244
245 /* Return */
247 return TRUE;
248}
249
250/*++
251 * @name CsrDereferenceWait
252 * @implemented NT4
253 *
254 * The CsrDereferenceWait routine dereferences a CSR Wait Block.
255 *
256 * @param WaitList
257 * Pointer to the Wait List associated to the wait.
258
259 * @return None.
260 *
261 * @remarks None.
262 *
263 *--*/
264VOID
265NTAPI
267{
268 PLIST_ENTRY NextEntry;
269 PCSR_WAIT_BLOCK WaitBlock;
270
271 /* Acquire the Process and Wait Locks */
274
275 /* Set the list pointers */
276 NextEntry = WaitList->Flink;
277
278 /* Start the loop */
279 while (NextEntry != WaitList)
280 {
281 /* Get the wait block */
282 WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
283
284 /* Move to the next entry */
285 NextEntry = NextEntry->Flink;
286
287 /* Check if there's no Wait Routine (satisfied wait) */
288 if (WaitBlock->WaitFunction == NULL)
289 {
290 /* Remove it from the Wait List */
291 if (WaitBlock->WaitList.Flink)
292 {
293 RemoveEntryList(&WaitBlock->WaitList);
294 }
295
296 /* Dereference the thread waiting on it */
298
299 /* Free the block */
300 RtlFreeHeap(CsrHeap, 0, WaitBlock);
301 }
302 }
303
304 /* Release the locks */
307}
308
309/*++
310 * @name CsrMoveSatisfiedWait
311 * @implemented NT5
312 *
313 * The CsrMoveSatisfiedWait routine moves satisfied waits from
314 * a wait list to another list.
315 *
316 * @param DestinationList
317 * Pointer to a list in which the satisfied waits will be added.
318 *
319 * @param WaitList
320 * Pointer to the wait list whose satisfied wait blocks
321 * will be moved away.
322 *
323 * @return None.
324 *
325 * @remarks None.
326 *
327 *--*/
328VOID
329NTAPI
331 IN PLIST_ENTRY WaitList)
332{
333 PLIST_ENTRY NextEntry;
334 PCSR_WAIT_BLOCK WaitBlock;
335
336 /* Acquire the Wait Lock */
338
339 /* Set the List pointers */
340 NextEntry = WaitList->Flink;
341
342 /* Start looping */
343 while (NextEntry != WaitList)
344 {
345 /* Get the Wait block */
346 WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
347
348 /* Go to the next entry */
349 NextEntry = NextEntry->Flink;
350
351 /* Check if there's no Wait Routine (satisfied wait) */
352 if (WaitBlock->WaitFunction == NULL)
353 {
354 /* Remove it from the Wait Block Queue */
355 RemoveEntryList(&WaitBlock->WaitList);
356
357 /* Insert the wait into the destination list */
358 InsertTailList(DestinationList, &WaitBlock->WaitList);
359 }
360 }
361
362 /* Release the wait lock */
364}
365
366/*++
367 * @name CsrNotifyWait
368 * @implemented NT4
369 *
370 * The CsrNotifyWait routine notifies CSR Wait Blocks.
371 *
372 * @param WaitList
373 * Pointer to the wait list whose wait blocks will be notified.
374 *
375 * @param NotifyAll
376 * Whether or not we must notify all the waits.
377 *
378 * @param WaitArgument[1-2]
379 * User-defined argument to pass on to the wait function.
380 *
381 * @return TRUE in case of success, FALSE otherwise.
382 *
383 * @remarks None.
384 *
385 *--*/
387NTAPI
389 IN BOOLEAN NotifyAll,
390 IN PVOID WaitArgument1,
391 IN PVOID WaitArgument2)
392{
393 PLIST_ENTRY NextEntry;
394 PCSR_WAIT_BLOCK WaitBlock;
395 BOOLEAN NotifySuccess = FALSE;
396
397 /* Acquire the Wait Lock */
399
400 /* Set the List pointers */
401 NextEntry = WaitList->Flink;
402
403 /* Start looping */
404 while (NextEntry != WaitList)
405 {
406 /* Get the Wait block */
407 WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
408
409 /* Go to the next entry */
410 NextEntry = NextEntry->Flink;
411
412 /* Check if there is a Wait Routine */
413 if (WaitBlock->WaitFunction != NULL)
414 {
415 /* Notify the Waiter */
416 NotifySuccess |= CsrNotifyWaitBlock(WaitBlock,
417 WaitList,
418 WaitArgument1,
419 WaitArgument2,
420 0,
421 FALSE);
422
423 /*
424 * We've already done a wait, so leave unless
425 * we want to notify all the waits...
426 */
427 if (!NotifyAll) break;
428 }
429 }
430
431 /* Release the wait lock and return */
433 return NotifySuccess;
434}
435
436/* EOF */
unsigned char BOOLEAN
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
BOOLEAN(NTAPI * CSR_WAIT_FUNCTION)(IN PLIST_ENTRY WaitList, IN PCSR_THREAD WaitThread, IN PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags)
Definition: csrsrv.h:145
VOID NTAPI CsrDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:776
struct _CSR_WAIT_BLOCK CSR_WAIT_BLOCK
@ CsrThreadTerminated
Definition: csrsrv.h:106
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
NTSTATUS NTAPI NtReplyPort(IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage)
Definition: reply.c:190
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
PORT_MESSAGE Header
Definition: csrmsg.h:102
PVOID WaitContext
Definition: csrsrv.h:159
PCSR_THREAD WaitThread
Definition: csrsrv.h:160
ULONG Size
Definition: csrsrv.h:157
LIST_ENTRY WaitList
Definition: csrsrv.h:158
CSR_WAIT_FUNCTION WaitFunction
Definition: csrsrv.h:161
CSR_API_MESSAGE WaitApiMessage
Definition: csrsrv.h:162
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
VOID NTAPI CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
Definition: api.c:1337
#define CsrAcquireWaitLock()
Definition: api.h:21
#define CsrAcquireProcessLock()
Definition: api.h:12
HANDLE CsrHeap
Definition: init.c:25
#define CsrReleaseProcessLock()
Definition: api.h:15
#define CsrReleaseWaitLock()
Definition: api.h:24
VOID NTAPI CsrDereferenceWait(IN PLIST_ENTRY WaitList)
Definition: wait.c:266
RTL_CRITICAL_SECTION CsrWaitListsLock
Definition: wait.c:19
BOOLEAN NTAPI CsrInitializeWait(IN CSR_WAIT_FUNCTION WaitFunction, IN PCSR_THREAD CsrWaitThread, IN OUT PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, OUT PCSR_WAIT_BLOCK *NewWaitBlock)
Definition: wait.c:50
VOID NTAPI CsrMoveSatisfiedWait(IN PLIST_ENTRY DestinationList, IN PLIST_ENTRY WaitList)
Definition: wait.c:330
BOOLEAN NTAPI CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock, IN PLIST_ENTRY WaitList, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags, IN BOOLEAN DereferenceThread)
Definition: wait.c:120
BOOLEAN NTAPI CsrCreateWait(IN PLIST_ENTRY WaitList, IN CSR_WAIT_FUNCTION WaitFunction, IN PCSR_THREAD CsrWaitThread, IN OUT PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext)
Definition: wait.c:209
BOOLEAN NTAPI CsrNotifyWait(IN PLIST_ENTRY WaitList, IN BOOLEAN NotifyAll, IN PVOID WaitArgument1, IN PVOID WaitArgument2)
Definition: wait.c:388
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533