ReactOS 0.4.15-dev-7887-g64a59a1
keyedevt.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/keyedevt.c
5 * PURPOSE: Support for keyed events
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* INTERNAL TYPES *************************************************************/
16
17#define NUM_KEY_HASH_BUCKETS 23
18typedef struct _EX_KEYED_EVENT
19{
20 struct
21 {
27
28/* GLOBALS *******************************************************************/
29
32
33static
35{
40};
41
42/* FUNCTIONS *****************************************************************/
43
45CODE_SEG("INIT")
49{
50 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer = {0};
51 UNICODE_STRING TypeName = RTL_CONSTANT_STRING(L"KeyedEvent");
52 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\KernelObjects\\CritSecOutOfMemoryEvent");
56
57 /* Set up the object type initializer */
58 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
59 ObjectTypeInitializer.GenericMapping = ExpKeyedEventMapping;
60 ObjectTypeInitializer.PoolType = PagedPool;
61 ObjectTypeInitializer.ValidAccessMask = KEYEDEVENT_ALL_ACCESS;
62 ObjectTypeInitializer.UseDefaultObject = TRUE;
63
64 /* Create the keyed event object type */
65 Status = ObCreateObjectType(&TypeName,
66 &ObjectTypeInitializer,
67 NULL,
69 if (!NT_SUCCESS(Status)) return FALSE;
70
71 /* Create the out of memory event for critical sections */
73 Status = ZwCreateKeyedEvent(&EventHandle,
76 0);
77 if (NT_SUCCESS(Status))
78 {
79 /* Take a reference so we can get rid of the handle */
85 NULL);
87 return TRUE;
88 }
89
90 return FALSE;
91}
92
93VOID
96 _Out_ PEX_KEYED_EVENT KeyedEvent)
97{
98 ULONG i;
99
100 /* Loop all hash buckets */
101 for (i = 0; i < NUM_KEY_HASH_BUCKETS; i++)
102 {
103 /* Initialize the mutex and the wait lists */
104 ExInitializePushLock(&KeyedEvent->HashTable[i].Lock);
105 InitializeListHead(&KeyedEvent->HashTable[i].WaitListHead);
106 InitializeListHead(&KeyedEvent->HashTable[i].ReleaseListHead);
107 }
108}
109
112NTAPI
113ExpReleaseOrWaitForKeyedEvent(
114 _Inout_ PEX_KEYED_EVENT KeyedEvent,
115 _In_ PVOID KeyedWaitValue,
119{
120 PETHREAD Thread, CurrentThread;
121 PEPROCESS CurrentProcess;
122 PLIST_ENTRY ListEntry, WaitListHead1, WaitListHead2;
124 ULONG_PTR HashIndex;
125 PVOID PreviousKeyedWaitValue;
126
127 /* Get the current process */
128 CurrentProcess = PsGetCurrentProcess();
129
130 /* Calculate the hash index */
131 HashIndex = (ULONG_PTR)KeyedWaitValue >> 5;
132 HashIndex ^= (ULONG_PTR)CurrentProcess >> 6;
133 HashIndex %= NUM_KEY_HASH_BUCKETS;
134
135 /* Lock the lists */
137 ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
138
139 /* Get the lists for search and wait, depending on whether
140 we want to wait for the event or signal it */
141 if (Release)
142 {
143 WaitListHead1 = &KeyedEvent->HashTable[HashIndex].WaitListHead;
144 WaitListHead2 = &KeyedEvent->HashTable[HashIndex].ReleaseListHead;
145 }
146 else
147 {
148 WaitListHead1 = &KeyedEvent->HashTable[HashIndex].ReleaseListHead;
149 WaitListHead2 = &KeyedEvent->HashTable[HashIndex].WaitListHead;
150 }
151
152 /* loop the first wait list */
153 ListEntry = WaitListHead1->Flink;
154 while (ListEntry != WaitListHead1)
155 {
156 /* Get the waiting thread. Note that this thread cannot be terminated
157 as long as we hold the list lock, since it either needs to wait to
158 be signaled by this thread or, when the wait is aborted due to thread
159 termination, then it first needs to acquire the list lock. */
160 Thread = CONTAINING_RECORD(ListEntry, ETHREAD, KeyedWaitChain);
161 ListEntry = ListEntry->Flink;
162
163 /* Check if this thread is a correct waiter */
164 if ((Thread->Tcb.Process == &CurrentProcess->Pcb) &&
165 (Thread->KeyedWaitValue == KeyedWaitValue))
166 {
167 /* Remove the thread from the list */
169
170 /* Initialize the list entry to show that it was removed */
172
173 /* Wake the thread */
176 1,
177 FALSE);
178 Thread = NULL;
179
180 /* Unlock the list. After this it is not safe to access Thread */
181 ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
183
184 return STATUS_SUCCESS;
185 }
186 }
187
188 /* Get the current thread */
189 CurrentThread = PsGetCurrentThread();
190
191 /* Set the wait key and remember the old value */
192 PreviousKeyedWaitValue = CurrentThread->KeyedWaitValue;
193 CurrentThread->KeyedWaitValue = KeyedWaitValue;
194
195 /* Initialize the wait semaphore */
196 KeInitializeSemaphore(&CurrentThread->KeyedWaitSemaphore, 0, 1);
197
198 /* Insert the current thread into the secondary wait list */
199 InsertTailList(WaitListHead2, &CurrentThread->KeyedWaitChain);
200
201 /* Unlock the list */
202 ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
204
205 /* Wait for the keyed wait semaphore */
209 Alertable,
210 Timeout);
211
212 /* Check if the wait was aborted or timed out */
213 if (Status != STATUS_SUCCESS)
214 {
215 /* Lock the lists to make sure no one else messes with the entry */
217 ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
218
219 /* Check if the wait list entry is still in the list */
220 if (!IsListEmpty(&CurrentThread->KeyedWaitChain))
221 {
222 /* Remove the thread from the list */
223 RemoveEntryList(&CurrentThread->KeyedWaitChain);
224 InitializeListHead(&CurrentThread->KeyedWaitChain);
225 }
226
227 /* Unlock the list */
228 ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
230 }
231
232 /* Restore the previous KeyedWaitValue, since this is a union member */
233 CurrentThread->KeyedWaitValue = PreviousKeyedWaitValue;
234
235 return Status;
236}
237
240NTAPI
241ExpWaitForKeyedEvent(
242 _Inout_ PEX_KEYED_EVENT KeyedEvent,
243 _In_ PVOID KeyedWaitValue,
246{
247 /* Call the generic internal function */
248 return ExpReleaseOrWaitForKeyedEvent(KeyedEvent,
249 KeyedWaitValue,
250 Alertable,
251 Timeout,
252 FALSE);
253}
254
257NTAPI
258ExpReleaseKeyedEvent(
259 _Inout_ PEX_KEYED_EVENT KeyedEvent,
260 _In_ PVOID KeyedWaitValue,
263{
264 /* Call the generic internal function */
265 return ExpReleaseOrWaitForKeyedEvent(KeyedEvent,
266 KeyedWaitValue,
267 Alertable,
268 Timeout,
269 TRUE);
270}
271
274NTAPI
276 _Out_ PHANDLE OutHandle,
280{
282 PEX_KEYED_EVENT KeyedEvent;
283 HANDLE KeyedEventHandle;
285
286 /* Check flags */
287 if (Flags != 0)
288 {
289 /* We don't support any flags yet */
291 }
292
293 /* Create the object */
298 NULL,
299 sizeof(EX_KEYED_EVENT),
300 0,
301 0,
302 (PVOID*)&KeyedEvent);
303
304 /* Check for success */
305 if (!NT_SUCCESS(Status)) return Status;
306
307 /* Initialize the keyed event */
308 ExpInitializeKeyedEvent(KeyedEvent);
309
310 /* Insert it */
311 Status = ObInsertObject(KeyedEvent,
312 NULL,
314 0,
315 NULL,
316 &KeyedEventHandle);
317
318 /* Check for success (ObInsertObject dereferences!) */
319 if (!NT_SUCCESS(Status)) return Status;
320
322 {
323 /* Enter SEH for return */
325 {
326 /* Return the handle to the caller */
327 ProbeForWrite(OutHandle, sizeof(HANDLE), sizeof(HANDLE));
328 *OutHandle = KeyedEventHandle;
329 }
331 {
332 /* Get the exception code */
334
335 /* Cleanup */
336 ObCloseHandle(KeyedEventHandle, PreviousMode);
337 }
338 _SEH2_END;
339 }
340 else
341 {
342 *OutHandle = KeyedEventHandle;
343 }
344
345 /* Return Status */
346 return Status;
347}
348
351NTAPI
353 _Out_ PHANDLE OutHandle,
356{
358 HANDLE KeyedEventHandle;
360
361 /* Open the object */
365 NULL,
367 NULL,
368 &KeyedEventHandle);
369
370 /* Check for success */
371 if (!NT_SUCCESS(Status)) return Status;
372
373 /* Enter SEH for return */
375 {
377 {
378 /* Return the handle to the caller */
379 ProbeForWrite(OutHandle, sizeof(HANDLE), sizeof(HANDLE));
380 *OutHandle = KeyedEventHandle;
381 }
383 {
384 /* Get the exception code */
386
387 /* Cleanup */
388 ObCloseHandle(KeyedEventHandle, PreviousMode);
389 }
390 _SEH2_END;
391 }
392 else
393 {
394 *OutHandle = KeyedEventHandle;
395 }
396
397 /* Return status */
398 return Status;
399}
400
403NTAPI
406 _In_ PVOID Key,
409{
411 PEX_KEYED_EVENT KeyedEvent;
413 LARGE_INTEGER TimeoutCopy;
414
415 /* Key must always be two-byte aligned */
416 if ((ULONG_PTR)Key & 1)
417 {
419 }
420
421 /* Check if the caller passed a timeout value and this is from user mode */
422 if ((Timeout != NULL) && (PreviousMode != KernelMode))
423 {
425 {
426 ProbeForRead(Timeout, sizeof(*Timeout), 1);
427 TimeoutCopy = *Timeout;
428 Timeout = &TimeoutCopy;
429 }
431 {
433 }
434 _SEH2_END;
435 }
436
437 /* Check if the caller provided a handle */
438 if (Handle != NULL)
439 {
440 /* Get the keyed event object */
445 (PVOID*)&KeyedEvent,
446 NULL);
447
448 /* Check for success */
449 if (!NT_SUCCESS(Status)) return Status;
450 }
451 else
452 {
453 /* Use the default keyed event for low memory critical sections */
454 KeyedEvent = ExpCritSecOutOfMemoryEvent;
455 }
456
457 /* Do the wait */
458 Status = ExpWaitForKeyedEvent(KeyedEvent, Key, Alertable, Timeout);
459
460 if (Handle != NULL)
461 {
462 /* Dereference the keyed event */
463 ObDereferenceObject(KeyedEvent);
464 }
465
466 /* Return the status */
467 return Status;
468}
469
472NTAPI
475 _In_ PVOID Key,
478{
480 PEX_KEYED_EVENT KeyedEvent;
482 LARGE_INTEGER TimeoutCopy;
483
484 /* Key must always be two-byte aligned */
485 if ((ULONG_PTR)Key & 1)
486 {
488 }
489
490 /* Check if the caller passed a timeout value and this is from user mode */
491 if ((Timeout != NULL) && (PreviousMode != KernelMode))
492 {
494 {
495 ProbeForRead(Timeout, sizeof(*Timeout), 1);
496 TimeoutCopy = *Timeout;
497 Timeout = &TimeoutCopy;
498 }
500 {
502 }
503 _SEH2_END;
504 }
505
506 /* Check if the caller provided a handle */
507 if (Handle != NULL)
508 {
509 /* Get the keyed event object */
514 (PVOID*)&KeyedEvent,
515 NULL);
516
517 /* Check for success */
518 if (!NT_SUCCESS(Status)) return Status;
519 }
520 else
521 {
522 /* Use the default keyed event for low memory critical sections */
523 KeyedEvent = ExpCritSecOutOfMemoryEvent;
524 }
525
526 /* Do the wait */
527 Status = ExpReleaseKeyedEvent(KeyedEvent, Key, Alertable, Timeout);
528
529 if (Handle != NULL)
530 {
531 /* Dereference the keyed event */
532 ObDereferenceObject(KeyedEvent);
533 }
534
535 /* Return the status */
536 return Status;
537}
538
539/* EOF */
#define CODE_SEG(...)
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
_In_ BOOLEAN Release
Definition: cdrom.h:920
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ULONG_PTR
Definition: config.h:101
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
#define ExInitializePushLock
Definition: ex.h:1013
BOOLEAN NTAPI ExpInitializeKeyedEventImplementation(VOID)
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
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
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define OBJ_PERMANENT
Definition: winternl.h:226
NTSYSAPI NTSTATUS WINAPI NtCreateKeyedEvent(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG)
NTSYSAPI NTSTATUS WINAPI NtOpenKeyedEvent(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *)
NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE, const void *, BOOLEAN, const LARGE_INTEGER *)
NTSYSAPI NTSTATUS WINAPI NtReleaseKeyedEvent(HANDLE, const void *, BOOLEAN, const LARGE_INTEGER *)
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
static GENERIC_MAPPING ExpKeyedEventMapping
Definition: keyedevt.c:34
#define NUM_KEY_HASH_BUCKETS
Definition: keyedevt.c:17
VOID NTAPI ExpInitializeKeyedEvent(_Out_ PEX_KEYED_EVENT KeyedEvent)
Definition: keyedevt.c:95
struct _EX_KEYED_EVENT * PEX_KEYED_EVENT
struct _EX_KEYED_EVENT EX_KEYED_EVENT
PEX_KEYED_EVENT ExpCritSecOutOfMemoryEvent
Definition: keyedevt.c:30
POBJECT_TYPE ExKeyedEventObjectType
Definition: keyedevt.c:31
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define KernelMode
Definition: asm.h:34
#define KeGetPreviousMode()
Definition: ketypes.h:1115
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:453
_In_ ACCESS_MASK AccessMask
Definition: exfuncs.h:186
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2532
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1039
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define KEYEDEVENT_WAIT
Definition: om.c:74
#define KEYEDEVENT_ALL_ACCESS
Definition: om.c:76
#define KEYEDEVENT_WAKE
Definition: om.c:75
static ULONG Timeout
Definition: ping.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: hash.c:67
KPROCESS Pcb
Definition: pstypes.h:1262
KTHREAD Tcb
Definition: pstypes.h:1103
PVOID KeyedWaitValue
Definition: pstypes.h:1121
KSEMAPHORE KeyedWaitSemaphore
Definition: pstypes.h:1130
LIST_ENTRY KeyedWaitChain
Definition: pstypes.h:1109
EX_PUSH_LOCK Lock
Definition: keyedevt.c:22
LIST_ENTRY WaitListHead
Definition: keyedevt.c:23
LIST_ENTRY ReleaseListHead
Definition: keyedevt.c:24
PKPROCESS Process
Definition: ketypes.h:1908
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Out_ PHANDLE EventHandle
Definition: iofuncs.h:857
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ WrKeyedEvent
Definition: ketypes.h:436
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103