merged SetFileValidData fix from RC_0_16

This commit is contained in:
Arvid Norberg 2014-02-08 09:18:09 +00:00
parent c937004443
commit cc08512ee3
2 changed files with 117 additions and 15 deletions

View File

@ -41,6 +41,7 @@
* fix uTP edge case where udp socket buffer fills up
* fix nagle implementation in uTP
* fix use of SetFileValidData on windows
* fix crash when using full allocation storage mode
* improve error_code and error_category support in python bindings
* fix python binding for external_ip_alert

View File

@ -1946,6 +1946,108 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
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)
{
TORRENT_ASSERT(is_open());
@ -1995,6 +2097,10 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
ec.assign(INVALID_SET_FILE_POINTER, get_system_category());
return false;
}
if ((m_open_mode & sparse) == 0)
set_file_valid_data(m_file_handle, s);
return true;
}
@ -2037,10 +2143,8 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
#else
typedef DWORD (WINAPI *GetCompressedFileSize_t)(LPCSTR lpFileName, LPDWORD lpFileSizeHigh);
#endif
typedef BOOL (WINAPI *SetFileValidData_t)(HANDLE hFile, LONGLONG ValidDataLength);
static GetCompressedFileSize_t GetCompressedFileSize_ = NULL;
static SetFileValidData_t SetFileValidData = NULL;
static bool failed_kernel32 = false;
@ -2054,11 +2158,6 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
#else
GetCompressedFileSize_ = (GetCompressedFileSize_t)GetProcAddress(kernel32, "GetCompressedFileSizeA");
#endif
SetFileValidData = (SetFileValidData_t)GetProcAddress(kernel32, "SetFileValidData");
if ((GetCompressedFileSize_ == NULL) || (SetFileValidData == NULL))
{
failed_kernel32 = true;
}
}
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
// is not fully allocated
@ -2078,13 +2178,14 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
ec.assign(GetLastError(), get_system_category());
if (ec) return false;
}
if (offs.QuadPart != s)
{
// if the user has permissions, avoid filling
// the file with zeroes, but just fill it with
// garbage instead
SetFileValidData(m_file_handle, offs.QuadPart);
}
}
if (offs.QuadPart != s)
{
// if the user has permissions, avoid filling
// the file with zeroes, but just fill it with
// garbage instead
set_file_valid_data(m_file_handle, s);
}
}
#else // NON-WINDOWS