Example #1
0
std::string msgDebugEngineComResult(HRESULT hr)
{
    switch (hr) {
    case S_OK:
        return std::string("S_OK");
    case S_FALSE:
        return std::string("S_FALSE");
    case E_FAIL:
        break;
    case E_INVALIDARG:
        return std::string("E_INVALIDARG");
    case E_NOINTERFACE:
        return std::string("E_NOINTERFACE");
    case E_OUTOFMEMORY:
        return std::string("E_OUTOFMEMORY");
    case E_UNEXPECTED:
        return std::string("E_UNEXPECTED");
    case E_NOTIMPL:
        return std::string("E_NOTIMPL");
    }
    if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
        return std::string("ERROR_ACCESS_DENIED");;
    if (hr == HRESULT_FROM_NT(STATUS_CONTROL_C_EXIT))
        return std::string("STATUS_CONTROL_C_EXIT");
    return std::string("E_FAIL ") + winErrorMessage(HRESULT_CODE(hr));
}
bool VirtualSerialDevice::waitForBytesWritten(int msecs)
{
    QMutexLocker locker(&lock);
    if (pendingWrites.count() == 0) return false;

    if (QThread::currentThread() != thread()) {
        // Wait for signal from main thread
        unsigned long timeout = msecs;
        if (msecs == -1) timeout = ULONG_MAX;
        if (waiterForBytesWritten == NULL)
            waiterForBytesWritten = new QWaitCondition;
        return waiterForBytesWritten->wait(&lock, timeout);
    }

    DWORD waitTime = msecs;
    if (msecs == -1) waitTime = INFINITE; // Ok these are probably bitwise the same, but just to prove I've thought about it...
    DWORD result = WaitForSingleObject(d->writeOverlapped.hEvent, waitTime); // Do I need WaitForSingleObjectEx and worry about alertable states?
    if (result == WAIT_TIMEOUT) {
        return false;
    }
    else if (result == WAIT_OBJECT_0) {
        DWORD bytesWritten;
        BOOL ok = GetOverlappedResult(d->portHandle, &d->writeOverlapped, &bytesWritten, TRUE);
        if (!ok) {
            setErrorString(tr("An error occurred while syncing on waitForBytesWritten for %1: %2").
                           arg(portName, winErrorMessage(GetLastError())));
            return false;
        }
        Q_ASSERT(bytesWritten == (DWORD)pendingWrites.first().length());

        doWriteCompleted(locker);
        return true;
    }
    else {
        setErrorString(QString("An error occurred in waitForBytesWritten() for %1: %2").
                       arg(portName, winErrorMessage(GetLastError())));
        return false;
    }
}
qint64 VirtualSerialDevice::writeNextBuffer(QMutexLocker& locker)
{
    Q_UNUSED(locker)
    // Must be locked on entry
    qint64 bufLen = pendingWrites[0].length();
    BOOL ok = WriteFile(d->portHandle, pendingWrites[0].constData(), bufLen, NULL, &d->writeOverlapped);
    if (ok || GetLastError() == ERROR_IO_PENDING) {
        // Apparently it can return true for a small asynchronous write...
        // Hopefully it still gets signalled in the same way!

        // Wait for signal via writeCompleted
        return bufLen;
    }
    else {
        setErrorString(tr("An error occurred while writing to %1: %2").
                       arg(portName, winErrorMessage(GetLastError())));
        pendingWrites.removeFirst();
        return -1;
    }
}
bool TrkDevice::write(const QByteArray &data, QString *errorMessage)
{
    if (verbose())
        logMessage("XWRITE " + data.toHex());
#ifdef Q_OS_WIN
    DWORD charsWritten;
    if (!WriteFile(d->hdevice, data.data(), data.size(), &charsWritten, NULL)) {
        *errorMessage = QString::fromLatin1("Error writing data: %1").arg(winErrorMessage(GetLastError()));
        return false;
    }
    FlushFileBuffers(d->hdevice);
    return true;
#else
    if (d->file.write(data) == -1 || !d->file.flush()) {
        *errorMessage = QString::fromLatin1("Cannot write: %1").arg(d->file.errorString());
        return false;
    }
    return  true;
#endif
}
qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize)
{
    QMutexLocker locker(&lock);
    // We do our reads synchronously
    OVERLAPPED readOverlapped;
    memset(&readOverlapped, 0, sizeof(OVERLAPPED));
    DWORD bytesRead;
    BOOL done = ReadFile(d->portHandle, data, maxSize, &bytesRead, &readOverlapped);
    if (done) return (qint64)bytesRead;

    if (GetLastError() == ERROR_IO_PENDING) {
        // Note the TRUE to wait for the read to complete
        done = GetOverlappedResult(d->portHandle, &readOverlapped, &bytesRead, TRUE);
        if (done) return (qint64)bytesRead;
    }

    // If we reach here an error has occurred
    setErrorString(tr("An error occurred while reading from %1: %2").
                   arg(portName, winErrorMessage(GetLastError())));
    return -1;
}
Example #6
0
QTCREATOR_UTILS_EXPORT QString winGetDLLVersion(WinDLLVersionType t,
                                                const QString &name,
                                                QString *errorMessage)
{
    // Resolve required symbols from the version.dll
    typedef DWORD (APIENTRY *GetFileVersionInfoSizeProtoType)(LPCTSTR, LPDWORD);
    typedef BOOL (APIENTRY *GetFileVersionInfoWProtoType)(LPCWSTR, DWORD, DWORD, LPVOID);
    typedef BOOL (APIENTRY *VerQueryValueWProtoType)(const LPVOID, LPWSTR lpSubBlock, LPVOID, PUINT);

    const char *versionDLLC = "version.dll";
    QLibrary versionLib(QLatin1String(versionDLLC), 0);
    if (!versionLib.load()) {
        *errorMessage = msgCannotLoad(versionDLLC, versionLib.errorString());
        return QString();
    }
    // MinGW requires old-style casts
    GetFileVersionInfoSizeProtoType getFileVersionInfoSizeW = (GetFileVersionInfoSizeProtoType)(versionLib.resolve("GetFileVersionInfoSizeW"));
    GetFileVersionInfoWProtoType getFileVersionInfoW = (GetFileVersionInfoWProtoType)(versionLib.resolve("GetFileVersionInfoW"));
    VerQueryValueWProtoType verQueryValueW = (VerQueryValueWProtoType)(versionLib.resolve("VerQueryValueW"));
    if (!getFileVersionInfoSizeW || !getFileVersionInfoW || !verQueryValueW) {
        *errorMessage = msgCannotResolve(versionDLLC);
        return QString();
    }

    // Now go ahead, read version info resource
    DWORD dummy = 0;
    const LPCTSTR fileName = reinterpret_cast<LPCTSTR>(name.utf16()); // MinGWsy
    const DWORD infoSize = (*getFileVersionInfoSizeW)(fileName, &dummy);
    if (infoSize == 0) {
        *errorMessage = QString::fromLatin1("Unable to determine the size of the version information of %1: %2").arg(name, winErrorMessage(GetLastError()));
        return QString();
    }
    QByteArray dataV(infoSize + 1, '\0');
    char *data = dataV.data();
    if (!(*getFileVersionInfoW)(fileName, dummy, infoSize, data)) {
        *errorMessage = QString::fromLatin1("Unable to determine the version information of %1: %2").arg(name, winErrorMessage(GetLastError()));
        return QString();
    }
    VS_FIXEDFILEINFO  *versionInfo;
    const LPCWSTR backslash = TEXT("\\");
    UINT len = 0;
    if (!(*verQueryValueW)(data, const_cast<LPWSTR>(backslash), &versionInfo, &len)) {
        *errorMessage = QString::fromLatin1("Unable to determine version string of %1: %2").arg(name, winErrorMessage(GetLastError()));
        return QString();
    }
    QString rc;
    switch (t) {
    case WinDLLFileVersion:
        QTextStream(&rc) << HIWORD(versionInfo->dwFileVersionMS) << '.' << LOWORD(versionInfo->dwFileVersionMS);
        break;
    case WinDLLProductVersion:
        QTextStream(&rc) << HIWORD(versionInfo->dwProductVersionMS) << '.' << LOWORD(versionInfo->dwProductVersionMS);
        break;
    }
    return rc;
}
QString msgFunctionFailed(const char *f, unsigned long error)
{
    return QString::fromLatin1("\"%1\" failed: %2").arg(QLatin1String(f), winErrorMessage(error));
}
Example #8
0
bool getPDBFiles(const QString &peExecutableFileName, QStringList *rc, QString *errorMessage)
{
    HANDLE hFile = NULL;
    HANDLE hFileMap = NULL;
    void *fileMemory = 0;
    bool success = false;

    rc->clear();
    do {
        // Create a memory mapping of the file
        hFile = CreateFile(reinterpret_cast<const WCHAR*>(peExecutableFileName.utf16()), GENERIC_READ, FILE_SHARE_READ, NULL,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {
            *errorMessage = QString::fromLatin1("Cannot open '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
            break;
        }

        hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (hFileMap == NULL) {
            *errorMessage = QString::fromLatin1("Cannot create file mapping of '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
            break;
        }

        fileMemory = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
        if (!fileMemory) {
            *errorMessage = QString::fromLatin1("Cannot map '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
            break;
        }

        IMAGE_NT_HEADERS *ntHeaders = getNtHeader(fileMemory, errorMessage);
        if (!ntHeaders)
            break;

        int debugSectionCount;
        IMAGE_DEBUG_DIRECTORY *debugDir;
        if (!getDebugDirectory(ntHeaders, fileMemory, &debugDir, &debugSectionCount, errorMessage))
            return false;
        if (debugSectionCount)
            collectPDBfiles(fileMemory, debugDir, debugSectionCount, rc);
        success = true;
    } while(false);

    if (fileMemory)
        UnmapViewOfFile(fileMemory);

    if (hFileMap != NULL)
        CloseHandle(hFileMap);

    if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
        CloseHandle(hFile);

    return success;
}
bool VirtualSerialDevice::open(OpenMode mode)
{
    Q_ASSERT(QThread::currentThread() == thread());
    if (isOpen()) return true;

    d->portHandle = CreateFileA(windowsPortName(portName).toAscii(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (d->portHandle == INVALID_HANDLE_VALUE) {
        setErrorString(tr("The port %1 could not be opened: %2").
                       arg(portName, winErrorMessage(GetLastError())));
        return false;
    }

    DCB commState;
    memset(&commState, 0, sizeof(DCB));
    commState.DCBlength = sizeof(DCB);
    bool ok = GetCommState(d->portHandle, &commState);
    if (ok) {
        commState.BaudRate = CBR_115200;
        commState.fBinary = TRUE;
        commState.fParity = FALSE;
        commState.fOutxCtsFlow = FALSE;
        commState.fOutxDsrFlow = FALSE;
        commState.fInX = FALSE;
        commState.fOutX = FALSE;
        commState.fNull = FALSE;
        commState.fAbortOnError = FALSE;
        commState.fDsrSensitivity = FALSE;
        commState.fDtrControl = DTR_CONTROL_DISABLE;
        commState.ByteSize = 8;
        commState.Parity = NOPARITY;
        commState.StopBits = ONESTOPBIT;
        ok = SetCommState(d->portHandle, &commState);
    }
    if (!ok) {
        qWarning("%s setting comm state", qPrintable(winErrorMessage(GetLastError())));
    }

    // http://msdn.microsoft.com/en-us/library/aa363190(v=vs.85).aspx says this means
    // "the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received"
    COMMTIMEOUTS timeouts;
    timeouts.ReadIntervalTimeout = MAXDWORD;
    timeouts.ReadTotalTimeoutMultiplier = 0;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;
    SetCommTimeouts(d->portHandle, &timeouts);

    d->writeOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    d->writeCompleteNotifier = new QWinEventNotifier(d->writeOverlapped.hEvent, this);
    connect(d->writeCompleteNotifier, SIGNAL(activated(HANDLE)), this, SLOT(writeCompleted()));

    // This is how we implement readyRead notifications
    d->commEventOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    d->commEventNotifier = new QWinEventNotifier(d->commEventOverlapped.hEvent, this);
    connect(d->commEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(commEventOccurred()));

    if (!SetCommMask(d->portHandle, EV_RXCHAR)) {
        // What to do?
        qWarning("%s: Could not set comm mask, err=%d", Q_FUNC_INFO, (int)GetLastError());
    }
    bool result = WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped);
    Q_ASSERT(result == false); // Can't see how it would make sense to be anything else...
    (void)result; // For release build
    if (GetLastError() != ERROR_IO_PENDING) {
        setErrorString(tr("An error occurred while waiting for read notifications from %1: %2").
                       arg(portName, winErrorMessage(GetLastError())));
        close();
        return false;
    }

    ok = QIODevice::open(mode);
    if (!ok) close();
    return ok;
}
Example #10
0
std::string winErrorMessage()
{
    return winErrorMessage(GetLastError());
}
Example #11
0
bool Win_WindowManager::sendCloseEventImpl(const QString &winId, Q_PID, QString *errorMessage)
{   
    // Convert window back.
    quintptr winIdIntPtr;
    QTextStream str(const_cast<QString*>(&winId), QIODevice::ReadOnly);
    str.setIntegerBase(16);
    str >> winIdIntPtr;
    if (str.status() != QTextStream::Ok) {
        *errorMessage = QString::fromLatin1("Invalid win id %1.").arg(winId);
        return false;
    }
    if (!PostMessage(reinterpret_cast<HWND>(winIdIntPtr), WM_CLOSE, 0, 0)) {
        *errorMessage = QString::fromLatin1("Cannot send event to 0x%1: %2").arg(winIdIntPtr, 0, 16).arg(winErrorMessage(GetLastError()));
        return false;
    }
    return true;
}
Example #12
0
// Read a PE executable and determine dependent libraries, word size
// and debug flags.
bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage,
                      QStringList *dependentLibrariesIn, unsigned *wordSizeIn,
                      bool *isDebugIn, bool isMinGW)
{
    bool result = false;
    HANDLE hFile = NULL;
    HANDLE hFileMap = NULL;
    void *fileMemory = 0;

    if (dependentLibrariesIn)
        dependentLibrariesIn->clear();
    if (wordSizeIn)
        *wordSizeIn = 0;
    if (isDebugIn)
        *isDebugIn = false;

    do {
        // Create a memory mapping of the file
        hFile = CreateFile(reinterpret_cast<const WCHAR*>(peExecutableFileName.utf16()), GENERIC_READ, FILE_SHARE_READ, NULL,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {
            *errorMessage = QString::fromLatin1("Cannot open '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
            break;
        }

        hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (hFileMap == NULL) {
            *errorMessage = QString::fromLatin1("Cannot create file mapping of '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
            break;
        }

        fileMemory = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
        if (!fileMemory) {
            *errorMessage = QString::fromLatin1("Cannot map '%1': %2").arg(peExecutableFileName, winErrorMessage(GetLastError()));
            break;
        }

        const IMAGE_NT_HEADERS *ntHeaders = getNtHeader(fileMemory, errorMessage);
        if (!ntHeaders)
            break;

        const unsigned wordSize = ntHeaderWordSize(ntHeaders);
        if (wordSizeIn)
            *wordSizeIn = wordSize;
        bool debug = false;
        if (wordSize == 32) {
            const IMAGE_NT_HEADERS32 *ntHeaders32 = reinterpret_cast<const IMAGE_NT_HEADERS32 *>(ntHeaders);

            if (!isMinGW) {
                debug = ntHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
            } else {
                // Use logic that's used e.g. in objdump / pfd library
                debug = !(ntHeaders32->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
            }

            if (dependentLibrariesIn)
                *dependentLibrariesIn = readImportSections(ntHeaders32, fileMemory, errorMessage);

        } else {
            const IMAGE_NT_HEADERS64 *ntHeaders64 = reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders);

            if (!isMinGW) {
                debug = ntHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
            } else {
                // Use logic that's used e.g. in objdump / pfd library
                debug = !(ntHeaders64->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
            }

            if (dependentLibrariesIn)
                *dependentLibrariesIn = readImportSections(ntHeaders64, fileMemory, errorMessage);
        }

        if (isDebugIn)
            *isDebugIn = debug;
        result = true;
        if (optVerboseLevel > 1)
            std::wcout << __FUNCTION__ << ": " << peExecutableFileName
                       << ' ' << wordSize << " bit, debug: " << debug << '\n';
    } while (false);

    if (fileMemory)
        UnmapViewOfFile(fileMemory);

    if (hFileMap != NULL)
        CloseHandle(hFileMap);

    if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
        CloseHandle(hFile);

    return result;
}
Example #13
0
// runProcess: Run a command line process (replacement for QProcess which
// does not exist in the bootstrap library).
bool runProcess(const QString &binary, const QStringList &args,
                const QString &workingDirectory,
                unsigned long *exitCode, QByteArray *stdOut, QByteArray *stdErr,
                QString *errorMessage)
{
    if (exitCode)
        *exitCode = 0;

    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);

    STARTUPINFO myInfo;
    GetStartupInfo(&myInfo);
    si.hStdInput = myInfo.hStdInput;
    si.hStdOutput = myInfo.hStdOutput;
    si.hStdError = myInfo.hStdError;

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    const QChar backSlash = QLatin1Char('\\');
    QString nativeWorkingDir = QDir::toNativeSeparators(workingDirectory.isEmpty() ?  QDir::currentPath() : workingDirectory);
    if (!nativeWorkingDir.endsWith(backSlash))
        nativeWorkingDir += backSlash;

    if (stdOut) {
        si.hStdOutput = createInheritableTemporaryFile();
        if (si.hStdOutput == INVALID_HANDLE_VALUE) {
            if (errorMessage)
                *errorMessage = QStringLiteral("Error creating stdout temporary file");
            return false;
        }
        si.dwFlags |= STARTF_USESTDHANDLES;
    }

    if (stdErr) {
        si.hStdError = createInheritableTemporaryFile();
        if (si.hStdError == INVALID_HANDLE_VALUE) {
            if (errorMessage)
                *errorMessage = QStringLiteral("Error creating stderr temporary file");
            return false;
        }
        si.dwFlags |= STARTF_USESTDHANDLES;
    }

    // Create a copy of the command line which CreateProcessW can modify.
    QString commandLine;
    appendToCommandLine(binary, &commandLine);
    foreach (const QString &a, args)
        appendToCommandLine(a, &commandLine);
    if (optVerboseLevel > 1)
        std::wcout << "Running: " << commandLine << '\n';

    QScopedArrayPointer<wchar_t> commandLineW(new wchar_t[commandLine.size() + 1]);
    commandLine.toWCharArray(commandLineW.data());
    commandLineW[commandLine.size()] = 0;
    if (!CreateProcessW(0, commandLineW.data(), 0, 0, /* InheritHandles */ TRUE, 0, 0,
                        (wchar_t *)nativeWorkingDir.utf16(), &si, &pi)) {
        if (stdOut)
            CloseHandle(si.hStdOutput);
        if (stdErr)
            CloseHandle(si.hStdError);
        if (errorMessage)
            *errorMessage = QStringLiteral("CreateProcessW failed: ") + winErrorMessage(GetLastError());
        return false;
    }

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    if (exitCode)
        GetExitCodeProcess(pi.hProcess, exitCode);
    CloseHandle(pi.hProcess);

    if (stdOut)
        readTemporaryProcessFile(si.hStdOutput, stdOut);
    if (stdErr)
        readTemporaryProcessFile(si.hStdError, stdErr);
    return true;
}
bool TrkDevice::open(const QString &port, QString *errorMessage)
{
    close();
#ifdef Q_OS_WIN
    d->hdevice = CreateFile(port.toStdWString().c_str(),
                           GENERIC_READ | GENERIC_WRITE,
                           0,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

    if (INVALID_HANDLE_VALUE == d->hdevice) {
        *errorMessage = QString::fromLatin1("Could not open device '%1': %2").arg(port, winErrorMessage(GetLastError()));
        return false;
    }
    d->timerId = startTimer(TimerInterval);
    return true;
#else
    d->file.setFileName(port);
    if (!d->file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) {
        *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(port, d->file.errorString());
        return false;
    }

    struct termios termInfo;
    if (tcgetattr(d->file.handle(), &termInfo) < 0) {
        *errorMessage = QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)));
        return false;
    }
    // Turn off terminal echo as not get messages back, among other things
    termInfo.c_cflag|=CREAD|CLOCAL;
    termInfo.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
    termInfo.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY));
    termInfo.c_oflag&=(~OPOST);
    termInfo.c_cc[VMIN]=0;
    termInfo.c_cc[VINTR] = _POSIX_VDISABLE;
    termInfo.c_cc[VQUIT] = _POSIX_VDISABLE;
    termInfo.c_cc[VSTART] = _POSIX_VDISABLE;
    termInfo.c_cc[VSTOP] = _POSIX_VDISABLE;
    termInfo.c_cc[VSUSP] = _POSIX_VDISABLE;
    if (tcsetattr(d->file.handle(), TCSAFLUSH, &termInfo) < 0) {
        *errorMessage = QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)));
        return false;
    }
    d->timerId = startTimer(TimerInterval);
    return true;
#endif
}