diff --git a/lib/file_system.c b/lib/file_system.c index f476b29..21ac3b2 100644 --- a/lib/file_system.c +++ b/lib/file_system.c @@ -86,7 +86,12 @@ int file_truncate(Handle fd, size_t new_size) #endif #ifdef _WIN32 - return -1; // TODO: Not implemented + DWORD result = SetFilePointer((HANDLE) fd.data, (LONG) new_size, NULL, FILE_BEGIN); + if (result == INVALID_SET_FILE_POINTER) + return -1; + if (!SetEndOfFile((HANDLE) fd.data)) + return -1; + return 0; #endif } diff --git a/quakey/include/quakey.h b/quakey/include/quakey.h index d8fb57f..737bd15 100644 --- a/quakey/include/quakey.h +++ b/quakey/include/quakey.h @@ -123,11 +123,13 @@ int mock_ioctlsocket(SOCKET fd, long cmd, unsigned long *argp); BOOL mock_QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount); BOOL mock_QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency); HANDLE mock_CreateFileW(WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); +DWORD mock_GetFileAttributesA(char *lpFileName); BOOL mock_CloseHandle(HANDLE handle); BOOL mock_ReadFile(HANDLE handle, char *dst, DWORD len, DWORD *num, OVERLAPPED *ov); BOOL mock_WriteFile(HANDLE handle, char *src, DWORD len, DWORD *num, OVERLAPPED *ov); BOOL mock_GetFileSizeEx(HANDLE handle, LARGE_INTEGER *buf); DWORD mock_SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); +BOOL mock_SetEndOfFile(HANDLE hFile); BOOL mock_LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh); BOOL mock_UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh); BOOL mock_FlushFileBuffers(HANDLE handle); @@ -199,6 +201,7 @@ void mock_free(void *ptr); #define close mock_close #define ftruncate mock_ftruncate #define CreateFileW mock_CreateFileW +#define GetFileAttributesA mock_GetFileAttributesA #define CloseHandle mock_CloseHandle #define ReadFile mock_ReadFile #define WriteFile mock_WriteFile @@ -208,6 +211,7 @@ void mock_free(void *ptr); #define GetFileSizeEx mock_GetFileSizeEx #define lseek mock_lseek #define SetFilePointer mock_SetFilePointer +#define SetEndOfFile mock_SetEndOfFile #define flock mock_flock #define LockFile mock_LockFile #define UnlockFile mock_UnlockFile diff --git a/quakey/src/quakey.c b/quakey/src/quakey.c index 9f1d0c3..dddedb6 100644 --- a/quakey/src/quakey.c +++ b/quakey/src/quakey.c @@ -4371,6 +4371,25 @@ HANDLE mock_CreateFileW(WCHAR *lpFileName, return (HANDLE)(long long)desc_idx; } +DWORD mock_GetFileAttributesA(char *lpFileName) +{ + Host *host = host___; + if (host == NULL) + abort_("Call to mock_GetFileAttributesA() with no node scheduled\n"); + + // Try opening the file read-only to check existence + int ret = host_open_file(host, lpFileName, MOCKFS_O_RDONLY); + if (ret < 0) { + *host_errno_ptr(host) = ERROR_FILE_NOT_FOUND; + return INVALID_FILE_ATTRIBUTES; + } + + // File exists — close it and return normal attributes + host_close(host, ret, false); + *host_errno_ptr(host) = ERROR_SUCCESS; + return FILE_ATTRIBUTE_NORMAL; +} + BOOL mock_CloseHandle(HANDLE handle) { Host *host = host___; @@ -4574,6 +4593,45 @@ DWORD mock_SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceTo return (DWORD)(new_pos & 0xFFFFFFFF); } +BOOL mock_SetEndOfFile(HANDLE hFile) +{ + Host *host = host___; + if (host == NULL) + abort_("Call to mock_SetEndOfFile() with no node scheduled\n"); + + if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) { + *host_errno_ptr(host) = ERROR_INVALID_HANDLE; + return 0; // FALSE + } + + int desc_idx = (int)(long long)hFile; + + // Get current file position to use as the new size + int cur_pos = host_lseek(host, desc_idx, 0, HOST_SEEK_CUR); + if (cur_pos < 0) { + *host_errno_ptr(host) = ERROR_INVALID_HANDLE; + return 0; // FALSE + } + + int ret = host_ftruncate(host, desc_idx, cur_pos); + if (ret < 0) { + switch (ret) { + case HOST_ERROR_BADIDX: + *host_errno_ptr(host) = ERROR_INVALID_HANDLE; + return 0; + case HOST_ERROR_NOSPC: + *host_errno_ptr(host) = ERROR_DISK_FULL; + return 0; + default: + *host_errno_ptr(host) = ERROR_INVALID_PARAMETER; + return 0; + } + } + + *host_errno_ptr(host) = ERROR_SUCCESS; + return 1; // TRUE +} + BOOL mock_GetFileSizeEx(HANDLE handle, LARGE_INTEGER *buf) { Host *host = host___;