From 7091a3d1f7a23221c8492b35e2880f702a2eb95b Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Mon, 13 Sep 2021 08:50:03 -0700 Subject: [PATCH] Switches to using NtAllocateVirtualMemory. --- lib/winapi/filemanip.c | 114 ++++++++++++++-------------------------- lib/winapi/winioctl.h | 18 ------- lib/xboxkrnl/xboxkrnl.h | 1 - 3 files changed, 40 insertions(+), 93 deletions(-) delete mode 100644 lib/winapi/winioctl.h diff --git a/lib/winapi/filemanip.c b/lib/winapi/filemanip.c index a1cbbd550..87504b7bd 100644 --- a/lib/winapi/filemanip.c +++ b/lib/winapi/filemanip.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -242,50 +241,8 @@ BOOL MoveFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName) } } -// Determines if the two given handles refer to the same underlying file. -static BOOL TestSameFile(HANDLE hFirst, HANDLE hSecond) { - NTSTATUS status; - IO_STATUS_BLOCK ioStatusBlock; - FILE_OBJECTID_BUFFER firstObjectId, secondObjectId; - - status = NtFsControlFile( - hFirst, - NULL, - NULL, - NULL, - &ioStatusBlock, - FSCTL_GET_OBJECT_ID, - NULL, - 0, - &firstObjectId, - sizeof(firstObjectId)); - if (!NT_SUCCESS(status)) { - SetLastError(RtlNtStatusToDosError(status)); - return FALSE; - } - - status = NtFsControlFile( - hSecond, - NULL, - NULL, - NULL, - &ioStatusBlock, - FSCTL_GET_OBJECT_ID, - NULL, - 0, - &secondObjectId, - sizeof(secondObjectId)); - if (!NT_SUCCESS(status)) { - SetLastError(RtlNtStatusToDosError(status)); - return FALSE; - } - - return !memcmp(&firstObjectId.ObjectId, &secondObjectId.ObjectId, sizeof(firstObjectId.ObjectId)); -} - BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists) { - static const DWORD readBufferSize = 0x10000; NTSTATUS status; HANDLE sourceHandle; HANDLE targetHandle = INVALID_HANDLE_VALUE; @@ -294,7 +251,8 @@ BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfE OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; FILE_NETWORK_OPEN_INFORMATION networkOpenInformation; - LPVOID readBuffer; + LPVOID readBuffer = NULL; + SIZE_T readBufferRegionSize = 0x1000; DWORD bytesRead; RtlInitAnsiString(&sourcePath, lpExistingFileName); @@ -312,21 +270,12 @@ BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfE return FALSE; } - // Fail overwriting the file if the target == the source. This is - // intentionally done after the check for existence of the source - // to set the most appropriate LastError value. - if (!strcmp(lpExistingFileName, lpNewFileName)) { - NtClose(sourceHandle); - SetLastError(ERROR_SHARING_VIOLATION); - return FALSE; - } - status = NtQueryInformationFile( - sourceHandle, - &ioStatusBlock, - &networkOpenInformation, - sizeof(networkOpenInformation), - FileNetworkOpenInformation); + sourceHandle, + &ioStatusBlock, + &networkOpenInformation, + sizeof(networkOpenInformation), + FileNetworkOpenInformation); if (!NT_SUCCESS(status)) { DWORD lastError = RtlNtStatusToDosError(status); SetLastError(lastError); @@ -336,16 +285,28 @@ BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfE RtlInitAnsiString(&targetPath, lpNewFileName); InitializeObjectAttributes(&objectAttributes, &targetPath, OBJ_CASE_INSENSITIVE, ObDosDevicesDirectory(), NULL); + // Fail overwriting the file if the target == the source. This is + // intentionally done after the check for existence of the source + // to set the most appropriate LastError value. + // + // NOTE: FATX does not have ".." entries in directory tables, so it is not + // possible to overlap a file via "subdir/../file". + if (!strcmp(lpExistingFileName, lpNewFileName)) { + NtClose(sourceHandle); + SetLastError(ERROR_SHARING_VIOLATION); + return FALSE; + } + status = NtCreateFile( - &targetHandle, // FileHandle - FILE_GENERIC_WRITE, // DesiredAccess - &objectAttributes, // ObjectAttributes - &ioStatusBlock, // IoStatusBlock - &networkOpenInformation.AllocationSize, // AllocationSize - networkOpenInformation.FileAttributes, // FileAttributes - FILE_SHARE_READ | FILE_SHARE_WRITE, // ShareAccess - bFailIfExists ? FILE_CREATE : FILE_SUPERSEDE, // CreateDisposition - FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); // CreateOptions + &targetHandle, + FILE_GENERIC_WRITE, + &objectAttributes, + &ioStatusBlock, + &networkOpenInformation.AllocationSize, + networkOpenInformation.FileAttributes, + FILE_SHARE_READ | FILE_SHARE_WRITE, + bFailIfExists ? FILE_CREATE : FILE_SUPERSEDE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (!NT_SUCCESS(status)) { NtClose(sourceHandle); DWORD lastError = RtlNtStatusToDosError(status); @@ -353,18 +314,23 @@ BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfE return FALSE; } - readBuffer = MmAllocateContiguousMemory(readBufferSize); - if (!readBuffer) { + status = NtAllocateVirtualMemory(&readBuffer, + 0, + &readBufferRegionSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(status)) { NtClose(sourceHandle); NtClose(targetHandle); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + DWORD lastError = RtlNtStatusToDosError(status); + SetLastError(lastError); return FALSE; } while (TRUE) { const BYTE *bufferPos = readBuffer; - if (!ReadFile(sourceHandle, readBuffer, readBufferSize, &bytesRead, NULL)) { - MmFreeContiguousMemory(readBuffer); + if (!ReadFile(sourceHandle, readBuffer, readBufferRegionSize, &bytesRead, NULL)) { + NtFreeVirtualMemory(&readBuffer, &readBufferRegionSize, MEM_RELEASE); NtClose(sourceHandle); NtClose(targetHandle); return FALSE; @@ -377,7 +343,7 @@ BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfE while (bytesRead > 0) { DWORD bytesWritten = 0; if (!WriteFile(targetHandle, bufferPos, bytesRead, &bytesWritten, NULL)) { - MmFreeContiguousMemory(readBuffer); + NtFreeVirtualMemory(&readBuffer, &readBufferRegionSize, MEM_RELEASE); NtClose(sourceHandle); NtClose(targetHandle); return FALSE; @@ -387,7 +353,7 @@ BOOL CopyFileA (LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfE } } - MmFreeContiguousMemory(readBuffer); + NtFreeVirtualMemory(&readBuffer, &readBufferRegionSize, MEM_RELEASE); status = NtClose(sourceHandle); if (!NT_SUCCESS(status)) { diff --git a/lib/winapi/winioctl.h b/lib/winapi/winioctl.h deleted file mode 100644 index 24dd3ae8e..000000000 --- a/lib/winapi/winioctl.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __WINIOCTL_H__ -#define __WINIOCTL_H__ - -#include - -typedef struct _FILE_OBJECTID_BUFFER { - BYTE ObjectId[16]; - union { - struct { - BYTE BirthVolumeId[16]; - BYTE BirthObjectId[16]; - BYTE DomainId[16]; - } DUMMYSTRUCTNAME; - BYTE ExtendedInfo[48]; - } DUMMYUNIONNAME; -} FILE_OBJECTID_BUFFER, *PFILE_OBJECTID_BUFFER; - -#endif // __WINIOCTL_H__ diff --git a/lib/xboxkrnl/xboxkrnl.h b/lib/xboxkrnl/xboxkrnl.h index 4713184dc..285456421 100644 --- a/lib/xboxkrnl/xboxkrnl.h +++ b/lib/xboxkrnl/xboxkrnl.h @@ -2861,7 +2861,6 @@ XBAPI NTSTATUS NTAPI NtOpenDirectoryObject #define FILE_DEVICE_FILE_SYSTEM 0x00000009 #define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) XBAPI NTSTATUS NTAPI NtFsControlFile (