Beispiel #1
0
NTSTATUS NTAPI
ConDrvGetConsoleInput(IN PCONSOLE Console,
                      IN PCONSOLE_INPUT_BUFFER InputBuffer,
                      IN BOOLEAN KeepEvents,
                      IN BOOLEAN WaitForMoreEvents,
                      IN BOOLEAN Unicode,
                      OUT PINPUT_RECORD InputRecord,
                      IN ULONG NumEventsToRead,
                      OUT PULONG NumEventsRead OPTIONAL)
{
    PLIST_ENTRY CurrentInput;
    ConsoleInput* Input;
    ULONG i = 0;

    if (Console == NULL || InputBuffer == NULL /* || InputRecord == NULL */)
        return STATUS_INVALID_PARAMETER;

    /* Validity checks */
    ASSERT(Console == InputBuffer->Header.Console);
    ASSERT( (InputRecord != NULL && NumEventsToRead >= 0) ||
            (InputRecord == NULL && NumEventsToRead == 0) );

    // Do NOT do that !! Use the existing number of events already read, if any...
    // if (NumEventsRead) *NumEventsRead = 0;

    if (IsListEmpty(&InputBuffer->InputEvents))
    {
        /*
         * No input is available. Wait for more input if requested,
         * otherwise, we don't wait, so we return success.
         */
        return (WaitForMoreEvents ? STATUS_PENDING : STATUS_SUCCESS);
    }

    /* Only get input if there is any */
    CurrentInput = InputBuffer->InputEvents.Flink;
    if (NumEventsRead) i = *NumEventsRead; // We will read the remaining events...

    while ((CurrentInput != &InputBuffer->InputEvents) && (i < NumEventsToRead))
    {
        Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);

        *InputRecord = Input->InputEvent;

        if (!Unicode)
        {
            ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
        }

        ++InputRecord;
        ++i;
        CurrentInput = CurrentInput->Flink;

        /* Remove the events from the queue if needed */
        if (!KeepEvents)
        {
            RemoveEntryList(&Input->ListEntry);
            ConsoleFreeHeap(Input);
        }
    }

    if (NumEventsRead) *NumEventsRead = i;

    if (IsListEmpty(&InputBuffer->InputEvents))
    {
        ResetEvent(InputBuffer->ActiveEvent);
    }

    /* We read all the inputs available, we return success */
    return STATUS_SUCCESS;
}
Beispiel #2
0
static NTSTATUS
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
                IN PCSR_API_MESSAGE ApiMessage,
                IN BOOLEAN CreateWaitBlock OPTIONAL)
{
    NTSTATUS Status;
    PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
    PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
    ULONG NumEventsRead;

    PINPUT_RECORD InputRecord;

    /*
     * 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.
     */
    if (GetInputRequest->NumRecords <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
    {
        /*
         * Adjust the internal pointer, because its old value points to
         * the static buffer in the original ApiMessage structure.
         */
        // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
        InputRecord = GetInputRequest->RecordStaticBuffer;
    }
    else
    {
        InputRecord = GetInputRequest->RecordBufPtr;
    }

    NumEventsRead = 0;
    Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
                                   InputBuffer,
                                   (GetInputRequest->Flags & CONSOLE_READ_KEEPEVENT) != 0,
                                   (GetInputRequest->Flags & CONSOLE_READ_CONTINUE ) == 0,
                                   InputRecord,
                                   GetInputRequest->NumRecords,
                                   &NumEventsRead);

    if (Status == STATUS_PENDING)
    {
        /* We haven't completed a read, so start a wait */
        return WaitBeforeReading(InputInfo,
                                 ApiMessage,
                                 ReadInputBufferThread,
                                 CreateWaitBlock);
    }
    else
    {
        /*
         * We read all what we wanted. Set the number of events read and
         * return the error code we were given.
         */
        GetInputRequest->NumRecords = NumEventsRead;

        if (NT_SUCCESS(Status))
        {
            /* Now translate everything to ANSI */
            if (!GetInputRequest->Unicode)
            {
                for (; NumEventsRead > 0; --NumEventsRead)
                {
                    ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord);
                }
            }
        }

        return Status;
        // return STATUS_SUCCESS;
    }
}