示例#1
0
NTSTATUS
NtSetEvent (
    IN HANDLE EventHandle,
    OUT PLONG PreviousState OPTIONAL
)

/*++

Routine Description:

    This function sets an event object to a Signaled state and attempts to
    satisfy as many waits as possible.

Arguments:

    EventHandle - Supplies a handle to an event object.

    PreviousState - Supplies an optional pointer to a variable that will
        receive the previous state of the event object.

Return Value:

    TBS

--*/

{

    PVOID Event;
    KPROCESSOR_MODE PreviousMode;
    LONG State;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the previous state address if
    // specified, reference the event object, and set the event object. If
    // the probe fails, then return the exception code as the service status.
    // Otherwise return the status value returned by the reference object by
    // handle routine.
    //

    try {

        //
        // Get previous processor mode and probe previous state address
        // if necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousState))) {
            ProbeForWriteLong(PreviousState);
        }

        //
        // Reference event object by handle.
        //

        Status = ObReferenceObjectByHandle(EventHandle,
                                           EVENT_MODIFY_STATE,
                                           ExEventObjectType,
                                           PreviousMode,
                                           &Event,
                                           NULL);

        //
        // If the reference was successful, then set the event object to the
        // Signaled state, dereference event object, and write the previous
        // state value if specified. If the write of the previous state fails,
        // then do not report an error. When the caller attempts to access the
        // previous state value, an access violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            State = KeSetEvent((PKEVENT)Event, ExpEventBoost, FALSE);
            ObDereferenceObject(Event);
            if (ARGUMENT_PRESENT(PreviousState)) {
                try {
                    *PreviousState = State;

                }
                except(ExSystemExceptionFilter()) {
                }
            }
        }

        //
        // If an exception occurs during the probe of the previous state, then
        // always handle the exception and return the exception code as the status
        // value.
        //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
示例#2
0
NTSTATUS
NtReleaseMutant (
    IN HANDLE MutantHandle,
    OUT PLONG PreviousCount OPTIONAL
    )

/*++

Routine Description:

    This function releases a mutant object.

Arguments:

    Mutant - Supplies a handle to a mutant object.

    PreviousCount - Supplies an optional pointer to a variable that will
        receive the previous mutant count.

Return Value:

    TBS

--*/

{

    LONG Count;
    PVOID Mutant;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the previous count address if
    // specified, reference the mutant object, and release the mutant object.
    // If the probe fails, then return the exception code as the service
    // status. Otherwise return the status value returned by the reference
    // object by handle routine.
    //

    try {

        //
        // Get previous processor mode and probe previous count address
        // if necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousCount))) {
            ProbeForWriteLong(PreviousCount);
        }

        //
        // Reference mutant object by handle.
        //
        // Note that the desired access is specified as zero since only the
        // owner can release a mutant object.
        //

        Status = ObReferenceObjectByHandle(MutantHandle,
                                           0,
                                           ExMutantObjectType,
                                           PreviousMode,
                                           &Mutant,
                                           NULL);

        //
        // If the reference was successful, then release the mutant object. If
        // an exception occurs because the caller is not the owner of the mutant
        // object, then dereference mutant object and return the exception code
        // as the service status. Otherise write the previous count value if
        // specified. If the write of the previous count fails, then do not
        // report an error. When the caller attempts to access the previous
        // count value, an access violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            try {
                Count = KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, FALSE, FALSE);
                ObDereferenceObject(Mutant);
                if (ARGUMENT_PRESENT(PreviousCount)) {
                    try {
                        *PreviousCount = Count;

                    } except(ExSystemExceptionFilter()) {
                    }
                }

            //
            // If an exception occurs because the caller is not the owner of
            // the mutant object, then always handle the exception, dereference
            // the mutant object, and return the exception code as the status
            // value.
            //

            } except(ExSystemExceptionFilter()) {
                ObDereferenceObject(Mutant);
                return GetExceptionCode();
            }
        }

    //
    // If an exception occurs during the probe of the previous count, then
    // always handle the exception and return the exception code as the status
    // value.
    //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}