This is an automated email from the git hooks/post-receive script.
www-data pushed a commit to branch master
in repository reactos.
View the commit online:
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bee374c82209d347088a…
commit 5bee374c82209d347088a42901e77d4d1a11b839
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Wed Oct 4 22:27:14 2017 +0200
[KERNEL32]: Reimplement GetDiskFreeSpaceW() to fix various issues in it. It also
brings support for appcompat
---
dll/win32/kernel32/client/file/disk.c | 135 +++++++++++++++++++++++++++-------
1 file changed, 108 insertions(+), 27 deletions(-)
diff --git a/dll/win32/kernel32/client/file/disk.c
b/dll/win32/kernel32/client/file/disk.c
index fd97a0e3a8..7ff6e88f1a 100644
--- a/dll/win32/kernel32/client/file/disk.c
+++ b/dll/win32/kernel32/client/file/disk.c
@@ -215,50 +215,131 @@ GetDiskFreeSpaceW(IN LPCWSTR lpRootPathName,
OUT LPDWORD lpNumberOfFreeClusters,
OUT LPDWORD lpTotalNumberOfClusters)
{
- FILE_FS_SIZE_INFORMATION FileFsSize;
+ BOOL Below2GB;
+ PCWSTR RootPath;
+ NTSTATUS Status;
+ HANDLE RootHandle;
+ UNICODE_STRING FileName;
IO_STATUS_BLOCK IoStatusBlock;
- WCHAR RootPathName[MAX_PATH];
- HANDLE hFile;
- NTSTATUS errCode;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ FILE_FS_SIZE_INFORMATION FileFsSize;
- if (lpRootPathName)
+ /* If no path provided, get root path */
+ RootPath = lpRootPathName;
+ if (lpRootPathName == NULL)
{
- wcsncpy (RootPathName, lpRootPathName, 3);
+ RootPath = L"\\";
}
- else
+
+ /* Convert the path to NT path */
+ if (!RtlDosPathNameToNtPathName_U(RootPath, &FileName, NULL, NULL))
{
- GetCurrentDirectoryW (MAX_PATH, RootPathName);
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
}
- RootPathName[3] = 0;
- hFile = InternalOpenDirW(RootPathName, FALSE);
- if (INVALID_HANDLE_VALUE == hFile)
+ /* 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))
{
- SetLastError(ERROR_PATH_NOT_FOUND);
+ BaseSetLastNTError(Status);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
+ if (lpBytesPerSector != NULL)
+ {
+ *lpBytesPerSector = 0;
+ }
+
return FALSE;
}
- errCode = NtQueryVolumeInformationFile(hFile,
- &IoStatusBlock,
- &FileFsSize,
- sizeof(FILE_FS_SIZE_INFORMATION),
- FileFsSizeInformation);
- if (!NT_SUCCESS(errCode))
+ /* 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))
{
- CloseHandle(hFile);
- BaseSetLastNTError (errCode);
+ BaseSetLastNTError(Status);
return FALSE;
}
- if (lpSectorsPerCluster)
+ /* 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;
- if (lpBytesPerSector)
+ }
+
+ if (lpBytesPerSector != NULL)
+ {
*lpBytesPerSector = FileFsSize.BytesPerSector;
- if (lpNumberOfFreeClusters)
- *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
- if (lpTotalNumberOfClusters)
- *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
- CloseHandle(hFile);
+ }
+
+ if (lpNumberOfFreeClusters != NULL)
+ {
+ 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;
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.