1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel 4 * FILE: ntoskrnl/ex/evtpair.c 5 * PURPOSE: Support for event pairs 6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7 * Thomas Weidenmueller 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 POBJECT_TYPE ExEventPairObjectType = NULL; 19 20 GENERIC_MAPPING ExEventPairMapping = 21 { 22 STANDARD_RIGHTS_READ | SYNCHRONIZE, 23 STANDARD_RIGHTS_WRITE | SYNCHRONIZE, 24 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, 25 EVENT_PAIR_ALL_ACCESS 26 }; 27 28 /* FUNCTIONS *****************************************************************/ 29 30 CODE_SEG("INIT") 31 BOOLEAN 32 NTAPI 33 ExpInitializeEventPairImplementation(VOID) 34 { 35 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 36 UNICODE_STRING Name; 37 NTSTATUS Status; 38 DPRINT("Creating Event Pair Object Type\n"); 39 40 /* Create the Event Pair Object Type */ 41 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 42 RtlInitUnicodeString(&Name, L"EventPair"); 43 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 44 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT_PAIR); 45 ObjectTypeInitializer.GenericMapping = ExEventPairMapping; 46 ObjectTypeInitializer.PoolType = NonPagedPool; 47 ObjectTypeInitializer.ValidAccessMask = EVENT_PAIR_ALL_ACCESS; 48 ObjectTypeInitializer.UseDefaultObject = TRUE; 49 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 50 Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExEventPairObjectType); 51 if (!NT_SUCCESS(Status)) return FALSE; 52 return TRUE; 53 } 54 55 NTSTATUS 56 NTAPI 57 NtCreateEventPair(OUT PHANDLE EventPairHandle, 58 IN ACCESS_MASK DesiredAccess, 59 IN POBJECT_ATTRIBUTES ObjectAttributes) 60 { 61 PKEVENT_PAIR EventPair; 62 HANDLE hEventPair; 63 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 64 NTSTATUS Status; 65 PAGED_CODE(); 66 DPRINT("NtCreateEventPair: 0x%p\n", EventPairHandle); 67 68 /* Check if we were called from user-mode */ 69 if (PreviousMode != KernelMode) 70 { 71 /* Enter SEH Block */ 72 _SEH2_TRY 73 { 74 /* Check handle pointer */ 75 ProbeForWriteHandle(EventPairHandle); 76 } 77 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 78 { 79 /* Return the exception code */ 80 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 81 } 82 _SEH2_END; 83 } 84 85 /* Create the Object */ 86 DPRINT("Creating EventPair\n"); 87 Status = ObCreateObject(PreviousMode, 88 ExEventPairObjectType, 89 ObjectAttributes, 90 PreviousMode, 91 NULL, 92 sizeof(KEVENT_PAIR), 93 0, 94 0, 95 (PVOID*)&EventPair); 96 97 /* Check for Success */ 98 if (NT_SUCCESS(Status)) 99 { 100 /* Initialize the Event */ 101 DPRINT("Initializing EventPair\n"); 102 KeInitializeEventPair(EventPair); 103 104 /* Insert it */ 105 Status = ObInsertObject((PVOID)EventPair, 106 NULL, 107 DesiredAccess, 108 0, 109 NULL, 110 &hEventPair); 111 112 /* Check for success */ 113 if (NT_SUCCESS(Status)) 114 { 115 /* Enter SEH */ 116 _SEH2_TRY 117 { 118 /* Return the handle */ 119 *EventPairHandle = hEventPair; 120 } 121 _SEH2_EXCEPT(ExSystemExceptionFilter()) 122 { 123 /* Get the exception code */ 124 Status = _SEH2_GetExceptionCode(); 125 } 126 _SEH2_END; 127 } 128 } 129 130 /* Return Status */ 131 return Status; 132 } 133 134 NTSTATUS 135 NTAPI 136 NtOpenEventPair(OUT PHANDLE EventPairHandle, 137 IN ACCESS_MASK DesiredAccess, 138 IN POBJECT_ATTRIBUTES ObjectAttributes) 139 { 140 HANDLE hEventPair; 141 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 142 NTSTATUS Status; 143 PAGED_CODE(); 144 145 /* Check if we were called from user-mode */ 146 if (PreviousMode != KernelMode) 147 { 148 /* Enter SEH Block */ 149 _SEH2_TRY 150 { 151 /* Check handle pointer */ 152 ProbeForWriteHandle(EventPairHandle); 153 } 154 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 155 { 156 /* Return the exception code */ 157 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 158 } 159 _SEH2_END; 160 } 161 162 /* Open the Object */ 163 Status = ObOpenObjectByName(ObjectAttributes, 164 ExEventPairObjectType, 165 PreviousMode, 166 NULL, 167 DesiredAccess, 168 NULL, 169 &hEventPair); 170 171 /* Check for success */ 172 if (NT_SUCCESS(Status)) 173 { 174 /* Enter SEH */ 175 _SEH2_TRY 176 { 177 /* Return the handle */ 178 *EventPairHandle = hEventPair; 179 } 180 _SEH2_EXCEPT(ExSystemExceptionFilter()) 181 { 182 /* Get the exception code */ 183 Status = _SEH2_GetExceptionCode(); 184 } 185 _SEH2_END; 186 } 187 188 /* Return status */ 189 return Status; 190 } 191 192 NTSTATUS 193 NTAPI 194 NtSetHighEventPair(IN HANDLE EventPairHandle) 195 { 196 PKEVENT_PAIR EventPair; 197 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 198 NTSTATUS Status; 199 PAGED_CODE(); 200 DPRINT("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle); 201 202 /* Open the Object */ 203 Status = ObReferenceObjectByHandle(EventPairHandle, 204 SYNCHRONIZE, 205 ExEventPairObjectType, 206 PreviousMode, 207 (PVOID*)&EventPair, 208 NULL); 209 210 /* Check for Success */ 211 if(NT_SUCCESS(Status)) 212 { 213 /* Set the Event */ 214 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE); 215 216 /* Dereference Object */ 217 ObDereferenceObject(EventPair); 218 } 219 220 /* Return status */ 221 return Status; 222 } 223 224 NTSTATUS 225 NTAPI 226 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle) 227 { 228 PKEVENT_PAIR EventPair; 229 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 230 NTSTATUS Status; 231 PAGED_CODE(); 232 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle); 233 234 /* Open the Object */ 235 Status = ObReferenceObjectByHandle(EventPairHandle, 236 SYNCHRONIZE, 237 ExEventPairObjectType, 238 PreviousMode, 239 (PVOID*)&EventPair, 240 NULL); 241 242 /* Check for Success */ 243 if(NT_SUCCESS(Status)) 244 { 245 /* Set the Event */ 246 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE); 247 248 /* Wait for the Other one */ 249 KeWaitForSingleObject(&EventPair->LowEvent, 250 WrEventPair, 251 PreviousMode, 252 FALSE, 253 NULL); 254 255 /* Dereference Object */ 256 ObDereferenceObject(EventPair); 257 } 258 259 /* Return status */ 260 return Status; 261 } 262 263 NTSTATUS 264 NTAPI 265 NtSetLowEventPair(IN HANDLE EventPairHandle) 266 { 267 PKEVENT_PAIR EventPair; 268 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 269 NTSTATUS Status; 270 PAGED_CODE(); 271 DPRINT1("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle); 272 273 /* Open the Object */ 274 Status = ObReferenceObjectByHandle(EventPairHandle, 275 SYNCHRONIZE, 276 ExEventPairObjectType, 277 PreviousMode, 278 (PVOID*)&EventPair, 279 NULL); 280 281 /* Check for Success */ 282 if(NT_SUCCESS(Status)) 283 { 284 /* Set the Event */ 285 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE); 286 287 /* Dereference Object */ 288 ObDereferenceObject(EventPair); 289 } 290 291 /* Return status */ 292 return Status; 293 } 294 295 NTSTATUS 296 NTAPI 297 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle) 298 { 299 PKEVENT_PAIR EventPair; 300 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 301 NTSTATUS Status; 302 PAGED_CODE(); 303 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle); 304 305 /* Open the Object */ 306 Status = ObReferenceObjectByHandle(EventPairHandle, 307 SYNCHRONIZE, 308 ExEventPairObjectType, 309 PreviousMode, 310 (PVOID*)&EventPair, 311 NULL); 312 313 /* Check for Success */ 314 if(NT_SUCCESS(Status)) 315 { 316 /* Set the Event */ 317 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE); 318 319 /* Wait for the Other one */ 320 KeWaitForSingleObject(&EventPair->HighEvent, 321 WrEventPair, 322 PreviousMode, 323 FALSE, 324 NULL); 325 326 /* Dereference Object */ 327 ObDereferenceObject(EventPair); 328 } 329 330 /* Return status */ 331 return Status; 332 } 333 334 335 NTSTATUS 336 NTAPI 337 NtWaitLowEventPair(IN HANDLE EventPairHandle) 338 { 339 PKEVENT_PAIR EventPair; 340 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 341 NTSTATUS Status; 342 PAGED_CODE(); 343 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle); 344 345 /* Open the Object */ 346 Status = ObReferenceObjectByHandle(EventPairHandle, 347 SYNCHRONIZE, 348 ExEventPairObjectType, 349 PreviousMode, 350 (PVOID*)&EventPair, 351 NULL); 352 353 /* Check for Success */ 354 if(NT_SUCCESS(Status)) 355 { 356 /* Wait for the Event */ 357 KeWaitForSingleObject(&EventPair->LowEvent, 358 WrEventPair, 359 PreviousMode, 360 FALSE, 361 NULL); 362 363 /* Dereference Object */ 364 ObDereferenceObject(EventPair); 365 } 366 367 /* Return status */ 368 return Status; 369 } 370 371 NTSTATUS 372 NTAPI 373 NtWaitHighEventPair(IN HANDLE EventPairHandle) 374 { 375 PKEVENT_PAIR EventPair; 376 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 377 NTSTATUS Status; 378 379 PAGED_CODE(); 380 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle); 381 382 /* Open the Object */ 383 Status = ObReferenceObjectByHandle(EventPairHandle, 384 SYNCHRONIZE, 385 ExEventPairObjectType, 386 PreviousMode, 387 (PVOID*)&EventPair, 388 NULL); 389 390 /* Check for Success */ 391 if(NT_SUCCESS(Status)) 392 { 393 /* Wait for the Event */ 394 KeWaitForSingleObject(&EventPair->HighEvent, 395 WrEventPair, 396 PreviousMode, 397 FALSE, 398 NULL); 399 400 /* Dereference Object */ 401 ObDereferenceObject(EventPair); 402 } 403 404 /* Return status */ 405 return Status; 406 } 407 408 /* EOF */ 409