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