Beispiel #1
0
/*
 * @implemented
 */
DWORD
WINAPI
SignalObjectAndWait(IN HANDLE hObjectToSignal,
                    IN HANDLE hObjectToWaitOn,
                    IN DWORD dwMilliseconds,
                    IN BOOL bAlertable)
{
    PLARGE_INTEGER TimePtr;
    LARGE_INTEGER Time;
    NTSTATUS Status;
    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx;

    /* APCs must execute with the default activation context */
    if (bAlertable)
    {
        /* Setup the frame */
        RtlZeroMemory(&ActCtx, sizeof(ActCtx));
        ActCtx.Size = sizeof(ActCtx);
        ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
        RtlActivateActivationContextUnsafeFast(&ActCtx, NULL);
    }

    /* Get real handle */
    hObjectToWaitOn = TranslateStdHandle(hObjectToWaitOn);

    /* Check for console handle */
    if ((IsConsoleHandle(hObjectToWaitOn)) &&
        (VerifyConsoleIoHandle(hObjectToWaitOn)))
    {
        /* Get the real wait handle */
        hObjectToWaitOn = GetConsoleInputWaitHandle();
    }

    /* Convert the timeout */
    TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds);

    /* Start wait loop */
    do
    {
        /* Do the wait */
        Status = NtSignalAndWaitForSingleObject(hObjectToSignal,
                                                hObjectToWaitOn,
                                                (BOOLEAN)bAlertable,
                                                TimePtr);
        if (!NT_SUCCESS(Status))
        {
            /* The wait failed */
            BaseSetLastNTError(Status);
            Status = WAIT_FAILED;
        }
    } while ((Status == STATUS_ALERTED) && (bAlertable));

    /* Cleanup the activation context */
    if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx);

    /* Return wait status */
    return Status;
}
Beispiel #2
0
DWORD
WINAPI
SignalObjectAndWait(
    HANDLE hObjectToSignal,
    HANDLE hObjectToWaitOn,
    DWORD dwMilliseconds,
    BOOL bAlertable
)
{
    NTSTATUS Status;
    LARGE_INTEGER TimeOut;
    PLARGE_INTEGER pTimeOut;
    PPEB Peb;

    Peb = NtCurrentPeb();
    switch( (DWORD)hObjectToWaitOn ) {
    case STD_INPUT_HANDLE:
        hObjectToWaitOn = Peb->ProcessParameters->StandardInput;
        break;
    case STD_OUTPUT_HANDLE:
        hObjectToWaitOn = Peb->ProcessParameters->StandardOutput;
        break;
    case STD_ERROR_HANDLE:
        hObjectToWaitOn = Peb->ProcessParameters->StandardError;
        break;
    }

    if (CONSOLE_HANDLE(hObjectToWaitOn) && VerifyConsoleIoHandle(hObjectToWaitOn)) {
        hObjectToWaitOn = GetConsoleInputWaitHandle();
    }

    pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
rewait:
    Status = NtSignalAndWaitForSingleObject(
                 hObjectToSignal,
                 hObjectToWaitOn,
                 (BOOLEAN)bAlertable,
                 pTimeOut
             );

    if ( !NT_SUCCESS(Status) ) {
        BaseSetLastNTError(Status);
        Status = (NTSTATUS)0xffffffff;
    }
    else {
        if ( bAlertable && Status == STATUS_ALERTED ) {
            goto rewait;
        }
    }
    return (DWORD)Status;
}
Beispiel #3
0
/*
 * @implemented
 */
HANDLE
WINAPI
RegisterWaitForSingleObjectEx(IN HANDLE hObject,
                              IN WAITORTIMERCALLBACK Callback,
                              IN PVOID Context,
                              IN ULONG dwMilliseconds,
                              IN ULONG dwFlags)
{
    NTSTATUS Status;
    HANDLE hNewWaitObject;

    /* Get real handle */
    hObject = TranslateStdHandle(hObject);

    /* Check for console handle */
    if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject)))
    {
        /* Get the real wait handle */
        hObject = GetConsoleInputWaitHandle();
    }

    /* Register the wait */
    Status = RtlRegisterWait(&hNewWaitObject,
                             hObject,
                             Callback,
                             Context,
                             dwMilliseconds,
                             dwFlags);
    if (!NT_SUCCESS(Status))
    {
        /* Return failure */
        BaseSetLastNTError(Status);
        return NULL;
    }

    /* Return the object */
    return hNewWaitObject;
}
Beispiel #4
0
/*
 * @implemented
 */
DWORD
WINAPI
WaitForMultipleObjectsEx(IN DWORD nCount,
                         IN CONST HANDLE *lpHandles,
                         IN BOOL bWaitAll,
                         IN DWORD dwMilliseconds,
                         IN BOOL bAlertable)
{
    PLARGE_INTEGER TimePtr;
    LARGE_INTEGER Time;
    PHANDLE HandleBuffer;
    HANDLE Handle[8];
    DWORD i;
    NTSTATUS Status;
    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx;

    /* APCs must execute with the default activation context */
    if (bAlertable)
    {
        /* Setup the frame */
        RtlZeroMemory(&ActCtx, sizeof(ActCtx));
        ActCtx.Size = sizeof(ActCtx);
        ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
        RtlActivateActivationContextUnsafeFast(&ActCtx, NULL);
    }

    /* Check if we have more handles then we locally optimize */
    if (nCount > 8)
    {
        /* Allocate a buffer for them */
        HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
                                       0,
                                       nCount * sizeof(HANDLE));
        if (!HandleBuffer)
        {
            /* No buffer, fail the wait */
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx);
            return WAIT_FAILED;
        }
    }
    else
    {
        /* Otherwise, use our local buffer */
        HandleBuffer = Handle;
    }

    /* Copy the handles into our buffer and loop them all */
    RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE));
    for (i = 0; i < nCount; i++)
    {
        /* Check what kind of handle this is */
        HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]);

        /* Check for console handle */
        if ((IsConsoleHandle(HandleBuffer[i])) &&
            (VerifyConsoleIoHandle(HandleBuffer[i])))
        {
            /* Get the real wait handle */
            HandleBuffer[i] = GetConsoleInputWaitHandle();
        }
    }

    /* Convert the timeout */
    TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds);

    /* Start wait loop */
    do
    {
        /* Do the wait */
        Status = NtWaitForMultipleObjects(nCount,
                                          HandleBuffer,
                                          bWaitAll ? WaitAll : WaitAny,
                                          (BOOLEAN)bAlertable,
                                          TimePtr);
        if (!NT_SUCCESS(Status))
        {
            /* Wait failed */
            BaseSetLastNTError(Status);
            Status = WAIT_FAILED;
        }
    } while ((Status == STATUS_ALERTED) && (bAlertable));

    /* Check if we didn't use our local buffer */
    if (HandleBuffer != Handle)
    {
        /* Free the allocated one */
        RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer);
    }

    /* Cleanup the activation context */
    if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx);

    /* Return wait status */
    return Status;
}
Beispiel #5
0
DWORD
APIENTRY
WaitForMultipleObjectsEx(
    DWORD nCount,
    CONST HANDLE *lpHandles,
    BOOL bWaitAll,
    DWORD dwMilliseconds,
    BOOL bAlertable
)

/*++

Routine Description:

    A wait operation on multiple waitable objects (up to
    MAXIMUM_WAIT_OBJECTS) is accomplished with the
    WaitForMultipleObjects function.

    This API can be used to wait on any of the specified objects to
    enter the signaled state, or all of the objects to enter the
    signaled state.

    If the bAlertable parameter is FALSE, the only way the wait
    terminates is because the specified timeout period expires, or
    because the specified objects entered the signaled state.  If the
    bAlertable parameter is TRUE, then the wait can return due to any one of
    the above wait termination conditions, or because an I/O completion
    callback terminated the wait early (return value of
    WAIT_IO_COMPLETION).

Arguments:

    nCount - A count of the number of objects that are to be waited on.

    lpHandles - An array of object handles.  Each handle must have
        SYNCHRONIZE access to the associated object.

    bWaitAll - A flag that supplies the wait type.  A value of TRUE
        indicates a "wait all".  A value of false indicates a "wait
        any".

    dwMilliseconds - A time-out value that specifies the relative time,
        in milliseconds, over which the wait is to be completed.  A
        timeout value of 0 specified that the wait is to timeout
        immediately.  This allows an application to test an object to
        determine if it is in the signaled state.  A timeout value of
        0xffffffff specifies an infinite timeout period.

    bAlertable - Supplies a flag that controls whether or not the
        wait may terminate early due to an I/O completion callback.
        A value of TRUE allows this API to complete early due to an I/O
        completion callback.  A value of FALSE will not allow I/O
        completion callbacks to terminate this call early.

Return Value:

    WAIT_TIME_OUT - indicates that the wait was terminated due to the
        TimeOut conditions.

    0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
        object, the object number which satisfied the wait.  In the case
        of wait for all objects, the value only indicates that the wait
        was completed successfully.

    0xffffffff - The wait terminated due to an error. GetLastError may be
        used to get additional error information.

    WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
        indicates, in the case of wait for any object, the object number
        which satisfied the event, and that the object which satisfied
        the event was abandoned.  In the case of wait for all objects,
        the value indicates that the wait was completed successfully and
        at least one of the objects was abandoned.

    WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
        completion callbacks.

--*/
{
    NTSTATUS Status;
    LARGE_INTEGER TimeOut;
    PLARGE_INTEGER pTimeOut;
    DWORD i;
    LPHANDLE HandleArray;
    HANDLE Handles[ 8 ];
    PPEB Peb;

    if (nCount > 8) {
        HandleArray = (LPHANDLE) RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), nCount*sizeof(HANDLE));
        if (HandleArray == NULL) {
            BaseSetLastNTError(STATUS_NO_MEMORY);
            return 0xffffffff;
        }
    } else {
        HandleArray = Handles;
    }
    RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE));

    Peb = NtCurrentPeb();
    for (i=0; i<nCount; i++) {
        switch( (DWORD)HandleArray[i] ) {
        case STD_INPUT_HANDLE:
            HandleArray[i] = Peb->ProcessParameters->StandardInput;
            break;
        case STD_OUTPUT_HANDLE:
            HandleArray[i] = Peb->ProcessParameters->StandardOutput;
            break;
        case STD_ERROR_HANDLE:
            HandleArray[i] = Peb->ProcessParameters->StandardError;
            break;
        }

        if (CONSOLE_HANDLE(HandleArray[i]) && VerifyConsoleIoHandle(HandleArray[i])) {
            HandleArray[i] = GetConsoleInputWaitHandle();
        }
    }

    pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
rewait:
    Status = NtWaitForMultipleObjects(
                 (CHAR)nCount,
                 HandleArray,
                 bWaitAll ? WaitAll : WaitAny,
                 (BOOLEAN)bAlertable,
                 pTimeOut
             );
    if ( !NT_SUCCESS(Status) ) {
        BaseSetLastNTError(Status);
        Status = (NTSTATUS)0xffffffff;
    }
    else {
        if ( bAlertable && Status == STATUS_ALERTED ) {
            goto rewait;
        }
    }

    if (HandleArray != Handles) {
        RtlFreeHeap(RtlProcessHeap(), 0, HandleArray);
    }

    return (DWORD)Status;
}
Beispiel #6
0
DWORD
APIENTRY
WaitForSingleObjectEx(
    HANDLE hHandle,
    DWORD dwMilliseconds,
    BOOL bAlertable
)

/*++

Routine Description:

    A wait operation on a waitable object is accomplished with the
    WaitForSingleObjectEx function.

    Waiting on an object checks the current state of the object.  If the
    current state of the object allows continued execution, any
    adjustments to the object state are made (for example, decrementing
    the semaphore count for a semaphore object) and the thread continues
    execution.  If the current state of the object does not allow
    continued execution, the thread is placed into the wait state
    pending the change of the object's state or time-out.

    If the bAlertable parameter is FALSE, the only way the wait
    terminates is because the specified timeout period expires, or
    because the specified object entered the signaled state.  If the
    bAlertable parameter is TRUE, then the wait can return due to any
    one of the above wait termination conditions, or because an I/O
    completion callback terminated the wait early (return value of
    WAIT_IO_COMPLETION).

Arguments:

    hHandle - An open handle to a waitable object. The handle must have
        SYNCHRONIZE access to the object.

    dwMilliseconds - A time-out value that specifies the relative time,
        in milliseconds, over which the wait is to be completed.  A
        timeout value of 0 specified that the wait is to timeout
        immediately.  This allows an application to test an object to
        determine if it is in the signaled state.  A timeout value of
        0xffffffff specifies an infinite timeout period.

    bAlertable - Supplies a flag that controls whether or not the
        wait may terminate early due to an I/O completion callback.
        A value of TRUE allows this API to complete early due to an I/O
        completion callback.  A value of FALSE will not allow I/O
        completion callbacks to terminate this call early.

Return Value:

    WAIT_TIME_OUT - Indicates that the wait was terminated due to the
        TimeOut conditions.

    0 - indicates the specified object attained a Signaled
        state thus completing the wait.

    0xffffffff - The wait terminated due to an error. GetLastError may be
        used to get additional error information.

    WAIT_ABANDONED - indicates the specified object attained a Signaled
        state but was abandoned.

    WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
        completion callbacks.

--*/
{
    NTSTATUS Status;
    LARGE_INTEGER TimeOut;
    PLARGE_INTEGER pTimeOut;
    PPEB Peb;

    Peb = NtCurrentPeb();
    switch( (DWORD)hHandle ) {
    case STD_INPUT_HANDLE:
        hHandle = Peb->ProcessParameters->StandardInput;
        break;
    case STD_OUTPUT_HANDLE:
        hHandle = Peb->ProcessParameters->StandardOutput;
        break;
    case STD_ERROR_HANDLE:
        hHandle = Peb->ProcessParameters->StandardError;
        break;
    }

    if (CONSOLE_HANDLE(hHandle) && VerifyConsoleIoHandle(hHandle)) {
        hHandle = GetConsoleInputWaitHandle();
    }

    pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
rewait:
    Status = NtWaitForSingleObject(hHandle,(BOOLEAN)bAlertable,pTimeOut);
    if ( !NT_SUCCESS(Status) ) {
        BaseSetLastNTError(Status);
        Status = (NTSTATUS)0xffffffff;
    }
    else {
        if ( bAlertable && Status == STATUS_ALERTED ) {
            goto rewait;
        }
    }
    return (DWORD)Status;
}
Beispiel #7
0
static DWORD
WINAPI
ConsoleEventThread(LPVOID Parameter)
{
    HANDLE ConsoleInput = (HANDLE)Parameter;
    HANDLE WaitHandles[2];
    DWORD  WaitResult;

    /*
     * For optimization purposes, Windows (and hence ReactOS, too, for
     * compatibility reasons) uses a static buffer if no more than five
     * input records are read. Otherwise a new buffer is used.
     * The client-side expects that we know this behaviour.
     * See consrv/coninput.c
     *
     * We exploit here this optimization by also using a buffer of 5 records.
     */
    INPUT_RECORD InputRecords[5];
    ULONG NumRecords, i;

    WaitHandles[0] = VdmTaskEvent;
    WaitHandles[1] = GetConsoleInputWaitHandle();

    while (VdmRunning)
    {
        /* Make sure the task event is signaled */
        WaitResult = WaitForMultipleObjects(ARRAYSIZE(WaitHandles),
                                            WaitHandles,
                                            TRUE,
                                            INFINITE);
        switch (WaitResult)
        {
            case WAIT_OBJECT_0 + 0:
            case WAIT_OBJECT_0 + 1:
                break;
            default:
                return GetLastError();
        }

        /* Wait for an input record */
        if (!ReadConsoleInputExW(ConsoleInput,
                                 InputRecords,
                                 ARRAYSIZE(InputRecords),
                                 &NumRecords,
                                 CONSOLE_READ_CONTINUE))
        {
            DWORD LastError = GetLastError();
            DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, NumRecords, LastError);
            return LastError;
        }

        // ASSERT(NumRecords != 0);
        if (NumRecords == 0)
        {
            DPRINT1("Got NumRecords == 0!\n");
            continue;
        }

        /* Dispatch the events */
        for (i = 0; i < NumRecords; i++)
        {
            /* Check the event type */
            switch (InputRecords[i].EventType)
            {
                /*
                 * Hardware events
                 */
                case KEY_EVENT:
                    KeyboardEventHandler(&InputRecords[i].Event.KeyEvent);
                    break;

                case MOUSE_EVENT:
                    MouseEventHandler(&InputRecords[i].Event.MouseEvent);
                    break;

                case WINDOW_BUFFER_SIZE_EVENT:
                    ScreenEventHandler(&InputRecords[i].Event.WindowBufferSizeEvent);
                    break;

                /*
                 * Interface events
                 */
                case MENU_EVENT:
                    MenuEventHandler(&InputRecords[i].Event.MenuEvent);
                    break;

                case FOCUS_EVENT:
                    FocusEventHandler(&InputRecords[i].Event.FocusEvent);
                    break;

                default:
                    DPRINT1("Unknown input event type 0x%04x\n", InputRecords[i].EventType);
                    break;
            }
        }

        /* Let the console subsystem queue some new events */
        Sleep(10);
    }

    return 0;
}