Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

983 lines
26 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. event.c
  5. Abstract:
  6. This module implements the executive event object. Functions are provided
  7. to create, open, set, reset, pulse, and query event objects.
  8. Author:
  9. David N. Cutler (davec) 8-May-1989
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "exp.h"
  15. //
  16. // Temporary so boost is patchable
  17. //
  18. ULONG ExpEventBoost = EVENT_INCREMENT;
  19. //
  20. // Address of event object type descriptor.
  21. //
  22. POBJECT_TYPE ExEventObjectType;
  23. //
  24. // Structure that describes the mapping of generic access rights to object
  25. // specific access rights for event objects.
  26. //
  27. #ifdef ALLOC_DATA_PRAGMA
  28. #pragma const_seg("INITCONST")
  29. #endif
  30. const GENERIC_MAPPING ExpEventMapping = {
  31. STANDARD_RIGHTS_READ |
  32. EVENT_QUERY_STATE,
  33. STANDARD_RIGHTS_WRITE |
  34. EVENT_MODIFY_STATE,
  35. STANDARD_RIGHTS_EXECUTE |
  36. SYNCHRONIZE,
  37. EVENT_ALL_ACCESS
  38. };
  39. #ifdef ALLOC_DATA_PRAGMA
  40. #pragma const_seg()
  41. #endif
  42. #ifdef ALLOC_PRAGMA
  43. #pragma alloc_text(INIT, ExpEventInitialization)
  44. #pragma alloc_text(PAGE, NtClearEvent)
  45. #pragma alloc_text(PAGE, NtCreateEvent)
  46. #pragma alloc_text(PAGE, NtOpenEvent)
  47. #pragma alloc_text(PAGE, NtPulseEvent)
  48. #pragma alloc_text(PAGE, NtQueryEvent)
  49. #pragma alloc_text(PAGE, NtResetEvent)
  50. #pragma alloc_text(PAGE, NtSetEvent)
  51. #pragma alloc_text(PAGE, NtSetEventBoostPriority)
  52. #endif
  53. BOOLEAN
  54. ExpEventInitialization (
  55. )
  56. /*++
  57. Routine Description:
  58. This function creates the event object type descriptor at system
  59. initialization and stores the address of the object type descriptor
  60. in global storage.
  61. Arguments:
  62. None.
  63. Return Value:
  64. A value of TRUE is returned if the event object type descriptor is
  65. successfully initialized. Otherwise a value of FALSE is returned.
  66. --*/
  67. {
  68. OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
  69. NTSTATUS Status;
  70. UNICODE_STRING TypeName;
  71. //
  72. // Initialize string descriptor.
  73. //
  74. RtlInitUnicodeString(&TypeName, L"Event");
  75. //
  76. // Create event object type descriptor.
  77. //
  78. RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
  79. ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
  80. ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
  81. ObjectTypeInitializer.GenericMapping = ExpEventMapping;
  82. ObjectTypeInitializer.PoolType = NonPagedPool;
  83. ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT);
  84. ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
  85. Status = ObCreateObjectType(&TypeName,
  86. &ObjectTypeInitializer,
  87. (PSECURITY_DESCRIPTOR)NULL,
  88. &ExEventObjectType);
  89. //
  90. // If the event object type descriptor was successfully created, then
  91. // return a value of TRUE. Otherwise return a value of FALSE.
  92. //
  93. return (BOOLEAN)(NT_SUCCESS(Status));
  94. }
  95. NTSTATUS
  96. NtClearEvent (
  97. IN HANDLE EventHandle
  98. )
  99. /*++
  100. Routine Description:
  101. This function sets an event object to a Not-Signaled state.
  102. Arguments:
  103. EventHandle - Supplies a handle to an event object.
  104. Return Value:
  105. NTSTATUS.
  106. --*/
  107. {
  108. PVOID Event;
  109. NTSTATUS Status;
  110. //
  111. // Reference event object by handle.
  112. //
  113. Status = ObReferenceObjectByHandle(EventHandle,
  114. EVENT_MODIFY_STATE,
  115. ExEventObjectType,
  116. KeGetPreviousMode(),
  117. &Event,
  118. NULL);
  119. //
  120. // If the reference was successful, then set the state of the event
  121. // object to Not-Signaled and dereference event object.
  122. //
  123. if (NT_SUCCESS(Status)) {
  124. PERFINFO_DECLARE_OBJECT(Event);
  125. KeClearEvent((PKEVENT)Event);
  126. ObDereferenceObject(Event);
  127. }
  128. //
  129. // Return service status.
  130. //
  131. return Status;
  132. }
  133. NTSTATUS
  134. NtCreateEvent (
  135. OUT PHANDLE EventHandle,
  136. IN ACCESS_MASK DesiredAccess,
  137. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  138. IN EVENT_TYPE EventType,
  139. IN BOOLEAN InitialState
  140. )
  141. /*++
  142. Routine Description:
  143. This function creates an event object, sets it initial state to the
  144. specified value, and opens a handle to the object with the specified
  145. desired access.
  146. Arguments:
  147. EventHandle - Supplies a pointer to a variable that will receive the
  148. event object handle.
  149. DesiredAccess - Supplies the desired types of access for the event object.
  150. ObjectAttributes - Supplies a pointer to an object attributes structure.
  151. EventType - Supplies the type of the event (autoclearing or notification).
  152. InitialState - Supplies the initial state of the event object.
  153. Return Value:
  154. NTSTATUS.
  155. --*/
  156. {
  157. PVOID Event;
  158. HANDLE Handle;
  159. KPROCESSOR_MODE PreviousMode;
  160. NTSTATUS Status;
  161. //
  162. // Establish an exception handler, probe the output handle address, and
  163. // attempt to create an event object. If the probe fails, then return the
  164. // exception code as the service status. Otherwise return the status value
  165. // returned by the object insertion routine.
  166. //
  167. PreviousMode = KeGetPreviousMode();
  168. //
  169. // Get previous processor mode and probe output handle address if
  170. // necessary.
  171. //
  172. if (PreviousMode != KernelMode) {
  173. try {
  174. ProbeForWriteHandle(EventHandle);
  175. } except(ExSystemExceptionFilter()) {
  176. return GetExceptionCode();
  177. }
  178. }
  179. //
  180. // Check argument validity.
  181. //
  182. if ((EventType != NotificationEvent) && (EventType != SynchronizationEvent)) {
  183. return STATUS_INVALID_PARAMETER;
  184. }
  185. //
  186. // Allocate event object.
  187. //
  188. Status = ObCreateObject(PreviousMode,
  189. ExEventObjectType,
  190. ObjectAttributes,
  191. PreviousMode,
  192. NULL,
  193. sizeof(KEVENT),
  194. 0,
  195. 0,
  196. (PVOID *)&Event);
  197. //
  198. // If the event object was successfully allocated, then initialize the
  199. // event object and attempt to insert the event object in the current
  200. // process' handle table.
  201. //
  202. if (NT_SUCCESS(Status)) {
  203. KeInitializeEvent((PKEVENT)Event, EventType, InitialState);
  204. Status = ObInsertObject(Event,
  205. NULL,
  206. DesiredAccess,
  207. 0,
  208. (PVOID *)NULL,
  209. &Handle);
  210. //
  211. // If the event object was successfully inserted in the current
  212. // process' handle table, then attempt to write the event object
  213. // handle value. If the write attempt fails, then do not report
  214. // an error. When the caller attempts to access the handle value,
  215. // an access violation will occur.
  216. //
  217. if (NT_SUCCESS(Status)) {
  218. if (PreviousMode != KernelMode) {
  219. try {
  220. *EventHandle = Handle;
  221. } except(ExSystemExceptionFilter()) {
  222. NOTHING;
  223. }
  224. }
  225. else {
  226. *EventHandle = Handle;
  227. }
  228. }
  229. }
  230. //
  231. // Return service status.
  232. //
  233. return Status;
  234. }
  235. NTSTATUS
  236. NtOpenEvent (
  237. OUT PHANDLE EventHandle,
  238. IN ACCESS_MASK DesiredAccess,
  239. IN POBJECT_ATTRIBUTES ObjectAttributes
  240. )
  241. /*++
  242. Routine Description:
  243. This function opens a handle to an event object with the specified
  244. desired access.
  245. Arguments:
  246. EventHandle - Supplies a pointer to a variable that will receive the
  247. event object handle.
  248. DesiredAccess - Supplies the desired types of access for the event object.
  249. ObjectAttributes - Supplies a pointer to an object attributes structure.
  250. Return Value:
  251. NTSTATUS.
  252. --*/
  253. {
  254. HANDLE Handle;
  255. KPROCESSOR_MODE PreviousMode;
  256. NTSTATUS Status;
  257. //
  258. // Establish an exception handler, probe the output handle address, and
  259. // attempt to open the event object. If the probe fails, then return the
  260. // exception code as the service status. Otherwise return the status value
  261. // returned by the object open routine.
  262. //
  263. //
  264. // Get previous processor mode and probe output handle address
  265. // if necessary.
  266. //
  267. PreviousMode = KeGetPreviousMode();
  268. if (PreviousMode != KernelMode) {
  269. try {
  270. ProbeForWriteHandle(EventHandle);
  271. } except(ExSystemExceptionFilter()) {
  272. return GetExceptionCode();
  273. }
  274. }
  275. //
  276. // Open handle to the event object with the specified desired access.
  277. //
  278. Status = ObOpenObjectByName(ObjectAttributes,
  279. ExEventObjectType,
  280. PreviousMode,
  281. NULL,
  282. DesiredAccess,
  283. NULL,
  284. &Handle);
  285. //
  286. // If the open was successful, then attempt to write the event object
  287. // handle value. If the write attempt fails, then do not report an
  288. // error. When the caller attempts to access the handle value, an
  289. // access violation will occur.
  290. //
  291. if (NT_SUCCESS(Status)) {
  292. if (PreviousMode != KernelMode) {
  293. try {
  294. *EventHandle = Handle;
  295. } except(ExSystemExceptionFilter()) {
  296. NOTHING;
  297. }
  298. }
  299. else {
  300. *EventHandle = Handle;
  301. }
  302. }
  303. //
  304. // Return service status.
  305. //
  306. return Status;
  307. }
  308. NTSTATUS
  309. NtPulseEvent (
  310. IN HANDLE EventHandle,
  311. OUT PLONG PreviousState OPTIONAL
  312. )
  313. /*++
  314. Routine Description:
  315. This function sets an event object to a Signaled state, attempts to
  316. satisfy as many waits as possible, and then resets the state of the
  317. event object to Not-Signaled.
  318. Arguments:
  319. EventHandle - Supplies a handle to an event object.
  320. PreviousState - Supplies an optional pointer to a variable that will
  321. receive the previous state of the event object.
  322. Return Value:
  323. NTSTATUS.
  324. --*/
  325. {
  326. PVOID Event;
  327. KPROCESSOR_MODE PreviousMode;
  328. LONG State;
  329. NTSTATUS Status;
  330. //
  331. // Establish an exception handler, probe the previous state address if
  332. // specified, reference the event object, and pulse the event object. If
  333. // the probe fails, then return the exception code as the service status.
  334. // Otherwise return the status value returned by the reference object by
  335. // handle routine.
  336. //
  337. //
  338. // Get previous processor mode and probe previous state address
  339. // if necessary.
  340. //
  341. PreviousMode = KeGetPreviousMode();
  342. if (ARGUMENT_PRESENT(PreviousState) && (PreviousMode != KernelMode)) {
  343. try {
  344. ProbeForWriteLong(PreviousState);
  345. } except(ExSystemExceptionFilter()) {
  346. return GetExceptionCode();
  347. }
  348. }
  349. //
  350. // Reference event object by handle.
  351. //
  352. Status = ObReferenceObjectByHandle(EventHandle,
  353. EVENT_MODIFY_STATE,
  354. ExEventObjectType,
  355. PreviousMode,
  356. &Event,
  357. NULL);
  358. //
  359. // If the reference was successful, then pulse the event object,
  360. // dereference event object, and write the previous state value if
  361. // specified. If the write of the previous state fails, then do not
  362. // report an error. When the caller attempts to access the previous
  363. // state value, an access violation will occur.
  364. //
  365. if (NT_SUCCESS(Status)) {
  366. PERFINFO_DECLARE_OBJECT(Event);
  367. State = KePulseEvent((PKEVENT)Event, ExpEventBoost, FALSE);
  368. ObDereferenceObject(Event);
  369. if (ARGUMENT_PRESENT(PreviousState)) {
  370. if (PreviousMode != KernelMode) {
  371. try {
  372. *PreviousState = State;
  373. } except(ExSystemExceptionFilter()) {
  374. NOTHING;
  375. }
  376. }
  377. else {
  378. *PreviousState = State;
  379. }
  380. }
  381. }
  382. //
  383. // Return service status.
  384. //
  385. return Status;
  386. }
  387. NTSTATUS
  388. NtQueryEvent (
  389. IN HANDLE EventHandle,
  390. IN EVENT_INFORMATION_CLASS EventInformationClass,
  391. OUT PVOID EventInformation,
  392. IN ULONG EventInformationLength,
  393. OUT PULONG ReturnLength OPTIONAL
  394. )
  395. /*++
  396. Routine Description:
  397. This function queries the state of an event object and returns the
  398. requested information in the specified record structure.
  399. Arguments:
  400. EventHandle - Supplies a handle to an event object.
  401. EventInformationClass - Supplies the class of information being requested.
  402. EventInformation - Supplies a pointer to a record that is to receive the
  403. requested information.
  404. EventInformationLength - Supplies the length of the record that is to
  405. receive the requested information.
  406. ReturnLength - Supplies an optional pointer to a variable that is to
  407. receive the actual length of information that is returned.
  408. Return Value:
  409. NTSTATUS.
  410. --*/
  411. {
  412. PKEVENT Event;
  413. KPROCESSOR_MODE PreviousMode;
  414. LONG State;
  415. NTSTATUS Status;
  416. EVENT_TYPE EventType;
  417. //
  418. // Check argument validity.
  419. //
  420. if (EventInformationClass != EventBasicInformation) {
  421. return STATUS_INVALID_INFO_CLASS;
  422. }
  423. if (EventInformationLength != sizeof(EVENT_BASIC_INFORMATION)) {
  424. return STATUS_INFO_LENGTH_MISMATCH;
  425. }
  426. //
  427. // Establish an exception handler, probe the output arguments, reference
  428. // the event object, and return the specified information. If the probe
  429. // fails, then return the exception code as the service status. Otherwise
  430. // return the status value returned by the reference object by handle
  431. // routine.
  432. //
  433. //
  434. // Get previous processor mode and probe output arguments if necessary.
  435. //
  436. PreviousMode = KeGetPreviousMode();
  437. if (PreviousMode != KernelMode) {
  438. try {
  439. ProbeForWrite(EventInformation,
  440. sizeof(EVENT_BASIC_INFORMATION),
  441. sizeof(ULONG));
  442. if (ARGUMENT_PRESENT(ReturnLength)) {
  443. ProbeForWriteUlong(ReturnLength);
  444. }
  445. } except(ExSystemExceptionFilter()) {
  446. return GetExceptionCode();
  447. }
  448. }
  449. //
  450. // Reference event object by handle.
  451. //
  452. Status = ObReferenceObjectByHandle(EventHandle,
  453. EVENT_QUERY_STATE,
  454. ExEventObjectType,
  455. PreviousMode,
  456. (PVOID *)&Event,
  457. NULL);
  458. //
  459. // If the reference was successful, then read the current state of
  460. // the event object, deference event object, fill in the information
  461. // structure, and return the length of the information structure if
  462. // specified. If the write of the event information or the return
  463. // length fails, then do not report an error. When the caller accesses
  464. // the information structure or length an access violation will occur.
  465. //
  466. if (NT_SUCCESS(Status)) {
  467. State = KeReadStateEvent(Event);
  468. EventType = Event->Header.Type;
  469. ObDereferenceObject(Event);
  470. if (PreviousMode != KernelMode) {
  471. try {
  472. ((PEVENT_BASIC_INFORMATION)EventInformation)->EventType = EventType;
  473. ((PEVENT_BASIC_INFORMATION)EventInformation)->EventState = State;
  474. if (ARGUMENT_PRESENT(ReturnLength)) {
  475. *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
  476. }
  477. } except(ExSystemExceptionFilter()) {
  478. NOTHING;
  479. }
  480. }
  481. else {
  482. ((PEVENT_BASIC_INFORMATION)EventInformation)->EventType = EventType;
  483. ((PEVENT_BASIC_INFORMATION)EventInformation)->EventState = State;
  484. if (ARGUMENT_PRESENT(ReturnLength)) {
  485. *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
  486. }
  487. }
  488. }
  489. //
  490. // Return service status.
  491. //
  492. return Status;
  493. }
  494. NTSTATUS
  495. NtResetEvent (
  496. IN HANDLE EventHandle,
  497. OUT PLONG PreviousState OPTIONAL
  498. )
  499. /*++
  500. Routine Description:
  501. This function sets an event object to a Not-Signaled state.
  502. Arguments:
  503. EventHandle - Supplies a handle to an event object.
  504. PreviousState - Supplies an optional pointer to a variable that will
  505. receive the previous state of the event object.
  506. Return Value:
  507. NTSTATUS.
  508. --*/
  509. {
  510. PVOID Event;
  511. KPROCESSOR_MODE PreviousMode;
  512. LONG State;
  513. NTSTATUS Status;
  514. //
  515. // Establish an exception handler, probe the previous state address if
  516. // specified, reference the event object, and reset the event object. If
  517. // the probe fails, then return the exception code as the service status.
  518. // Otherwise return the status value returned by the reference object by
  519. // handle routine.
  520. //
  521. //
  522. // Get previous processor mode and probe previous state address
  523. // if necessary.
  524. //
  525. PreviousMode = KeGetPreviousMode();
  526. if ((ARGUMENT_PRESENT(PreviousState)) && (PreviousMode != KernelMode)) {
  527. try {
  528. ProbeForWriteLong(PreviousState);
  529. } except(ExSystemExceptionFilter()) {
  530. return GetExceptionCode();
  531. }
  532. }
  533. //
  534. // Reference event object by handle.
  535. //
  536. Status = ObReferenceObjectByHandle(EventHandle,
  537. EVENT_MODIFY_STATE,
  538. ExEventObjectType,
  539. PreviousMode,
  540. &Event,
  541. NULL);
  542. //
  543. // If the reference was successful, then set the state of the event
  544. // object to Not-Signaled, dereference event object, and write the
  545. // previous state value if specified. If the write of the previous
  546. // state fails, then do not report an error. When the caller attempts
  547. // to access the previous state value, an access violation will occur.
  548. //
  549. if (NT_SUCCESS(Status)) {
  550. PERFINFO_DECLARE_OBJECT(Event);
  551. State = KeResetEvent((PKEVENT)Event);
  552. ObDereferenceObject(Event);
  553. if (ARGUMENT_PRESENT(PreviousState)) {
  554. if (PreviousMode != KernelMode) {
  555. try {
  556. *PreviousState = State;
  557. } except(ExSystemExceptionFilter()) {
  558. NOTHING;
  559. }
  560. }
  561. else {
  562. *PreviousState = State;
  563. }
  564. }
  565. }
  566. //
  567. // Return service status.
  568. //
  569. return Status;
  570. }
  571. NTSTATUS
  572. NtSetEvent (
  573. IN HANDLE EventHandle,
  574. OUT PLONG PreviousState OPTIONAL
  575. )
  576. /*++
  577. Routine Description:
  578. This function sets an event object to a Signaled state and attempts to
  579. satisfy as many waits as possible.
  580. Arguments:
  581. EventHandle - Supplies a handle to an event object.
  582. PreviousState - Supplies an optional pointer to a variable that will
  583. receive the previous state of the event object.
  584. Return Value:
  585. NTSTATUS.
  586. --*/
  587. {
  588. PVOID Event;
  589. KPROCESSOR_MODE PreviousMode;
  590. LONG State;
  591. NTSTATUS Status;
  592. #if DBG
  593. //
  594. // Sneaky trick here to catch sleazy apps (csrss) that erroneously call
  595. // NtSetEvent on an event that happens to be somebody else's
  596. // critical section. Only allow setting a protected handle if the low
  597. // bit of PreviousState is set.
  598. //
  599. OBJECT_HANDLE_INFORMATION HandleInfo;
  600. #endif
  601. //
  602. // Establish an exception handler, probe the previous state address if
  603. // specified, reference the event object, and set the event object. If
  604. // the probe fails, then return the exception code as the service status.
  605. // Otherwise return the status value returned by the reference object by
  606. // handle routine.
  607. //
  608. //
  609. // Get previous processor mode and probe previous state address
  610. // if necessary.
  611. //
  612. PreviousMode = KeGetPreviousMode();
  613. try {
  614. #if DBG
  615. if ((PreviousMode != KernelMode) &&
  616. (ARGUMENT_PRESENT(PreviousState)) &&
  617. (PreviousState != (PLONG)1)) {
  618. ProbeForWriteLong(PreviousState);
  619. }
  620. #else
  621. if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousState))) {
  622. ProbeForWriteLong(PreviousState);
  623. }
  624. #endif
  625. //
  626. // Reference event object by handle.
  627. //
  628. #if DBG
  629. Status = ObReferenceObjectByHandle(EventHandle,
  630. EVENT_MODIFY_STATE,
  631. ExEventObjectType,
  632. PreviousMode,
  633. &Event,
  634. &HandleInfo);
  635. if (NT_SUCCESS(Status)) {
  636. if ((HandleInfo.HandleAttributes & 1) &&
  637. (PreviousState != (PLONG)1)) {
  638. #if 0
  639. //
  640. // This is a protected handle. If the low bit of PreviousState is NOT set,
  641. // break into the debugger
  642. //
  643. DbgPrint("NtSetEvent: Illegal call to NtSetEvent on a protected handle\n");
  644. DbgBreakPoint();
  645. PreviousState = NULL;
  646. #endif
  647. }
  648. } else {
  649. if ((KeGetPreviousMode() != KernelMode) &&
  650. (EventHandle != NULL) &&
  651. ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
  652. (PsGetCurrentProcess()->DebugPort != NULL))) {
  653. if (!KeIsAttachedProcess()) {
  654. KeRaiseUserException (STATUS_INVALID_HANDLE);
  655. }
  656. return Status;
  657. }
  658. }
  659. #else
  660. Status = ObReferenceObjectByHandle(EventHandle,
  661. EVENT_MODIFY_STATE,
  662. ExEventObjectType,
  663. PreviousMode,
  664. &Event,
  665. NULL);
  666. #endif
  667. //
  668. // If the reference was successful, then set the event object to the
  669. // Signaled state, dereference event object, and write the previous
  670. // state value if specified. If the write of the previous state fails,
  671. // then do not report an error. When the caller attempts to access the
  672. // previous state value, an access violation will occur.
  673. //
  674. if (NT_SUCCESS(Status)) {
  675. PERFINFO_DECLARE_OBJECT(Event);
  676. State = KeSetEvent((PKEVENT)Event, ExpEventBoost, FALSE);
  677. ObDereferenceObject(Event);
  678. if (ARGUMENT_PRESENT(PreviousState)) {
  679. try {
  680. *PreviousState = State;
  681. } except(ExSystemExceptionFilter()) {
  682. }
  683. }
  684. }
  685. //
  686. // If an exception occurs during the probe of the previous state, then
  687. // always handle the exception and return the exception code as the status
  688. // value.
  689. //
  690. } except(ExSystemExceptionFilter()) {
  691. return GetExceptionCode();
  692. }
  693. //
  694. // Return service status.
  695. //
  696. return Status;
  697. }
  698. NTSTATUS
  699. NtSetEventBoostPriority (
  700. IN HANDLE EventHandle
  701. )
  702. /*++
  703. Routine Description:
  704. This function sets an event object to a Signaled state and performs
  705. a special priority boost operation.
  706. N.B. This service can only be performed on synchronization events.
  707. Arguments:
  708. EventHandle - Supplies a handle to an event object.
  709. PreviousState - Supplies an optional pointer to a variable that will
  710. receive the previous state of the event object.
  711. Return Value:
  712. NTSTATUS.
  713. --*/
  714. {
  715. PKEVENT Event;
  716. NTSTATUS Status;
  717. //
  718. // Reference event object by handle.
  719. //
  720. Status = ObReferenceObjectByHandle(EventHandle,
  721. EVENT_MODIFY_STATE,
  722. ExEventObjectType,
  723. KeGetPreviousMode(),
  724. &Event,
  725. NULL);
  726. //
  727. // If the reference was successful, then check the type of event object.
  728. // If the event object is a notification event, then return an object
  729. // type mismatch status. Otherwise, set the specified event and boost
  730. // the unwaited thread priority as appropriate.
  731. //
  732. if (NT_SUCCESS(Status)) {
  733. if (Event->Header.Type == NotificationEvent) {
  734. Status = STATUS_OBJECT_TYPE_MISMATCH;
  735. } else {
  736. KeSetEventBoostPriority(Event, NULL);
  737. }
  738. ObDereferenceObject(Event);
  739. }
  740. //
  741. // Return service status.
  742. //
  743. return Status;
  744. }