|
19 | 19 |
|
20 | 20 | #include "Common.h" |
21 | 21 |
|
| 22 | +#include <QtCore/QCoreApplication> |
| 23 | +#include <QtCore/QDir> |
22 | 24 | #include <QtCore/QOperatingSystemVersion> |
23 | 25 | #include <QtCore/QSettings> |
| 26 | +#include <QtCore/QStandardPaths> |
| 27 | +#include <QtCore/QThread> |
| 28 | +#include <QtNetwork/QLocalServer> |
| 29 | +#include <QtNetwork/QLocalSocket> |
| 30 | + |
| 31 | +#include <chrono> |
| 32 | + |
| 33 | +using namespace std::chrono_literals; |
24 | 34 |
|
25 | 35 | #ifdef Q_OS_WIN |
26 | 36 | #include <qt_windows.h> |
27 | 37 | #include <Regstr.h> |
28 | 38 | #include <Setupapi.h> |
29 | 39 |
|
30 | 40 | using namespace Qt::StringLiterals; |
31 | | -#elif defined(Q_OS_MAC) |
| 41 | +#elifdef Q_OS_MAC |
32 | 42 | #include <PCSC/wintypes.h> |
33 | 43 | #include <PCSC/winscard.h> |
34 | 44 | #include <arpa/inet.h> |
@@ -73,7 +83,7 @@ QStringList Common::drivers() |
73 | 83 | { |
74 | 84 | QStringList list; |
75 | 85 | #ifdef Q_OS_WIN |
76 | | - GUID guid {0x50dd5230L, 0xba8a, 0x11d1, 0xbf, 0x5d, 0x00, 0x00, 0xf8, 0x05, 0xf5, 0x30}; // SmartCardReader |
| 86 | + static const GUID guid {0x50dd5230L, 0xba8a, 0x11d1, 0xbf, 0x5d, 0x00, 0x00, 0xf8, 0x05, 0xf5, 0x30}; // SmartCardReader |
77 | 87 | HDEVINFO h = SetupDiGetClassDevs(&guid, nullptr, 0, DIGCF_PRESENT); |
78 | 88 | if(!h) |
79 | 89 | return list; |
@@ -111,8 +121,56 @@ QStringList Common::drivers() |
111 | 121 | if(SCardListReaders(context, nullptr, data.data(), &size) != SCARD_S_SUCCESS) |
112 | 122 | data.clear(); |
113 | 123 | SCardReleaseContext(context); |
114 | | - list = QString::fromLatin1(data).split('\0'); |
115 | | - list.removeAll({}); |
| 124 | + for(const char *name = data.data(); *name; name += std::char_traits<char>::length(name) + 1) |
| 125 | + list.append(QString::fromLatin1(name)); |
116 | 126 | #endif |
117 | 127 | return list; |
118 | 128 | } |
| 129 | + |
| 130 | +static QString serverName() |
| 131 | +{ |
| 132 | +#ifdef Q_OS_WIN |
| 133 | + return QCoreApplication::applicationName(); |
| 134 | +#else |
| 135 | + QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); |
| 136 | + if(runtimeDir.isEmpty()) |
| 137 | + runtimeDir = QDir::tempPath(); |
| 138 | + return runtimeDir + QLatin1Char('/') + QCoreApplication::applicationName(); |
| 139 | +#endif |
| 140 | +} |
| 141 | + |
| 142 | +bool Common::sendLocalMessage(const QStringList &args) |
| 143 | +{ |
| 144 | + QLocalSocket socket; |
| 145 | + int timeout = 5000; |
| 146 | + for(int i = 0; i < 2; i++) { |
| 147 | + socket.connectToServer(serverName(), QLocalSocket::WriteOnly); |
| 148 | + if(socket.waitForConnected(timeout/2)) |
| 149 | + break; |
| 150 | + if(i) |
| 151 | + return false; |
| 152 | + QThread::sleep(250ms); |
| 153 | + } |
| 154 | + QDataStream ds(&socket); |
| 155 | + ds << args; |
| 156 | + return socket.waitForBytesWritten(timeout); |
| 157 | +} |
| 158 | + |
| 159 | +bool Common::startLocalServer(QObject *parent, std::function<void (const QStringList&)> f) |
| 160 | +{ |
| 161 | + auto *server = new QLocalServer(parent); |
| 162 | + QObject::connect(server, &QLocalServer::newConnection, parent, [server, parent, f = std::move(f)] { |
| 163 | + while(QLocalSocket *socket = server->nextPendingConnection()) |
| 164 | + { |
| 165 | + QObject::connect(socket, &QLocalSocket::readyRead, parent, [socket, f = std::move(f)] { |
| 166 | + QDataStream ds(socket); |
| 167 | + QStringList args; |
| 168 | + ds >> args; |
| 169 | + socket->waitForDisconnected(1000); |
| 170 | + socket->deleteLater(); |
| 171 | + f(args); |
| 172 | + }); |
| 173 | + } |
| 174 | + }); |
| 175 | + return server->listen(serverName()); |
| 176 | +} |
0 commit comments