From a7138869a7d76d9413567cd28900d9338db2393e Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Sat, 30 Mar 2019 18:25:48 +0500 Subject: [PATCH] UI: AppUtil: Add getInfo(). --- src/ui/FortFirewall.pro | 3 +- src/ui/FortFirewall.rc | 4 +- src/ui/util/app/apputil.cpp | 78 ++++++++++++++++++++++++++++++++++--- src/ui/util/app/apputil.h | 16 +++++--- 4 files changed, 87 insertions(+), 14 deletions(-) diff --git a/src/ui/FortFirewall.pro b/src/ui/FortFirewall.pro index b0f3f315..e674c327 100644 --- a/src/ui/FortFirewall.pro +++ b/src/ui/FortFirewall.pro @@ -168,8 +168,9 @@ RESOURCES += db/migrations.qrc } # Windows -LIBS += -lfwpuclnt -lkernel32 -luser32 -luuid -lws2_32 +LIBS += -lfwpuclnt -lkernel32 -luser32 -luuid -lversion -lws2_32 RC_FILE = FortFirewall.rc +OTHER_FILES += $${RC_FILE} # Kernel Driver installer_build { diff --git a/src/ui/FortFirewall.rc b/src/ui/FortFirewall.rc index ab263540..c893c5fb 100644 --- a/src/ui/FortFirewall.rc +++ b/src/ui/FortFirewall.rc @@ -8,10 +8,10 @@ #define VER_PRODUCTVERSION VER_FILEVERSION #define VER_PRODUCTVERSION_STR APP_VERSION_STR -#define VER_COMPANYNAME_STR "Open Source Developer, Nodir Temirkhodjaev" +#define VER_COMPANYNAME_STR "Nodir Temirkhodjaev" #define VER_FILEDESCRIPTION_STR "Fort Firewall" #define VER_INTERNALNAME_STR "FortFirewall" -#define VER_LEGALCOPYRIGHT_STR "Copyright 2015 Nodir Temirkhodjaev" +#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 2015-2019 Nodir Temirkhodjaev. All Rights Reserved." #define VER_LEGALTRADEMARKS1_STR "" #define VER_LEGALTRADEMARKS2_STR "" #define VER_ORIGINALFILENAME_STR "FortFirewall.exe" diff --git a/src/ui/util/app/apputil.cpp b/src/ui/util/app/apputil.cpp index 04de8577..ff8b2297 100644 --- a/src/ui/util/app/apputil.cpp +++ b/src/ui/util/app/apputil.cpp @@ -31,8 +31,7 @@ static QPixmap pixmapFromImageList(int iImageList, const SHFILEINFO &info) static QPixmap extractShellIcon(const QString &appPath) { - const QString nativePath = QDir::toNativeSeparators(appPath); - const wchar_t *nativePathW = reinterpret_cast(nativePath.utf16()); + const wchar_t *appPathW = (LPCWSTR) appPath.utf16(); const UINT flags = SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES; @@ -41,7 +40,7 @@ static QPixmap extractShellIcon(const QString &appPath) SHFILEINFOW info; ZeroMemory(&info, sizeof(SHFILEINFOW)); - const HRESULT hr = SHGetFileInfoW(nativePathW, 0, &info, + const HRESULT hr = SHGetFileInfoW(appPathW, 0, &info, sizeof(SHFILEINFOW), flags); if (SUCCEEDED(hr)) { pixmap = pixmapFromImageList(SHIL_JUMBO, info); @@ -50,14 +49,83 @@ static QPixmap extractShellIcon(const QString &appPath) return pixmap; } +static QString extractInfoText(LPVOID infoData, const WORD *langInfo, + const WCHAR *name) +{ + WCHAR verStrName[128]; + wsprintfW(verStrName, L"\\StringFileInfo\\%04x%04x\\%s", + langInfo[0], langInfo[1], name); + + WCHAR *content; + UINT len; + if (VerQueryValueW(infoData, verStrName, + (LPVOID *) &content, &len) + && len > 1) { + return QString::fromWCharArray(content, len - 1); + } + + return QString(); } -AppUtil::AppUtil(QObject *parent) : - QObject(parent) +static bool extractAppInfo(const QString &appPath, AppInfo &appInfo) { + const wchar_t *appPathW = (LPCWSTR) appPath.utf16(); + + const DWORD flags = FILE_VER_GET_NEUTRAL | FILE_VER_GET_PREFETCHED; + + DWORD dummy; + const DWORD infoSize = GetFileVersionInfoSizeExW(flags, appPathW, &dummy); + if (infoSize == 0) + return false; + + QScopedArrayPointer infoBuf(new BYTE[infoSize]); + LPVOID infoData = infoBuf.data(); + + if (!GetFileVersionInfoExW(flags, appPathW, 0, infoSize, infoData)) + return false; + + // Product Version + { + VS_FIXEDFILEINFO *ffi; + if (!VerQueryValueA(infoData, "\\", (LPVOID *) &ffi, (PUINT) dummy)) + return false; + + const DWORD leftMost = HIWORD(ffi->dwProductVersionMS); + const DWORD secondLeft = LOWORD(ffi->dwProductVersionMS); + const DWORD secondRight = HIWORD(ffi->dwProductVersionLS); + const DWORD rightMost = LOWORD(ffi->dwProductVersionLS); + + appInfo.productVersion = QString("%1.%2.%3.%4").arg( + QString::number(leftMost), QString::number(secondLeft), + QString::number(secondRight), QString::number(rightMost)); + + if (rightMost == 0) { + appInfo.productVersion.chop(2); + } + } + + // Language info + WORD *langInfo; + if (!VerQueryValueA(infoData, "\\VarFileInfo\\Translation", + (LPVOID *) &langInfo, (PUINT) dummy)) + return false; + + // Texts + appInfo.productName = extractInfoText(infoData, langInfo, L"ProductName"); + appInfo.companyName = extractInfoText(infoData, langInfo, L"CompanyName"); + appInfo.fileDescription = extractInfoText(infoData, langInfo, L"FileDescription"); + + return true; +} + } QPixmap AppUtil::getIcon(const QString &appPath) { return extractShellIcon(appPath); } + +bool AppUtil::getInfo(const QString &appPath, AppInfo &appInfo) +{ + return extractAppInfo(appPath, appInfo); +} diff --git a/src/ui/util/app/apputil.h b/src/ui/util/app/apputil.h index 68c1325b..d8fb4ad2 100644 --- a/src/ui/util/app/apputil.h +++ b/src/ui/util/app/apputil.h @@ -4,14 +4,18 @@ #include #include -class AppUtil : public QObject +typedef struct AppInfo { + QString fileDescription; + QString companyName; + QString productName; + QString productVersion; +} AppInfo; + +class AppUtil { - Q_OBJECT - public: - explicit AppUtil(QObject *parent = nullptr); - - Q_INVOKABLE static QPixmap getIcon(const QString &appPath); + static QPixmap getIcon(const QString &appPath); + static bool getInfo(const QString &appPath, AppInfo &appInfo); }; #endif // APPUTIL_H