test: event.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# event.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     event.c
    00008
    00009 Abstract:
    00010
    00011    This module implements the executive event object. Functions are provided
    00012    to create, open, set, reset, pulse, and query event objects.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 8-May-1989
    00017
    00018 Environment:
    00019
    00020     Kernel mode only.
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026 #include "exp.h"
    00027
    00028 //
    00029 // Temporary so boost is patchable
    00030 //
    00031
    00032 ULONG ExpEventBoost = EVENT_INCREMENT;
    00033
    00034 //
    00035 // Address of event object type descriptor.
    00036 //
    00037
    00038 POBJECT_TYPE ExEventObjectType;
    00039
    00040 //
    00041 // Structure that describes the mapping of generic access rights to object
    00042 // specific access rights for event objects.
    00043 //
    00044
    00045 GENERIC_MAPPING ExpEventMapping = {
    00046     STANDARD_RIGHTS_READ |
    00047         EVENT_QUERY_STATE,
    00048     STANDARD_RIGHTS_WRITE |
    00049         EVENT_MODIFY_STATE,
    00050     STANDARD_RIGHTS_EXECUTE |
    00051         SYNCHRONIZE,
    00052     EVENT_ALL_ACCESS
    00053 };
    00054
    00055 #ifdef ALLOC_PRAGMA
    00056 #pragma alloc_text(INIT, ExpEventInitialization)
    00057 #pragma alloc_text(PAGE, NtClearEvent)
    00058 #pragma alloc_text(PAGE, NtCreateEvent)
    00059 #pragma alloc_text(PAGE, NtOpenEvent)
    00060 #pragma alloc_text(PAGE, NtPulseEvent)
    00061 #pragma alloc_text(PAGE, NtQueryEvent)
    00062 #pragma alloc_text(PAGE, NtResetEvent)
    00063 #pragma alloc_text(PAGE, NtSetEvent)
    00064 #endif
    00065
    00066 BOOLEAN
    00067 ExpEventInitialization (
    00068     )
    00069
    00070 /*++
    00071
    00072 Routine Description:
    00073
    00074     This function creates the event object type descriptor at system
    00075     initialization and stores the address of the object type descriptor
    00076     in global storage.
    00077
    00078 Arguments:
    00079
    00080     None.
    00081
    00082 Return Value:
    00083
    00084     A value of TRUE is returned if the event object type descriptor is
    00085     successfully initialized. Otherwise a value of FALSE is returned.
    00086
    00087 --*/
    00088
    00089 {
    00090
    00091     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    00092     NTSTATUS Status;
    00093     UNICODE_STRING TypeName;
    00094
    00095     //
    00096     // Initialize string descriptor.
    00097     //
    00098
    00099     RtlInitUnicodeString(&TypeName, L"Event");
    00100
    00101     //
    00102     // Create event object type descriptor.
    00103     //
    00104
    00105     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
    00106     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
    00107     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
    00108     ObjectTypeInitializer.GenericMapping = ExpEventMapping;
    00109     ObjectTypeInitializer.PoolType = NonPagedPool;
    00110     ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT);
    00111     ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
    00112     Status = ObCreateObjectType(&TypeName,
    00113                                 &ObjectTypeInitializer,
    00114                                 (PSECURITY_DESCRIPTOR)NULL,
    00115                                 &ExEventObjectType);
    00116
    00117     //
    00118     // If the event object type descriptor was successfully created, then
    00119     // return a value of TRUE. Otherwise return a value of FALSE.
    00120     //
    00121
    00122     return (BOOLEAN)(NT_SUCCESS(Status));
    00123 }
    00124
    00125 NTSTATUS
    00126 NtClearEvent (
    00127     IN HANDLE EventHandle
    00128     )
    00129
    00130 /*++
    00131
    00132 Routine Description:
    00133
    00134     This function sets an event object to a Not-Signaled state.
    00135
    00136 Arguments:
    00137
    00138     EventHandle - Supplies a handle to an event object.
    00139
    00140 Return Value:
    00141
    00142     TBS
    00143
    00144 --*/
    00145
    00146 {
    00147
    00148     PVOID Event;
    00149     NTSTATUS Status;
    00150
    00151     //
    00152     // Reference event object by handle.
    00153     //
    00154
    00155     Status = ObReferenceObjectByHandle(EventHandle,
    00156                                        EVENT_MODIFY_STATE,
    00157                                        ExEventObjectType,
    00158                                        KeGetPreviousMode(),
    00159                                        &Event,
    00160                                        NULL);
    00161
    00162     //
    00163     // If the reference was successful, then set the state of the event
    00164     // object to Not-Signaled and dereference event object.
    00165     //
    00166
    00167     if (NT_SUCCESS(Status)) {
    00168         KeClearEvent((PKEVENT)Event);
    00169         ObDereferenceObject(Event);
    00170     }
    00171
    00172     //
    00173     // Return service status.
    00174     //
    00175
    00176     return Status;
    00177 }
    00178
    00179 NTSTATUS
    00180 NtCreateEvent (
    00181     OUT PHANDLE EventHandle,
    00182     IN ACCESS_MASK DesiredAccess,
    00183     IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    00184     IN EVENT_TYPE EventType,
    00185     IN BOOLEAN InitialState
    00186     )
    00187
    00188 /*++
    00189
    00190 Routine Description:
    00191
    00192     This function creates an event object, sets it initial state to the
    00193     specified value, and opens a handle to the object with the specified
    00194     desired access.
    00195
    00196 Arguments:
    00197
    00198     EventHandle - Supplies a pointer to a variable that will receive the
    00199         event object handle.
    00200
    00201     DesiredAccess - Supplies the desired types of access for the event object.
    00202
    00203     ObjectAttributes - Supplies a pointer to an object attributes structure.
    00204
    00205     EventType - Supplies the type of the event (autoclearing or notification).
    00206
    00207     InitialState - Supplies the initial state of the event object.
    00208
    00209 Return Value:
    00210
    00211     TBS
    00212
    00213 --*/
    00214
    00215 {
    00216
    00217     PVOID Event;
    00218     HANDLE Handle;
    00219     KPROCESSOR_MODE PreviousMode;
    00220     NTSTATUS Status;
    00221
    00222     //
    00223     // Establish an exception handler, probe the output handle address, and
    00224     // attempt to create an event object. If the probe fails, then return the
    00225     // exception code as the service status. Otherwise return the status value
    00226     // returned by the object insertion routine.
    00227     //
    00228
    00229     try {
    00230
    00231         //
    00232         // Get previous processor mode and probe output handle address if
    00233         // necessary.
    00234         //
    00235
    00236         PreviousMode = KeGetPreviousMode();
    00237         if (PreviousMode != KernelMode) {
    00238             ProbeForWriteHandle(EventHandle);
    00239         }
    00240
    00241         //
    00242         // Check argument validity.
    00243         //
    00244
    00245         if ((EventType != NotificationEvent) && (EventType != SynchronizationEvent)) {
    00246             return STATUS_INVALID_PARAMETER;
    00247         }
    00248
    00249         //
    00250         // Allocate event object.
    00251         //
    00252
    00253         Status = ObCreateObject(PreviousMode,
    00254                                 ExEventObjectType,
    00255                                 ObjectAttributes,
    00256                                 PreviousMode,
    00257                                 NULL,
    00258                                 sizeof(KEVENT),
    00259                                 0,
    00260                                 0,
    00261                                 (PVOID *)&Event);
    00262
    00263         //
    00264         // If the event object was successfully allocated, then initialize the
    00265         // event object and attempt to insert the event object in the current
    00266         // process' handle table.
    00267         //
    00268
    00269         if (NT_SUCCESS(Status)) {
    00270             KeInitializeEvent((PKEVENT)Event, EventType, InitialState);
    00271             Status = ObInsertObject(Event,
    00272                                     NULL,
    00273                                     DesiredAccess,
    00274                                     0,
    00275                                     (PVOID *)NULL,
    00276                                     &Handle);
    00277
    00278             //
    00279             // If the event object was successfully inserted in the current
    00280             // process' handle table, then attempt to write the event object
    00281             // handle value. If the write attempt fails, then do not report
    00282             // an error. When the caller attempts to access the handle value,
    00283             // an access violation will occur.
    00284             //
    00285
    00286             if (NT_SUCCESS(Status)) {
    00287                 try {
    00288                     *EventHandle = Handle;
    00289
    00290                 } except(ExSystemExceptionFilter()) {
    00291                 }
    00292             }
    00293         }
    00294
    00295     //
    00296     // If an exception occurs during the probe of the output handle address,
    00297     // then always handle the exception and return the exception code as the
    00298     // status value.
    00299     //
    00300
    00301     } except(ExSystemExceptionFilter()) {
    00302         return GetExceptionCode();
    00303     }
    00304
    00305     //
    00306     // Return service status.
    00307     //
    00308
    00309     return Status;
    00310 }
    00311
    00312 NTSTATUS
    00313 NtOpenEvent (
    00314     OUT PHANDLE EventHandle,
    00315     IN ACCESS_MASK DesiredAccess,
    00316     IN POBJECT_ATTRIBUTES ObjectAttributes
    00317     )
    00318
    00319 /*++
    00320
    00321 Routine Description:
    00322
    00323     This function opens a handle to an event object with the specified
    00324     desired access.
    00325
    00326 Arguments:
    00327
    00328     EventHandle - Supplies a pointer to a variable that will receive the
    00329         event object handle.
    00330
    00331     DesiredAccess - Supplies the desired types of access for the event object.
    00332
    00333     ObjectAttributes - Supplies a pointer to an object attributes structure.
    00334
    00335 Return Value:
    00336
    00337     TBS
    00338
    00339 --*/
    00340
    00341 {
    00342
    00343     HANDLE Handle;
    00344     KPROCESSOR_MODE PreviousMode;
    00345     NTSTATUS Status;
    00346
    00347
    00348     //
    00349     // Establish an exception handler, probe the output handle address, and
    00350     // attempt to open the event object. If the probe fails, then return the
    00351     // exception code as the service status. Otherwise return the status value
    00352     // returned by the object open routine.
    00353     //
    00354
    00355     try {
    00356
    00357         //
    00358         // Get previous processor mode and probe output handle address
    00359         // if necessary.
    00360         //
    00361
    00362         PreviousMode = KeGetPreviousMode();
    00363         if (PreviousMode != KernelMode) {
    00364             ProbeForWriteHandle(EventHandle);
    00365         }
    00366
    00367         //
    00368         // Open handle to the event object with the specified desired access.
    00369         //
    00370
    00371         Status = ObOpenObjectByName(ObjectAttributes,
    00372                                     ExEventObjectType,
    00373                                     PreviousMode,
    00374                                     NULL,
    00375                                     DesiredAccess,
    00376                                     NULL,
    00377                                     &Handle);
    00378
    00379         //
    00380         // If the open was successful, then attempt to write the event object
    00381         // handle value. If the write attempt fails, then do not report an
    00382         // error. When the caller attempts to access the handle value, an
    00383         // access violation will occur.
    00384         //
    00385
    00386         if (NT_SUCCESS(Status)) {
    00387             try {
    00388                 *EventHandle = Handle;
    00389
    00390             } except(ExSystemExceptionFilter()) {
    00391             }
    00392         }
    00393
    00394     //
    00395     // If an exception occurs during the probe of the output event handle,
    00396     // then always handle the exception and return the exception code as the
    00397     // status value.
    00398     //
    00399
    00400     } except(ExSystemExceptionFilter()) {
    00401         return GetExceptionCode();
    00402     }
    00403
    00404     //
    00405     // Return service status.
    00406     //
    00407
    00408     return Status;
    00409 }
    00410
    00411 NTSTATUS
    00412 NtPulseEvent (
    00413     IN HANDLE EventHandle,
    00414     OUT PLONG PreviousState OPTIONAL
    00415     )
    00416
    00417 /*++
    00418
    00419 Routine Description:
    00420
    00421     This function sets an event object to a Signaled state, attempts to
    00422     satisfy as many waits as possible, and then resets the state of the
    00423     event object to Not-Signaled.
    00424
    00425 Arguments:
    00426
    00427     EventHandle - Supplies a handle to an event object.
    00428
    00429     PreviousState - Supplies an optional pointer to a variable that will
    00430         receive the previous state of the event object.
    00431
    00432 Return Value:
    00433
    00434     TBS
    00435
    00436 --*/
    00437
    00438 {
    00439
    00440     PVOID Event;
    00441     KPROCESSOR_MODE PreviousMode;
    00442     LONG State;
    00443     NTSTATUS Status;
    00444
    00445     //
    00446     // Establish an exception handler, probe the previous state address if
    00447     // specified, reference the event object, and pulse the event object. If
    00448     // the probe fails, then return the exception code as the service status.
    00449     // Otherwise return the status value returned by the reference object by
    00450     // handle routine.
    00451     //
    00452
    00453     try {
    00454
    00455         //
    00456         // Get previous processor mode and probe previous state address
    00457         // if necessary.
    00458         //
    00459
    00460         PreviousMode = KeGetPreviousMode();
    00461         if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousState))) {
    00462             ProbeForWriteLong(PreviousState);
    00463         }
    00464
    00465         //
    00466         // Reference event object by handle.
    00467         //
    00468
    00469         Status = ObReferenceObjectByHandle(EventHandle,
    00470                                            EVENT_MODIFY_STATE,
    00471                                            ExEventObjectType,
    00472                                            PreviousMode,
    00473                                            &Event,
    00474                                            NULL);
    00475
    00476         //
    00477         // If the reference was successful, then pulse the event object,
    00478         // dereference event object, and write the previous state value if
    00479         // specified. If the write of the previous state fails, then do not
    00480         // report an error. When the caller attempts to access the previous
    00481         // state value, an access violation will occur.
    00482         //
    00483
    00484         if (NT_SUCCESS(Status)) {
    00485             State = KePulseEvent((PKEVENT)Event, ExpEventBoost, FALSE);
    00486             ObDereferenceObject(Event);
    00487             if (ARGUMENT_PRESENT(PreviousState)) {
    00488                 try {
    00489                     *PreviousState = State;
    00490
    00491                 } except(ExSystemExceptionFilter()) {
    00492                 }
    00493             }
    00494         }
    00495
    00496     //
    00497     // If an exception occurs during the probe of the previous state, then
    00498     // always handle the exception and return the exception code as the status
    00499     // value.
    00500     //
    00501
    00502     } except(ExSystemExceptionFilter()) {
    00503         return GetExceptionCode();
    00504     }
    00505
    00506     //
    00507     // Return service status.
    00508     //
    00509
    00510     return Status;
    00511 }
    00512
    00513 NTSTATUS
    00514 NtQueryEvent (
    00515     IN HANDLE EventHandle,
    00516     IN EVENT_INFORMATION_CLASS EventInformationClass,
    00517     OUT PVOID EventInformation,
    00518     IN ULONG EventInformationLength,
    00519     OUT PULONG ReturnLength OPTIONAL
    00520     )
    00521
    00522 /*++
    00523
    00524 Routine Description:
    00525
    00526     This function queries the state of an event object and returns the
    00527     requested information in the specified record structure.
    00528
    00529 Arguments:
    00530
    00531     EventHandle - Supplies a handle to an event object.
    00532
    00533     EventInformationClass - Supplies the class of information being requested.
    00534
    00535     EventInformation - Supplies a pointer to a record that is to receive the
    00536         requested information.
    00537
    00538     EventInformationLength - Supplies the length of the record that is to
    00539         receive the requested information.
    00540
    00541     ReturnLength - Supplies an optional pointer to a variable that is to
    00542         receive the actual length of information that is returned.
    00543
    00544 Return Value:
    00545
    00546     TBS
    00547
    00548 --*/
    00549
    00550 {
    00551
    00552     PKEVENT Event;
    00553     KPROCESSOR_MODE PreviousMode;
    00554     LONG State;
    00555     NTSTATUS Status;
    00556     EVENT_TYPE EventType;
    00557
    00558     //
    00559     // Check argument validity.
    00560     //
    00561
    00562     if (EventInformationClass != EventBasicInformation) {
    00563         return STATUS_INVALID_INFO_CLASS;
    00564     }
    00565
    00566     if (EventInformationLength != sizeof(EVENT_BASIC_INFORMATION)) {
    00567         return STATUS_INFO_LENGTH_MISMATCH;
    00568     }
    00569
    00570     //
    00571     // Establish an exception handler, probe the output arguments, reference
    00572     // the event object, and return the specified information. If the probe
    00573     // fails, then return the exception code as the service status. Otherwise
    00574     // return the status value returned by the reference object by handle
    00575     // routine.
    00576     //
    00577
    00578     try {
    00579
    00580         //
    00581         // Get previous processor mode and probe output arguments if necessary.
    00582         //
    00583
    00584         PreviousMode = KeGetPreviousMode();
    00585         if (PreviousMode != KernelMode) {
    00586             ProbeForWrite(EventInformation,
    00587                           sizeof(EVENT_BASIC_INFORMATION),
    00588                           sizeof(ULONG));
    00589
    00590             if (ARGUMENT_PRESENT(ReturnLength)) {
    00591                 ProbeForWriteUlong(ReturnLength);
    00592             }
    00593         }
    00594
    00595         //
    00596         // Reference event object by handle.
    00597         //
    00598
    00599         Status = ObReferenceObjectByHandle(EventHandle,
    00600                                            EVENT_QUERY_STATE,
    00601                                            ExEventObjectType,
    00602                                            PreviousMode,
    00603                                            (PVOID *)&Event,
    00604                                            NULL);
    00605
    00606         //
    00607         // If the reference was successful, then read the current state of
    00608         // the event object, deference event object, fill in the information
    00609         // structure, and return the length of the information structure if
    00610         // specified. If the write of the event information or the return
    00611         // length fails, then do not report an error. When the caller accesses
    00612         // the information structure or length an access violation will occur.
    00613         //
    00614
    00615         if (NT_SUCCESS(Status)) {
    00616             State = KeReadStateEvent(Event);
    00617             EventType = Event->Header.Type;
    00618             ObDereferenceObject(Event);
    00619             try {
    00620                 ((PEVENT_BASIC_INFORMATION)EventInformation)->EventType = EventType;
    00621                 ((PEVENT_BASIC_INFORMATION)EventInformation)->EventState = State;
    00622                 if (ARGUMENT_PRESENT(ReturnLength)) {
    00623                     *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
    00624                 }
    00625
    00626             } except(ExSystemExceptionFilter()) {
    00627             }
    00628         }
    00629
    00630     //
    00631     // If an exception occurs during the probe of the output arguments, then
    00632     // always handle the exception and return the exception code as the status
    00633     // value.
    00634     //
    00635
    00636     } except(ExSystemExceptionFilter()) {
    00637         return GetExceptionCode();
    00638     }
    00639
    00640     //
    00641     // Return service status.
    00642     //
    00643
    00644     return Status;
    00645 }
    00646
    00647 NTSTATUS
    00648 NtResetEvent (
    00649     IN HANDLE EventHandle,
    00650     OUT PLONG PreviousState OPTIONAL
    00651     )
    00652
    00653 /*++
    00654
    00655 Routine Description:
    00656
    00657     This function sets an event object to a Not-Signaled state.
    00658
    00659 Arguments:
    00660
    00661     EventHandle - Supplies a handle to an event object.
    00662
    00663     PreviousState - Supplies an optional pointer to a variable that will
    00664         receive the previous state of the event object.
    00665
    00666 Return Value:
    00667
    00668     TBS
    00669
    00670 --*/
    00671
    00672 {
    00673
    00674     PVOID Event;
    00675     KPROCESSOR_MODE PreviousMode;
    00676     LONG State;
    00677     NTSTATUS Status;
    00678
    00679     //
    00680     // Establish an exception handler, probe the previous state address if
    00681     // specified, reference the event object, and reset the event object. If
    00682     // the probe fails, then return the exception code as the service status.
    00683     // Otherwise return the status value returned by the reference object by
    00684     // handle routine.
    00685     //
    00686
    00687     try {
    00688
    00689         //
    00690         // Get previous processor mode and probe previous state address
    00691         // if necessary.
    00692         //
    00693
    00694         PreviousMode = KeGetPreviousMode();
    00695         if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousState))) {
    00696             ProbeForWriteLong(PreviousState);
    00697         }
    00698
    00699         //
    00700         // Reference event object by handle.
    00701         //
    00702
    00703         Status = ObReferenceObjectByHandle(EventHandle,
    00704                                            EVENT_MODIFY_STATE,
    00705                                            ExEventObjectType,
    00706                                            PreviousMode,
    00707                                            &Event,
    00708                                            NULL);
    00709
    00710         //
    00711         // If the reference was successful, then set the state of the event
    00712         // object to Not-Signaled, dereference event object, and write the
    00713         // previous state value if specified. If the write of the previous
    00714         // state fails, then do not report an error. When the caller attempts
    00715         // to access the previous state value, an access violation will occur.
    00716         //
    00717
    00718         if (NT_SUCCESS(Status)) {
    00719             State = KeResetEvent((PKEVENT)Event);
    00720             ObDereferenceObject(Event);
    00721             if (ARGUMENT_PRESENT(PreviousState)) {
    00722                 try {
    00723                     *PreviousState = State;
    00724
    00725                 } except(ExSystemExceptionFilter()) {
    00726                 }
    00727             }
    00728         }
    00729
    00730     //
    00731     // If an exception occurs during the probe of the previous state, then
    00732     // always handle the exception and return the exception code as the status
    00733     // value.
    00734     //
    00735
    00736     } except(ExSystemExceptionFilter()) {
    00737         return GetExceptionCode();
    00738     }
    00739
    00740     //
    00741     // Return service status.
    00742     //
    00743
    00744     return Status;
    00745 }
    00746
    00747 NTSTATUS
    00748 NtSetEvent (
    00749     IN HANDLE EventHandle,
    00750     OUT PLONG PreviousState OPTIONAL
    00751     )
    00752
    00753 /*++
    00754
    00755 Routine Description:
    00756
    00757     This function sets an event object to a Signaled state and attempts to
    00758     satisfy as many waits as possible.
    00759
    00760 Arguments:
    00761
    00762     EventHandle - Supplies a handle to an event object.
    00763
    00764     PreviousState - Supplies an optional pointer to a variable that will
    00765         receive the previous state of the event object.
    00766
    00767 Return Value:
    00768
    00769     TBS
    00770
    00771 --*/
    00772
    00773 {
    00774
    00775     PVOID Event;
    00776     KPROCESSOR_MODE PreviousMode;
    00777     LONG State;
    00778     NTSTATUS Status;
    00779 #if DBG
    00780
    00781     //
    00782     // Sneaky trick here to catch sleazy apps (csrss) that erroneously call
    00783     // NtSetEvent on an event that happens to be somebody else's
    00784     // critical section. Only allow setting a protected handle if the low
    00785     // bit of PreviousState is set.
    00786     //
    00787     OBJECT_HANDLE_INFORMATION HandleInfo;
    00788
    00789 #endif
    00790
    00791     //
    00792     // Establish an exception handler, probe the previous state address if
    00793     // specified, reference the event object, and set the event object. If
    00794     // the probe fails, then return the exception code as the service status.
    00795     // Otherwise return the status value returned by the reference object by
    00796     // handle routine.
    00797     //
    00798
    00799     try {
    00800
    00801         //
    00802         // Get previous processor mode and probe previous state address
    00803         // if necessary.
    00804         //
    00805
    00806         PreviousMode = KeGetPreviousMode();
    00807 #if DBG
    00808         if ((PreviousMode != KernelMode) &&
    00809             (ARGUMENT_PRESENT(PreviousState)) &&
    00810             (PreviousState != (PLONG)1)) {
    00811             ProbeForWriteLong(PreviousState);
    00812         }
    00813 #else
    00814         if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousState))) {
    00815             ProbeForWriteLong(PreviousState);
    00816         }
    00817 #endif
    00818
    00819         //
    00820         // Reference event object by handle.
    00821         //
    00822
    00823 #if DBG
    00824         Status = ObReferenceObjectByHandle(EventHandle,
    00825                                            EVENT_MODIFY_STATE,
    00826                                            ExEventObjectType,
    00827                                            PreviousMode,
    00828                                            &Event,
    00829                                            &HandleInfo);
    00830         if (NT_SUCCESS(Status)) {
    00831
    00832             if ((HandleInfo.HandleAttributes & 1) &&
    00833                 (PreviousState != (PLONG)1)) {
    00834 #if 0
    00835                 //
    00836                 // This is a protected handle. If the low bit of PreviousState is NOT set,
    00837                 // break into the debugger
    00838                 //
    00839
    00840                 DbgPrint("NtSetEvent: Illegal call to NtSetEvent on a protected handle\n");
    00841                 DbgBreakPoint();
    00842                 PreviousState = NULL;
    00843 #endif
    00844             }
    00845         } else {
    00846             if ((KeGetPreviousMode() != KernelMode) &&
    00847                 (EventHandle != NULL) &&
    00848                 ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
    00849                  (PsGetCurrentProcess()->DebugPort != NULL))) {
    00850
    00851                 Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
    00852
    00853             }
    00854         }
    00855 #else
    00856         Status = ObReferenceObjectByHandle(EventHandle,
    00857                                            EVENT_MODIFY_STATE,
    00858                                            ExEventObjectType,
    00859                                            PreviousMode,
    00860                                            &Event,
    00861                                            NULL);
    00862 #endif
    00863
    00864         //
    00865         // If the reference was successful, then set the event object to the
    00866         // Signaled state, dereference event object, and write the previous
    00867         // state value if specified. If the write of the previous state fails,
    00868         // then do not report an error. When the caller attempts to access the
    00869         // previous state value, an access violation will occur.
    00870         //
    00871
    00872         if (NT_SUCCESS(Status)) {
    00873             State = KeSetEvent((PKEVENT)Event, ExpEventBoost, FALSE);
    00874             ObDereferenceObject(Event);
    00875             if (ARGUMENT_PRESENT(PreviousState)) {
    00876                 try {
    00877                     *PreviousState = State;
    00878
    00879                 } except(ExSystemExceptionFilter()) {
    00880                 }
    00881             }
    00882         }
    00883
    00884     //
    00885     // If an exception occurs during the probe of the previous state, then
    00886     // always handle the exception and return the exception code as the status
    00887     // value.
    00888     //
    00889
    00890     } except(ExSystemExceptionFilter()) {
    00891         return GetExceptionCode();
    00892     }
    00893
    00894     //
    00895     // Return service status.
    00896     //
    00897
    00898     return Status;
    00899 }