ReactOS  0.4.14-dev-593-g1793dcc
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  *--*/
48 BOOLEAN
49 NTAPI
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  *--*/
118 BOOLEAN
119 NTAPI
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  *--*/
207 BOOLEAN
208 NTAPI
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  *--*/
264 VOID
265 NTAPI
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 */
297  CsrDereferenceThread(WaitBlock->WaitThread);
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  *--*/
328 VOID
329 NTAPI
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  *--*/
386 BOOLEAN
387 NTAPI
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 */
#define IN
Definition: typedefs.h:38
ULONG Size
Definition: csrsrv.h:157
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
PCSR_THREAD WaitThread
Definition: csrsrv.h:160
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
LIST_ENTRY WaitList
Definition: csrsrv.h:158
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
VOID NTAPI CsrDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:775
#define InsertTailList(ListHead, Entry)
#define CsrReleaseWaitLock()
Definition: api.h:24
#define CsrReleaseProcessLock()
Definition: api.h:15
NTSTATUS NTAPI NtReplyPort(IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage)
Definition: reply.c:190
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID NTAPI CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
Definition: api.c:1235
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
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
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
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID NTAPI CsrDereferenceWait(IN PLIST_ENTRY WaitList)
Definition: wait.c:266
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
#define CsrAcquireProcessLock()
Definition: api.h:12
struct _CSR_WAIT_BLOCK CSR_WAIT_BLOCK
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
RTL_CRITICAL_SECTION CsrWaitListsLock
Definition: wait.c:19
BOOLEAN NTAPI CsrNotifyWait(IN PLIST_ENTRY WaitList, IN BOOLEAN NotifyAll, IN PVOID WaitArgument1, IN PVOID WaitArgument2)
Definition: wait.c:388
CSR_WAIT_FUNCTION WaitFunction
Definition: csrsrv.h:161
PVOID WaitContext
Definition: csrsrv.h:159
#define CsrAcquireWaitLock()
Definition: api.h:21
CSR_API_MESSAGE WaitApiMessage
Definition: csrsrv.h:162
VOID NTAPI CsrMoveSatisfiedWait(IN PLIST_ENTRY DestinationList, IN PLIST_ENTRY WaitList)
Definition: wait.c:330
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
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
HANDLE CsrHeap
Definition: init.c:25
PORT_MESSAGE Header
Definition: csrmsg.h:104
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