diff --git a/src/app/application.cpp b/src/app/application.cpp index 4e1f31b65..c92146c7d 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -64,7 +64,6 @@ #ifndef DISABLE_GUI #ifdef Q_OS_WIN -#include #include #include #endif // Q_OS_WIN @@ -682,7 +681,7 @@ void Application::cleanup() #ifdef Q_OS_WIN typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); - PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonCreate"); + const auto shutdownBRCreate = Utils::Misc::loadWinAPI("User32.dll", "ShutdownBlockReasonCreate"); // Only available on Vista+ if (shutdownBRCreate) shutdownBRCreate((HWND)m_window->effectiveWinId(), tr("Saving torrent progress...").toStdWString().c_str()); @@ -724,7 +723,7 @@ void Application::cleanup() if (m_window) { #ifdef Q_OS_WIN typedef BOOL (WINAPI *PSHUTDOWNBRDESTROY)(HWND); - PSHUTDOWNBRDESTROY shutdownBRDestroy = (PSHUTDOWNBRDESTROY)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonDestroy"); + const auto shutdownBRDestroy = Utils::Misc::loadWinAPI("User32.dll", "ShutdownBlockReasonDestroy"); // Only available on Vista+ if (shutdownBRDestroy) shutdownBRDestroy((HWND)m_window->effectiveWinId()); diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 68aa34b9b..b8189d126 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -4543,11 +4543,11 @@ namespace return uuid.toString().toUpper(); // Libtorrent expects the GUID in uppercase using PCONVERTIFACENAMETOLUID = NETIO_STATUS (WINAPI *)(const WCHAR *, PNET_LUID); - PCONVERTIFACENAMETOLUID ConvertIfaceNameToLuid = reinterpret_cast(::GetProcAddress(::GetModuleHandleW(L"Iphlpapi.dll"), "ConvertInterfaceNameToLuidW")); + const auto ConvertIfaceNameToLuid = Utils::Misc::loadWinAPI("Iphlpapi.dll", "ConvertInterfaceNameToLuidW"); if (!ConvertIfaceNameToLuid) return QString(); using PCONVERTIFACELUIDTOGUID = NETIO_STATUS (WINAPI *)(const NET_LUID *, GUID *); - PCONVERTIFACELUIDTOGUID ConvertIfaceLuidToGuid = reinterpret_cast(::GetProcAddress(::GetModuleHandleW(L"Iphlpapi.dll"), "ConvertInterfaceLuidToGuid")); + const auto ConvertIfaceLuidToGuid = Utils::Misc::loadWinAPI("Iphlpapi.dll", "ConvertInterfaceLuidToGuid"); if (!ConvertIfaceLuidToGuid) return QString(); NET_LUID luid; diff --git a/src/base/utils/misc.cpp b/src/base/utils/misc.cpp index d4027b3d2..b09ab07c1 100644 --- a/src/base/utils/misc.cpp +++ b/src/base/utils/misc.cpp @@ -28,34 +28,17 @@ * Contact : chris@qbittorrent.org */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "misc.h" + #include #include -#ifdef DISABLE_GUI -#include -#else -#include -#include -#include -#endif - #ifdef Q_OS_WIN #include -#include #include -const int UNLEN = 256; #else -#include #include +#include #endif #ifdef Q_OS_MAC @@ -63,33 +46,47 @@ const int UNLEN = 256; #include #endif -#ifndef DISABLE_GUI +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DISABLE_GUI +#include +#else +#include +#include +#include +#include +#include #if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) #include #include #endif -#endif // DISABLE_GUI - -#ifndef DISABLE_GUI -#include -#include #endif #include "base/utils/string.h" #include "base/unicodestrings.h" #include "base/logger.h" -#include "misc.h" #include "fs.h" -static struct { const char *source; const char *comment; } units[] = { - QT_TRANSLATE_NOOP3("misc", "B", "bytes"), - QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), - QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), - QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), - QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"), - QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"), - QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)") -}; +namespace +{ + const struct { const char *source; const char *comment; } units[] = { + QT_TRANSLATE_NOOP3("misc", "B", "bytes"), + QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), + QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), + QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), + QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"), + QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"), + QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)") + }; +} void Utils::Misc::shutdownComputer(const ShutdownDialogAction &action) { @@ -115,12 +112,23 @@ void Utils::Misc::shutdownComputer(const ShutdownDialogAction &action) if (GetLastError() != ERROR_SUCCESS) return; - if (action == ShutdownDialogAction::Suspend) - SetSuspendState(false, false, false); - else if (action == ShutdownDialogAction::Hibernate) - SetSuspendState(true, false, false); - else - InitiateSystemShutdownA(0, QCoreApplication::translate("misc", "qBittorrent will shutdown the computer now because all downloads are complete.").toLocal8Bit().data(), 10, true, false); + using PSETSUSPENDSTATE = BOOLEAN (WINAPI *)(BOOLEAN, BOOLEAN, BOOLEAN); + const auto setSuspendState = Utils::Misc::loadWinAPI("PowrProf.dll", "SetSuspendState"); + + if (action == ShutdownDialogAction::Suspend) { + if (setSuspendState) + setSuspendState(false, false, false); + } + else if (action == ShutdownDialogAction::Hibernate) { + if (setSuspendState) + setSuspendState(true, false, false); + } + else { + const QString msg = QCoreApplication::translate("misc", "qBittorrent will shutdown the computer now because all downloads are complete."); + std::unique_ptr msgWchar(new wchar_t[msg.length() + 1] {}); + msg.toWCharArray(msgWchar.get()); + ::InitiateSystemShutdownW(nullptr, msgWchar.get(), 10, true, false); + } // Disable shutdown privilege. tkp.Privileges[0].Attributes = 0; @@ -474,6 +482,7 @@ QString Utils::Misc::getUserIDString() { QString uid = "0"; #ifdef Q_OS_WIN + const int UNLEN = 256; WCHAR buffer[UNLEN + 1] = {0}; DWORD buffer_len = sizeof(buffer) / sizeof(*buffer); if (GetUserNameW(buffer, &buffer_len)) diff --git a/src/base/utils/misc.h b/src/base/utils/misc.h index 157b30113..db9617ce3 100644 --- a/src/base/utils/misc.h +++ b/src/base/utils/misc.h @@ -31,15 +31,24 @@ #ifndef UTILS_MISC_H #define UTILS_MISC_H +#include #include + +#include + +#ifdef Q_OS_WIN +#include +#include +#endif + +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include + #include "base/types.h" /* Miscellaneous functions that can be useful */ @@ -107,6 +116,22 @@ namespace Utils #ifdef Q_OS_WIN QString windowsSystemPath(); + + template + T loadWinAPI(const QString &source, const char *funcName) + { + QString path = windowsSystemPath(); + if (!path.endsWith('\\')) + path += '\\'; + + path += source; + + std::unique_ptr pathWchar(new wchar_t[path.length() + 1] {}); + path.toWCharArray(pathWchar.get()); + + return reinterpret_cast( + ::GetProcAddress(::LoadLibraryW(pathWchar.get()), funcName)); + } #endif } } diff --git a/winconf.pri b/winconf.pri index 146e5eebb..19f240ba9 100644 --- a/winconf.pri +++ b/winconf.pri @@ -33,8 +33,8 @@ win32-g++* { } RC_FILE = qbittorrent_mingw.rc - - LIBS += libadvapi32 libshell32 libuser32 libole32 libwsock32 libws2_32 libpowrprof + + LIBS += libadvapi32 libshell32 libuser32 libole32 libwsock32 libws2_32 } else:win32-msvc* { CONFIG -= embed_manifest_exe @@ -42,8 +42,8 @@ else:win32-msvc* { QMAKE_LFLAGS_RELEASE += "/OPT:REF /OPT:ICF" RC_FILE = qbittorrent.rc - - LIBS += advapi32.lib shell32.lib crypt32.lib User32.lib ole32.lib PowrProf.lib + + LIBS += advapi32.lib shell32.lib crypt32.lib User32.lib ole32.lib } # See an example build configuration in "conf.pri.windows"