void ReadSerialWriteConsole()

in BusTools/MinComm/main.cpp [395:529]


void ReadSerialWriteConsole (HANDLE serialHandle)
{
    HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!SetConsoleMode(
        stdOut,
        ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT)) {

        throw wexception(
            L"Failed to set console mode for stdout. GetLastError() = 0x%x",
            GetLastError());
    }

    Event overlappedEvent(CreateEventW(NULL, TRUE, FALSE, NULL));
    if (!overlappedEvent.IsValid()) {
        throw wexception(
            L"Failed to create event for overlapped IO. "
            L"(GetLastError() = 0x%x)",
            GetLastError());
    }

    for (;;) {
        auto overlapped = OVERLAPPED();
        overlapped.hEvent = overlappedEvent.Get();

        CHAR buf[512];
        DWORD bytesRead = 0;
        if (!ReadFile(
                serialHandle,
                reinterpret_cast<BYTE*>(buf),
                sizeof(buf),
                &bytesRead,
                &overlapped) && (GetLastError() != ERROR_IO_PENDING)) {

            DWORD error = GetLastError();
            if (error == ERROR_OPERATION_ABORTED) {
                return; // error is due to application exit
            }

            throw wexception(
                L"Failed to read from serial device. (GetLastError = 0x%x)",
                error);
        }

        if (!GetOverlappedResult(
                serialHandle,
                &overlapped,
                &bytesRead,
                TRUE)) {

            DWORD error = GetLastError();
            if (error == ERROR_OPERATION_ABORTED) {
                return; // error is due to application exit
            }

            throw wexception(
                L"GetOverlappedResult() for ReadFile() failed. "
                L"(GetLastError() = 0x%x)",
                error);
        }

        WCHAR wbuf[ARRAYSIZE(buf)];
        int charsConverted = MultiByteToWideChar(
                CP_ACP,
                MB_PRECOMPOSED,
                buf,
                bytesRead,
                wbuf,
                ARRAYSIZE(wbuf));
        if (!charsConverted) {
            throw wexception(
                L"Failed to convert string to unicode. (GetLastError() = 0x%x)",
                GetLastError());
        }

        const WCHAR* chunkBegin = wbuf;
        const WCHAR* const bufEnd = wbuf + charsConverted;
        do {
            // scan for cairrage returns and backspaces
            bool specialCharFound;
            const WCHAR* chunkEnd = FindSpecialChar(
                    chunkBegin,
                    static_cast<ULONG>(bufEnd - chunkBegin),
                    &specialCharFound);

            DWORD charsWritten;
            if (!WriteConsole(
                    stdOut,
                    chunkBegin,
                    static_cast<ULONG>(chunkEnd - chunkBegin),
                    &charsWritten,
                    NULL)) {

                throw wexception(
                    L"WriteConsole failed. (GetLastError() = 0x%x)",
                    GetLastError());
            }

            // Handle special character if one was found. The special
            // character is the last character of the chunk.
            if (specialCharFound)
            {
                switch (chunkEnd[-1]) {
                case '\r':
                {
                    const WCHAR lf = L'\n';
                    if (!WriteConsole(stdOut, &lf, 1, &charsWritten, NULL)) {
                        throw wexception(
                            L"WriteConsole failed. (GetLastError() = 0x%x)",
                            GetLastError());
                    }
                    break;
                }
                case '\b':
                {
                    const WCHAR backspace[] = {L' ', L'\b'};
                    if (!WriteConsole(
                            stdOut,
                            &backspace,
                            ARRAYSIZE(backspace),
                            &charsWritten,
                            NULL)) {

                        throw wexception(
                            L"WriteConsole failed. (GetLastError() = 0x%x)",
                            GetLastError());
                    }
                    break;
                }
                } // switch
            }

            chunkBegin = chunkEnd;
        } while (chunkBegin != bufEnd);
    }
}