Fix previous patch fixing deadlock in DllMain (#3158)
Simplify `get_manage_volume_privs()` and renamed it
This commit is contained in:
parent
d2d35b69fd
commit
490d8eb328
|
@ -1,3 +1,5 @@
|
||||||
|
* fix potential deadlock on Windows, caused by performing restricted
|
||||||
|
tasks from within DllMain
|
||||||
* fix issue when subsequent file priority updates cause torrent to stop
|
* fix issue when subsequent file priority updates cause torrent to stop
|
||||||
|
|
||||||
1.1.8 release
|
1.1.8 release
|
||||||
|
|
76
src/file.cpp
76
src/file.cpp
|
@ -314,7 +314,7 @@ done:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
# else
|
# else
|
||||||
# undef _BSD_SOURCE
|
# undef _BSD_SOURCE
|
||||||
# define _BSD_SOURCE // deprecated since glibc 2.20
|
# define _BSD_SOURCE // deprecated since glibc 2.20
|
||||||
|
@ -1314,7 +1314,7 @@ namespace libtorrent
|
||||||
|
|
||||||
|
|
||||||
#ifdef TORRENT_WINDOWS
|
#ifdef TORRENT_WINDOWS
|
||||||
bool get_manage_volume_privs();
|
void acquire_manage_volume_privs();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
file::file()
|
file::file()
|
||||||
|
@ -1426,6 +1426,13 @@ namespace libtorrent
|
||||||
| FILE_FLAG_OVERLAPPED
|
| FILE_FLAG_OVERLAPPED
|
||||||
| ((mode & no_cache) ? FILE_FLAG_WRITE_THROUGH : 0);
|
| ((mode & no_cache) ? FILE_FLAG_WRITE_THROUGH : 0);
|
||||||
|
|
||||||
|
if ((mode & sparse) == 0)
|
||||||
|
{
|
||||||
|
// Enable privilege required by SetFileValidData()
|
||||||
|
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfilevaliddata
|
||||||
|
acquire_manage_volume_privs();
|
||||||
|
}
|
||||||
|
|
||||||
handle_type handle = CreateFile_(file_path.c_str(), m.rw_mode
|
handle_type handle = CreateFile_(file_path.c_str(), m.rw_mode
|
||||||
, (mode & lock_file) ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE
|
, (mode & lock_file) ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE
|
||||||
, 0, m.create_mode, flags, 0);
|
, 0, m.create_mode, flags, 0);
|
||||||
|
@ -1930,8 +1937,14 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TORRENT_WINDOWS
|
#ifdef TORRENT_WINDOWS
|
||||||
bool get_manage_volume_privs()
|
void acquire_manage_volume_privs()
|
||||||
{
|
{
|
||||||
|
static bool called_once = false;
|
||||||
|
|
||||||
|
if (called_once) return;
|
||||||
|
|
||||||
|
called_once = true;
|
||||||
|
|
||||||
typedef BOOL (WINAPI *OpenProcessToken_t)(
|
typedef BOOL (WINAPI *OpenProcessToken_t)(
|
||||||
HANDLE ProcessHandle,
|
HANDLE ProcessHandle,
|
||||||
DWORD DesiredAccess,
|
DWORD DesiredAccess,
|
||||||
|
@ -1950,59 +1963,48 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
PTOKEN_PRIVILEGES PreviousState,
|
PTOKEN_PRIVILEGES PreviousState,
|
||||||
PDWORD ReturnLength);
|
PDWORD ReturnLength);
|
||||||
|
|
||||||
static OpenProcessToken_t pOpenProcessToken = NULL;
|
HMODULE advapi = LoadLibraryA("advapi32");
|
||||||
static LookupPrivilegeValue_t pLookupPrivilegeValue = NULL;
|
|
||||||
static AdjustTokenPrivileges_t pAdjustTokenPrivileges = NULL;
|
if (advapi == NULL) return;
|
||||||
static bool failed_advapi = false;
|
|
||||||
HMODULE advapi = NULL;
|
|
||||||
|
|
||||||
BOOST_SCOPE_EXIT(&advapi) {
|
BOOST_SCOPE_EXIT(&advapi) {
|
||||||
if (advapi) FreeLibrary(advapi);
|
FreeLibrary(advapi);
|
||||||
} BOOST_SCOPE_EXIT_END
|
} BOOST_SCOPE_EXIT_END
|
||||||
|
|
||||||
if (pOpenProcessToken == NULL && !failed_advapi)
|
OpenProcessToken_t const pOpenProcessToken =
|
||||||
|
(OpenProcessToken_t)GetProcAddress(advapi, "OpenProcessToken");
|
||||||
|
LookupPrivilegeValue_t const pLookupPrivilegeValue =
|
||||||
|
(LookupPrivilegeValue_t)GetProcAddress(advapi, "LookupPrivilegeValueA");
|
||||||
|
AdjustTokenPrivileges_t const pAdjustTokenPrivileges =
|
||||||
|
(AdjustTokenPrivileges_t)GetProcAddress(advapi, "AdjustTokenPrivileges");
|
||||||
|
|
||||||
|
if (pOpenProcessToken == NULL
|
||||||
|
|| pLookupPrivilegeValue == NULL
|
||||||
|
|| pAdjustTokenPrivileges == NULL)
|
||||||
{
|
{
|
||||||
advapi = LoadLibraryA("advapi32");
|
return;
|
||||||
if (advapi == NULL)
|
|
||||||
{
|
|
||||||
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 == NULL
|
|
||||||
|| pLookupPrivilegeValue == NULL
|
|
||||||
|| pAdjustTokenPrivileges == NULL)
|
|
||||||
{
|
|
||||||
failed_advapi = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE token = NULL;
|
HANDLE token = NULL;
|
||||||
if (!pOpenProcessToken(GetCurrentProcess()
|
if (!pOpenProcessToken(GetCurrentProcess()
|
||||||
, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
BOOST_SCOPE_EXIT(&token) {
|
BOOST_SCOPE_EXIT(&token) {
|
||||||
CloseHandle(token);
|
CloseHandle(token);
|
||||||
} BOOST_SCOPE_EXIT_END
|
} BOOST_SCOPE_EXIT_END
|
||||||
|
|
||||||
TOKEN_PRIVILEGES privs;
|
TOKEN_PRIVILEGES privs = { 0 };
|
||||||
if (!pLookupPrivilegeValue(NULL, "SeManageVolumePrivilege"
|
if (!pLookupPrivilegeValue(NULL, "SeManageVolumePrivilege"
|
||||||
, &privs.Privileges[0].Luid))
|
, &privs.Privileges[0].Luid))
|
||||||
{
|
{
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, NULL, NULL)
|
pAdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, NULL);
|
||||||
&& GetLastError() == ERROR_SUCCESS;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_file_valid_data(HANDLE f, boost::int64_t size)
|
void set_file_valid_data(HANDLE f, boost::int64_t size)
|
||||||
|
@ -2011,12 +2013,10 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
static SetFileValidData_t const pSetFileValidData = (SetFileValidData_t)
|
static SetFileValidData_t const pSetFileValidData = (SetFileValidData_t)
|
||||||
GetProcAddress(GetModuleHandleA("kernel32"), "SetFileValidData");
|
GetProcAddress(GetModuleHandleA("kernel32"), "SetFileValidData");
|
||||||
|
|
||||||
if (pSetFileValidData == NULL) return;
|
if (pSetFileValidData)
|
||||||
|
|
||||||
static bool const has_manage_volume_privs = get_manage_volume_privs();
|
|
||||||
|
|
||||||
if (has_manage_volume_privs)
|
|
||||||
{
|
{
|
||||||
|
// we don't necessarily expect to have enough
|
||||||
|
// privilege to do this, so ignore errors.
|
||||||
pSetFileValidData(f, size);
|
pSetFileValidData(f, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue