forked from premiere/premiere-libtorrent
merged SetFileValidData fix from RC_0_16
This commit is contained in:
parent
c937004443
commit
cc08512ee3
|
@ -41,6 +41,7 @@
|
||||||
* fix uTP edge case where udp socket buffer fills up
|
* fix uTP edge case where udp socket buffer fills up
|
||||||
* fix nagle implementation in uTP
|
* fix nagle implementation in uTP
|
||||||
|
|
||||||
|
* fix use of SetFileValidData on windows
|
||||||
* fix crash when using full allocation storage mode
|
* fix crash when using full allocation storage mode
|
||||||
* improve error_code and error_category support in python bindings
|
* improve error_code and error_category support in python bindings
|
||||||
* fix python binding for external_ip_alert
|
* fix python binding for external_ip_alert
|
||||||
|
|
131
src/file.cpp
131
src/file.cpp
|
@ -1946,6 +1946,108 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TORRENT_WINDOWS
|
||||||
|
bool get_manage_volume_privs()
|
||||||
|
{
|
||||||
|
typedef BOOL (WINAPI *OpenProcessToken_t)(
|
||||||
|
HANDLE ProcessHandle,
|
||||||
|
DWORD DesiredAccess,
|
||||||
|
PHANDLE TokenHandle);
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *LookupPrivilegeValue_t)(
|
||||||
|
LPCSTR lpSystemName,
|
||||||
|
LPCSTR lpName,
|
||||||
|
PLUID lpLuid);
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *AdjustTokenPrivileges_t)(
|
||||||
|
HANDLE TokenHandle,
|
||||||
|
BOOL DisableAllPrivileges,
|
||||||
|
PTOKEN_PRIVILEGES NewState,
|
||||||
|
DWORD BufferLength,
|
||||||
|
PTOKEN_PRIVILEGES PreviousState,
|
||||||
|
PDWORD ReturnLength);
|
||||||
|
|
||||||
|
static OpenProcessToken_t pOpenProcessToken = NULL;
|
||||||
|
static LookupPrivilegeValue_t pLookupPrivilegeValue = NULL;
|
||||||
|
static AdjustTokenPrivileges_t pAdjustTokenPrivileges = NULL;
|
||||||
|
static bool failed_advapi = false;
|
||||||
|
|
||||||
|
if (pOpenProcessToken == NULL && !failed_advapi)
|
||||||
|
{
|
||||||
|
HMODULE advapi = LoadLibraryA("advapi32");
|
||||||
|
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;
|
||||||
|
if (!pOpenProcessToken(GetCurrentProcess()
|
||||||
|
, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TOKEN_PRIVILEGES privs;
|
||||||
|
if (!pLookupPrivilegeValue(NULL, "SeManageVolumePrivilege"
|
||||||
|
, &privs.Privileges[0].Luid))
|
||||||
|
{
|
||||||
|
CloseHandle(token);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
privs.PrivilegeCount = 1;
|
||||||
|
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
|
bool ret = pAdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, NULL)
|
||||||
|
&& GetLastError() == ERROR_SUCCESS;
|
||||||
|
|
||||||
|
CloseHandle(token);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_file_valid_data(HANDLE f, boost::int64_t size)
|
||||||
|
{
|
||||||
|
static bool has_privs = get_manage_volume_privs();
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *SetFileValidData_t)(HANDLE, LONGLONG);
|
||||||
|
static SetFileValidData_t pSetFileValidData = NULL;
|
||||||
|
static bool failed_kernel32 = false;
|
||||||
|
|
||||||
|
if (pSetFileValidData == NULL && !failed_kernel32)
|
||||||
|
{
|
||||||
|
HMODULE k32 = LoadLibraryA("kernel32");
|
||||||
|
if (k32 == NULL)
|
||||||
|
{
|
||||||
|
failed_kernel32 = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pSetFileValidData = (SetFileValidData_t)GetProcAddress(k32, "SetFileValidData");
|
||||||
|
if (pSetFileValidData == NULL)
|
||||||
|
{
|
||||||
|
failed_kernel32 = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_ASSERT(pSetFileValidData);
|
||||||
|
|
||||||
|
// we don't necessarily expect to have enough
|
||||||
|
// privilege to do this, so ignore errors.
|
||||||
|
pSetFileValidData(f, size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool file::set_size(size_type s, error_code& ec)
|
bool file::set_size(size_type s, error_code& ec)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_open());
|
TORRENT_ASSERT(is_open());
|
||||||
|
@ -1995,6 +2097,10 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
ec.assign(INVALID_SET_FILE_POINTER, get_system_category());
|
ec.assign(INVALID_SET_FILE_POINTER, get_system_category());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((m_open_mode & sparse) == 0)
|
||||||
|
set_file_valid_data(m_file_handle, s);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2037,10 +2143,8 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
#else
|
#else
|
||||||
typedef DWORD (WINAPI *GetCompressedFileSize_t)(LPCSTR lpFileName, LPDWORD lpFileSizeHigh);
|
typedef DWORD (WINAPI *GetCompressedFileSize_t)(LPCSTR lpFileName, LPDWORD lpFileSizeHigh);
|
||||||
#endif
|
#endif
|
||||||
typedef BOOL (WINAPI *SetFileValidData_t)(HANDLE hFile, LONGLONG ValidDataLength);
|
|
||||||
|
|
||||||
static GetCompressedFileSize_t GetCompressedFileSize_ = NULL;
|
static GetCompressedFileSize_t GetCompressedFileSize_ = NULL;
|
||||||
static SetFileValidData_t SetFileValidData = NULL;
|
|
||||||
|
|
||||||
static bool failed_kernel32 = false;
|
static bool failed_kernel32 = false;
|
||||||
|
|
||||||
|
@ -2054,11 +2158,6 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
#else
|
#else
|
||||||
GetCompressedFileSize_ = (GetCompressedFileSize_t)GetProcAddress(kernel32, "GetCompressedFileSizeA");
|
GetCompressedFileSize_ = (GetCompressedFileSize_t)GetProcAddress(kernel32, "GetCompressedFileSizeA");
|
||||||
#endif
|
#endif
|
||||||
SetFileValidData = (SetFileValidData_t)GetProcAddress(kernel32, "SetFileValidData");
|
|
||||||
if ((GetCompressedFileSize_ == NULL) || (SetFileValidData == NULL))
|
|
||||||
{
|
|
||||||
failed_kernel32 = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2066,7 +2165,8 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!failed_kernel32 && GetCompressedFileSize_ && SetFileValidData)
|
offs.QuadPart = 0;
|
||||||
|
if (GetCompressedFileSize_)
|
||||||
{
|
{
|
||||||
// only allocate the space if the file
|
// only allocate the space if the file
|
||||||
// is not fully allocated
|
// is not fully allocated
|
||||||
|
@ -2078,13 +2178,14 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||||
ec.assign(GetLastError(), get_system_category());
|
ec.assign(GetLastError(), get_system_category());
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
}
|
}
|
||||||
if (offs.QuadPart != s)
|
}
|
||||||
{
|
|
||||||
// if the user has permissions, avoid filling
|
if (offs.QuadPart != s)
|
||||||
// the file with zeroes, but just fill it with
|
{
|
||||||
// garbage instead
|
// if the user has permissions, avoid filling
|
||||||
SetFileValidData(m_file_handle, offs.QuadPart);
|
// the file with zeroes, but just fill it with
|
||||||
}
|
// garbage instead
|
||||||
|
set_file_valid_data(m_file_handle, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else // NON-WINDOWS
|
#else // NON-WINDOWS
|
||||||
|
|
Loading…
Reference in New Issue