forked from premiere/premiere-libtorrent
move LoadLibrary logic to new win_util module (#1464)
move LoadLibrary logic to new win_util module. use get_library_procedure as common windows dyn proc load routine
This commit is contained in:
parent
08aab3a879
commit
e10edb5e0b
|
@ -184,6 +184,7 @@ nobase_include_HEADERS = \
|
||||||
aux_/has_block.hpp \
|
aux_/has_block.hpp \
|
||||||
aux_/scope_end.hpp \
|
aux_/scope_end.hpp \
|
||||||
aux_/vector.hpp \
|
aux_/vector.hpp \
|
||||||
|
aux_/win_util.hpp \
|
||||||
\
|
\
|
||||||
extensions/smart_ban.hpp \
|
extensions/smart_ban.hpp \
|
||||||
extensions/ut_metadata.hpp \
|
extensions/ut_metadata.hpp \
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2016, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TORRENT_WIN_UTIL_HPP
|
||||||
|
#define TORRENT_WIN_UTIL_HPP
|
||||||
|
|
||||||
|
#include "libtorrent/config.hpp"
|
||||||
|
|
||||||
|
namespace libtorrent { namespace aux
|
||||||
|
{
|
||||||
|
template <typename Library>
|
||||||
|
HMODULE get_library_handle()
|
||||||
|
{
|
||||||
|
static bool handle_checked = false;
|
||||||
|
static HMODULE handle = 0;
|
||||||
|
|
||||||
|
if (!handle_checked)
|
||||||
|
{
|
||||||
|
handle = LoadLibraryA(Library::library_name);
|
||||||
|
handle_checked = true;
|
||||||
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Library, typename Signature>
|
||||||
|
Signature get_library_procedure(LPCSTR name)
|
||||||
|
{
|
||||||
|
static Signature proc = nullptr;
|
||||||
|
static bool failed_proc = false;
|
||||||
|
|
||||||
|
if ((proc == nullptr) && !failed_proc)
|
||||||
|
{
|
||||||
|
HMODULE const handle = get_library_handle<Library>();
|
||||||
|
if (handle) proc = (Signature)GetProcAddress(handle, name);
|
||||||
|
failed_proc = (proc == nullptr);
|
||||||
|
}
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iphlpapi {
|
||||||
|
static constexpr char const* library_name = "iphlpapi.dll";
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kernel32 {
|
||||||
|
static constexpr char const* library_name = "kernel32.dll";
|
||||||
|
};
|
||||||
|
|
||||||
|
struct advapi32 {
|
||||||
|
static constexpr char const* library_name = "advapi32.dll";
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace aux
|
||||||
|
} // namespace libtorrent
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -35,6 +35,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/broadcast_socket.hpp"
|
#include "libtorrent/broadcast_socket.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
#include "libtorrent/socket_type.hpp"
|
#include "libtorrent/socket_type.hpp"
|
||||||
|
#ifdef TORRENT_WINDOWS
|
||||||
|
#include "libtorrent/aux_/win_util.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstdlib> // for wcstombscstombs
|
#include <cstdlib> // for wcstombscstombs
|
||||||
|
@ -385,41 +388,6 @@ namespace libtorrent
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TORRENT_WINDOWS
|
|
||||||
struct iphlpapi {
|
|
||||||
static constexpr char const* library_name = "iphlpapi.dll";
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Library>
|
|
||||||
HMODULE get_library_handle()
|
|
||||||
{
|
|
||||||
static bool handle_checked = false;
|
|
||||||
static HMODULE handle = 0;
|
|
||||||
|
|
||||||
if (!handle_checked)
|
|
||||||
{
|
|
||||||
handle = LoadLibraryA(Library::library_name);
|
|
||||||
handle_checked = true;
|
|
||||||
}
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Library, typename Signature>
|
|
||||||
Signature get_library_procedure(LPCSTR name)
|
|
||||||
{
|
|
||||||
static Signature proc = nullptr;
|
|
||||||
static bool failed_proc = false;
|
|
||||||
|
|
||||||
if ((proc == nullptr) && !failed_proc)
|
|
||||||
{
|
|
||||||
HMODULE const handle = get_library_handle<Library>();
|
|
||||||
if (handle) proc = (Signature)GetProcAddress(handle, name);
|
|
||||||
failed_proc = (proc == nullptr);
|
|
||||||
}
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TORRENT_USE_GETIPFORWARDTABLE
|
#if TORRENT_USE_GETIPFORWARDTABLE
|
||||||
address build_netmask(int bits, int family)
|
address build_netmask(int bits, int family)
|
||||||
{
|
{
|
||||||
|
@ -628,7 +596,7 @@ namespace libtorrent
|
||||||
typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
|
typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
|
||||||
// Get GetAdaptersAddresses() pointer
|
// Get GetAdaptersAddresses() pointer
|
||||||
auto GetAdaptersAddresses =
|
auto GetAdaptersAddresses =
|
||||||
get_library_procedure<iphlpapi, GetAdaptersAddresses_t>("GetAdaptersAddresses");
|
aux::get_library_procedure<aux::iphlpapi, GetAdaptersAddresses_t>("GetAdaptersAddresses");
|
||||||
|
|
||||||
if (GetAdaptersAddresses != nullptr)
|
if (GetAdaptersAddresses != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -988,7 +956,7 @@ namespace libtorrent
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef DWORD (WINAPI *GetIfEntry_t)(PMIB_IFROW pIfRow);
|
typedef DWORD (WINAPI *GetIfEntry_t)(PMIB_IFROW pIfRow);
|
||||||
auto GetIfEntry = get_library_procedure<iphlpapi, GetIfEntry_t>("GetIfEntry");
|
auto GetIfEntry = aux::get_library_procedure<aux::iphlpapi, GetIfEntry_t>("GetIfEntry");
|
||||||
|
|
||||||
if (GetIfEntry == nullptr)
|
if (GetIfEntry == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -1001,8 +969,8 @@ namespace libtorrent
|
||||||
ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2*);
|
ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2*);
|
||||||
typedef void (WINAPI *FreeMibTable_t)(PVOID Memory);
|
typedef void (WINAPI *FreeMibTable_t)(PVOID Memory);
|
||||||
|
|
||||||
auto GetIpForwardTable2 = get_library_procedure<iphlpapi, GetIpForwardTable2_t>("GetIpForwardTable2");
|
auto GetIpForwardTable2 = aux::get_library_procedure<aux::iphlpapi, GetIpForwardTable2_t>("GetIpForwardTable2");
|
||||||
auto FreeMibTable = get_library_procedure<iphlpapi, FreeMibTable_t>("FreeMibTable");
|
auto FreeMibTable = aux::get_library_procedure<aux::iphlpapi, FreeMibTable_t>("FreeMibTable");
|
||||||
if (GetIpForwardTable2 != nullptr && FreeMibTable != nullptr)
|
if (GetIpForwardTable2 != nullptr && FreeMibTable != nullptr)
|
||||||
{
|
{
|
||||||
MIB_IPFORWARD_TABLE2* routes = nullptr;
|
MIB_IPFORWARD_TABLE2* routes = nullptr;
|
||||||
|
@ -1035,7 +1003,7 @@ namespace libtorrent
|
||||||
// Get GetIpForwardTable() pointer
|
// Get GetIpForwardTable() pointer
|
||||||
typedef DWORD (WINAPI *GetIpForwardTable_t)(PMIB_IPFORWARDTABLE pIpForwardTable,PULONG pdwSize,BOOL bOrder);
|
typedef DWORD (WINAPI *GetIpForwardTable_t)(PMIB_IPFORWARDTABLE pIpForwardTable,PULONG pdwSize,BOOL bOrder);
|
||||||
|
|
||||||
auto GetIpForwardTable = get_library_procedure<iphlpapi, GetIpForwardTable_t>("GetIpForwardTable");
|
auto GetIpForwardTable = aux::get_library_procedure<aux::iphlpapi, GetIpForwardTable_t>("GetIpForwardTable");
|
||||||
if (GetIpForwardTable == nullptr)
|
if (GetIpForwardTable == nullptr)
|
||||||
{
|
{
|
||||||
ec = boost::asio::error::operation_not_supported;
|
ec = boost::asio::error::operation_not_supported;
|
||||||
|
|
84
src/file.cpp
84
src/file.cpp
|
@ -99,6 +99,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libtorrent/utf8.hpp"
|
#include "libtorrent/utf8.hpp"
|
||||||
|
#include "libtorrent/aux_/win_util.hpp"
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
@ -1976,38 +1977,23 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
PTOKEN_PRIVILEGES PreviousState,
|
PTOKEN_PRIVILEGES PreviousState,
|
||||||
PDWORD ReturnLength);
|
PDWORD ReturnLength);
|
||||||
|
|
||||||
static OpenProcessToken_t pOpenProcessToken = nullptr;
|
auto OpenProcessToken =
|
||||||
static LookupPrivilegeValue_t pLookupPrivilegeValue = nullptr;
|
aux::get_library_procedure<aux::advapi32, OpenProcessToken_t>("OpenProcessToken");
|
||||||
static AdjustTokenPrivileges_t pAdjustTokenPrivileges = nullptr;
|
auto LookupPrivilegeValue =
|
||||||
static bool failed_advapi = false;
|
aux::get_library_procedure<aux::advapi32, LookupPrivilegeValue_t>("LookupPrivilegeValueA");
|
||||||
|
auto AdjustTokenPrivileges =
|
||||||
|
aux::get_library_procedure<aux::advapi32, AdjustTokenPrivileges_t>("AdjustTokenPrivileges");
|
||||||
|
|
||||||
|
if (OpenProcessToken == nullptr || LookupPrivilegeValue == nullptr || AdjustTokenPrivileges == nullptr) return false;
|
||||||
|
|
||||||
if (pOpenProcessToken == nullptr && !failed_advapi)
|
|
||||||
{
|
|
||||||
HMODULE advapi = LoadLibraryA("advapi32");
|
|
||||||
if (advapi == nullptr)
|
|
||||||
{
|
|
||||||
failed_advapi = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pOpenProcessToken = (OpenProcessToken_t)GetProcAddress(advapi, "OpenProcessToken");
|
|
||||||
pLookupPrivilegeValue = (LookupPrivilegeValue_t)GetProcAddress(advapi, "LookupPrivilegeValueA");
|
|
||||||
pAdjustTokenPrivileges = (AdjustTokenPrivileges_t)GetProcAddress(advapi, "AdjustTokenPrivileges");
|
|
||||||
if (pOpenProcessToken == nullptr
|
|
||||||
|| pLookupPrivilegeValue == nullptr
|
|
||||||
|| pAdjustTokenPrivileges == nullptr)
|
|
||||||
{
|
|
||||||
failed_advapi = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE token;
|
HANDLE token;
|
||||||
if (!pOpenProcessToken(GetCurrentProcess()
|
if (!OpenProcessToken(GetCurrentProcess()
|
||||||
, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TOKEN_PRIVILEGES privs;
|
TOKEN_PRIVILEGES privs;
|
||||||
if (!pLookupPrivilegeValue(nullptr, "SeManageVolumePrivilege"
|
if (!LookupPrivilegeValue(nullptr, "SeManageVolumePrivilege"
|
||||||
, &privs.Privileges[0].Luid))
|
, &privs.Privileges[0].Luid))
|
||||||
{
|
{
|
||||||
CloseHandle(token);
|
CloseHandle(token);
|
||||||
|
@ -2017,7 +2003,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
privs.PrivilegeCount = 1;
|
privs.PrivilegeCount = 1;
|
||||||
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
bool ret = pAdjustTokenPrivileges(token, FALSE, &privs, 0, nullptr, nullptr)
|
bool ret = AdjustTokenPrivileges(token, FALSE, &privs, 0, nullptr, nullptr)
|
||||||
&& GetLastError() == ERROR_SUCCESS;
|
&& GetLastError() == ERROR_SUCCESS;
|
||||||
|
|
||||||
CloseHandle(token);
|
CloseHandle(token);
|
||||||
|
@ -2028,30 +2014,14 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
void set_file_valid_data(HANDLE f, std::int64_t size)
|
void set_file_valid_data(HANDLE f, std::int64_t size)
|
||||||
{
|
{
|
||||||
typedef BOOL (WINAPI *SetFileValidData_t)(HANDLE, LONGLONG);
|
typedef BOOL (WINAPI *SetFileValidData_t)(HANDLE, LONGLONG);
|
||||||
static SetFileValidData_t pSetFileValidData = nullptr;
|
auto SetFileValidData =
|
||||||
static bool failed_kernel32 = false;
|
aux::get_library_procedure<aux::kernel32, SetFileValidData_t>("SetFileValidData");
|
||||||
|
|
||||||
if (pSetFileValidData == nullptr && !failed_kernel32)
|
if (SetFileValidData == nullptr) return;
|
||||||
{
|
|
||||||
HMODULE k32 = LoadLibraryA("kernel32");
|
|
||||||
if (k32 == nullptr)
|
|
||||||
{
|
|
||||||
failed_kernel32 = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pSetFileValidData = (SetFileValidData_t)GetProcAddress(k32, "SetFileValidData");
|
|
||||||
if (pSetFileValidData == nullptr)
|
|
||||||
{
|
|
||||||
failed_kernel32 = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TORRENT_ASSERT(pSetFileValidData);
|
|
||||||
|
|
||||||
// we don't necessarily expect to have enough
|
// we don't necessarily expect to have enough
|
||||||
// privilege to do this, so ignore errors.
|
// privilege to do this, so ignore errors.
|
||||||
pSetFileValidData(f, size);
|
SetFileValidData(f, size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2095,30 +2065,16 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
, LPVOID lpFileInformation
|
, LPVOID lpFileInformation
|
||||||
, DWORD dwBufferSize);
|
, DWORD dwBufferSize);
|
||||||
|
|
||||||
static GetFileInformationByHandleEx_t GetFileInformationByHandleEx_ = nullptr;
|
auto GetFileInformationByHandleEx =
|
||||||
|
aux::get_library_procedure<aux::kernel32, GetFileInformationByHandleEx_t>("GetFileInformationByHandleEx");
|
||||||
static bool failed_kernel32 = false;
|
|
||||||
|
|
||||||
if ((GetFileInformationByHandleEx_ == nullptr) && !failed_kernel32)
|
|
||||||
{
|
|
||||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
|
||||||
if (kernel32)
|
|
||||||
{
|
|
||||||
GetFileInformationByHandleEx_ = (GetFileInformationByHandleEx_t)GetProcAddress(kernel32, "GetFileInformationByHandleEx");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
failed_kernel32 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
offs.QuadPart = 0;
|
offs.QuadPart = 0;
|
||||||
if (GetFileInformationByHandleEx_)
|
if (GetFileInformationByHandleEx != nullptr)
|
||||||
{
|
{
|
||||||
// only allocate the space if the file
|
// only allocate the space if the file
|
||||||
// is not fully allocated
|
// is not fully allocated
|
||||||
FILE_STANDARD_INFO inf;
|
FILE_STANDARD_INFO inf;
|
||||||
if (GetFileInformationByHandleEx_(native_handle()
|
if (GetFileInformationByHandleEx(native_handle()
|
||||||
, FileStandardInfo, &inf, sizeof(inf)) == FALSE)
|
, FileStandardInfo, &inf, sizeof(inf)) == FALSE)
|
||||||
{
|
{
|
||||||
ec.assign(GetLastError(), system_category());
|
ec.assign(GetLastError(), system_category());
|
||||||
|
|
|
@ -37,6 +37,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/error_code.hpp"
|
#include "libtorrent/error_code.hpp"
|
||||||
#include "libtorrent/file_storage.hpp"
|
#include "libtorrent/file_storage.hpp"
|
||||||
#include "libtorrent/units.hpp"
|
#include "libtorrent/units.hpp"
|
||||||
|
#ifdef TORRENT_WINDOWS
|
||||||
|
#include "libtorrent/aux_/win_util.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
@ -85,30 +88,10 @@ namespace libtorrent
|
||||||
} FILE_IO_PRIORITY_HINT_INFO_LOCAL;
|
} FILE_IO_PRIORITY_HINT_INFO_LOCAL;
|
||||||
|
|
||||||
typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS_LOCAL FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
|
typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS_LOCAL FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
|
||||||
static SetFileInformationByHandle_t SetFileInformationByHandle = nullptr;
|
auto SetFileInformationByHandle =
|
||||||
|
aux::get_library_procedure<aux::kernel32, SetFileInformationByHandle_t>("SetFileInformationByHandle");
|
||||||
|
|
||||||
static bool failed_kernel_load = false;
|
if (SetFileInformationByHandle == nullptr) return;
|
||||||
|
|
||||||
if (failed_kernel_load) return;
|
|
||||||
|
|
||||||
if (SetFileInformationByHandle == nullptr)
|
|
||||||
{
|
|
||||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
|
||||||
if (kernel32 == nullptr)
|
|
||||||
{
|
|
||||||
failed_kernel_load = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetFileInformationByHandle = (SetFileInformationByHandle_t)GetProcAddress(kernel32, "SetFileInformationByHandle");
|
|
||||||
if (SetFileInformationByHandle == nullptr)
|
|
||||||
{
|
|
||||||
failed_kernel_load = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TORRENT_ASSERT(SetFileInformationByHandle);
|
|
||||||
|
|
||||||
FILE_IO_PRIORITY_HINT_INFO_LOCAL io_hint;
|
FILE_IO_PRIORITY_HINT_INFO_LOCAL io_hint;
|
||||||
io_hint.PriorityHint = IoPriorityHintLow;
|
io_hint.PriorityHint = IoPriorityHintLow;
|
||||||
|
|
Loading…
Reference in New Issue