From 7f5d618eba1e60c0a6cdb9c1832318fa85c6cb55 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Sun, 22 Nov 2015 21:45:09 +0100 Subject: [PATCH] Some code refactoring: Dynamic loading of DLL functions is now handled at a centralized place. --- MUtilities_VS2015.vcxproj | 2 + MUtilities_VS2015.vcxproj.filters | 6 ++ src/CPUFeatures_Win32.cpp | 7 +- src/GUI.cpp | 8 ++- src/OSSupport_Win32.cpp | 140 +++++++------------------------------- src/Terminal_Win32.cpp | 2 +- src/Utils_Win32.cpp | 115 +++++++++++++++++++++++++++++++ src/Utils_Win32.h | 29 +++----- 8 files changed, 171 insertions(+), 138 deletions(-) create mode 100644 src/Utils_Win32.cpp diff --git a/MUtilities_VS2015.vcxproj b/MUtilities_VS2015.vcxproj index 9181bc0..793ef1e 100644 --- a/MUtilities_VS2015.vcxproj +++ b/MUtilities_VS2015.vcxproj @@ -38,6 +38,7 @@ + @@ -62,6 +63,7 @@ + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)" MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" diff --git a/MUtilities_VS2015.vcxproj.filters b/MUtilities_VS2015.vcxproj.filters index 1bcd39b..33c5c99 100644 --- a/MUtilities_VS2015.vcxproj.filters +++ b/MUtilities_VS2015.vcxproj.filters @@ -99,6 +99,9 @@ Source Files + + Source Files + @@ -170,6 +173,9 @@ Public Headers + + Header Files + diff --git a/src/CPUFeatures_Win32.cpp b/src/CPUFeatures_Win32.cpp index 336ef84..9b6eb43 100644 --- a/src/CPUFeatures_Win32.cpp +++ b/src/CPUFeatures_Win32.cpp @@ -26,6 +26,7 @@ //MUtils #include #include +#include "Utils_Win32.h" //Qt #include @@ -94,11 +95,11 @@ MUtils::CPUFetaures::cpu_info_t MUtils::CPUFetaures::detect(void) if(strlen(features.vendor) < 1) strncpy_s(features.vendor, 0x40, "Unknown", _TRUNCATE); #if (!(defined(_M_X64) || defined(_M_IA64))) - QLibrary Kernel32Lib("kernel32.dll"); - if(IsWow64ProcessFun IsWow64ProcessPtr = (IsWow64ProcessFun) Kernel32Lib.resolve("IsWow64Process")) + const IsWow64ProcessFun isWow64ProcessPtr = MUtils::Win32Utils::resolve(QLatin1String("kernel32"), QLatin1String("IsWow64Process")); + if(isWow64ProcessPtr) { BOOL x64flag = FALSE; - if(IsWow64ProcessPtr(GetCurrentProcess(), &x64flag)) + if(isWow64ProcessPtr(GetCurrentProcess(), &x64flag)) { features.x64 = (x64flag == TRUE); } diff --git a/src/GUI.cpp b/src/GUI.cpp index 002ae4f..3284fcf 100644 --- a/src/GUI.cpp +++ b/src/GUI.cpp @@ -32,6 +32,12 @@ #include #include +//Win32 API +#ifndef _INC_WINDOWS +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif //_INC_WINDOWS + /////////////////////////////////////////////////////////////////////////////// // BROADCAST /////////////////////////////////////////////////////////////////////////////// @@ -109,7 +115,7 @@ bool MUtils::GUI::set_window_icon(QWidget *const window, const QIcon &icon, cons if((!icon.isNull()) && window->winId()) { const int extend = (bIsBigIcon ? 32 : 16); - if(HICON hIcon = qicon_to_hicon(icon, extend, extend)) + if(HICON hIcon = (HICON) MUtils::Win32Utils::qicon_to_hicon(icon, extend, extend)) { if(new Internal::WindowIconHelper(window, hIcon, bIsBigIcon)) { diff --git a/src/OSSupport_Win32.cpp b/src/OSSupport_Win32.cpp index 133f3ad..88e32cb 100644 --- a/src/OSSupport_Win32.cpp +++ b/src/OSSupport_Win32.cpp @@ -40,6 +40,7 @@ #include #include #include "CriticalSection_Win32.h" +#include "Utils_Win32.h" //Qt #include @@ -486,17 +487,8 @@ static QReadWriteLock g_wine_lock; static const bool detect_wine(void) { - bool is_wine = false; - - QLibrary ntdll("ntdll.dll"); - if(ntdll.load()) - { - if(ntdll.resolve("wine_nt_to_unix_file_name") != NULL) is_wine = true; - if(ntdll.resolve("wine_get_version") != NULL) is_wine = true; - ntdll.unload(); - } - - return is_wine; + void *const ptr = MUtils::Win32Utils::resolve(QLatin1String("ntdll"), QLatin1String("wine_get_version")); + return (ptr != NULL); } const bool &MUtils::OS::running_on_wine(void) @@ -531,11 +523,9 @@ const bool &MUtils::OS::running_on_wine(void) typedef QMap KFMap; typedef HRESULT (WINAPI *SHGetKnownFolderPath_t)(const GUID &rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath); -typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath); +typedef HRESULT (WINAPI *SHGetFolderPath_t) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath); static QScopedPointer g_known_folders_map; -static SHGetKnownFolderPath_t g_known_folders_fpGetKnownFolderPath; -static SHGetFolderPath_t g_known_folders_fpGetFolderPath; static QReadWriteLock g_known_folders_lock; const QString &MUtils::OS::known_folder(known_folder_t folder_id) @@ -598,22 +588,16 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id) //Initialize on first call if(g_known_folders_map.isNull()) { - QLibrary shell32("shell32.dll"); - if(shell32.load()) - { - g_known_folders_fpGetFolderPath = (SHGetFolderPath_t) shell32.resolve("SHGetFolderPathW"); - g_known_folders_fpGetKnownFolderPath = (SHGetKnownFolderPath_t) shell32.resolve("SHGetKnownFolderPath"); - } g_known_folders_map.reset(new QMap()); } QString folderPath; //Now try to get the folder path! - if(g_known_folders_fpGetKnownFolderPath) + if(const SHGetKnownFolderPath_t known_folders_fpGetKnownFolderPath = MUtils::Win32Utils::resolve(QLatin1String("shell32"), QLatin1String("SHGetKnownFolderPath"))) { WCHAR *path = NULL; - if(g_known_folders_fpGetKnownFolderPath(s_folders[folderId].guid, KF_FLAG_CREATE, NULL, &path) == S_OK) + if(known_folders_fpGetKnownFolderPath(s_folders[folderId].guid, KF_FLAG_CREATE, NULL, &path) == S_OK) { //MessageBoxW(0, path, L"SHGetKnownFolderPath", MB_TOPMOST); QDir folderTemp = QDir(QDir::fromNativeSeparators(MUTILS_QSTR(path))); @@ -624,10 +608,10 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id) CoTaskMemFree(path); } } - else if(g_known_folders_fpGetFolderPath) + else if(const SHGetFolderPath_t known_folders_fpGetFolderPath = MUtils::Win32Utils::resolve(QLatin1String("shell32"), QLatin1String("SHGetFolderPathW"))) { QScopedArrayPointer path(new WCHAR[4096]); - if(g_known_folders_fpGetFolderPath(NULL, s_folders[folderId].csidl | CSIDL_FLAG_CREATE, NULL, NULL, path.data()) == S_OK) + if(known_folders_fpGetFolderPath(NULL, s_folders[folderId].csidl | CSIDL_FLAG_CREATE, NULL, NULL, path.data()) == S_OK) { //MessageBoxW(0, path, L"SHGetFolderPathW", MB_TOPMOST); QDir folderTemp = QDir(QDir::fromNativeSeparators(MUTILS_QSTR(path.data()))); @@ -721,10 +705,6 @@ quint64 MUtils::OS::current_file_time(void) typedef DWORD(_stdcall *GetPathNameByHandleFun)(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags); -static QReadWriteLock g_getFilePath_lock; -static QScopedPointer g_getFilePath_kernel32; -static GetPathNameByHandleFun g_getFilePath_prt = NULL; - static QString get_file_path_drive_list(void) { QString list; @@ -797,55 +777,24 @@ static QString get_file_path_fallback(const HANDLE &hFile) return filePath; } -static bool get_file_path_init() -{ - QWriteLocker writeLock(&g_getFilePath_lock); - if (g_getFilePath_prt) - { - return true; /*already initialized*/ - } - - if (g_getFilePath_kernel32.isNull()) - { - g_getFilePath_kernel32.reset(new QLibrary("kernel32.dll")); - } - - if (!g_getFilePath_kernel32->isLoaded()) - { - if (!g_getFilePath_kernel32->load()) - { - return false; /*faild to load kernel32.dll*/ - } - } - - g_getFilePath_prt = (GetPathNameByHandleFun) g_getFilePath_kernel32->resolve("GetFinalPathNameByHandleW"); - return (g_getFilePath_prt != NULL); -} - QString MUtils::OS::get_file_path(const int &fd) { if (fd >= 0) { - QReadLocker readLock(&g_getFilePath_lock); - - if (!g_getFilePath_prt) + const GetPathNameByHandleFun getPathNameByHandleFun = MUtils::Win32Utils::resolve(QLatin1String("kernel32"), QLatin1String("GetFinalPathNameByHandleW")); + if (!getPathNameByHandleFun) { - readLock.unlock(); - if (!get_file_path_init()) - { - qWarning("MUtils::OS::get_file_path() --> fallback!"); - return get_file_path_fallback((HANDLE)_get_osfhandle(fd)); - } - readLock.relock(); + qWarning("MUtils::OS::get_file_path() --> fallback!"); + return get_file_path_fallback((HANDLE)_get_osfhandle(fd)); } const HANDLE handle = (HANDLE) _get_osfhandle(fd); - const DWORD len = g_getFilePath_prt(handle, NULL, 0, FILE_NAME_OPENED); + const DWORD len = getPathNameByHandleFun(handle, NULL, 0, FILE_NAME_OPENED); if (len > 0) { if (wchar_t *const buffer = (wchar_t*)_malloca(sizeof(wchar_t) * len)) { - const DWORD ret = g_getFilePath_prt(handle, buffer, len, FILE_NAME_OPENED); + const DWORD ret = getPathNameByHandleFun(handle, buffer, len, FILE_NAME_OPENED); if ((ret > 0) && (ret < len)) { const QString path(MUTILS_QSTR(buffer)); @@ -1414,67 +1363,28 @@ void MUtils::OS::shell_change_notification(void) typedef BOOL (_stdcall *Wow64DisableWow64FsRedirectionFun)(void *OldValue); typedef BOOL (_stdcall *Wow64RevertWow64FsRedirectionFun )(void *OldValue); -static QReadWriteLock g_wow64redir_lock; -static QScopedPointer g_wow64redir_kernel32; -static Wow64DisableWow64FsRedirectionFun g_wow64redir_disable = NULL; -static Wow64RevertWow64FsRedirectionFun g_wow64redir_revert = NULL; - -static bool wow64fsredir_init() +bool MUtils::OS::wow64fsredir_disable(void *oldValue) { - QWriteLocker writeLock(&g_wow64redir_lock); - if(g_wow64redir_disable && g_wow64redir_revert) - { - return true; /*already initialized*/ - } - - if(g_wow64redir_kernel32.isNull()) + const Wow64DisableWow64FsRedirectionFun wow64redir_disable = MUtils::Win32Utils::resolve(QLatin1String("kernel32"), QLatin1String("Wow64DisableWow64FsRedirection")); + if(wow64redir_disable) { - g_wow64redir_kernel32.reset(new QLibrary("kernel32.dll")); - } - - if(!g_wow64redir_kernel32->isLoaded()) - { - if(!g_wow64redir_kernel32->load()) + if (wow64redir_disable(oldValue)) { - return false; /*faild to load kernel32.dll*/ + return true; } } - - g_wow64redir_disable = (Wow64DisableWow64FsRedirectionFun) g_wow64redir_kernel32->resolve("Wow64DisableWow64FsRedirection"); - g_wow64redir_revert = (Wow64RevertWow64FsRedirectionFun) g_wow64redir_kernel32->resolve("Wow64RevertWow64FsRedirection"); - - return (g_wow64redir_disable && g_wow64redir_revert); -} - -#define WOW64FSREDIR_INIT(RDLOCK) do \ -{ \ - while(!(g_wow64redir_disable && g_wow64redir_revert)) \ - { \ - (RDLOCK).unlock(); \ - if(!wow64fsredir_init()) return false; \ - (RDLOCK).relock(); \ - } \ -} \ -while(0) - -bool MUtils::OS::wow64fsredir_disable(void *oldValue) -{ - QReadLocker readLock(&g_wow64redir_lock); - WOW64FSREDIR_INIT(readLock); - if(g_wow64redir_disable(oldValue)) - { - return true; - } return false; } bool MUtils::OS::wow64fsredir_revert(void *oldValue) { - QReadLocker readLock(&g_wow64redir_lock); - WOW64FSREDIR_INIT(readLock); - if(g_wow64redir_revert(oldValue)) + const Wow64RevertWow64FsRedirectionFun wow64redir_disable = MUtils::Win32Utils::resolve(QLatin1String("kernel32"), QLatin1String("Wow64RevertWow64FsRedirection")); + if (wow64redir_disable) { - return true; + if (wow64redir_disable(oldValue)) + { + return true; + } } return false; } diff --git a/src/Terminal_Win32.cpp b/src/Terminal_Win32.cpp index 8731dcb..773f022 100644 --- a/src/Terminal_Win32.cpp +++ b/src/Terminal_Win32.cpp @@ -413,7 +413,7 @@ void MUtils::Terminal::set_icon(const QIcon &icon) typedef DWORD (__stdcall *SetConsoleIconFun)(HICON); if(SetConsoleIconFun SetConsoleIconPtr = (SetConsoleIconFun) kernel32.resolve("SetConsoleIcon")) { - if(HICON hIcon = qicon_to_hicon(icon, 16, 16)) + if(HICON hIcon = (HICON) MUtils::Win32Utils::qicon_to_hicon(icon, 16, 16)) { SetConsoleIconPtr(hIcon); DestroyIcon(hIcon); diff --git a/src/Utils_Win32.cpp b/src/Utils_Win32.cpp new file mode 100644 index 0000000..f891780 --- /dev/null +++ b/src/Utils_Win32.cpp @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2015 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#include "Utils_Win32.h" + +//Win32 API +#ifndef _INC_WINDOWS +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif //_INC_WINDOWS + +//Qt +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// QICON TO HICON +/////////////////////////////////////////////////////////////////////////////// + +uintptr_t MUtils::Win32Utils::qicon_to_hicon(const QIcon &icon, const int w, const int h) +{ + if(!icon.isNull()) + { + QPixmap pixmap = icon.pixmap(w, h); + if(!pixmap.isNull()) + { + return (uintptr_t) pixmap.toWinHICON(); + } + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// RESOLVE FUNCTION +/////////////////////////////////////////////////////////////////////////////// + +typedef QHash FunctionMap; +typedef QPair, FunctionMap> LibraryItem; + +static QReadWriteLock g_resolve_lock; +static QHash g_resolve_libs; + +uintptr_t MUtils::Win32Utils::resolve_helper(const QString &libraryName, const QString &functionName) +{ + QReadLocker rdLock(&g_resolve_lock); + + //Fuction already loaded? + const QString libNameLower = libraryName.toLower(); + if (g_resolve_libs.contains(libNameLower)) + { + LibraryItem &lib = g_resolve_libs[libNameLower]; + if (lib.second.contains(functionName)) + { + qWarning("TEST: Function already there!"); + return lib.second[functionName]; + } + } + + //Accquire write access! + rdLock.unlock(); + QWriteLocker wrLock(&g_resolve_lock); + + //Load library + while (!g_resolve_libs.contains(libNameLower)) + { + qWarning("TEST: Library not there -> going to load now!"); + QSharedPointer lib(new QLibrary(libNameLower)); + if (!(lib->isLoaded() || lib->load())) + { + qWarning("Failed to load library: \"%s\"", MUTILS_UTF8(libNameLower)); + return NULL; + } + g_resolve_libs.insert(libNameLower, qMakePair(lib, FunctionMap())); + } + + //Lookup the function + LibraryItem &lib = g_resolve_libs[libNameLower]; + while (!lib.second.contains(functionName)) + { + qWarning("TEST: Function not there -> going to resolve now!"); + void *const ptr = lib.first->resolve(functionName.toLatin1().constData()); + if (!ptr) + { + lib.second.insert(functionName, NULL); + qWarning("Failed to resolve function: \"%s\"", MUTILS_UTF8(functionName)); + return NULL; + } + qWarning("TEST: Function resolved to 0x%p", ptr); + lib.second.insert(functionName, reinterpret_cast(ptr)); + } + + //Return function pointer + return lib.second[functionName]; +} diff --git a/src/Utils_Win32.h b/src/Utils_Win32.h index bb6512f..51e82ea 100644 --- a/src/Utils_Win32.h +++ b/src/Utils_Win32.h @@ -21,28 +21,21 @@ #pragma once -//Win32 API -#ifndef _INC_WINDOWS -#define WIN32_LEAN_AND_MEAN 1 -#include -#endif //_INC_WINDOWS +#include +#include +class QIcon; -//Qt -#include - -/////////////////////////////////////////////////////////////////////////////// -// QICON TO HICON -/////////////////////////////////////////////////////////////////////////////// - -static HICON qicon_to_hicon(const QIcon &icon, const int w, const int h) +namespace MUtils { - if(!icon.isNull()) + namespace Win32Utils { - QPixmap pixmap = icon.pixmap(w, h); - if(!pixmap.isNull()) + uintptr_t qicon_to_hicon(const QIcon &icon, const int w, const int h); + uintptr_t resolve_helper(const QString &libraryName, const QString &functionName); + + template + T resolve(const QString &libraryName, const QString &functionName) { - return pixmap.toWinHICON(); + return reinterpret_cast(resolve_helper(libraryName, functionName)); } } - return NULL; } -- 2.11.0