diff --git a/src/tests/FortFirewallTest.pro b/src/tests/FortFirewallTest.pro index 1963616f..ede4b70f 100644 --- a/src/tests/FortFirewallTest.pro +++ b/src/tests/FortFirewallTest.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ + fileutil \ logbuffer diff --git a/src/tests/fileutil/FileUtil.pro b/src/tests/fileutil/FileUtil.pro new file mode 100644 index 00000000..61197fa1 --- /dev/null +++ b/src/tests/fileutil/FileUtil.pro @@ -0,0 +1,9 @@ +include(../common/Test.pri) + +SOURCES += \ + $$UIPATH/util/fileutil.cpp \ + $$UIPATH/util/processinfo.cpp + +HEADERS += \ + $$UIPATH/util/fileutil.h \ + $$UIPATH/util/processinfo.h diff --git a/src/tests/fileutil/test.cpp b/src/tests/fileutil/test.cpp new file mode 100644 index 00000000..e1d075a8 --- /dev/null +++ b/src/tests/fileutil/test.cpp @@ -0,0 +1,30 @@ +#include "test.h" + +#include + +#include "util/fileutil.h" +#include "util/processinfo.h" + +void Test::paths() +{ + const QString driveC("C:"); + const QString dosNameC("\\Device\\HarddiskVolume1"); + const QString subPath("\\test\\"); + + const QString path = driveC + subPath; + const QString dosPath = dosNameC + subPath; + + QCOMPARE(FileUtil::dosNameToDrive(dosNameC), driveC); + QCOMPARE(FileUtil::driveToDosName(driveC), dosNameC); + + QCOMPARE(FileUtil::dosPathToPath(dosPath), path); + QCOMPARE(FileUtil::pathToDosPath(path), dosPath); +} + +void Test::process() +{ + const ProcessInfo pi(ProcessInfo::currentPid()); + + QVERIFY(pi.isValid()); + QVERIFY(!pi.dosPath().isEmpty()); +} diff --git a/src/tests/fileutil/test.h b/src/tests/fileutil/test.h new file mode 100644 index 00000000..74e28fdf --- /dev/null +++ b/src/tests/fileutil/test.h @@ -0,0 +1,15 @@ +#ifndef TEST_H +#define TEST_H + +#include + +class Test : public QObject +{ + Q_OBJECT + +private slots: + void paths(); + void process(); +}; + +#endif // TEST_H diff --git a/src/ui/FortFirewall.pro b/src/ui/FortFirewall.pro index a2aa0a8a..704f2106 100644 --- a/src/ui/FortFirewall.pro +++ b/src/ui/FortFirewall.pro @@ -11,12 +11,16 @@ SOURCES += \ main.cpp \ firewallLog/logbuffer.cpp \ firewallLog/logentry.cpp \ - fortcommon.cpp + fortcommon.cpp \ + util/fileutil.cpp \ + util/processinfo.cpp HEADERS += \ firewallLog/logbuffer.h \ firewallLog/logentry.h \ - fortcommon.h + fortcommon.h \ + util/fileutil.h \ + util/processinfo.h QML_FILES += \ qml/*.qml @@ -35,7 +39,7 @@ RESOURCES += fort_i18n.qrc RESOURCES += fort_ini.qrc # Windows -LIBS += -lfwpuclnt -lkernel32 -luser32 -luuid +LIBS += -lfwpuclnt -lkernel32 -lpsapi -luser32 -luuid RC_FILE = fort.rc # Kernel Driver diff --git a/src/ui/util/fileutil.cpp b/src/ui/util/fileutil.cpp new file mode 100644 index 00000000..a79c7e69 --- /dev/null +++ b/src/ui/util/fileutil.cpp @@ -0,0 +1,70 @@ +#include "fileutil.h" + +#include + +#define WIN32_LEAN_AND_MEAN +#include + +FileUtil::FileUtil(QObject *parent) : + QObject(parent) +{ + Q_ASSERT(sizeof(wchar_t) == sizeof(QChar)); +} + +// Convert "\\Device\\HarddiskVolume1" to "C:" +QString FileUtil::dosNameToDrive(const QString &dosName) +{ + const QString dosNameLower = dosName.toLower(); + + foreach (const QFileInfo &fi, QDir::drives()) { + const QString driveName = fi.path().left(2); + const QString driveDosName = driveToDosName(driveName); + + if (dosNameLower == driveDosName.toLower()) { + return driveName; + } + } + return QString(); +} + +// Convert "C:" to "\\Device\\HarddiskVolume1" +QString FileUtil::driveToDosName(const QString &drive) +{ + char driveName[3] = {drive.at(0).toLatin1(), ':', '\0'}; + + char buf[MAX_PATH]; + const int len = QueryDosDeviceA((LPCSTR) driveName, + buf, MAX_PATH); + + return (len > 0) ? QString::fromLatin1(buf) + : QString(); +} + +// Convert "\\Device\\HarddiskVolume1\\path" to "C:\\path" +QString FileUtil::dosPathToPath(const QString &dosPath) +{ + const QLatin1Char sep('\\'); + + if (dosPath.startsWith(sep)) { + const int sepPos1 = dosPath.indexOf(sep, 1); + if (sepPos1 > 0) { + const int sepPos2 = dosPath.indexOf(sep, sepPos1 + 1); + if (sepPos2 > 0) { + const QString dosName = dosPath.left(sepPos2); + return dosNameToDrive(dosName) + dosPath.mid(sepPos2); + } + } + } + return dosPath; +} + +// Convert "C:\\path" to "\\Device\\HarddiskVolume1\\path" +QString FileUtil::pathToDosPath(const QString &path) +{ + const QString drive = path.left(2); + + if (drive.at(0).isLetter() && drive.at(1) == QLatin1Char(':')) { + return driveToDosName(drive) + path.mid(2); + } + return path; +} diff --git a/src/ui/util/fileutil.h b/src/ui/util/fileutil.h new file mode 100644 index 00000000..ed299915 --- /dev/null +++ b/src/ui/util/fileutil.h @@ -0,0 +1,29 @@ +#ifndef FILEUTIL_H +#define FILEUTIL_H + +#include +#include + +class FileUtil : public QObject +{ + Q_OBJECT + +public: + explicit FileUtil(QObject *parent = nullptr); + + // Convert DOS device name to drive letter (A: .. Z:) + static QString dosNameToDrive(const QString &dosName); + + // Convert drive letter (A: .. Z:) to DOS device name + static QString driveToDosName(const QString &drive); + + // Convert Native path to Win32 path + static QString dosPathToPath(const QString &dosPath); + + // Convert Win32 path to Native path + static QString pathToDosPath(const QString &path); + +private: +}; + +#endif // FILEUTIL_H diff --git a/src/ui/util/processinfo.cpp b/src/ui/util/processinfo.cpp new file mode 100644 index 00000000..6f8e03c4 --- /dev/null +++ b/src/ui/util/processinfo.cpp @@ -0,0 +1,63 @@ +#include "processinfo.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include /* GetProcessImageFileName */ + +#define PROC_PATH_MAX 65536 + +ProcessInfo::ProcessInfo(quint32 pid, QObject *parent) : + QObject(parent), + m_pid(pid), + m_handle(PROC_INVALID_HANDLE) +{ + openProcess(); +} + +ProcessInfo::~ProcessInfo() +{ + closeProcess(); +} + +quint32 ProcessInfo::currentPid() +{ + return GetCurrentProcessId(); +} + +void ProcessInfo::openProcess() +{ + if (m_pid == PROC_INVALID_PID) + return; + + if (m_pid == currentPid()) { + m_handle = GetCurrentProcess(); + } else { + const DWORD access = (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ); + + m_handle = OpenProcess(access, FALSE, m_pid); + } +} + +void ProcessInfo::closeProcess() +{ + if (isValid()) { + CloseHandle(m_handle); + m_handle = PROC_INVALID_HANDLE; + } +} + +QString ProcessInfo::dosPath() const +{ + if (isValid()) { + QByteArray buf(PROC_PATH_MAX * sizeof(wchar_t), Qt::Uninitialized); + wchar_t *p = (wchar_t *) buf.data(); + + const DWORD len = GetProcessImageFileNameW( + m_handle, (LPWSTR) p, PROC_PATH_MAX); + if (len) { + return QString::fromWCharArray(p, len); + } + } + + return QString(); +} diff --git a/src/ui/util/processinfo.h b/src/ui/util/processinfo.h new file mode 100644 index 00000000..4dad59ef --- /dev/null +++ b/src/ui/util/processinfo.h @@ -0,0 +1,44 @@ +#ifndef PROCESSINFO_H +#define PROCESSINFO_H + +#include + +typedef void *phandle_t; + +#define PROC_INVALID_PID -1 +#define PROC_INVALID_HANDLE nullptr + +class ProcessInfo : public QObject +{ + Q_OBJECT + Q_PROPERTY(quint32 pid READ pid CONSTANT) + +public: + explicit ProcessInfo(quint32 pid = PROC_INVALID_PID, + QObject *parent = nullptr); + virtual ~ProcessInfo(); + + quint32 pid() const { return m_pid; } + + bool isValid() const { + return m_pid != PROC_INVALID_PID + && m_handle != PROC_INVALID_HANDLE; + } + + static quint32 currentPid(); + +signals: + +public slots: + QString dosPath() const; + +private: + void openProcess(); + void closeProcess(); + +private: + quint32 m_pid; + phandle_t m_handle; +}; + +#endif // PROCESSINFO_H