/* * Win32 memory management functions * * Copyright 1997 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include "ntstatus.h" #define WIN32_NO_STATUS #define NONAMELESSUNION #include "windef.h" #include "winbase.h" #include "winnls.h" #include "winternl.h" #include "winerror.h" #include "kernelbase.h" #include "wine/exception.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(virtual); /*********************************************************************** * Virtual memory functions ***********************************************************************/ /*********************************************************************** * FlushViewOfFile (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size ) { NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 ); if (status) { if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS; else SetLastError( RtlNtStatusToDosError(status) ); } return !status; } /*********************************************************************** * GetWriteWatch (kernelbase.@) */ UINT WINAPI DECLSPEC_HOTPATCH GetWriteWatch( DWORD flags, void *base, SIZE_T size, void **addresses, ULONG_PTR *count, ULONG *granularity ) { if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags, base, size, addresses, count, granularity ))) return ~0u; return 0; } /*********************************************************************** * MapViewOfFile (kernelbase.@) */ LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile( HANDLE mapping, DWORD access, DWORD offset_high, DWORD offset_low, SIZE_T count ) { return MapViewOfFileEx( mapping, access, offset_high, offset_low, count, NULL ); } /*********************************************************************** * MapViewOfFileEx (kernelbase.@) */ LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileEx( HANDLE handle, DWORD access, DWORD offset_high, DWORD offset_low, SIZE_T count, LPVOID addr ) { NTSTATUS status; LARGE_INTEGER offset; ULONG protect; BOOL exec; offset.u.LowPart = offset_low; offset.u.HighPart = offset_high; exec = access & FILE_MAP_EXECUTE; access &= ~FILE_MAP_EXECUTE; if (access == FILE_MAP_COPY) protect = exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY; else if (access & FILE_MAP_WRITE) protect = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; else if (access & FILE_MAP_READ) protect = exec ? PAGE_EXECUTE_READ : PAGE_READONLY; else protect = PAGE_NOACCESS; if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, protect )) < 0) { SetLastError( RtlNtStatusToDosError(status) ); addr = NULL; } return addr; } /*********************************************************************** * MapViewOfFileExNuma (kernelbase.@) */ LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileExNuma( HANDLE handle, DWORD access, DWORD offset_high, DWORD offset_low, SIZE_T count, LPVOID addr, DWORD numa_node ) { FIXME( "Ignoring preferred numa_node\n" ); return MapViewOfFileEx( handle, access, offset_high, offset_low, count, addr ); } /*********************************************************************** * ReadProcessMemory (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH ReadProcessMemory( HANDLE process, const void *addr, void *buffer, SIZE_T size, SIZE_T *bytes_read ) { return set_ntstatus( NtReadVirtualMemory( process, addr, buffer, size, bytes_read )); } /*********************************************************************** * ResetWriteWatch (kernelbase.@) */ UINT WINAPI DECLSPEC_HOTPATCH ResetWriteWatch( void *base, SIZE_T size ) { if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base, size ))) return ~0u; return 0; } /*********************************************************************** * UnmapViewOfFile (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH UnmapViewOfFile( const void *addr ) { if (GetVersion() & 0x80000000) { MEMORY_BASIC_INFORMATION info; if (!VirtualQuery( addr, &info, sizeof(info) ) || info.AllocationBase != addr) { SetLastError( ERROR_INVALID_ADDRESS ); return FALSE; } } return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr )); } /*********************************************************************** * VirtualAlloc (kernelbase.@) */ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc( void *addr, SIZE_T size, DWORD type, DWORD protect ) { return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect ); } /*********************************************************************** * VirtualAllocEx (kernelbase.@) */ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocEx( HANDLE process, void *addr, SIZE_T size, DWORD type, DWORD protect ) { LPVOID ret = addr; if (!set_ntstatus( NtAllocateVirtualMemory( process, &ret, 0, &size, type, protect ))) return NULL; return ret; } /*********************************************************************** * VirtualAllocExNuma (kernelbase.@) */ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocExNuma( HANDLE process, void *addr, SIZE_T size, DWORD type, DWORD protect, DWORD numa_node ) { FIXME( "Ignoring preferred numa_node\n" ); return VirtualAllocEx( process, addr, size, type, protect ); } /*********************************************************************** * VirtualFree (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH VirtualFree( void *addr, SIZE_T size, DWORD type ) { return VirtualFreeEx( GetCurrentProcess(), addr, size, type ); } /*********************************************************************** * VirtualFreeEx (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH VirtualFreeEx( HANDLE process, void *addr, SIZE_T size, DWORD type ) { return set_ntstatus( NtFreeVirtualMemory( process, &addr, &size, type )); } /*********************************************************************** * VirtualLock (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH VirtualLock( void *addr, SIZE_T size ) { return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 )); } /*********************************************************************** * VirtualProtect (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtect( void *addr, SIZE_T size, DWORD new_prot, DWORD *old_prot ) { return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot ); } /*********************************************************************** * VirtualProtectEx (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtectEx( HANDLE process, void *addr, SIZE_T size, DWORD new_prot, DWORD *old_prot ) { DWORD prot; /* Win9x allows passing NULL as old_prot while this fails on NT */ if (!old_prot && (GetVersion() & 0x80000000)) old_prot = &prot; return set_ntstatus( NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot )); } /*********************************************************************** * VirtualQuery (kernelbase.@) */ SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len ) { return VirtualQueryEx( GetCurrentProcess(), addr, info, len ); } /*********************************************************************** * VirtualQueryEx (kernelbase.@) */ SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQueryEx( HANDLE process, LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len ) { SIZE_T ret; if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret ))) return 0; return ret; } /*********************************************************************** * VirtualUnlock (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size ) { return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 )); } /*********************************************************************** * WriteProcessMemory (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer, SIZE_T size, SIZE_T *bytes_written ) { return set_ntstatus( NtWriteVirtualMemory( process, addr, buffer, size, bytes_written )); } /*********************************************************************** * Heap functions ***********************************************************************/ /*********************************************************************** * HeapCompact (kernelbase.@) */ SIZE_T WINAPI DECLSPEC_HOTPATCH HeapCompact( HANDLE heap, DWORD flags ) { return RtlCompactHeap( heap, flags ); } /*********************************************************************** * HeapCreate (kernelbase.@) */ HANDLE WINAPI DECLSPEC_HOTPATCH HeapCreate( DWORD flags, SIZE_T init_size, SIZE_T max_size ) { HANDLE ret = RtlCreateHeap( flags, NULL, max_size, init_size, NULL, NULL ); if (!ret) SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return ret; } /*********************************************************************** * HeapDestroy (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH HeapDestroy( HANDLE heap ) { if (!RtlDestroyHeap( heap )) return TRUE; SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } /*********************************************************************** * HeapLock (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH HeapLock( HANDLE heap ) { return RtlLockHeap( heap ); } /*********************************************************************** * HeapQueryInformation (kernelbase.@) */ BOOL WINAPI HeapQueryInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class, PVOID info, SIZE_T size, PSIZE_T size_out ) { return set_ntstatus( RtlQueryHeapInformation( heap, info_class, info, size, size_out )); } /*********************************************************************** * HeapSetInformation (kernelbase.@) */ BOOL WINAPI HeapSetInformation( HANDLE heap, HEAP_INFORMATION_CLASS infoclass, PVOID info, SIZE_T size ) { return set_ntstatus( RtlSetHeapInformation( heap, infoclass, info, size )); } /*********************************************************************** * HeapUnlock (kernelbase.@) */ BOOL WINAPI HeapUnlock( HANDLE heap ) { return RtlUnlockHeap( heap ); } /*********************************************************************** * HeapValidate (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH HeapValidate( HANDLE heap, DWORD flags, LPCVOID ptr ) { return RtlValidateHeap( heap, flags, ptr ); } /*********************************************************************** * HeapWalk (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry ) { return set_ntstatus( RtlWalkHeap( heap, entry )); }