hackedteam/vector-rmi

View on GitHub
wps/Serial.cpp

Summary

Maintainability
Test Coverage
#include "Serial.h"

Serial::Serial() : hSerial(INVALID_HANDLE_VALUE) {
    m_ComTimeouts.ReadIntervalTimeout = 0;
    m_ComTimeouts.ReadTotalTimeoutMultiplier = 1;
    m_ComTimeouts.ReadTotalTimeoutConstant = 200;
    m_ComTimeouts.WriteTotalTimeoutMultiplier = 10;
    m_ComTimeouts.WriteTotalTimeoutConstant = 40;
}

Serial::~Serial() {
    if (hSerial != INVALID_HANDLE_VALUE) {
        CloseHandle(hSerial);
        hSerial = INVALID_HANDLE_VALUE;
    }
}

BOOL Serial::Open(PWCHAR pwPort) {
    DCB dcbSerial = {0};
    wstring strPort;

    if (pwPort == NULL) {
        wprintf(L"[ERROR] Missing port number\n");
        return FALSE;
    }

    if (wcslen(pwPort) < 4 || wcslen(pwPort) > 6) {
        wprintf(L"[ERROR] Wrong port format, should be: COMX (e.g.: COM1, COM2, COM12...)\n");
        return FALSE;
    }

    if (pwPort[0] != 'C' || pwPort[1] != 'O' || pwPort[2] != 'M') {
        wprintf(L"[ERROR] Wrong port name, should be: COMX (e.g.: COM1, COM2, COM12...)\n");
        return FALSE;
    }

    if (hSerial != INVALID_HANDLE_VALUE) {
        wprintf(L"[WARNING] Port already opened, trying to reuse connection\n");
        return TRUE;
    }

    strPort = L"\\\\.\\";
    strPort += pwPort;

    hSerial = CreateFile(strPort.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    if (hSerial == INVALID_HANDLE_VALUE) {
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
            //wprintf(L"[ERROR] Port %s doesn't exist (try to restart GSM modem)\n", pwPort);
            return FALSE;
        }

        wprintf(L"[ERROR] Port %s cannot be opened\n", pwPort);
        return FALSE;
    }

    dcbSerial.DCBlength = sizeof(DCB);

    if (!GetCommState(hSerial, &dcbSerial)) {
        wprintf(L"[ERROR] Cannot get COM port state\n");
        CloseHandle(hSerial);
        hSerial = INVALID_HANDLE_VALUE;
        return FALSE;
    }

    dcbSerial.BaudRate = CBR_115200;
    dcbSerial.ByteSize = 8;
    dcbSerial.StopBits = ONESTOPBIT;
    dcbSerial.Parity = NOPARITY;

    if (!SetCommState(hSerial, &dcbSerial)){
        wprintf(L"[ERROR] Cannot set COM port state\n");
        CloseHandle(hSerial);
        hSerial = INVALID_HANDLE_VALUE;
        return FALSE;
    }

    if (!SetCommTimeouts(hSerial, &m_ComTimeouts)) {
        wprintf(L"[WARNING] Cannot set COM port timeouts, trying with defaults\n");
    }

    EscapeCommFunction(hSerial, SETDTR);

    wprintf(L"[NOTICE] Port %s successfully opened\n", pwPort);
    return TRUE;
}

BOOL Serial::Open(wstring &strPort) {
    return Open((PWCHAR)strPort.c_str());
}

INT Serial::Read(PBYTE pBuffer, UINT uBufSize) {
    DWORD dwBytesRead = 0;

    if (hSerial == INVALID_HANDLE_VALUE) {
        wprintf(L"[ERROR] There is no open COM port to read from\n");
        return -1;
    }

    PBYTE pTmp = pBuffer;

    while (ReadFile(hSerial, pTmp, uBufSize, &dwBytesRead, NULL)) {
        if (dwBytesRead == 0)
            return 0;

        if (pTmp + dwBytesRead < pBuffer + uBufSize)
            pTmp += dwBytesRead;
        else
            return dwBytesRead;
    }

    wprintf(L"[ERROR] Cannot read from COM port\n");
    return -1;
}

INT Serial::Write(PBYTE pBuffer, UINT uBufSize) {
    DWORD dwBytesWritten = 0;

    if (hSerial == INVALID_HANDLE_VALUE) {
        wprintf(L"[ERROR] There is no open COM port to write to\n");
        return -1;
    }

    if (!WriteFile(hSerial, pBuffer, uBufSize, &dwBytesWritten, NULL)){
        wprintf(L"[ERROR] Cannot write to COM port\n");
        return -1;
    }

    return dwBytesWritten;
}

BOOL Serial::Close() {
    if (hSerial == INVALID_HANDLE_VALUE) {
        wprintf(L"[WARNING] Port is not open\n");
        return TRUE;
    }

    if (CloseHandle(hSerial)) {
        wprintf(L"[NOTICE] Port closed successfully\n");
        hSerial = INVALID_HANDLE_VALUE;
        return TRUE;
    }

    wprintf(L"[ERROR] Error closing COM port\n");
    return FALSE;
}

BOOL Serial::SetComReadWaitTime(DWORD dwWait) {
    if (hSerial == INVALID_HANDLE_VALUE) {
        wprintf(L"[WARNING] Port is not open\n");
        return FALSE;
    }

    m_ComTimeouts.ReadTotalTimeoutConstant = dwWait;

    if (!SetCommTimeouts(hSerial, &m_ComTimeouts)) {
        wprintf(L"[WARNING] Cannot set COM port timeout\n");
        return FALSE;
    }

    return TRUE;
}