Remove old ConPty stuff, fix Windows build, update submodule

This commit is contained in:
Vitaly Petrov
2019-03-20 22:35:16 +03:00
parent 2c919cf6c5
commit eea2684433
13 changed files with 130 additions and 461 deletions
+5 -2
View File
@@ -13,6 +13,8 @@ environment:
matrix:
- PLATFORM: x64
QT_DIR: C:\Qt\5.12.1\msvc2017_64
- PLATFORM: x86
QT_DIR: C:\Qt\5.12.1\msvc2017
matrix:
fast_finish: true
@@ -36,5 +38,6 @@ build_script:
- cmake.exe --build .
- dir thirdparty\winpty\src\winpty
#test_script:
# - ctest -C %CONFIGURATION% --output-on-failure
test_script:
- set PATH=%PATH%;%QT_DIR%
- ctest -C %CONFIGURATION% --output-on-failure
+10 -19
View File
@@ -11,6 +11,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
#params
#available params:
# - NO_BUILD_TESTS=1
# - NO_BUILD_EXAMPLES=1
# - WINPTY_ROOT_DIR=<path/to/winpty> - if you set this parameter, winpty doesn't be auto-downloaded like dependency
IF(CMAKE_BUILD_TYPE MATCHES Debug)
set(PTYQT_DEBUG TRUE)
add_definitions(-DPTYQT_DEBUG)
@@ -64,22 +68,9 @@ enable_testing()
#sub projects
add_subdirectory(core)
add_subdirectory(tests)
add_subdirectory(examples)
#add_executable(${PROJECT_NAME} "main.cpp")
#target_link_libraries(${PROJECT_NAME} Qt5::Core)
#Ubuntu package generator
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
set(CPACK_PACKAGE_CONTACT v31337@gmail.com)
set(CPACK_GENERATOR DEB)
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
include (CPack)
if (NOT "${NO_BUILD_TESTS}" STREQUAL "1")
add_subdirectory(tests)
endif()
if (NOT "${NO_BUILD_EXAMPLES}" STREQUAL "1")
add_subdirectory(examples)
endif()
+2 -5
View File
@@ -11,11 +11,8 @@ if (MSVC)
${SOURCE_FILES}
winptyprocess.h
winptyprocess.cpp
#conptynamedpipeprocess.h
#conptynamedpipeprocess.cpp
conptyanonymouspipeprocess.h
conptyanonymouspipeprocess.cpp
conpty_shared.h
conptyprocess.h
conptyprocess.cpp
)
else()
set(SOURCE_FILES
-72
View File
@@ -1,72 +0,0 @@
#ifndef CONPTYANONYMOUSPIPEPROCESS_H
#define CONPTYANONYMOUSPIPEPROCESS_H
#include "conpty_shared.h"
#include <QMutex>
#include <QTimer>
#include <QThread>
class PtyBuffer : public QIODevice
{
friend class ConPtyAnonymousPipeProcess;
Q_OBJECT
public:
PtyBuffer() { }
~PtyBuffer() { }
//just empty realization, we need only 'readyRead' signal of this class
qint64 readData(char *data, qint64 maxlen) { return 0; }
qint64 writeData(const char *data, qint64 len) { return 0; }
bool isSequential() { return true; }
qint64 bytesAvailable() { return m_readBuffer.size(); }
qint64 size() { return m_readBuffer.size(); }
void emitReadyRead()
{
//for emit signal from PtyBuffer own thread
QTimer::singleShot(1, this, [this]()
{
emit readyRead();
});
}
private:
QByteArray m_readBuffer;
};
class ConPtyAnonymousPipeProcess : public IPtyProcess
{
public:
ConPtyAnonymousPipeProcess();
~ConPtyAnonymousPipeProcess();
bool startProcess(const QString &shellPath, QStringList environment, qint16 cols, qint16 rows);
bool resize(qint16 cols, qint16 rows);
bool kill();
PtyType type();
#ifdef PTYQT_DEBUG
QString dumpDebugInfo();
#endif
virtual QIODevice *notifier();
virtual QByteArray readAll();
virtual qint64 write(const QByteArray &byteArray);
bool isAvailable();
private:
HRESULT createPseudoConsoleAndPipes(HPCON* phPC, HANDLE* phPipeIn, HANDLE* phPipeOut, qint16 cols, qint16 rows);
HRESULT initializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX* pStartupInfo, HPCON hPC);
private:
WindowsContext m_winContext;
HPCON m_ptyHandler;
HANDLE m_hPipeIn, m_hPipeOut;
QThread *m_readThread;
QMutex m_bufferMutex;
PtyBuffer m_buffer;
};
#endif // CONPTYANONYMOUSPIPEPROCESS_H
-274
View File
@@ -1,274 +0,0 @@
#include "conptynamedpipeprocess.h"
#include <QFileInfo>
#include <QMutex>
#include <sstream>
#include <QCryptographicHash>
#include <QUuid>
#include <QSocketNotifier>
#include<QThread>
#include <QSysInfo>
ConPtyNamedPipeProcess::ConPtyNamedPipeProcess()
: IWindowsPtyProcess()
, m_ptyHandler(INVALID_HANDLE_VALUE)
, m_hShell(INVALID_HANDLE_VALUE)
{
}
ConPtyNamedPipeProcess::~ConPtyNamedPipeProcess()
{
kill();
}
bool ConPtyNamedPipeProcess::startProcess(const QString &shellPath, QStringList environment, qint16 cols, qint16 rows)
{
//shared between all objects in all threads
static QMutex pipeNameCounterMutex;
static qint64 pipeNameCounter = 0;
if (!isAvailable())
{
m_lastError = m_winContext.lastError();
return false;
}
//already running
if (m_ptyHandler != INVALID_HANDLE_VALUE)
return false;
QFileInfo fi(shellPath);
if (fi.isRelative() || !QFile::exists(shellPath))
{
//todo add auto-find executable in PATH env var
m_lastError = QString("WinPty Error: shell file path must be absolute");
return false;
}
m_shellPath = shellPath;
m_size = QPair<qint16, qint16>(cols, rows);
auto createNamedPipe = [] (bool writeChannel,
HANDLE *hNamedPipe,
QString &resultName,
const QString &pipeName) -> bool
{
*hNamedPipe = INVALID_HANDLE_VALUE;
resultName = "\\\\.\\pipe\\" + pipeName;
const DWORD winOpenMode = PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE/* | FILE_FLAG_OVERLAPPED */;
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
*hNamedPipe = CreateNamedPipeW(
resultName.toStdWString().c_str(),
/*dwOpenMode=*/winOpenMode,
/*dwPipeMode=*/PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
/*nMaxInstances=*/1,
/*nOutBufferSize=*/0,
/*nInBufferSize=*/0,
/*nDefaultTimeOut=*/30000,
&sa);
return *hNamedPipe != INVALID_HANDLE_VALUE;
};
//shared between all objects in all threads
qint64 pipeCounterValue = 0;
{
QMutexLocker locker(&pipeNameCounterMutex);
pipeCounterValue = pipeNameCounter;
pipeNameCounter++;
}
//
QByteArray randPart = QCryptographicHash::hash(QByteArray::number(qrand()) + QByteArray::number(pipeCounterValue) + QUuid::createUuid().toByteArray(), QCryptographicHash::Sha256).left(16);
bool createPipeRes = createNamedPipe(true, &m_inPipeShellSide, m_conInName, QString("conpty-conin-%1-%2").arg(pipeCounterValue).arg(QString::fromLatin1(randPart.toHex())));
if (!createPipeRes)
{
m_lastError = QString("ConPty Error: Unable to create IN pipe -> %1").arg(GetLastError());
return false;
}
randPart = QCryptographicHash::hash(QByteArray::number(qrand()) + QByteArray::number(pipeCounterValue) + QUuid::createUuid().toByteArray(), QCryptographicHash::Sha256).left(16);
createPipeRes = createNamedPipe(false, &m_outPipeShellSide, m_conOutName, QString("conpty-conout-%1-%2").arg(pipeCounterValue).arg(QString::fromLatin1(randPart.toHex())));
if (!createPipeRes)
{
m_lastError = QString("ConPty Error: Unable to create OUT pipe -> %1").arg(GetLastError());
return false;
}
HRESULT result = m_winContext.createPseudoConsole({cols, rows}, m_inPipeShellSide, m_outPipeShellSide, 0, &m_ptyHandler);
if (result != S_OK)
{
//error can be E_HANDLE
m_lastError = QString("ConPty Error: Unable to launch ConPty -> %1").arg(QString::number(result, 16));
return false;
}
//console created
//env
std::wstringstream envBlock;
foreach (QString line, environment)
{
envBlock << line.toStdWString() << L'\0';
}
envBlock << L'\0';
std::wstring env = envBlock.str();
auto envV = vectorFromString(env);
LPWSTR envArg = envV.empty() ? nullptr : envV.data();
LPWSTR cmdArg = (LPWSTR)m_shellPath.utf16();
//this code runned in separate thread, because current thread will stops on API call 'ConnectNamedPipe'
QThread *thread = QThread::create([this]()
{
QThread::msleep(10);
m_inSocket.connectToServer(m_conInName, QIODevice::WriteOnly);
m_inSocket.waitForConnected();
m_outSocket.connectToServer(m_conOutName, QIODevice::ReadOnly);
m_outSocket.waitForConnected();
if (m_inSocket.state() != QLocalSocket::ConnectedState || m_outSocket.state() != QLocalSocket::ConnectedState)
{
m_lastError = QString("ConPty Error: Unable to connect local sockets -> %1 / %2").arg(m_inSocket.errorString()).arg(m_outSocket.errorString());
}
//qDebug() << "socketDescriptors" << m_inSocket.fullServerName() << m_inSocket.socketDescriptor() << m_outSocket.socketDescriptor() << m_inSocket.errorString() << m_outSocket.errorString();
QThread::currentThread()->deleteLater();
});
//connect to Pty
thread->start();
bool connected = ConnectNamedPipe(m_inPipeShellSide, nullptr) && ConnectNamedPipe(m_outPipeShellSide, nullptr);
if (!connected)
{
m_lastError = QString("ConPty Error: Unable to connect named pipes");
return false;
}
//attach the pseudoconsole to the client application we're creating
STARTUPINFOEXW pStartupInfo{0};
pStartupInfo.StartupInfo.cb = sizeof(STARTUPINFOEXW);
//get the size of the thread attribute list.
size_t size;
InitializeProcThreadAttributeList(NULL, 1, 0, reinterpret_cast<PSIZE_T>(&size));
pStartupInfo.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
bool fSuccess = InitializeProcThreadAttributeList(pStartupInfo.lpAttributeList, 1, 0, reinterpret_cast<PSIZE_T>(&size));
if (!fSuccess)
{
m_lastError = QString("ConPty Error: InitializeProcThreadAttributeList failed");
return false;
}
fSuccess = UpdateProcThreadAttribute(pStartupInfo.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
m_ptyHandler,
sizeof(HPCON),
NULL,
NULL);
if (!fSuccess)
{
m_lastError = QString("ConPty Error: UpdateProcThreadAttribute failed");
return false;
}
//create process
PROCESS_INFORMATION piClient{};
fSuccess = !!CreateProcessW(
nullptr,
cmdArg,
nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes
false, // bInheritHandles VERY IMPORTANT that this is false
EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
envArg, // lpEnvironment
nullptr, // lpCurrentDirectory
&pStartupInfo.StartupInfo, // lpStartupInfo
&piClient // lpProcessInformation
);
if (!fSuccess)
{
m_lastError = QString("ConPty Error: Cannot create process -> %1").arg(QString::number(GetLastError(), 10));
return false;
}
// Update handle
m_hShell = piClient.hProcess;
m_pid = piClient.dwProcessId;
return true;
}
bool ConPtyNamedPipeProcess::resize(qint16 cols, qint16 rows)
{
if (m_ptyHandler == nullptr)
{
return false;
}
bool res = SUCCEEDED(m_winContext.resizePseudoConsole(m_ptyHandler, {cols, rows}));
if (res)
{
m_size = QPair<qint16, qint16>(cols, rows);
}
return res;
}
bool ConPtyNamedPipeProcess::kill()
{
bool exitCode = false;
if (m_hShell != 0 && m_ptyHandler != 0)
{
m_inSocket.disconnectFromServer();
m_outSocket.disconnectFromServer();
m_winContext.closePseudoConsole(m_ptyHandler);
exitCode = CloseHandle(m_hShell);
m_hShell = INVALID_HANDLE_VALUE;
m_ptyHandler = INVALID_HANDLE_VALUE;
m_conInName = QString();
m_conOutName = QString();
m_inPipeShellSide = INVALID_HANDLE_VALUE;
m_outPipeShellSide = INVALID_HANDLE_VALUE;
m_pid = 0;
}
return exitCode;
}
IPtyProcess::PtyType ConPtyNamedPipeProcess::type()
{
return PtyType::ConPtyNamedPipe;
}
#ifdef PTYQT_DEBUG
QString ConPtyNamedPipeProcess::dumpDebugInfo()
{
return QString("PID: %1, ConIn: %2, ConOut: %3, Type: %4, Cols: %5, Rows: %6, IsRunning: %7, Shell: %8")
.arg(m_pid).arg(m_conInName).arg(m_conOutName).arg(type())
.arg(m_size.first).arg(m_size.second).arg(m_ptyHandler != nullptr)
.arg(m_shellPath);
}
#endif
bool ConPtyNamedPipeProcess::isAvailable()
{
#ifdef TOO_OLD_WINSDK
return false; //very importnant! ConPty can be built, but it doesn't work if built with old sdk and Win10 < 1903
#endif
qint32 buildNumber = QSysInfo::kernelVersion().split(".").last().toInt();
if (buildNumber < CONPTY_MINIMAL_WINDOWS_VERSION)
return false;
return m_winContext.init();
}
-28
View File
@@ -1,28 +0,0 @@
#ifndef CONPTYNAMEDPIPEPROCESS_H
#define CONPTYNAMEDPIPEPROCESS_H
#include "conpty_shared.h"
class ConPtyNamedPipeProcess : public IWindowsPtyProcess
{
public:
ConPtyNamedPipeProcess();
~ConPtyNamedPipeProcess();
bool startProcess(const QString &shellPath, QStringList environment, qint16 cols, qint16 rows);
bool resize(qint16 cols, qint16 rows);
bool kill();
PtyType type();
#ifdef PTYQT_DEBUG
QString dumpDebugInfo();
#endif
bool isAvailable();
private:
WindowsContext m_winContext;
HPCON m_ptyHandler;
HANDLE m_hShell;
HANDLE m_inPipeShellSide, m_outPipeShellSide;
};
#endif // CONPTYNAMEDPIPEPROCESS_H
@@ -1,4 +1,4 @@
#include "conptyanonymouspipeprocess.h"
#include "conptyprocess.h"
#include <QFile>
#include <QFileInfo>
#include <QThread>
@@ -9,7 +9,7 @@
#define READ_INTERVAL_MSEC 500
HRESULT ConPtyAnonymousPipeProcess::createPseudoConsoleAndPipes(HPCON* phPC, HANDLE* phPipeIn, HANDLE* phPipeOut, qint16 cols, qint16 rows)
HRESULT ConPtyProcess::createPseudoConsoleAndPipes(HPCON* phPC, HANDLE* phPipeIn, HANDLE* phPipeOut, qint16 cols, qint16 rows)
{
HRESULT hr{ E_UNEXPECTED };
HANDLE hPipePTYIn{ INVALID_HANDLE_VALUE };
@@ -34,7 +34,7 @@ HRESULT ConPtyAnonymousPipeProcess::createPseudoConsoleAndPipes(HPCON* phPC, HAN
// Initializes the specified startup info struct with the required properties and
// updates its thread attribute list with the specified ConPTY handle
HRESULT ConPtyAnonymousPipeProcess::initializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX* pStartupInfo, HPCON hPC)
HRESULT ConPtyProcess::initializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX* pStartupInfo, HPCON hPC)
{
HRESULT hr{ E_UNEXPECTED };
@@ -75,7 +75,7 @@ HRESULT ConPtyAnonymousPipeProcess::initializeStartupInfoAttachedToPseudoConsole
return hr;
}
ConPtyAnonymousPipeProcess::ConPtyAnonymousPipeProcess()
ConPtyProcess::ConPtyProcess()
: IPtyProcess()
, m_ptyHandler { INVALID_HANDLE_VALUE }
, m_hPipeIn { INVALID_HANDLE_VALUE }
@@ -85,12 +85,12 @@ ConPtyAnonymousPipeProcess::ConPtyAnonymousPipeProcess()
}
ConPtyAnonymousPipeProcess::~ConPtyAnonymousPipeProcess()
ConPtyProcess::~ConPtyProcess()
{
kill();
}
bool ConPtyAnonymousPipeProcess::startProcess(const QString &shellPath, QStringList environment, qint16 cols, qint16 rows)
bool ConPtyProcess::startProcess(const QString &shellPath, QStringList environment, qint16 cols, qint16 rows)
{
if (!isAvailable())
{
@@ -213,7 +213,7 @@ bool ConPtyAnonymousPipeProcess::startProcess(const QString &shellPath, QStringL
return true;
}
bool ConPtyAnonymousPipeProcess::resize(qint16 cols, qint16 rows)
bool ConPtyProcess::resize(qint16 cols, qint16 rows)
{
if (m_ptyHandler == nullptr)
{
@@ -232,7 +232,7 @@ bool ConPtyAnonymousPipeProcess::resize(qint16 cols, qint16 rows)
return true;
}
bool ConPtyAnonymousPipeProcess::kill()
bool ConPtyProcess::kill()
{
bool exitCode = false;
@@ -261,13 +261,13 @@ bool ConPtyAnonymousPipeProcess::kill()
return exitCode;
}
IPtyProcess::PtyType ConPtyAnonymousPipeProcess::type()
IPtyProcess::PtyType ConPtyProcess::type()
{
return PtyType::ConPty;
}
#ifdef PTYQT_DEBUG
QString ConPtyAnonymousPipeProcess::dumpDebugInfo()
QString ConPtyProcess::dumpDebugInfo()
{
return QString("PID: %1, Type: %2, Cols: %3, Rows: %4")
.arg(m_pid).arg(type())
@@ -275,25 +275,25 @@ QString ConPtyAnonymousPipeProcess::dumpDebugInfo()
}
#endif
QIODevice *ConPtyAnonymousPipeProcess::notifier()
QIODevice *ConPtyProcess::notifier()
{
return &m_buffer;
}
QByteArray ConPtyAnonymousPipeProcess::readAll()
QByteArray ConPtyProcess::readAll()
{
QMutexLocker locker(&m_bufferMutex);
return m_buffer.m_readBuffer;
}
qint64 ConPtyAnonymousPipeProcess::write(const QByteArray &byteArray)
qint64 ConPtyProcess::write(const QByteArray &byteArray)
{
DWORD dwBytesWritten{};
WriteFile(m_hPipeOut, byteArray.data(), byteArray.size(), &dwBytesWritten, NULL);
return dwBytesWritten;
}
bool ConPtyAnonymousPipeProcess::isAvailable()
bool ConPtyProcess::isAvailable()
{
#ifdef TOO_OLD_WINSDK
return false; //very importnant! ConPty can be built, but it doesn't work if built with old sdk and Win10 < 1903
+69 -3
View File
@@ -1,11 +1,14 @@
#ifndef CONPTY_SHARED_H
#define CONPTY_SHARED_H
#ifndef CONPTYPROCESS_H
#define CONPTYPROCESS_H
#include "iptyprocess.h"
#include <windows.h>
#include <process.h>
#include <QLibrary>
#include <stdio.h>
#include <QMutex>
#include <QTimer>
#include <QThread>
//Taken from the RS5 Windows SDK, but redefined here in case we're targeting <= 17733
//Just for compile, ConPty doesn't work with Windows SDK < 17733
@@ -92,4 +95,67 @@ private:
QString m_lastError;
};
#endif // CONPTY_SHARED_H
class PtyBuffer : public QIODevice
{
friend class ConPtyProcess;
Q_OBJECT
public:
PtyBuffer() { }
~PtyBuffer() { }
//just empty realization, we need only 'readyRead' signal of this class
qint64 readData(char *data, qint64 maxlen) { return 0; }
qint64 writeData(const char *data, qint64 len) { return 0; }
bool isSequential() { return true; }
qint64 bytesAvailable() { return m_readBuffer.size(); }
qint64 size() { return m_readBuffer.size(); }
void emitReadyRead()
{
//for emit signal from PtyBuffer own thread
QTimer::singleShot(1, this, [this]()
{
emit readyRead();
});
}
private:
QByteArray m_readBuffer;
};
class ConPtyProcess : public IPtyProcess
{
public:
ConPtyProcess();
~ConPtyProcess();
bool startProcess(const QString &shellPath, QStringList environment, qint16 cols, qint16 rows);
bool resize(qint16 cols, qint16 rows);
bool kill();
PtyType type();
#ifdef PTYQT_DEBUG
QString dumpDebugInfo();
#endif
virtual QIODevice *notifier();
virtual QByteArray readAll();
virtual qint64 write(const QByteArray &byteArray);
bool isAvailable();
private:
HRESULT createPseudoConsoleAndPipes(HPCON* phPC, HANDLE* phPipeIn, HANDLE* phPipeOut, qint16 cols, qint16 rows);
HRESULT initializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX* pStartupInfo, HPCON hPC);
private:
WindowsContext m_winContext;
HPCON m_ptyHandler;
HANDLE m_hPipeIn, m_hPipeOut;
QThread *m_readThread;
QMutex m_bufferMutex;
PtyBuffer m_buffer;
};
#endif // CONPTYPROCESS_H
+2 -33
View File
@@ -17,9 +17,8 @@ public:
{
UnixPty = 0,
WinPty = 1,
//ConPtyNamedPipe = 2,
ConPty = 3,
AutoPty = 4
ConPty = 2,
AutoPty = 3
};
IPtyProcess()
@@ -49,34 +48,4 @@ protected:
QPair<qint16, qint16> m_size; //cols / rows
};
#ifdef Q_OS_WIN
class IWindowsPtyProcess : public IPtyProcess
{
protected:
IWindowsPtyProcess()
: IPtyProcess()
{ }
QIODevice *notifier()
{
return &m_outSocket;
}
QByteArray readAll()
{
return m_outSocket.readAll();
}
qint64 write(const QByteArray &byteArray)
{
return m_inSocket.write(byteArray);
}
protected:
QString m_conInName;
QString m_conOutName;
QLocalSocket m_inSocket;
QLocalSocket m_outSocket;
};
#endif
#endif // IPTYPROCESS_H
+4 -8
View File
@@ -3,8 +3,7 @@
#ifdef Q_OS_WIN
#include "winptyprocess.h"
//#include "conptynamedpipeprocess.h"
#include "conptyanonymouspipeprocess.h"
#include "conptyprocess.h"
#endif
#ifdef Q_OS_UNIX
@@ -19,11 +18,8 @@ IPtyProcess *PtyQt::createPtyProcess(IPtyProcess::PtyType ptyType)
case IPtyProcess::PtyType::WinPty:
return new WinPtyProcess();
break;
// case IPtyProcess::PtyType::ConPtyNamedPipe:
// return new ConPtyNamedPipeProcess();
// break;
case IPtyProcess::PtyType::ConPty:
return new ConPtyAnonymousPipeProcess();
return new ConPtyProcess();
break;
#endif
#ifdef Q_OS_UNIX
@@ -37,8 +33,8 @@ IPtyProcess *PtyQt::createPtyProcess(IPtyProcess::PtyType ptyType)
}
#ifdef Q_OS_WIN
if (ConPtyAnonymousPipeProcess().isAvailable())
return new ConPtyAnonymousPipeProcess();
if (ConPtyProcess().isAvailable())
return new ConPtyProcess();
else
return new WinPtyProcess();
#endif
+16 -1
View File
@@ -16,7 +16,7 @@ QString castErrorToString(winpty_error_ptr_t error_ptr)
}
WinPtyProcess::WinPtyProcess()
: IWindowsPtyProcess()
: IPtyProcess()
, m_ptyHandler(nullptr)
, m_innerHandle(nullptr)
{
@@ -189,6 +189,21 @@ QString WinPtyProcess::dumpDebugInfo()
.arg(m_size.first).arg(m_size.second).arg(m_ptyHandler != nullptr)
.arg(m_shellPath);
}
QIODevice *WinPtyProcess::notifier()
{
return &m_outSocket;
}
QByteArray WinPtyProcess::readAll()
{
return m_outSocket.readAll();
}
qint64 WinPtyProcess::write(const QByteArray &byteArray)
{
return m_inSocket.write(byteArray);
}
#endif
bool WinPtyProcess::isAvailable()
+8 -1
View File
@@ -4,7 +4,7 @@
#include "iptyprocess.h"
#include "winpty.h"
class WinPtyProcess : public IWindowsPtyProcess
class WinPtyProcess : public IPtyProcess
{
public:
WinPtyProcess();
@@ -17,11 +17,18 @@ public:
#ifdef PTYQT_DEBUG
QString dumpDebugInfo();
#endif
QIODevice *notifier();
QByteArray readAll();
qint64 write(const QByteArray &byteArray);
bool isAvailable();
private:
winpty_t *m_ptyHandler;
HANDLE m_innerHandle;
QString m_conInName;
QString m_conOutName;
QLocalSocket m_inSocket;
QLocalSocket m_outSocket;
};
#endif // WINPTYPROCESS_H
-1
View File
@@ -193,7 +193,6 @@ private slots:
{
qDebug() << "Test" << shellPath;
IPtyProcess::PtyType ptyType = IPtyProcess::ConPty;
//ptyType = IPtyProcess::ConPtyNamedPipe;
QScopedPointer<IPtyProcess> conPty(PtyQt::createPtyProcess(ptyType));
QCOMPARE(conPty->type(), ptyType);
QVERIFY(conPty->isAvailable());