fixed bug #1946112 - Wrong free space calculation
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@5638 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
be25de5c8d
commit
931beb47e1
1 changed files with 39 additions and 9 deletions
|
@ -982,7 +982,7 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
if (uMsg == WM_IN_UPDATEMSG || uMsg == WM_NOTIFY_START)
|
if (uMsg == WM_IN_UPDATEMSG || uMsg == WM_NOTIFY_START)
|
||||||
{
|
{
|
||||||
static char s[NSIS_MAX_STRLEN];
|
static char s[NSIS_MAX_STRLEN];
|
||||||
char *p;
|
char *root;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int available_set = 0;
|
int available_set = 0;
|
||||||
unsigned total, available = 0xFFFFFFFF;
|
unsigned total, available = 0xFFFFFFFF;
|
||||||
|
@ -991,10 +991,24 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
if (!is_valid_instpath(dir))
|
if (!is_valid_instpath(dir))
|
||||||
error = NSIS_INSTDIR_INVALID;
|
error = NSIS_INSTDIR_INVALID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This part is tricky. We need to make sure a few things:
|
||||||
|
*
|
||||||
|
* 1. GetDiskFreeSpaceEx is always called at least once for large HD.
|
||||||
|
* Even if skip_root() returned NULL (e.g. "C:").
|
||||||
|
* Note that trimslashtoend() will nullify "C:".
|
||||||
|
* 2. GetDiskFreeSpaceEx is called with the deepest valid directory.
|
||||||
|
* e.g. C:\drive when the user types C:\drive\folder1\folder2.
|
||||||
|
* This makes sure NTFS mount points are treated properly (#1946112).
|
||||||
|
* 3. `s' stays valid after the loop for GetDiskFreeSpace.
|
||||||
|
* This means there is no cutting beyond what skip_root() returns.
|
||||||
|
* 4. If GetDiskFreeSpaceEx doesn't exist, GetDiskFreeSpace is used.
|
||||||
|
* 5. `dir' is never modified.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
mystrcpy(s,dir);
|
mystrcpy(s,dir);
|
||||||
p=skip_root(s);
|
root=skip_root(s);
|
||||||
if (p)
|
|
||||||
*p=0;
|
|
||||||
|
|
||||||
// Test for and use the GetDiskFreeSpaceEx API
|
// Test for and use the GetDiskFreeSpaceEx API
|
||||||
{
|
{
|
||||||
|
@ -1004,22 +1018,38 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
{
|
{
|
||||||
ULARGE_INTEGER available64;
|
ULARGE_INTEGER available64;
|
||||||
ULARGE_INTEGER a, b;
|
ULARGE_INTEGER a, b;
|
||||||
if (GDFSE(s, &available64, &a, &b))
|
char *p;
|
||||||
|
for (p = s; root != p; p = trimslashtoend(s))
|
||||||
{
|
{
|
||||||
|
if (GDFSE(s, &available64, &a, &b))
|
||||||
|
{
|
||||||
#ifndef _NSIS_NO_INT64_SHR
|
#ifndef _NSIS_NO_INT64_SHR
|
||||||
available = (int)(available64.QuadPart >> 10);
|
available = (int)(available64.QuadPart >> 10);
|
||||||
#else
|
#else
|
||||||
available = (int)(Int64ShrlMod32(available64.QuadPart, 10));
|
available = (int)(Int64ShrlMod32(available64.QuadPart, 10));
|
||||||
#endif
|
#endif
|
||||||
available_set++;
|
available_set++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!root)
|
||||||
|
{
|
||||||
|
// don't call trimslashtoend() which will destroy the string
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!available_set)
|
if (!available_set)
|
||||||
{
|
{
|
||||||
// GetDiskFreeSpaceEx is not available
|
|
||||||
DWORD spc, bps, fc, tc;
|
DWORD spc, bps, fc, tc;
|
||||||
|
|
||||||
|
// GetDiskFreeSpaceEx accepts any path, but GetDiskFreeSpace accepts only the root
|
||||||
|
if (root)
|
||||||
|
*root=0;
|
||||||
|
|
||||||
|
// GetDiskFreeSpaceEx is not available
|
||||||
if (GetDiskFreeSpace(s, &spc, &bps, &fc, &tc))
|
if (GetDiskFreeSpace(s, &spc, &bps, &fc, &tc))
|
||||||
{
|
{
|
||||||
available = (int)MulDiv(bps * spc, fc, 1 << 10);
|
available = (int)MulDiv(bps * spc, fc, 1 << 10);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue