mirror of
https://github.com/reactos/reactos.git
synced 2025-06-03 08:20:27 +00:00
[KERNEL32]: Refactor a bit GetDiskFreeSpaceExW(), no ground breaking changes
This commit is contained in:
parent
87448f3d8b
commit
1e2424ee98
1 changed files with 70 additions and 56 deletions
|
@ -383,103 +383,117 @@ GetDiskFreeSpaceExW(IN LPCWSTR lpDirectoryName OPTIONAL,
|
||||||
OUT PULARGE_INTEGER lpTotalNumberOfBytes,
|
OUT PULARGE_INTEGER lpTotalNumberOfBytes,
|
||||||
OUT PULARGE_INTEGER lpTotalNumberOfFreeBytes)
|
OUT PULARGE_INTEGER lpTotalNumberOfFreeBytes)
|
||||||
{
|
{
|
||||||
union
|
PCWSTR RootPath;
|
||||||
{
|
|
||||||
FILE_FS_SIZE_INFORMATION FsSize;
|
|
||||||
FILE_FS_FULL_SIZE_INFORMATION FsFullSize;
|
|
||||||
} FsInfo;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
ULARGE_INTEGER BytesPerCluster;
|
|
||||||
HANDLE hFile;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
HANDLE RootHandle;
|
||||||
|
UNICODE_STRING FileName;
|
||||||
|
DWORD BytesPerAllocationUnit;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
FILE_FS_SIZE_INFORMATION FileFsSize;
|
||||||
|
|
||||||
|
/* If no path provided, get root path */
|
||||||
|
RootPath = lpDirectoryName;
|
||||||
if (lpDirectoryName == NULL)
|
if (lpDirectoryName == NULL)
|
||||||
lpDirectoryName = L"\\";
|
|
||||||
|
|
||||||
hFile = InternalOpenDirW(lpDirectoryName, FALSE);
|
|
||||||
if (INVALID_HANDLE_VALUE == hFile)
|
|
||||||
{
|
{
|
||||||
|
RootPath = L"\\";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the path to NT path */
|
||||||
|
if (!RtlDosPathNameToNtPathName_U(RootPath, &FileName, NULL, NULL))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpFreeBytesAvailableToCaller != NULL || lpTotalNumberOfBytes != NULL)
|
/* Open it for disk space query! */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &FileName,
|
||||||
|
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
Status = NtOpenFile(&RootHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_FREE_SPACE_QUERY);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* To get the free space available to the user associated with the
|
BaseSetLastNTError(Status);
|
||||||
current thread, try FileFsFullSizeInformation. If this is not
|
/* If error conversion lead to file not found, override to use path not found
|
||||||
supported by the file system, fall back to FileFsSize */
|
* which is more accurate
|
||||||
|
*/
|
||||||
|
if (GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
Status = NtQueryVolumeInformationFile(hFile,
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
|
||||||
&IoStatusBlock,
|
|
||||||
&FsInfo.FsFullSize,
|
return FALSE;
|
||||||
sizeof(FsInfo.FsFullSize),
|
}
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
|
||||||
|
|
||||||
|
/* If user asks for lpTotalNumberOfFreeBytes, try to use full size information */
|
||||||
|
if (lpTotalNumberOfFreeBytes != NULL)
|
||||||
|
{
|
||||||
|
FILE_FS_FULL_SIZE_INFORMATION FileFsFullSize;
|
||||||
|
|
||||||
|
/* Issue the full fs size request */
|
||||||
|
Status = NtQueryVolumeInformationFile(RootHandle, &IoStatusBlock, &FileFsFullSize,
|
||||||
|
sizeof(FILE_FS_FULL_SIZE_INFORMATION),
|
||||||
FileFsFullSizeInformation);
|
FileFsFullSizeInformation);
|
||||||
|
/* If it succeed, complete out buffers */
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Close the handle before returning data
|
/* We can close here, we'll return */
|
||||||
to avoid a handle leak in case of a fault! */
|
NtClose(RootHandle);
|
||||||
CloseHandle(hFile);
|
|
||||||
|
|
||||||
BytesPerCluster.QuadPart =
|
/* Compute the size of an AU */
|
||||||
FsInfo.FsFullSize.BytesPerSector * FsInfo.FsFullSize.SectorsPerAllocationUnit;
|
BytesPerAllocationUnit = FileFsFullSize.SectorsPerAllocationUnit * FileFsFullSize.BytesPerSector;
|
||||||
|
|
||||||
|
/* And then return what was asked */
|
||||||
if (lpFreeBytesAvailableToCaller != NULL)
|
if (lpFreeBytesAvailableToCaller != NULL)
|
||||||
{
|
{
|
||||||
lpFreeBytesAvailableToCaller->QuadPart =
|
lpFreeBytesAvailableToCaller->QuadPart = FileFsFullSize.CallerAvailableAllocationUnits.QuadPart * BytesPerAllocationUnit;
|
||||||
BytesPerCluster.QuadPart * FsInfo.FsFullSize.CallerAvailableAllocationUnits.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpTotalNumberOfBytes != NULL)
|
if (lpTotalNumberOfBytes != NULL)
|
||||||
{
|
{
|
||||||
lpTotalNumberOfBytes->QuadPart =
|
lpTotalNumberOfBytes->QuadPart = FileFsFullSize.TotalAllocationUnits.QuadPart * BytesPerAllocationUnit;
|
||||||
BytesPerCluster.QuadPart * FsInfo.FsFullSize.TotalAllocationUnits.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpTotalNumberOfFreeBytes != NULL)
|
/* No need to check for nullness ;-) */
|
||||||
{
|
lpTotalNumberOfFreeBytes->QuadPart = FileFsFullSize.ActualAvailableAllocationUnits.QuadPart * BytesPerAllocationUnit;
|
||||||
lpTotalNumberOfFreeBytes->QuadPart =
|
|
||||||
BytesPerCluster.QuadPart * FsInfo.FsFullSize.ActualAvailableAllocationUnits.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = NtQueryVolumeInformationFile(hFile,
|
/* Otherwise, fallback to normal size information */
|
||||||
&IoStatusBlock,
|
Status = NtQueryVolumeInformationFile(RootHandle, &IoStatusBlock,
|
||||||
&FsInfo.FsSize,
|
&FileFsSize, sizeof(FILE_FS_SIZE_INFORMATION),
|
||||||
sizeof(FsInfo.FsSize),
|
|
||||||
FileFsSizeInformation);
|
FileFsSizeInformation);
|
||||||
|
NtClose(RootHandle);
|
||||||
/* Close the handle before returning data
|
|
||||||
to avoid a handle leak in case of a fault! */
|
|
||||||
CloseHandle(hFile);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError (Status);
|
BaseSetLastNTError(Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BytesPerCluster.QuadPart =
|
/* Compute the size of an AU */
|
||||||
FsInfo.FsSize.BytesPerSector * FsInfo.FsSize.SectorsPerAllocationUnit;
|
BytesPerAllocationUnit = FileFsSize.SectorsPerAllocationUnit * FileFsSize.BytesPerSector;
|
||||||
|
|
||||||
if (lpFreeBytesAvailableToCaller)
|
/* And then return what was asked, available is free, the same! */
|
||||||
|
if (lpFreeBytesAvailableToCaller != NULL)
|
||||||
{
|
{
|
||||||
lpFreeBytesAvailableToCaller->QuadPart =
|
lpFreeBytesAvailableToCaller->QuadPart = FileFsSize.AvailableAllocationUnits.QuadPart * BytesPerAllocationUnit;
|
||||||
BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpTotalNumberOfBytes)
|
if (lpTotalNumberOfBytes != NULL)
|
||||||
{
|
{
|
||||||
lpTotalNumberOfBytes->QuadPart =
|
lpTotalNumberOfBytes->QuadPart = FileFsSize.TotalAllocationUnits.QuadPart * BytesPerAllocationUnit;
|
||||||
BytesPerCluster.QuadPart * FsInfo.FsSize.TotalAllocationUnits.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpTotalNumberOfFreeBytes)
|
if (lpTotalNumberOfFreeBytes != NULL)
|
||||||
{
|
{
|
||||||
lpTotalNumberOfFreeBytes->QuadPart =
|
lpTotalNumberOfFreeBytes->QuadPart = FileFsSize.AvailableAllocationUnits.QuadPart * BytesPerAllocationUnit;
|
||||||
BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in a new issue