mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[KERNEL32]: Reimplement GetDiskFreeSpaceW() to fix various issues in it. It also brings support for appcompat
This commit is contained in:
parent
55ae20931f
commit
5bee374c82
1 changed files with 109 additions and 28 deletions
|
@ -215,50 +215,131 @@ GetDiskFreeSpaceW(IN LPCWSTR lpRootPathName,
|
||||||
OUT LPDWORD lpNumberOfFreeClusters,
|
OUT LPDWORD lpNumberOfFreeClusters,
|
||||||
OUT LPDWORD lpTotalNumberOfClusters)
|
OUT LPDWORD lpTotalNumberOfClusters)
|
||||||
{
|
{
|
||||||
FILE_FS_SIZE_INFORMATION FileFsSize;
|
BOOL Below2GB;
|
||||||
|
PCWSTR RootPath;
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE RootHandle;
|
||||||
|
UNICODE_STRING FileName;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
WCHAR RootPathName[MAX_PATH];
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
HANDLE hFile;
|
FILE_FS_SIZE_INFORMATION FileFsSize;
|
||||||
NTSTATUS errCode;
|
|
||||||
|
|
||||||
if (lpRootPathName)
|
/* If no path provided, get root path */
|
||||||
|
RootPath = lpRootPathName;
|
||||||
|
if (lpRootPathName == NULL)
|
||||||
{
|
{
|
||||||
wcsncpy (RootPathName, lpRootPathName, 3);
|
RootPath = L"\\";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
GetCurrentDirectoryW (MAX_PATH, RootPathName);
|
|
||||||
}
|
|
||||||
RootPathName[3] = 0;
|
|
||||||
|
|
||||||
hFile = InternalOpenDirW(RootPathName, FALSE);
|
/* Convert the path to NT path */
|
||||||
if (INVALID_HANDLE_VALUE == hFile)
|
if (!RtlDosPathNameToNtPathName_U(RootPath, &FileName, NULL, NULL))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
errCode = NtQueryVolumeInformationFile(hFile,
|
/* Open it for disk space query! */
|
||||||
&IoStatusBlock,
|
InitializeObjectAttributes(&ObjectAttributes, &FileName,
|
||||||
&FileFsSize,
|
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
sizeof(FILE_FS_SIZE_INFORMATION),
|
Status = NtOpenFile(&RootHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock,
|
||||||
FileFsSizeInformation);
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
if (!NT_SUCCESS(errCode))
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_FREE_SPACE_QUERY);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
CloseHandle(hFile);
|
BaseSetLastNTError(Status);
|
||||||
BaseSetLastNTError (errCode);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
|
||||||
|
if (lpBytesPerSector != NULL)
|
||||||
|
{
|
||||||
|
*lpBytesPerSector = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpSectorsPerCluster)
|
/* We don't need the name any longer */
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
|
||||||
|
|
||||||
|
/* Query disk space! */
|
||||||
|
Status = NtQueryVolumeInformationFile(RootHandle, &IoStatusBlock, &FileFsSize,
|
||||||
|
sizeof(FILE_FS_SIZE_INFORMATION),
|
||||||
|
FileFsSizeInformation);
|
||||||
|
NtClose(RootHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
BaseSetLastNTError(Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are we in some compatibility mode where size must be below 2GB? */
|
||||||
|
Below2GB = ((NtCurrentPeb()->AppCompatFlags.LowPart & GetDiskFreeSpace2GB) == GetDiskFreeSpace2GB);
|
||||||
|
|
||||||
|
/* If we're to overflow output, make sure we return the maximum */
|
||||||
|
if (FileFsSize.TotalAllocationUnits.HighPart != 0)
|
||||||
|
{
|
||||||
|
FileFsSize.TotalAllocationUnits.LowPart = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileFsSize.AvailableAllocationUnits.HighPart != 0)
|
||||||
|
{
|
||||||
|
FileFsSize.AvailableAllocationUnits.LowPart = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return what user asked for */
|
||||||
|
if (lpSectorsPerCluster != NULL)
|
||||||
|
{
|
||||||
*lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
|
*lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
|
||||||
if (lpBytesPerSector)
|
}
|
||||||
|
|
||||||
|
if (lpBytesPerSector != NULL)
|
||||||
|
{
|
||||||
*lpBytesPerSector = FileFsSize.BytesPerSector;
|
*lpBytesPerSector = FileFsSize.BytesPerSector;
|
||||||
if (lpNumberOfFreeClusters)
|
}
|
||||||
*lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
|
|
||||||
if (lpTotalNumberOfClusters)
|
if (lpNumberOfFreeClusters != NULL)
|
||||||
*lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
|
{
|
||||||
CloseHandle(hFile);
|
if (!Below2GB)
|
||||||
|
{
|
||||||
|
*lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.LowPart;
|
||||||
|
}
|
||||||
|
/* If we have to remain below 2GB... */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD FreeClusters;
|
||||||
|
|
||||||
|
/* Compute how many clusters there are in less than 2GB: 2 * 1024 * 1024 * 1024- 1 */
|
||||||
|
FreeClusters = 0x7FFFFFFF / (FileFsSize.SectorsPerAllocationUnit * FileFsSize.BytesPerSector);
|
||||||
|
/* If that's higher than what was queried, then return the queried value, it's OK! */
|
||||||
|
if (FreeClusters > FileFsSize.AvailableAllocationUnits.LowPart)
|
||||||
|
{
|
||||||
|
FreeClusters = FileFsSize.AvailableAllocationUnits.LowPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
*lpNumberOfFreeClusters = FreeClusters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpTotalNumberOfClusters != NULL)
|
||||||
|
{
|
||||||
|
if (!Below2GB)
|
||||||
|
{
|
||||||
|
*lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.LowPart;
|
||||||
|
}
|
||||||
|
/* If we have to remain below 2GB... */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD TotalClusters;
|
||||||
|
|
||||||
|
/* Compute how many clusters there are in less than 2GB: 2 * 1024 * 1024 * 1024- 1 */
|
||||||
|
TotalClusters = 0x7FFFFFFF / (FileFsSize.SectorsPerAllocationUnit * FileFsSize.BytesPerSector);
|
||||||
|
/* If that's higher than what was queried, then return the queried value, it's OK! */
|
||||||
|
if (TotalClusters > FileFsSize.TotalAllocationUnits.LowPart)
|
||||||
|
{
|
||||||
|
TotalClusters = FileFsSize.TotalAllocationUnits.LowPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
*lpTotalNumberOfClusters = TotalClusters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue