2 * Win32 memory management functions
4 * Copyright 1997 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <sys/types.h>
28 #define WIN32_NO_STATUS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
38 #include "kernelbase.h"
39 #include "wine/exception.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(heap
);
43 WINE_DECLARE_DEBUG_CHANNEL(virtual);
46 /***********************************************************************
47 * Virtual memory functions
48 ***********************************************************************/
51 /***********************************************************************
52 * FlushViewOfFile (kernelbase.@)
54 BOOL WINAPI DECLSPEC_HOTPATCH
FlushViewOfFile( const void *base
, SIZE_T size
)
56 NTSTATUS status
= NtFlushVirtualMemory( GetCurrentProcess(), &base
, &size
, 0 );
58 if (status
== STATUS_NOT_MAPPED_DATA
) status
= STATUS_SUCCESS
;
59 return set_ntstatus( status
);
63 /***********************************************************************
64 * GetLargePageMinimum (kernelbase.@)
66 SIZE_T WINAPI
GetLargePageMinimum(void)
68 return 2 * 1024 * 1024;
72 /***********************************************************************
73 * GetNativeSystemInfo (kernelbase.@)
75 void WINAPI DECLSPEC_HOTPATCH
GetNativeSystemInfo( SYSTEM_INFO
*si
)
78 if (!is_wow64
) return;
79 switch (si
->u
.s
.wProcessorArchitecture
)
81 case PROCESSOR_ARCHITECTURE_INTEL
:
82 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_AMD64
;
83 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
86 FIXME( "Add the proper information for %d in wow64 mode\n", si
->u
.s
.wProcessorArchitecture
);
91 /***********************************************************************
92 * GetSystemInfo (kernelbase.@)
94 void WINAPI DECLSPEC_HOTPATCH
GetSystemInfo( SYSTEM_INFO
*si
)
96 SYSTEM_BASIC_INFORMATION basic_info
;
97 SYSTEM_CPU_INFORMATION cpu_info
;
99 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
100 &basic_info
, sizeof(basic_info
), NULL
)) ||
101 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation
,
102 &cpu_info
, sizeof(cpu_info
), NULL
)))
105 si
->u
.s
.wProcessorArchitecture
= cpu_info
.Architecture
;
106 si
->u
.s
.wReserved
= 0;
107 si
->dwPageSize
= basic_info
.PageSize
;
108 si
->lpMinimumApplicationAddress
= basic_info
.LowestUserAddress
;
109 si
->lpMaximumApplicationAddress
= basic_info
.HighestUserAddress
;
110 si
->dwActiveProcessorMask
= basic_info
.ActiveProcessorsAffinityMask
;
111 si
->dwNumberOfProcessors
= basic_info
.NumberOfProcessors
;
112 si
->dwAllocationGranularity
= basic_info
.AllocationGranularity
;
113 si
->wProcessorLevel
= cpu_info
.Level
;
114 si
->wProcessorRevision
= cpu_info
.Revision
;
116 switch (cpu_info
.Architecture
)
118 case PROCESSOR_ARCHITECTURE_INTEL
:
119 switch (cpu_info
.Level
)
121 case 3: si
->dwProcessorType
= PROCESSOR_INTEL_386
; break;
122 case 4: si
->dwProcessorType
= PROCESSOR_INTEL_486
; break;
124 case 6: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
125 default: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
128 case PROCESSOR_ARCHITECTURE_PPC
:
129 switch (cpu_info
.Level
)
131 case 1: si
->dwProcessorType
= PROCESSOR_PPC_601
; break;
133 case 6: si
->dwProcessorType
= PROCESSOR_PPC_603
; break;
134 case 4: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
135 case 9: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
136 case 20: si
->dwProcessorType
= PROCESSOR_PPC_620
; break;
137 default: si
->dwProcessorType
= 0;
140 case PROCESSOR_ARCHITECTURE_AMD64
:
141 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
143 case PROCESSOR_ARCHITECTURE_ARM
:
144 switch (cpu_info
.Level
)
146 case 4: si
->dwProcessorType
= PROCESSOR_ARM_7TDMI
; break;
147 default: si
->dwProcessorType
= PROCESSOR_ARM920
;
150 case PROCESSOR_ARCHITECTURE_ARM64
:
151 si
->dwProcessorType
= 0;
154 FIXME( "Unknown processor architecture %x\n", cpu_info
.Architecture
);
155 si
->dwProcessorType
= 0;
161 /***********************************************************************
162 * GetSystemFileCacheSize (kernelbase.@)
164 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemFileCacheSize( SIZE_T
*mincache
, SIZE_T
*maxcache
, DWORD
*flags
)
166 FIXME( "stub: %p %p %p\n", mincache
, maxcache
, flags
);
167 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
172 /***********************************************************************
173 * GetWriteWatch (kernelbase.@)
175 UINT WINAPI DECLSPEC_HOTPATCH
GetWriteWatch( DWORD flags
, void *base
, SIZE_T size
, void **addresses
,
176 ULONG_PTR
*count
, ULONG
*granularity
)
178 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags
, base
, size
,
179 addresses
, count
, granularity
)))
185 /***********************************************************************
186 * MapViewOfFile (kernelbase.@)
188 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile( HANDLE mapping
, DWORD access
, DWORD offset_high
,
189 DWORD offset_low
, SIZE_T count
)
191 return MapViewOfFileEx( mapping
, access
, offset_high
, offset_low
, count
, NULL
);
195 /***********************************************************************
196 * MapViewOfFileEx (kernelbase.@)
198 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileEx( HANDLE handle
, DWORD access
, DWORD offset_high
,
199 DWORD offset_low
, SIZE_T count
, LPVOID addr
)
202 LARGE_INTEGER offset
;
206 offset
.u
.LowPart
= offset_low
;
207 offset
.u
.HighPart
= offset_high
;
209 exec
= access
& FILE_MAP_EXECUTE
;
210 access
&= ~FILE_MAP_EXECUTE
;
212 if (access
== FILE_MAP_COPY
)
213 protect
= exec
? PAGE_EXECUTE_WRITECOPY
: PAGE_WRITECOPY
;
214 else if (access
& FILE_MAP_WRITE
)
215 protect
= exec
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
216 else if (access
& FILE_MAP_READ
)
217 protect
= exec
? PAGE_EXECUTE_READ
: PAGE_READONLY
;
218 else protect
= PAGE_NOACCESS
;
220 if ((status
= NtMapViewOfSection( handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
221 &count
, ViewShare
, 0, protect
)) < 0)
223 SetLastError( RtlNtStatusToDosError(status
) );
230 /***********************************************************************
231 * ReadProcessMemory (kernelbase.@)
233 BOOL WINAPI DECLSPEC_HOTPATCH
ReadProcessMemory( HANDLE process
, const void *addr
, void *buffer
,
234 SIZE_T size
, SIZE_T
*bytes_read
)
236 return set_ntstatus( NtReadVirtualMemory( process
, addr
, buffer
, size
, bytes_read
));
240 /***********************************************************************
241 * ResetWriteWatch (kernelbase.@)
243 UINT WINAPI DECLSPEC_HOTPATCH
ResetWriteWatch( void *base
, SIZE_T size
)
245 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base
, size
)))
251 /***********************************************************************
252 * SetSystemFileCacheSize (kernelbase.@)
254 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemFileCacheSize( SIZE_T mincache
, SIZE_T maxcache
, DWORD flags
)
256 FIXME( "stub: %ld %ld %d\n", mincache
, maxcache
, flags
);
257 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
262 /***********************************************************************
263 * UnmapViewOfFile (kernelbase.@)
265 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile( const void *addr
)
267 if (GetVersion() & 0x80000000)
269 MEMORY_BASIC_INFORMATION info
;
270 if (!VirtualQuery( addr
, &info
, sizeof(info
) ) || info
.AllocationBase
!= addr
)
272 SetLastError( ERROR_INVALID_ADDRESS
);
276 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr
));
280 /***********************************************************************
281 * VirtualAlloc (kernelbase.@)
283 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc( void *addr
, SIZE_T size
, DWORD type
, DWORD protect
)
285 return VirtualAllocEx( GetCurrentProcess(), addr
, size
, type
, protect
);
289 /***********************************************************************
290 * VirtualAllocEx (kernelbase.@)
292 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocEx( HANDLE process
, void *addr
, SIZE_T size
,
293 DWORD type
, DWORD protect
)
297 if (!set_ntstatus( NtAllocateVirtualMemory( process
, &ret
, 0, &size
, type
, protect
))) return NULL
;
302 /***********************************************************************
303 * VirtualAlloc2 (kernelbase.@)
305 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc2( HANDLE process
, void *addr
, SIZE_T size
,
306 DWORD type
, DWORD protect
,
307 MEM_EXTENDED_PARAMETER
*parameters
, ULONG count
)
311 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process
, &ret
, &size
, type
, protect
, parameters
, count
)))
317 /***********************************************************************
318 * VirtualFree (kernelbase.@)
320 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFree( void *addr
, SIZE_T size
, DWORD type
)
322 return VirtualFreeEx( GetCurrentProcess(), addr
, size
, type
);
326 /***********************************************************************
327 * VirtualFreeEx (kernelbase.@)
329 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFreeEx( HANDLE process
, void *addr
, SIZE_T size
, DWORD type
)
331 return set_ntstatus( NtFreeVirtualMemory( process
, &addr
, &size
, type
));
335 /***********************************************************************
336 * VirtualLock (kernelbase.@)
338 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualLock( void *addr
, SIZE_T size
)
340 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
344 /***********************************************************************
345 * VirtualProtect (kernelbase.@)
347 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtect( void *addr
, SIZE_T size
, DWORD new_prot
, DWORD
*old_prot
)
349 return VirtualProtectEx( GetCurrentProcess(), addr
, size
, new_prot
, old_prot
);
353 /***********************************************************************
354 * VirtualProtectEx (kernelbase.@)
356 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtectEx( HANDLE process
, void *addr
, SIZE_T size
,
357 DWORD new_prot
, DWORD
*old_prot
)
361 /* Win9x allows passing NULL as old_prot while this fails on NT */
362 if (!old_prot
&& (GetVersion() & 0x80000000)) old_prot
= &prot
;
363 return set_ntstatus( NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
));
367 /***********************************************************************
368 * VirtualQuery (kernelbase.@)
370 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQuery( LPCVOID addr
, PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
372 return VirtualQueryEx( GetCurrentProcess(), addr
, info
, len
);
376 /***********************************************************************
377 * VirtualQueryEx (kernelbase.@)
379 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQueryEx( HANDLE process
, LPCVOID addr
,
380 PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
384 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryBasicInformation
, info
, len
, &ret
)))
390 /***********************************************************************
391 * VirtualUnlock (kernelbase.@)
393 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualUnlock( void *addr
, SIZE_T size
)
395 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
399 /***********************************************************************
400 * WriteProcessMemory (kernelbase.@)
402 BOOL WINAPI DECLSPEC_HOTPATCH
WriteProcessMemory( HANDLE process
, void *addr
, const void *buffer
,
403 SIZE_T size
, SIZE_T
*bytes_written
)
405 return set_ntstatus( NtWriteVirtualMemory( process
, addr
, buffer
, size
, bytes_written
));
409 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
410 BOOL WINAPI
IsBadStringPtrA( LPCSTR str
, UINT_PTR max
)
412 if (!str
) return TRUE
;
415 volatile const char *p
= str
;
416 while (p
!= str
+ max
) if (!*p
++) break;
427 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
428 BOOL WINAPI
IsBadStringPtrW( LPCWSTR str
, UINT_PTR max
)
430 if (!str
) return TRUE
;
433 volatile const WCHAR
*p
= str
;
434 while (p
!= str
+ max
) if (!*p
++) break;
445 /***********************************************************************
447 ***********************************************************************/
450 /***********************************************************************
451 * HeapCompact (kernelbase.@)
453 SIZE_T WINAPI DECLSPEC_HOTPATCH
HeapCompact( HANDLE heap
, DWORD flags
)
455 return RtlCompactHeap( heap
, flags
);
459 /***********************************************************************
460 * HeapCreate (kernelbase.@)
462 HANDLE WINAPI DECLSPEC_HOTPATCH
HeapCreate( DWORD flags
, SIZE_T init_size
, SIZE_T max_size
)
464 HANDLE ret
= RtlCreateHeap( flags
, NULL
, max_size
, init_size
, NULL
, NULL
);
465 if (!ret
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
470 /***********************************************************************
471 * HeapDestroy (kernelbase.@)
473 BOOL WINAPI DECLSPEC_HOTPATCH
HeapDestroy( HANDLE heap
)
475 if (!RtlDestroyHeap( heap
)) return TRUE
;
476 SetLastError( ERROR_INVALID_HANDLE
);
481 /***********************************************************************
482 * HeapLock (kernelbase.@)
484 BOOL WINAPI DECLSPEC_HOTPATCH
HeapLock( HANDLE heap
)
486 return RtlLockHeap( heap
);
490 /***********************************************************************
491 * HeapQueryInformation (kernelbase.@)
493 BOOL WINAPI
HeapQueryInformation( HANDLE heap
, HEAP_INFORMATION_CLASS info_class
,
494 PVOID info
, SIZE_T size
, PSIZE_T size_out
)
496 return set_ntstatus( RtlQueryHeapInformation( heap
, info_class
, info
, size
, size_out
));
500 /***********************************************************************
501 * HeapSetInformation (kernelbase.@)
503 BOOL WINAPI
HeapSetInformation( HANDLE heap
, HEAP_INFORMATION_CLASS infoclass
, PVOID info
, SIZE_T size
)
505 return set_ntstatus( RtlSetHeapInformation( heap
, infoclass
, info
, size
));
509 /***********************************************************************
510 * HeapUnlock (kernelbase.@)
512 BOOL WINAPI
HeapUnlock( HANDLE heap
)
514 return RtlUnlockHeap( heap
);
518 /***********************************************************************
519 * HeapValidate (kernelbase.@)
521 BOOL WINAPI DECLSPEC_HOTPATCH
HeapValidate( HANDLE heap
, DWORD flags
, LPCVOID ptr
)
523 return RtlValidateHeap( heap
, flags
, ptr
);
527 /***********************************************************************
528 * HeapWalk (kernelbase.@)
530 BOOL WINAPI DECLSPEC_HOTPATCH
HeapWalk( HANDLE heap
, PROCESS_HEAP_ENTRY
*entry
)
532 return set_ntstatus( RtlWalkHeap( heap
, entry
));
536 /***********************************************************************
537 * Global/local heap functions
538 ***********************************************************************/
540 #include "pshpack1.h"
552 #define MAGIC_LOCAL_USED 0x5342
553 /* align the storage needed for the HLOCAL on an 8-byte boundary thus
554 * LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
555 * size = 8*k, where k=1,2,3,... allocs exactly the given size.
556 * The Minolta DiMAGE Image Viewer heavily relies on this, corrupting
557 * the output jpeg's > 1 MB if not */
558 #define HLOCAL_STORAGE (sizeof(HLOCAL) * 2)
560 static inline struct local_header
*get_header( HLOCAL hmem
)
562 return (struct local_header
*)((char *)hmem
- 2);
565 static inline HLOCAL
get_handle( struct local_header
*header
)
570 static inline BOOL
is_pointer( HLOCAL hmem
)
572 return !((ULONG_PTR
)hmem
& 2);
575 /***********************************************************************
576 * GlobalAlloc (kernelbase.@)
578 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalAlloc( UINT flags
, SIZE_T size
)
580 /* mask out obsolete flags */
581 flags
&= ~(GMEM_NOCOMPACT
| GMEM_NOT_BANKED
| GMEM_NOTIFY
);
583 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
584 if (!(flags
& GMEM_MOVEABLE
) && !size
) size
= 1;
586 return LocalAlloc( flags
, size
);
590 /***********************************************************************
591 * GlobalFree (kernelbase.@)
593 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalFree( HLOCAL hmem
)
595 return LocalFree( hmem
);
599 /***********************************************************************
600 * LocalAlloc (kernelbase.@)
602 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalAlloc( UINT flags
, SIZE_T size
)
604 struct local_header
*header
;
605 DWORD heap_flags
= 0;
608 if (flags
& LMEM_ZEROINIT
) heap_flags
= HEAP_ZERO_MEMORY
;
610 if (!(flags
& LMEM_MOVEABLE
)) /* pointer */
612 ptr
= HeapAlloc( GetProcessHeap(), heap_flags
, size
);
613 TRACE( "(flags=%04x) returning %p\n", flags
, ptr
);
617 if (size
> INT_MAX
- HLOCAL_STORAGE
)
619 SetLastError( ERROR_OUTOFMEMORY
);
622 if (!(header
= HeapAlloc( GetProcessHeap(), 0, sizeof(*header
) ))) return 0;
624 header
->magic
= MAGIC_LOCAL_USED
;
625 header
->flags
= flags
>> 8;
630 if (!(ptr
= HeapAlloc(GetProcessHeap(), heap_flags
, size
+ HLOCAL_STORAGE
)))
632 HeapFree( GetProcessHeap(), 0, header
);
635 *(HLOCAL
*)ptr
= get_handle( header
);
636 header
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
638 else header
->ptr
= NULL
;
640 TRACE( "(flags=%04x) returning handle %p pointer %p\n",
641 flags
, get_handle( header
), header
->ptr
);
642 return get_handle( header
);
646 /***********************************************************************
647 * LocalFree (kernelbase.@)
649 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalFree( HLOCAL hmem
)
651 struct local_header
*header
;
654 RtlLockHeap( GetProcessHeap() );
658 if (is_pointer(hmem
)) /* POINTER */
660 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, hmem
))
662 SetLastError( ERROR_INVALID_HANDLE
);
668 header
= get_header( hmem
);
669 if (header
->magic
== MAGIC_LOCAL_USED
)
671 header
->magic
= 0xdead;
674 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
,
675 (char *)header
->ptr
- HLOCAL_STORAGE
))
678 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, header
)) ret
= hmem
;
682 WARN( "invalid handle %p (magic: 0x%04x)\n", hmem
, header
->magic
);
683 SetLastError( ERROR_INVALID_HANDLE
);
690 WARN( "invalid handle %p\n", hmem
);
691 SetLastError( ERROR_INVALID_HANDLE
);
695 RtlUnlockHeap( GetProcessHeap() );
700 /***********************************************************************
701 * LocalLock (kernelbase.@)
703 LPVOID WINAPI DECLSPEC_HOTPATCH
LocalLock( HLOCAL hmem
)
707 if (is_pointer( hmem
))
711 volatile char *p
= hmem
;
722 RtlLockHeap( GetProcessHeap() );
725 struct local_header
*header
= get_header( hmem
);
726 if (header
->magic
== MAGIC_LOCAL_USED
)
729 if (!header
->ptr
) SetLastError( ERROR_DISCARDED
);
730 else if (header
->lock
< LMEM_LOCKCOUNT
) header
->lock
++;
734 WARN( "invalid handle %p (magic: 0x%04x)\n", hmem
, header
->magic
);
735 SetLastError( ERROR_INVALID_HANDLE
);
740 WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem
);
741 SetLastError( ERROR_INVALID_HANDLE
);
744 RtlUnlockHeap( GetProcessHeap() );
749 /***********************************************************************
750 * LocalReAlloc (kernelbase.@)
752 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalReAlloc( HLOCAL hmem
, SIZE_T size
, UINT flags
)
754 struct local_header
*header
;
757 DWORD heap_flags
= (flags
& LMEM_ZEROINIT
) ? HEAP_ZERO_MEMORY
: 0;
759 RtlLockHeap( GetProcessHeap() );
760 if (flags
& LMEM_MODIFY
) /* modify flags */
762 if (is_pointer( hmem
) && (flags
& LMEM_MOVEABLE
))
764 /* make a fixed block moveable
765 * actually only NT is able to do this. But it's soo simple
769 WARN( "null handle\n");
770 SetLastError( ERROR_NOACCESS
);
774 size
= RtlSizeHeap( GetProcessHeap(), 0, hmem
);
775 ret
= LocalAlloc( flags
, size
);
776 ptr
= LocalLock( ret
);
777 memcpy( ptr
, hmem
, size
);
782 else if (!is_pointer( hmem
) && (flags
& LMEM_DISCARDABLE
))
784 /* change the flags to make our block "discardable" */
785 header
= get_header( hmem
);
786 header
->flags
|= LMEM_DISCARDABLE
>> 8;
789 else SetLastError( ERROR_INVALID_PARAMETER
);
793 if (is_pointer( hmem
))
795 /* reallocate fixed memory */
796 if (!(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
797 ret
= HeapReAlloc( GetProcessHeap(), heap_flags
, hmem
, size
);
801 /* reallocate a moveable block */
802 header
= get_header( hmem
);
805 if (size
<= INT_MAX
- HLOCAL_STORAGE
)
809 if ((ptr
= HeapReAlloc( GetProcessHeap(), heap_flags
,
810 (char *)header
->ptr
- HLOCAL_STORAGE
,
811 size
+ HLOCAL_STORAGE
)))
813 header
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
819 if ((ptr
= HeapAlloc( GetProcessHeap(), heap_flags
, size
+ HLOCAL_STORAGE
)))
821 *(HLOCAL
*)ptr
= hmem
;
822 header
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
827 else SetLastError( ERROR_OUTOFMEMORY
);
831 if (header
->lock
== 0)
835 HeapFree( GetProcessHeap(), 0, (char *)header
->ptr
- HLOCAL_STORAGE
);
840 else WARN( "not freeing memory associated with locked handle\n" );
844 RtlUnlockHeap( GetProcessHeap() );
849 /***********************************************************************
850 * LocalUnlock (kernelbase.@)
852 BOOL WINAPI DECLSPEC_HOTPATCH
LocalUnlock( HLOCAL hmem
)
856 if (is_pointer( hmem
))
858 SetLastError( ERROR_NOT_LOCKED
);
862 RtlLockHeap( GetProcessHeap() );
865 struct local_header
*header
= get_header( hmem
);
866 if (header
->magic
== MAGIC_LOCAL_USED
)
871 ret
= (header
->lock
!= 0);
872 if (!ret
) SetLastError( NO_ERROR
);
876 WARN( "%p not locked\n", hmem
);
877 SetLastError( ERROR_NOT_LOCKED
);
882 WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem
, header
->magic
);
883 SetLastError( ERROR_INVALID_HANDLE
);
888 WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem
);
889 SetLastError( ERROR_INVALID_PARAMETER
);
892 RtlUnlockHeap( GetProcessHeap() );
897 /***********************************************************************
898 * Memory resource functions
899 ***********************************************************************/
902 /***********************************************************************
903 * CreateMemoryResourceNotification (kernelbase.@)
905 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type
)
908 UNICODE_STRING nameW
;
909 OBJECT_ATTRIBUTES attr
;
913 case LowMemoryResourceNotification
:
914 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\LowMemoryCondition" );
916 case HighMemoryResourceNotification
:
917 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\HighMemoryCondition" );
920 SetLastError( ERROR_INVALID_PARAMETER
);
924 InitializeObjectAttributes( &attr
, &nameW
, 0, 0, NULL
);
925 if (!set_ntstatus( NtOpenEvent( &ret
, EVENT_ALL_ACCESS
, &attr
))) return 0;
929 /***********************************************************************
930 * QueryMemoryResourceNotification (kernelbase.@)
932 BOOL WINAPI DECLSPEC_HOTPATCH
QueryMemoryResourceNotification( HANDLE handle
, BOOL
*state
)
934 switch (WaitForSingleObject( handle
, 0 ))
943 SetLastError( ERROR_INVALID_PARAMETER
);
948 /***********************************************************************
949 * Physical memory functions
950 ***********************************************************************/
953 /***********************************************************************
954 * AllocateUserPhysicalPages (kernelbase.@)
956 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
957 ULONG_PTR
*userarray
)
959 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
960 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
965 /***********************************************************************
966 * FreeUserPhysicalPages (kernelbase.@)
968 BOOL WINAPI DECLSPEC_HOTPATCH
FreeUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
969 ULONG_PTR
*userarray
)
971 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
973 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
978 /***********************************************************************
979 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
981 BOOL WINAPI DECLSPEC_HOTPATCH
GetPhysicallyInstalledSystemMemory( ULONGLONG
*memory
)
983 MEMORYSTATUSEX status
;
987 SetLastError( ERROR_INVALID_PARAMETER
);
990 status
.dwLength
= sizeof(status
);
991 GlobalMemoryStatusEx( &status
);
992 *memory
= status
.ullTotalPhys
/ 1024;
997 /***********************************************************************
998 * GlobalMemoryStatusEx (kernelbase.@)
1000 BOOL WINAPI DECLSPEC_HOTPATCH
GlobalMemoryStatusEx( MEMORYSTATUSEX
*status
)
1002 static MEMORYSTATUSEX cached_status
;
1003 static DWORD last_check
;
1004 SYSTEM_BASIC_INFORMATION basic_info
;
1005 SYSTEM_PERFORMANCE_INFORMATION perf_info
;
1007 if (status
->dwLength
!= sizeof(*status
))
1009 SetLastError( ERROR_INVALID_PARAMETER
);
1012 if ((NtGetTickCount() - last_check
) < 1000)
1014 *status
= cached_status
;
1017 last_check
= NtGetTickCount();
1019 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
1020 &basic_info
, sizeof(basic_info
), NULL
)) ||
1021 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation
,
1022 &perf_info
, sizeof(perf_info
), NULL
)))
1025 status
->dwMemoryLoad
= 0;
1026 status
->ullTotalPhys
= perf_info
.TotalCommitLimit
;
1027 status
->ullAvailPhys
= perf_info
.AvailablePages
;
1028 status
->ullTotalPageFile
= perf_info
.TotalCommitLimit
+ 1; /* Titan Quest refuses to run if TotalPageFile <= TotalPhys */
1029 status
->ullAvailPageFile
= status
->ullTotalPageFile
- perf_info
.TotalCommittedPages
;
1030 status
->ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
;
1031 status
->ullAvailVirtual
= status
->ullTotalVirtual
- 64 * 1024; /* FIXME */
1032 status
->ullAvailExtendedVirtual
= 0;
1034 status
->ullTotalPhys
*= basic_info
.PageSize
;
1035 status
->ullAvailPhys
*= basic_info
.PageSize
;
1036 status
->ullTotalPageFile
*= basic_info
.PageSize
;
1037 status
->ullAvailPageFile
*= basic_info
.PageSize
;
1039 if (status
->ullTotalPhys
)
1040 status
->dwMemoryLoad
= (status
->ullTotalPhys
- status
->ullAvailPhys
) / (status
->ullTotalPhys
/ 100);
1042 TRACE_(virtual)( "MemoryLoad %d, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1043 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1044 status
->dwMemoryLoad
, wine_dbgstr_longlong(status
->ullTotalPhys
),
1045 wine_dbgstr_longlong(status
->ullAvailPhys
), wine_dbgstr_longlong(status
->ullTotalPageFile
),
1046 wine_dbgstr_longlong(status
->ullAvailPageFile
), wine_dbgstr_longlong(status
->ullTotalVirtual
),
1047 wine_dbgstr_longlong(status
->ullAvailVirtual
) );
1049 cached_status
= *status
;
1054 /***********************************************************************
1055 * MapUserPhysicalPages (kernelbase.@)
1057 BOOL WINAPI DECLSPEC_HOTPATCH
MapUserPhysicalPages( void *addr
, ULONG_PTR page_count
, ULONG_PTR
*pages
)
1059 FIXME( "stub: %p %lu %p\n", addr
, page_count
, pages
);
1061 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1066 /***********************************************************************
1068 ***********************************************************************/
1071 /***********************************************************************
1072 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1074 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPagesNuma( HANDLE process
, ULONG_PTR
*pages
,
1075 ULONG_PTR
*userarray
, DWORD node
)
1077 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1078 return AllocateUserPhysicalPages( process
, pages
, userarray
);
1082 /***********************************************************************
1083 * CreateFileMappingNumaW (kernelbase.@)
1085 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileMappingNumaW( HANDLE file
, LPSECURITY_ATTRIBUTES sa
,
1086 DWORD protect
, DWORD size_high
, DWORD size_low
,
1087 LPCWSTR name
, DWORD node
)
1089 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1090 return CreateFileMappingW( file
, sa
, protect
, size_high
, size_low
, name
);
1094 /***********************************************************************
1095 * GetLogicalProcessorInformation (kernelbase.@)
1097 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buffer
,
1104 SetLastError( ERROR_INVALID_PARAMETER
);
1107 status
= NtQuerySystemInformation( SystemLogicalProcessorInformation
, buffer
, *len
, len
);
1108 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1109 return set_ntstatus( status
);
1113 /***********************************************************************
1114 * GetLogicalProcessorInformationEx (kernelbase.@)
1116 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship
,
1117 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buffer
, DWORD
*len
)
1123 SetLastError( ERROR_INVALID_PARAMETER
);
1126 status
= NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx
, &relationship
,
1127 sizeof(relationship
), buffer
, *len
, len
);
1128 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1129 return set_ntstatus( status
);
1133 /**********************************************************************
1134 * GetNumaHighestNodeNumber (kernelbase.@)
1136 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaHighestNodeNumber( ULONG
*node
)
1138 FIXME( "semi-stub: %p\n", node
);
1144 /**********************************************************************
1145 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1147 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaNodeProcessorMaskEx( USHORT node
, GROUP_AFFINITY
*mask
)
1149 FIXME( "stub: %hu %p\n", node
, mask
);
1150 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1155 /***********************************************************************
1156 * GetNumaProximityNodeEx (kernelbase.@)
1158 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaProximityNodeEx( ULONG proximity_id
, USHORT
*node
)
1160 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1165 /***********************************************************************
1166 * MapViewOfFileExNuma (kernelbase.@)
1168 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileExNuma( HANDLE handle
, DWORD access
, DWORD offset_high
,
1169 DWORD offset_low
, SIZE_T count
, LPVOID addr
,
1172 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1173 return MapViewOfFileEx( handle
, access
, offset_high
, offset_low
, count
, addr
);
1177 /***********************************************************************
1178 * VirtualAllocExNuma (kernelbase.@)
1180 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocExNuma( HANDLE process
, void *addr
, SIZE_T size
,
1181 DWORD type
, DWORD protect
, DWORD node
)
1183 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1184 return VirtualAllocEx( process
, addr
, size
, type
, protect
);
1188 /***********************************************************************
1190 ***********************************************************************/
1193 #if defined(__i386__) || defined(__x86_64__)
1194 /***********************************************************************
1195 * GetEnabledXStateFeatures (kernelbase.@)
1197 DWORD64 WINAPI
GetEnabledXStateFeatures(void)
1200 return RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 );
1204 /***********************************************************************
1205 * InitializeContext2 (kernelbase.@)
1207 BOOL WINAPI
InitializeContext2( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
,
1208 ULONG64 compaction_mask
)
1213 TRACE( "buffer %p, context_flags %#x, context %p, ret_length %p, compaction_mask %s.\n",
1214 buffer
, context_flags
, context
, length
, wine_dbgstr_longlong(compaction_mask
) );
1216 orig_length
= *length
;
1218 if ((status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
)))
1220 if (status
== STATUS_NOT_SUPPORTED
&& context_flags
& 0x40)
1222 context_flags
&= ~0x40;
1223 status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
);
1227 return set_ntstatus( status
);
1230 if (!buffer
|| orig_length
< *length
)
1232 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1236 if ((status
= RtlInitializeExtendedContext2( buffer
, context_flags
, (CONTEXT_EX
**)context
, compaction_mask
)))
1237 return set_ntstatus( status
);
1239 *context
= (CONTEXT
*)((BYTE
*)*context
+ (*(CONTEXT_EX
**)context
)->Legacy
.Offset
);
1244 /***********************************************************************
1245 * InitializeContext (kernelbase.@)
1247 BOOL WINAPI
InitializeContext( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
)
1249 return InitializeContext2( buffer
, context_flags
, context
, length
, ~(ULONG64
)0 );
1252 /***********************************************************************
1253 * CopyContext (kernelbase.@)
1255 BOOL WINAPI
CopyContext( CONTEXT
*dst
, DWORD context_flags
, CONTEXT
*src
)
1257 DWORD context_size
, arch_flag
, flags_offset
, dst_flags
, src_flags
;
1258 static const DWORD arch_mask
= 0x110000;
1262 TRACE("dst %p, context_flags %#x, src %p.\n", dst
, context_flags
, src
);
1264 if (context_flags
& 0x40 && !RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 ))
1266 SetLastError(ERROR_NOT_SUPPORTED
);
1270 arch_flag
= context_flags
& arch_mask
;
1274 case 0x10000: context_size
= 0x2cc; flags_offset
= 0; break;
1275 case 0x100000: context_size
= 0x4d0; flags_offset
= 0x30; break;
1277 SetLastError( ERROR_INVALID_PARAMETER
);
1283 dst_flags
= *(DWORD
*)(d
+ flags_offset
);
1284 src_flags
= *(DWORD
*)(s
+ flags_offset
);
1286 if ((dst_flags
& arch_mask
) != arch_flag
1287 || (src_flags
& arch_mask
) != arch_flag
)
1289 SetLastError( ERROR_INVALID_PARAMETER
);
1293 context_flags
&= src_flags
;
1295 if (context_flags
& ~dst_flags
& 0x40)
1297 SetLastError(ERROR_MORE_DATA
);
1301 if ((status
= RtlCopyExtendedContext( (CONTEXT_EX
*)(d
+ context_size
), context_flags
,
1302 (CONTEXT_EX
*)(s
+ context_size
) )))
1303 return set_ntstatus( status
);
1310 #if defined(__x86_64__)
1311 /***********************************************************************
1312 * LocateXStateFeature (kernelbase.@)
1314 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1316 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1319 if (feature_id
>= 2)
1320 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1321 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1323 if (feature_id
== 1)
1326 *length
= sizeof(M128A
) * 16;
1328 return &context
->u
.FltSave
.XmmRegisters
;
1332 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1334 return &context
->u
.FltSave
;
1337 /***********************************************************************
1338 * SetXStateFeaturesMask (kernelbase.@)
1340 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1342 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1345 if (feature_mask
& 0x3)
1346 context
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
1348 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1349 return !(feature_mask
& ~(DWORD64
)3);
1351 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1355 /***********************************************************************
1356 * GetXStateFeaturesMask (kernelbase.@)
1358 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1360 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1363 *feature_mask
= (context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
1366 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1367 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1371 #elif defined(__i386__)
1372 /***********************************************************************
1373 * LocateXStateFeature (kernelbase.@)
1375 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1377 if (!(context
->ContextFlags
& CONTEXT_X86
))
1380 if (feature_id
>= 2)
1381 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1382 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1384 if (feature_id
== 1)
1387 *length
= sizeof(M128A
) * 8;
1389 return (BYTE
*)&context
->ExtendedRegisters
+ offsetof(XSAVE_FORMAT
, XmmRegisters
);
1393 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1395 return &context
->ExtendedRegisters
;
1398 /***********************************************************************
1399 * SetXStateFeaturesMask (kernelbase.@)
1401 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1403 if (!(context
->ContextFlags
& CONTEXT_X86
))
1406 if (feature_mask
& 0x3)
1407 context
->ContextFlags
|= CONTEXT_EXTENDED_REGISTERS
;
1409 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1410 return !(feature_mask
& ~(DWORD64
)3);
1412 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1416 /***********************************************************************
1417 * GetXStateFeaturesMask (kernelbase.@)
1419 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1421 if (!(context
->ContextFlags
& CONTEXT_X86
))
1424 *feature_mask
= (context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
1427 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1428 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1434 /***********************************************************************
1435 * Firmware functions
1436 ***********************************************************************/
1439 /***********************************************************************
1440 * EnumSystemFirmwareTable (kernelbase.@)
1442 UINT WINAPI
EnumSystemFirmwareTables( DWORD provider
, void *buffer
, DWORD size
)
1444 FIXME( "(0x%08x, %p, %d)\n", provider
, buffer
, size
);
1449 /***********************************************************************
1450 * GetSystemFirmwareTable (kernelbase.@)
1452 UINT WINAPI
GetSystemFirmwareTable( DWORD provider
, DWORD id
, void *buffer
, DWORD size
)
1454 SYSTEM_FIRMWARE_TABLE_INFORMATION
*info
;
1455 ULONG buffer_size
= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
) + size
;
1457 TRACE( "(0x%08x, 0x%08x, %p, %d)\n", provider
, id
, buffer
, size
);
1459 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, buffer_size
)))
1461 SetLastError( ERROR_OUTOFMEMORY
);
1465 info
->ProviderSignature
= provider
;
1466 info
->Action
= SystemFirmwareTable_Get
;
1469 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation
,
1470 info
, buffer_size
, &buffer_size
));
1471 buffer_size
-= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
1472 if (buffer_size
<= size
) memcpy( buffer
, info
->TableBuffer
, buffer_size
);
1474 HeapFree( GetProcessHeap(), 0, info
);