Some code refactoring: Dynamic loading of DLL functions is now handled at a centralized place.

This commit is contained in:
LoRd_MuldeR 2015-11-22 21:45:09 +01:00
parent b82098a29e
commit 7f5d618eba
8 changed files with 172 additions and 139 deletions

View File

@ -38,6 +38,7 @@
<ClCompile Include="src\Terminal_Win32.cpp" />
<ClCompile Include="src\Translation.cpp" />
<ClCompile Include="src\UpdateChecker.cpp" />
<ClCompile Include="src\Utils_Win32.cpp" />
<ClCompile Include="src\Version.cpp" />
</ItemGroup>
<ItemGroup>
@ -62,6 +63,7 @@
<ClInclude Include="src\3rd_party\keccak\include\keccak_impl.h" />
<ClInclude Include="src\3rd_party\strnatcmp\include\strnatcmp.h" />
<ClInclude Include="src\DirLocker.h" />
<ClInclude Include="src\Utils_Win32.h" />
<CustomBuild Include="include\Mutils\UpdateChecker.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)"</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp"</Message>

View File

@ -99,6 +99,9 @@
<ClCompile Include="src\Registry_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Utils_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CriticalSection_Win32.h">
@ -170,6 +173,9 @@
<ClInclude Include="include\MUtils\Registry.h">
<Filter>Public Headers</Filter>
</ClInclude>
<ClInclude Include="src\Utils_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="include\Mutils\UpdateChecker.h">

View File

@ -26,6 +26,7 @@
//MUtils
#include <MUtils/CPUFeatures.h>
#include <MUtils/OSSupport.h>
#include "Utils_Win32.h"
//Qt
#include <QLibrary>
@ -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<IsWow64ProcessFun>(QLatin1String("kernel32"), QLatin1String("IsWow64Process"));
if(isWow64ProcessPtr)
{
BOOL x64flag = FALSE;
if(IsWow64ProcessPtr(GetCurrentProcess(), &x64flag))
if(isWow64ProcessPtr(GetCurrentProcess(), &x64flag))
{
features.x64 = (x64flag == TRUE);
}

View File

@ -32,6 +32,12 @@
#include <QWidget>
#include <QMutex>
//Win32 API
#ifndef _INC_WINDOWS
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#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))
{

View File

@ -40,6 +40,7 @@
#include <MUtils/OSSupport.h>
#include <MUtils/GUI.h>
#include "CriticalSection_Win32.h"
#include "Utils_Win32.h"
//Qt
#include <QMap>
@ -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<void*>(QLatin1String("ntdll"), QLatin1String("wine_get_version"));
return (ptr != NULL);
}
const bool &MUtils::OS::running_on_wine(void)
@ -534,8 +526,6 @@ typedef HRESULT (WINAPI *SHGetKnownFolderPath_t)(const GUID &rfid, DWORD dwFlags
typedef HRESULT (WINAPI *SHGetFolderPath_t) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath);
static QScopedPointer<KFMap> 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<size_t, QString>());
}
QString folderPath;
//Now try to get the folder path!
if(g_known_folders_fpGetKnownFolderPath)
if(const SHGetKnownFolderPath_t known_folders_fpGetKnownFolderPath = MUtils::Win32Utils::resolve<SHGetKnownFolderPath_t>(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<SHGetFolderPath_t>(QLatin1String("shell32"), QLatin1String("SHGetFolderPathW")))
{
QScopedArrayPointer<WCHAR> 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<QLibrary> 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)
{
readLock.unlock();
if (!get_file_path_init())
const GetPathNameByHandleFun getPathNameByHandleFun = MUtils::Win32Utils::resolve<GetPathNameByHandleFun>(QLatin1String("kernel32"), QLatin1String("GetFinalPathNameByHandleW"));
if (!getPathNameByHandleFun)
{
qWarning("MUtils::OS::get_file_path() --> fallback!");
return get_file_path_fallback((HANDLE)_get_osfhandle(fd));
}
readLock.relock();
}
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,68 +1363,29 @@ 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<QLibrary> g_wow64redir_kernel32;
static Wow64DisableWow64FsRedirectionFun g_wow64redir_disable = NULL;
static Wow64RevertWow64FsRedirectionFun g_wow64redir_revert = NULL;
static bool wow64fsredir_init()
{
QWriteLocker writeLock(&g_wow64redir_lock);
if(g_wow64redir_disable && g_wow64redir_revert)
{
return true; /*already initialized*/
}
if(g_wow64redir_kernel32.isNull())
{
g_wow64redir_kernel32.reset(new QLibrary("kernel32.dll"));
}
if(!g_wow64redir_kernel32->isLoaded())
{
if(!g_wow64redir_kernel32->load())
{
return false; /*faild to load kernel32.dll*/
}
}
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))
const Wow64DisableWow64FsRedirectionFun wow64redir_disable = MUtils::Win32Utils::resolve<Wow64DisableWow64FsRedirectionFun>(QLatin1String("kernel32"), QLatin1String("Wow64DisableWow64FsRedirection"));
if(wow64redir_disable)
{
if (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<Wow64RevertWow64FsRedirectionFun>(QLatin1String("kernel32"), QLatin1String("Wow64RevertWow64FsRedirection"));
if (wow64redir_disable)
{
if (wow64redir_disable(oldValue))
{
return true;
}
}
return false;
}

View File

@ -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);

115
src/Utils_Win32.cpp Normal file
View File

@ -0,0 +1,115 @@
///////////////////////////////////////////////////////////////////////////////
// MuldeR's Utilities for Qt
// Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
//
// 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 <Windows.h>
#endif //_INC_WINDOWS
//Qt
#include <QIcon>
#include <QPair>
#include <QReadWriteLock>
#include <QLibrary>
#include <QHash>
///////////////////////////////////////////////////////////////////////////////
// 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<QString, uintptr_t> FunctionMap;
typedef QPair<QSharedPointer<QLibrary>, FunctionMap> LibraryItem;
static QReadWriteLock g_resolve_lock;
static QHash<QString, LibraryItem> 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<QLibrary> 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<uintptr_t>(ptr));
}
//Return function pointer
return lib.second[functionName];
}

View File

@ -21,28 +21,21 @@
#pragma once
//Win32 API
#ifndef _INC_WINDOWS
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#endif //_INC_WINDOWS
#include <stdint.h>
#include <MUtils/Global.h>
class QIcon;
//Qt
#include <QIcon>
namespace MUtils
{
namespace Win32Utils
{
uintptr_t qicon_to_hicon(const QIcon &icon, const int w, const int h);
uintptr_t resolve_helper(const QString &libraryName, const QString &functionName);
///////////////////////////////////////////////////////////////////////////////
// QICON TO HICON
///////////////////////////////////////////////////////////////////////////////
static HICON qicon_to_hicon(const QIcon &icon, const int w, const int h)
template<class T>
T resolve(const QString &libraryName, const QString &functionName)
{
if(!icon.isNull())
{
QPixmap pixmap = icon.pixmap(w, h);
if(!pixmap.isNull())
{
return pixmap.toWinHICON();
return reinterpret_cast<T>(resolve_helper(libraryName, functionName));
}
}
return NULL;
}