diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index 14dc483..9defeb9 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -400,6 +400,8 @@ void *resolveByName(const char *name) { return (void *)kernel32::MapViewOfFileEx; if (strcmp(name, "UnmapViewOfFile") == 0) return (void *)kernel32::UnmapViewOfFile; + if (strcmp(name, "FlushViewOfFile") == 0) + return (void *)kernel32::FlushViewOfFile; if (strcmp(name, "DeleteFileA") == 0) return (void *)kernel32::DeleteFileA; if (strcmp(name, "DeleteFileW") == 0) diff --git a/dll/kernel32/memoryapi.cpp b/dll/kernel32/memoryapi.cpp index 79b2363..52cbdcc 100644 --- a/dll/kernel32/memoryapi.cpp +++ b/dll/kernel32/memoryapi.cpp @@ -708,6 +708,81 @@ BOOL WIN_FUNC UnmapViewOfFile(LPCVOID lpBaseAddress) { return TRUE; } +BOOL WIN_FUNC FlushViewOfFile(LPCVOID lpBaseAddress, SIZE_T dwNumberOfBytesToFlush) { + HOST_CONTEXT_GUARD(); + DEBUG_LOG("FlushViewOfFile(%p, %zu)\n", lpBaseAddress, dwNumberOfBytesToFlush); + + if (!lpBaseAddress) { + wibo::lastError = ERROR_INVALID_PARAMETER; + return FALSE; + } + + uintptr_t address = reinterpret_cast(lpBaseAddress); + uintptr_t viewBase = 0; + size_t viewLength = 0; + uintptr_t allocationBase = 0; + size_t allocationLength = 0; + + { + std::lock_guard guard(g_viewInfoMutex); + auto it = g_viewInfo.upper_bound(address); + if (it == g_viewInfo.begin()) { + wibo::lastError = ERROR_INVALID_PARAMETER; + return FALSE; + } + --it; + const auto &view = it->second; + if (address < view.viewBase || address >= view.viewBase + view.viewLength) { + wibo::lastError = ERROR_INVALID_PARAMETER; + return FALSE; + } + viewBase = view.viewBase; + viewLength = view.viewLength; + allocationBase = view.allocationBase; + allocationLength = view.allocationLength; + } + + size_t offsetIntoView = static_cast(address - viewBase); + size_t bytesToFlush = dwNumberOfBytesToFlush; + size_t maxFlush = viewLength - offsetIntoView; + if (bytesToFlush == 0 || bytesToFlush > maxFlush) { + bytesToFlush = maxFlush; + } + if (bytesToFlush == 0) { + return TRUE; + } + + uintptr_t flushStart = address; + uintptr_t flushEnd = flushStart + bytesToFlush; + const size_t pageSize = systemPageSize(); + uintptr_t alignedStart = alignDown(flushStart, pageSize); + uintptr_t alignedEnd = alignUp(flushEnd, pageSize); + if (alignedEnd == std::numeric_limits::max()) { + alignedEnd = flushEnd; + } + + uintptr_t mappingEnd = allocationBase + allocationLength; + if (alignedEnd > mappingEnd) { + alignedEnd = mappingEnd; + } + if (alignedEnd < alignedStart) { + wibo::lastError = ERROR_INVALID_PARAMETER; + return FALSE; + } + + size_t length = static_cast(alignedEnd - alignedStart); + if (length == 0) { + length = pageSize; + } + + if (msync(reinterpret_cast(alignedStart), length, MS_SYNC) != 0) { + wibo::lastError = wibo::winErrorFromErrno(errno); + return FALSE; + } + + return TRUE; +} + LPVOID WIN_FUNC VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) { HOST_CONTEXT_GUARD(); DEBUG_LOG("VirtualAlloc(%p, %zu, %u, %u)\n", lpAddress, dwSize, flAllocationType, flProtect); diff --git a/dll/kernel32/memoryapi.h b/dll/kernel32/memoryapi.h index ffceb2e..767fc3b 100644 --- a/dll/kernel32/memoryapi.h +++ b/dll/kernel32/memoryapi.h @@ -26,6 +26,7 @@ LPVOID WIN_FUNC MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, LPVOID WIN_FUNC MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress); BOOL WIN_FUNC UnmapViewOfFile(LPCVOID lpBaseAddress); +BOOL WIN_FUNC FlushViewOfFile(LPCVOID lpBaseAddress, SIZE_T dwNumberOfBytesToFlush); LPVOID WIN_FUNC VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); BOOL WIN_FUNC VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); diff --git a/dll/ntdll.cpp b/dll/ntdll.cpp index ee2d2e7..7e45e2e 100644 --- a/dll/ntdll.cpp +++ b/dll/ntdll.cpp @@ -124,6 +124,11 @@ namespace ntdll { constexpr LARGE_INTEGER FILE_WRITE_TO_END_OF_FILE = static_cast(-1); constexpr LARGE_INTEGER FILE_USE_FILE_POINTER_POSITION = static_cast(-2); +void *WIN_ENTRY memset(void *dest, int ch, size_t count) { + VERBOSE_LOG("ntdll::memset(%p, %i, %zu)\n", dest, ch, count); + return std::memset(dest, ch, count); +} + NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) { @@ -420,6 +425,8 @@ static void *resolveByName(const char *name) { return (void *)ntdll::RtlGetVersion; if (strcmp(name, "NtQueryInformationProcess") == 0) return (void *)ntdll::NtQueryInformationProcess; + if (strcmp(name, "memset") == 0) + return (void *)ntdll::memset; return nullptr; }