Skip to content

Commit 628e228

Browse files
authored
Merge pull request #1085 from amnezia-vpn/bugfix/win_check_ps
Refactoring wmic to winapi
2 parents 17984ad + c9cd860 commit 628e228

File tree

4 files changed

+128
-60
lines changed

4 files changed

+128
-60
lines changed

client/ui/controllers/connectionController.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
3434

3535
void ConnectionController::openConnection()
3636
{
37-
// #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
38-
// if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true))
39-
// {
40-
// emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning);
41-
// return;
42-
// }
43-
// #endif
37+
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
38+
if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true))
39+
{
40+
emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning);
41+
return;
42+
}
43+
#endif
4444

4545
int serverIndex = m_serversModel->getDefaultServerIndex();
4646
QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex);

client/ui/controllers/installController.cpp

100644100755
+1-26
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,6 @@ namespace
3434
constexpr char apiConfig[] = "api_config";
3535
constexpr char authData[] = "auth_data";
3636
}
37-
38-
#ifdef Q_OS_WINDOWS
39-
QString getNextDriverLetter()
40-
{
41-
QProcess drivesProc;
42-
drivesProc.start("wmic logicaldisk get caption");
43-
drivesProc.waitForFinished();
44-
QString drives = drivesProc.readAll();
45-
qDebug() << drives;
46-
47-
QString letters = "CFGHIJKLMNOPQRSTUVWXYZ";
48-
QString letter;
49-
for (int i = letters.size() - 1; i > 0; i--) {
50-
letter = letters.at(i);
51-
if (!drives.contains(letter + ":"))
52-
break;
53-
}
54-
if (letter == "C:") {
55-
// set err info
56-
qDebug() << "Can't find free drive letter";
57-
return "";
58-
}
59-
return letter;
60-
}
61-
#endif
6237
}
6338

6439
InstallController::InstallController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
@@ -668,7 +643,7 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
668643
QString hostname = serverCredentials.hostName;
669644

670645
#ifdef Q_OS_WINDOWS
671-
mountPath = getNextDriverLetter() + ":";
646+
mountPath = Utils::getNextDriverLetter() + ":";
672647
// QString cmd = QString("net use \\\\sshfs\\%[email protected]!%2 /USER:%1 %3")
673648
// .arg(labelTftpUserNameText())
674649
// .arg(labelTftpPortText())

client/utilities.cpp

100644100755
+116-25
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,62 @@
1010
#include <QJsonObject>
1111

1212
#include "utilities.h"
13-
#include "version.h"
13+
14+
#ifdef Q_OS_WINDOWS
15+
QString printErrorMessage(DWORD errorCode) {
16+
LPVOID lpMsgBuf;
17+
18+
DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
19+
FORMAT_MESSAGE_FROM_SYSTEM |
20+
FORMAT_MESSAGE_IGNORE_INSERTS;
21+
22+
DWORD dwLanguageId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
23+
24+
FormatMessageW(
25+
dwFlags,
26+
NULL,
27+
errorCode,
28+
dwLanguageId,
29+
(LPWSTR)&lpMsgBuf,
30+
0,
31+
NULL
32+
);
33+
34+
QString errorMsg = QString::fromWCharArray((LPCWSTR)lpMsgBuf);
35+
LocalFree(lpMsgBuf);
36+
return errorMsg.trimmed();
37+
}
38+
39+
QString Utils::getNextDriverLetter()
40+
{
41+
DWORD drivesBitmask = GetLogicalDrives();
42+
if (drivesBitmask == 0) {
43+
DWORD error = GetLastError();
44+
qDebug() << "GetLogicalDrives failed. Error code:" << error;
45+
return "";
46+
}
47+
48+
QString letters = "FGHIJKLMNOPQRSTUVWXYZ";
49+
QString availableLetter;
50+
51+
for (int i = letters.size() - 1; i >= 0; --i) {
52+
QChar letterChar = letters.at(i);
53+
int driveIndex = letterChar.toLatin1() - 'A';
54+
55+
if ((drivesBitmask & (1 << driveIndex)) == 0) {
56+
availableLetter = letterChar;
57+
break;
58+
}
59+
}
60+
61+
if (availableLetter.isEmpty()) {
62+
qDebug() << "Can't find free drive letter";
63+
return "";
64+
}
65+
66+
return availableLetter;
67+
}
68+
#endif
1469

1570
QString Utils::getRandomString(int len)
1671
{
@@ -108,30 +163,34 @@ QString Utils::usrExecutable(const QString &baseName)
108163
bool Utils::processIsRunning(const QString &fileName, const bool fullFlag)
109164
{
110165
#ifdef Q_OS_WIN
111-
QProcess process;
112-
process.setReadChannel(QProcess::StandardOutput);
113-
process.setProcessChannelMode(QProcess::MergedChannels);
114-
process.start("wmic.exe",
115-
QStringList() << "/OUTPUT:STDOUT"
116-
<< "PROCESS"
117-
<< "get"
118-
<< "Caption");
119-
process.waitForStarted();
120-
process.waitForFinished();
121-
QString processData(process.readAll());
122-
QStringList processList = processData.split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts);
123-
foreach (const QString &rawLine, processList) {
124-
const QString line = rawLine.simplified();
125-
if (line.isEmpty()) {
126-
continue;
127-
}
166+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
167+
if (hSnapshot == INVALID_HANDLE_VALUE) {
168+
qWarning() << "Utils::processIsRunning error CreateToolhelp32Snapshot";
169+
return false;
170+
}
171+
172+
PROCESSENTRY32W pe32;
173+
pe32.dwSize = sizeof(PROCESSENTRY32W);
174+
175+
if (!Process32FirstW(hSnapshot, &pe32)) {
176+
CloseHandle(hSnapshot);
177+
qWarning() << "Utils::processIsRunning error Process32FirstW";
178+
return false;
179+
}
180+
181+
do {
182+
QString exeFile = QString::fromWCharArray(pe32.szExeFile);
128183

129-
if (line == fileName) {
184+
if (exeFile.compare(fileName, Qt::CaseInsensitive) == 0) {
185+
CloseHandle(hSnapshot);
130186
return true;
131187
}
132-
}
188+
} while (Process32NextW(hSnapshot, &pe32));
189+
190+
CloseHandle(hSnapshot);
133191
return false;
134-
#elif defined(Q_OS_IOS)
192+
193+
#elif defined(Q_OS_IOS) || defined(Q_OS_ANDROID)
135194
return false;
136195
#else
137196
QProcess process;
@@ -149,13 +208,45 @@ bool Utils::processIsRunning(const QString &fileName, const bool fullFlag)
149208
#endif
150209
}
151210

152-
void Utils::killProcessByName(const QString &name)
211+
bool Utils::killProcessByName(const QString &name)
153212
{
154213
qDebug().noquote() << "Kill process" << name;
155214
#ifdef Q_OS_WIN
156-
QProcess::execute("taskkill", QStringList() << "/IM" << name << "/F");
157-
#elif defined Q_OS_IOS
158-
return;
215+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
216+
if (hSnapshot == INVALID_HANDLE_VALUE)
217+
return false;
218+
219+
PROCESSENTRY32W pe32;
220+
pe32.dwSize = sizeof(PROCESSENTRY32W);
221+
222+
bool success = false;
223+
224+
if (Process32FirstW(hSnapshot, &pe32)) {
225+
do {
226+
QString exeFile = QString::fromWCharArray(pe32.szExeFile);
227+
228+
if (exeFile.compare(name, Qt::CaseInsensitive) == 0) {
229+
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
230+
if (hProcess != NULL) {
231+
if (TerminateProcess(hProcess, 0)) {
232+
success = true;
233+
} else {
234+
DWORD error = GetLastError();
235+
qCritical() << "Can't terminate process" << exeFile << "(PID:" << pe32.th32ProcessID << "). Error:" << printErrorMessage(error);
236+
}
237+
CloseHandle(hProcess);
238+
} else {
239+
DWORD error = GetLastError();
240+
qCritical() << "Can't open process for termination" << exeFile << "(PID:" << pe32.th32ProcessID << "). Error:" << printErrorMessage(error);
241+
}
242+
}
243+
} while (Process32NextW(hSnapshot, &pe32));
244+
}
245+
246+
CloseHandle(hSnapshot);
247+
return success;
248+
#elif defined Q_OS_IOS || defined(Q_OS_ANDROID)
249+
return false;
159250
#else
160251
QProcess::execute(QString("pkill %1").arg(name));
161252
#endif

client/utilities.h

100644100755
+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
#include <QJsonDocument>
88

99
#ifdef Q_OS_WIN
10-
#include "Windows.h"
10+
#include <windows.h>
11+
#include <tlhelp32.h>
1112
#endif
1213

1314
class Utils : public QObject
@@ -27,7 +28,7 @@ class Utils : public QObject
2728
static bool initializePath(const QString &path);
2829

2930
static bool processIsRunning(const QString &fileName, const bool fullFlag = false);
30-
static void killProcessByName(const QString &name);
31+
static bool killProcessByName(const QString &name);
3132

3233
static QString openVpnExecPath();
3334
static QString wireguardExecPath();
@@ -39,6 +40,7 @@ class Utils : public QObject
3940

4041
#ifdef Q_OS_WIN
4142
static bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent);
43+
static QString getNextDriverLetter();
4244
#endif
4345
};
4446

0 commit comments

Comments
 (0)