xref: /reactos/win32ss/gdi/eng/engevent.c (revision c2c66aff)
1 /*
2  * PROJECT:         ReactOS Win32K
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            win32ss/gdi/eng/engevent.c
5  * PURPOSE:         Event Support Routines
6  * PROGRAMMERS:     Aleksey Bragin <aleksey@reactos.org>
7  *                  ReactOS Portable Systems Group
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <win32k.h>
13 
14 #include <ntddvdeo.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 /* PUBLIC FUNCTIONS ***********************************************************/
20 
21 _Must_inspect_result_
22 _Success_(return != FALSE)
23 BOOL
24 APIENTRY
EngCreateEvent(_Outptr_ PEVENT * ppEvent)25 EngCreateEvent(
26     _Outptr_ PEVENT *ppEvent)
27 {
28     BOOLEAN Result = TRUE;
29     PENG_EVENT EngEvent;
30 
31     /* Allocate memory for the event structure */
32     EngEvent = ExAllocatePoolWithTag(NonPagedPool,
33                                      sizeof(ENG_EVENT) + sizeof(KEVENT),
34                                      GDITAG_ENG_EVENT);
35     if (EngEvent)
36     {
37         /* Set KEVENT pointer */
38         EngEvent->fFlags = 0;
39         EngEvent->pKEvent = EngEvent + 1;
40 
41         /* Initialize the kernel event */
42         KeInitializeEvent(EngEvent->pKEvent,
43                           SynchronizationEvent,
44                           FALSE);
45 
46         /* Pass pointer to our structure to the caller */
47         *ppEvent = EngEvent;
48         DPRINT("EngCreateEvent() created %p\n", EngEvent);
49     }
50     else
51     {
52         /* Out of memory */
53         DPRINT("EngCreateEvent() failed\n");
54         Result = FALSE;
55     }
56 
57     /* Return result */
58     return Result;
59 }
60 
61 BOOL
62 APIENTRY
EngDeleteEvent(_In_ _Post_ptr_invalid_ PEVENT Event)63 EngDeleteEvent(
64     _In_ _Post_ptr_invalid_ PEVENT Event)
65 {
66     DPRINT("EngDeleteEvent(%p)\n", Event);
67 
68     /* Check if it's a usermapped event */
69     if (Event->fFlags & ENG_EVENT_USERMAPPED)
70     {
71         /* Disallow deletion of usermapped events */
72         DPRINT1("Driver attempted to delete a usermapped event!\n");
73         return FALSE;
74     }
75 
76     /* Free the allocated memory */
77     ExFreePoolWithTag(Event, GDITAG_ENG_EVENT);
78 
79     /* Return success */
80     return TRUE;
81 }
82 
83 VOID
84 APIENTRY
EngClearEvent(_In_ PEVENT Event)85 EngClearEvent(
86     _In_ PEVENT Event)
87 {
88     /* Clear the event */
89     KeClearEvent(Event->pKEvent);
90 }
91 
92 LONG
93 APIENTRY
EngSetEvent(_In_ PEVENT Event)94 EngSetEvent(
95     _In_ PEVENT Event)
96 {
97     /* Set the event */
98     return KeSetEvent(Event->pKEvent,
99                       IO_NO_INCREMENT,
100                       FALSE);
101 }
102 
103 LONG
104 APIENTRY
EngReadStateEvent(_In_ PEVENT Event)105 EngReadStateEvent(
106     _In_ PEVENT Event)
107 {
108     /* Read the event state */
109     return KeReadStateEvent(Event->pKEvent);
110 }
111 
112 PEVENT
113 APIENTRY
EngMapEvent(_In_ HDEV hDev,_In_ HANDLE hUserObject,_Reserved_ PVOID Reserved1,_Reserved_ PVOID Reserved2,_Reserved_ PVOID Reserved3)114 EngMapEvent(
115     _In_ HDEV hDev,
116     _In_ HANDLE hUserObject,
117     _Reserved_ PVOID Reserved1,
118     _Reserved_ PVOID Reserved2,
119     _Reserved_ PVOID Reserved3)
120 {
121     PENG_EVENT EngEvent;
122     PVOID pvEvent;
123     NTSTATUS Status;
124 
125     /* Allocate memory for the event structure */
126     EngEvent = ExAllocatePoolWithTag(NonPagedPool,
127                                      sizeof(ENG_EVENT),
128                                      GDITAG_ENG_EVENT);
129     if (!EngEvent) return NULL;
130 
131     /* Zero it out */
132     EngEvent->fFlags = 0;
133     EngEvent->pKEvent = NULL;
134 
135     /* Create a handle, and have Ob fill out the pKEvent field */
136     Status = ObReferenceObjectByHandle(hUserObject,
137                                        EVENT_ALL_ACCESS,
138                                        *ExEventObjectType,
139                                        UserMode,
140                                        &pvEvent,
141                                        NULL);
142     if (NT_SUCCESS(Status))
143     {
144         /* Pulse the event and set that it's mapped by user */
145         KePulseEvent(pvEvent, EVENT_INCREMENT, FALSE);
146         EngEvent->pKEvent = pvEvent;
147         EngEvent->fFlags |= ENG_EVENT_USERMAPPED;
148     }
149     else
150     {
151         /* Free the allocation */
152         ExFreePoolWithTag(EngEvent, GDITAG_ENG_EVENT);
153         EngEvent = NULL;
154     }
155 
156     /* Support legacy interface */
157     if (Reserved1) *(PVOID*)Reserved1 = EngEvent;
158     return EngEvent;
159 }
160 
161 BOOL
162 APIENTRY
EngUnmapEvent(_In_ PEVENT Event)163 EngUnmapEvent(
164     _In_ PEVENT Event)
165 {
166     /* Must be a usermapped event */
167     if (!(Event->fFlags & ENG_EVENT_USERMAPPED)) return FALSE;
168 
169     /* Dereference the object, destroying it */
170     ObDereferenceObject(Event->pKEvent);
171 
172     /* Free the Eng object */
173     ExFreePoolWithTag(Event, GDITAG_ENG_EVENT);
174     return TRUE;
175 }
176 
177 BOOL
178 APIENTRY
EngWaitForSingleObject(_In_ PEVENT Event,_In_opt_ PLARGE_INTEGER TimeOut)179 EngWaitForSingleObject(
180     _In_ PEVENT Event,
181     _In_opt_ PLARGE_INTEGER TimeOut)
182 {
183     NTSTATUS Status;
184     DPRINT("EngWaitForSingleObject(%p %I64d)\n", Event, TimeOut->QuadPart);
185 
186     /* Validate parameters */
187     if (!Event) return FALSE;
188 
189     /* Check if it's a usermapped event and fail in that case */
190     if (Event->fFlags & ENG_EVENT_USERMAPPED)
191     {
192         /* Disallow deletion of usermapped events */
193         DPRINT1("Driver attempted to wait on a usermapped event!\n");
194         return FALSE;
195     }
196 
197     /* Wait for the event */
198     Status = KeWaitForSingleObject(Event->pKEvent,
199                                    Executive,
200                                    KernelMode,
201                                    FALSE,
202                                    TimeOut);
203 
204     /* Check if there is a failure or a timeout */
205     return NT_SUCCESS(Status);
206 }
207 
208 /* EOF */
209