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
37 #include "kernelbase.h"
38 #include "wine/exception.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(heap
);
42 WINE_DECLARE_DEBUG_CHANNEL(virtual);
45 /***********************************************************************
46 * Virtual memory functions
47 ***********************************************************************/
50 /***********************************************************************
51 * FlushViewOfFile (kernelbase.@)
53 BOOL WINAPI DECLSPEC_HOTPATCH
FlushViewOfFile( const void *base
, SIZE_T size
)
55 NTSTATUS status
= NtFlushVirtualMemory( GetCurrentProcess(), &base
, &size
, 0 );
57 if (status
== STATUS_NOT_MAPPED_DATA
) status
= STATUS_SUCCESS
;
58 return set_ntstatus( status
);
62 /***********************************************************************
63 * GetLargePageMinimum (kernelbase.@)
65 SIZE_T WINAPI
GetLargePageMinimum(void)
67 return 2 * 1024 * 1024;
71 /***********************************************************************
72 * GetNativeSystemInfo (kernelbase.@)
74 void WINAPI DECLSPEC_HOTPATCH
GetNativeSystemInfo( SYSTEM_INFO
*si
)
77 if (!is_wow64
) return;
78 switch (si
->u
.s
.wProcessorArchitecture
)
80 case PROCESSOR_ARCHITECTURE_INTEL
:
81 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_AMD64
;
82 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
85 FIXME( "Add the proper information for %d in wow64 mode\n", si
->u
.s
.wProcessorArchitecture
);
90 /***********************************************************************
91 * GetSystemInfo (kernelbase.@)
93 void WINAPI DECLSPEC_HOTPATCH
GetSystemInfo( SYSTEM_INFO
*si
)
95 SYSTEM_BASIC_INFORMATION basic_info
;
96 SYSTEM_CPU_INFORMATION cpu_info
;
98 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
99 &basic_info
, sizeof(basic_info
), NULL
)) ||
100 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation
,
101 &cpu_info
, sizeof(cpu_info
), NULL
)))
104 si
->u
.s
.wProcessorArchitecture
= cpu_info
.Architecture
;
105 si
->u
.s
.wReserved
= 0;
106 si
->dwPageSize
= basic_info
.PageSize
;
107 si
->lpMinimumApplicationAddress
= basic_info
.LowestUserAddress
;
108 si
->lpMaximumApplicationAddress
= basic_info
.HighestUserAddress
;
109 si
->dwActiveProcessorMask
= basic_info
.ActiveProcessorsAffinityMask
;
110 si
->dwNumberOfProcessors
= basic_info
.NumberOfProcessors
;
111 si
->dwAllocationGranularity
= basic_info
.AllocationGranularity
;
112 si
->wProcessorLevel
= cpu_info
.Level
;
113 si
->wProcessorRevision
= cpu_info
.Revision
;
115 switch (cpu_info
.Architecture
)
117 case PROCESSOR_ARCHITECTURE_INTEL
:
118 switch (cpu_info
.Level
)
120 case 3: si
->dwProcessorType
= PROCESSOR_INTEL_386
; break;
121 case 4: si
->dwProcessorType
= PROCESSOR_INTEL_486
; break;
123 case 6: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
124 default: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
127 case PROCESSOR_ARCHITECTURE_PPC
:
128 switch (cpu_info
.Level
)
130 case 1: si
->dwProcessorType
= PROCESSOR_PPC_601
; break;
132 case 6: si
->dwProcessorType
= PROCESSOR_PPC_603
; break;
133 case 4: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
134 case 9: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
135 case 20: si
->dwProcessorType
= PROCESSOR_PPC_620
; break;
136 default: si
->dwProcessorType
= 0;
139 case PROCESSOR_ARCHITECTURE_AMD64
:
140 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
142 case PROCESSOR_ARCHITECTURE_ARM
:
143 switch (cpu_info
.Level
)
145 case 4: si
->dwProcessorType
= PROCESSOR_ARM_7TDMI
; break;
146 default: si
->dwProcessorType
= PROCESSOR_ARM920
;
149 case PROCESSOR_ARCHITECTURE_ARM64
:
150 si
->dwProcessorType
= 0;
153 FIXME( "Unknown processor architecture %x\n", cpu_info
.Architecture
);
154 si
->dwProcessorType
= 0;
160 /***********************************************************************
161 * GetSystemFileCacheSize (kernelbase.@)
163 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemFileCacheSize( SIZE_T
*mincache
, SIZE_T
*maxcache
, DWORD
*flags
)
165 FIXME( "stub: %p %p %p\n", mincache
, maxcache
, flags
);
166 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
171 /***********************************************************************
172 * GetWriteWatch (kernelbase.@)
174 UINT WINAPI DECLSPEC_HOTPATCH
GetWriteWatch( DWORD flags
, void *base
, SIZE_T size
, void **addresses
,
175 ULONG_PTR
*count
, ULONG
*granularity
)
177 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags
, base
, size
,
178 addresses
, count
, granularity
)))
184 /***********************************************************************
185 * MapViewOfFile (kernelbase.@)
187 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile( HANDLE mapping
, DWORD access
, DWORD offset_high
,
188 DWORD offset_low
, SIZE_T count
)
190 return MapViewOfFileEx( mapping
, access
, offset_high
, offset_low
, count
, NULL
);
194 /***********************************************************************
195 * MapViewOfFileEx (kernelbase.@)
197 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileEx( HANDLE handle
, DWORD access
, DWORD offset_high
,
198 DWORD offset_low
, SIZE_T count
, LPVOID addr
)
201 LARGE_INTEGER offset
;
205 offset
.u
.LowPart
= offset_low
;
206 offset
.u
.HighPart
= offset_high
;
208 exec
= access
& FILE_MAP_EXECUTE
;
209 access
&= ~FILE_MAP_EXECUTE
;
211 if (access
== FILE_MAP_COPY
)
212 protect
= exec
? PAGE_EXECUTE_WRITECOPY
: PAGE_WRITECOPY
;
213 else if (access
& FILE_MAP_WRITE
)
214 protect
= exec
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
215 else if (access
& FILE_MAP_READ
)
216 protect
= exec
? PAGE_EXECUTE_READ
: PAGE_READONLY
;
217 else protect
= PAGE_NOACCESS
;
219 if ((status
= NtMapViewOfSection( handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
220 &count
, ViewShare
, 0, protect
)) < 0)
222 SetLastError( RtlNtStatusToDosError(status
) );
229 /***********************************************************************
230 * ReadProcessMemory (kernelbase.@)
232 BOOL WINAPI DECLSPEC_HOTPATCH
ReadProcessMemory( HANDLE process
, const void *addr
, void *buffer
,
233 SIZE_T size
, SIZE_T
*bytes_read
)
235 return set_ntstatus( NtReadVirtualMemory( process
, addr
, buffer
, size
, bytes_read
));
239 /***********************************************************************
240 * ResetWriteWatch (kernelbase.@)
242 UINT WINAPI DECLSPEC_HOTPATCH
ResetWriteWatch( void *base
, SIZE_T size
)
244 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base
, size
)))
250 /***********************************************************************
251 * SetSystemFileCacheSize (kernelbase.@)
253 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemFileCacheSize( SIZE_T mincache
, SIZE_T maxcache
, DWORD flags
)
255 FIXME( "stub: %ld %ld %d\n", mincache
, maxcache
, flags
);
256 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
261 /***********************************************************************
262 * UnmapViewOfFile (kernelbase.@)
264 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile( const void *addr
)
266 if (GetVersion() & 0x80000000)
268 MEMORY_BASIC_INFORMATION info
;
269 if (!VirtualQuery( addr
, &info
, sizeof(info
) ) || info
.AllocationBase
!= addr
)
271 SetLastError( ERROR_INVALID_ADDRESS
);
275 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr
));
279 /***********************************************************************
280 * VirtualAlloc (kernelbase.@)
282 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc( void *addr
, SIZE_T size
, DWORD type
, DWORD protect
)
284 return VirtualAllocEx( GetCurrentProcess(), addr
, size
, type
, protect
);
288 /***********************************************************************
289 * VirtualAllocEx (kernelbase.@)
291 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocEx( HANDLE process
, void *addr
, SIZE_T size
,
292 DWORD type
, DWORD protect
)
296 if (!set_ntstatus( NtAllocateVirtualMemory( process
, &ret
, 0, &size
, type
, protect
))) return NULL
;
301 /***********************************************************************
302 * VirtualFree (kernelbase.@)
304 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFree( void *addr
, SIZE_T size
, DWORD type
)
306 return VirtualFreeEx( GetCurrentProcess(), addr
, size
, type
);
310 /***********************************************************************
311 * VirtualFreeEx (kernelbase.@)
313 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFreeEx( HANDLE process
, void *addr
, SIZE_T size
, DWORD type
)
315 return set_ntstatus( NtFreeVirtualMemory( process
, &addr
, &size
, type
));
319 /***********************************************************************
320 * VirtualLock (kernelbase.@)
322 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualLock( void *addr
, SIZE_T size
)
324 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
328 /***********************************************************************
329 * VirtualProtect (kernelbase.@)
331 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtect( void *addr
, SIZE_T size
, DWORD new_prot
, DWORD
*old_prot
)
333 return VirtualProtectEx( GetCurrentProcess(), addr
, size
, new_prot
, old_prot
);
337 /***********************************************************************
338 * VirtualProtectEx (kernelbase.@)
340 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtectEx( HANDLE process
, void *addr
, SIZE_T size
,
341 DWORD new_prot
, DWORD
*old_prot
)
345 /* Win9x allows passing NULL as old_prot while this fails on NT */
346 if (!old_prot
&& (GetVersion() & 0x80000000)) old_prot
= &prot
;
347 return set_ntstatus( NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
));
351 /***********************************************************************
352 * VirtualQuery (kernelbase.@)
354 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQuery( LPCVOID addr
, PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
356 return VirtualQueryEx( GetCurrentProcess(), addr
, info
, len
);
360 /***********************************************************************
361 * VirtualQueryEx (kernelbase.@)
363 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQueryEx( HANDLE process
, LPCVOID addr
,
364 PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
368 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryBasicInformation
, info
, len
, &ret
)))
374 /***********************************************************************
375 * VirtualUnlock (kernelbase.@)
377 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualUnlock( void *addr
, SIZE_T size
)
379 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
383 /***********************************************************************
384 * WriteProcessMemory (kernelbase.@)
386 BOOL WINAPI DECLSPEC_HOTPATCH
WriteProcessMemory( HANDLE process
, void *addr
, const void *buffer
,
387 SIZE_T size
, SIZE_T
*bytes_written
)
389 return set_ntstatus( NtWriteVirtualMemory( process
, addr
, buffer
, size
, bytes_written
));
393 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
394 BOOL WINAPI
IsBadStringPtrA( LPCSTR str
, UINT_PTR max
)
396 if (!str
) return TRUE
;
399 volatile const char *p
= str
;
400 while (p
!= str
+ max
) if (!*p
++) break;
411 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
412 BOOL WINAPI
IsBadStringPtrW( LPCWSTR str
, UINT_PTR max
)
414 if (!str
) return TRUE
;
417 volatile const WCHAR
*p
= str
;
418 while (p
!= str
+ max
) if (!*p
++) break;
429 /***********************************************************************
431 ***********************************************************************/
434 /***********************************************************************
435 * HeapCompact (kernelbase.@)
437 SIZE_T WINAPI DECLSPEC_HOTPATCH
HeapCompact( HANDLE heap
, DWORD flags
)
439 return RtlCompactHeap( heap
, flags
);
443 /***********************************************************************
444 * HeapCreate (kernelbase.@)
446 HANDLE WINAPI DECLSPEC_HOTPATCH
HeapCreate( DWORD flags
, SIZE_T init_size
, SIZE_T max_size
)
448 HANDLE ret
= RtlCreateHeap( flags
, NULL
, max_size
, init_size
, NULL
, NULL
);
449 if (!ret
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
454 /***********************************************************************
455 * HeapDestroy (kernelbase.@)
457 BOOL WINAPI DECLSPEC_HOTPATCH
HeapDestroy( HANDLE heap
)
459 if (!RtlDestroyHeap( heap
)) return TRUE
;
460 SetLastError( ERROR_INVALID_HANDLE
);
465 /***********************************************************************
466 * HeapLock (kernelbase.@)
468 BOOL WINAPI DECLSPEC_HOTPATCH
HeapLock( HANDLE heap
)
470 return RtlLockHeap( heap
);
474 /***********************************************************************
475 * HeapQueryInformation (kernelbase.@)
477 BOOL WINAPI
HeapQueryInformation( HANDLE heap
, HEAP_INFORMATION_CLASS info_class
,
478 PVOID info
, SIZE_T size
, PSIZE_T size_out
)
480 return set_ntstatus( RtlQueryHeapInformation( heap
, info_class
, info
, size
, size_out
));
484 /***********************************************************************
485 * HeapSetInformation (kernelbase.@)
487 BOOL WINAPI
HeapSetInformation( HANDLE heap
, HEAP_INFORMATION_CLASS infoclass
, PVOID info
, SIZE_T size
)
489 return set_ntstatus( RtlSetHeapInformation( heap
, infoclass
, info
, size
));
493 /***********************************************************************
494 * HeapUnlock (kernelbase.@)
496 BOOL WINAPI
HeapUnlock( HANDLE heap
)
498 return RtlUnlockHeap( heap
);
502 /***********************************************************************
503 * HeapValidate (kernelbase.@)
505 BOOL WINAPI DECLSPEC_HOTPATCH
HeapValidate( HANDLE heap
, DWORD flags
, LPCVOID ptr
)
507 return RtlValidateHeap( heap
, flags
, ptr
);
511 /***********************************************************************
512 * HeapWalk (kernelbase.@)
514 BOOL WINAPI DECLSPEC_HOTPATCH
HeapWalk( HANDLE heap
, PROCESS_HEAP_ENTRY
*entry
)
516 return set_ntstatus( RtlWalkHeap( heap
, entry
));
520 /***********************************************************************
521 * Global/local heap functions
522 ***********************************************************************/
524 #include "pshpack1.h"
536 #define MAGIC_LOCAL_USED 0x5342
537 /* align the storage needed for the HLOCAL on an 8-byte boundary thus
538 * LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
539 * size = 8*k, where k=1,2,3,... allocs exactly the given size.
540 * The Minolta DiMAGE Image Viewer heavily relies on this, corrupting
541 * the output jpeg's > 1 MB if not */
542 #define HLOCAL_STORAGE (sizeof(HLOCAL) * 2)
544 static inline struct local_header
*get_header( HLOCAL hmem
)
546 return (struct local_header
*)((char *)hmem
- 2);
549 static inline HLOCAL
get_handle( struct local_header
*header
)
554 static inline BOOL
is_pointer( HLOCAL hmem
)
556 return !((ULONG_PTR
)hmem
& 2);
559 /***********************************************************************
560 * GlobalAlloc (kernelbase.@)
562 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalAlloc( UINT flags
, SIZE_T size
)
564 /* mask out obsolete flags */
565 flags
&= ~(GMEM_NOCOMPACT
| GMEM_NOT_BANKED
| GMEM_NOTIFY
);
567 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
568 if (!(flags
& GMEM_MOVEABLE
) && !size
) size
= 1;
570 return LocalAlloc( flags
, size
);
574 /***********************************************************************
575 * GlobalFree (kernelbase.@)
577 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalFree( HLOCAL hmem
)
579 return LocalFree( hmem
);
583 /***********************************************************************
584 * LocalAlloc (kernelbase.@)
586 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalAlloc( UINT flags
, SIZE_T size
)
588 struct local_header
*header
;
589 DWORD heap_flags
= 0;
592 if (flags
& LMEM_ZEROINIT
) heap_flags
= HEAP_ZERO_MEMORY
;
594 if (!(flags
& LMEM_MOVEABLE
)) /* pointer */
596 ptr
= HeapAlloc( GetProcessHeap(), heap_flags
, size
);
597 TRACE( "(flags=%04x) returning %p\n", flags
, ptr
);
601 if (size
> INT_MAX
- HLOCAL_STORAGE
)
603 SetLastError( ERROR_OUTOFMEMORY
);
606 if (!(header
= HeapAlloc( GetProcessHeap(), 0, sizeof(*header
) ))) return 0;
608 header
->magic
= MAGIC_LOCAL_USED
;
609 header
->flags
= flags
>> 8;
614 if (!(ptr
= HeapAlloc(GetProcessHeap(), heap_flags
, size
+ HLOCAL_STORAGE
)))
616 HeapFree( GetProcessHeap(), 0, header
);
619 *(HLOCAL
*)ptr
= get_handle( header
);
620 header
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
622 else header
->ptr
= NULL
;
624 TRACE( "(flags=%04x) returning handle %p pointer %p\n",
625 flags
, get_handle( header
), header
->ptr
);
626 return get_handle( header
);
630 /***********************************************************************
631 * LocalFree (kernelbase.@)
633 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalFree( HLOCAL hmem
)
635 struct local_header
*header
;
638 RtlLockHeap( GetProcessHeap() );
642 if (is_pointer(hmem
)) /* POINTER */
644 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, hmem
))
646 SetLastError( ERROR_INVALID_HANDLE
);
652 header
= get_header( hmem
);
653 if (header
->magic
== MAGIC_LOCAL_USED
)
655 header
->magic
= 0xdead;
658 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
,
659 (char *)header
->ptr
- HLOCAL_STORAGE
))
662 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, header
)) ret
= hmem
;
666 WARN( "invalid handle %p (magic: 0x%04x)\n", hmem
, header
->magic
);
667 SetLastError( ERROR_INVALID_HANDLE
);
674 WARN( "invalid handle %p\n", hmem
);
675 SetLastError( ERROR_INVALID_HANDLE
);
679 RtlUnlockHeap( GetProcessHeap() );
684 /***********************************************************************
685 * LocalLock (kernelbase.@)
687 LPVOID WINAPI DECLSPEC_HOTPATCH
LocalLock( HLOCAL hmem
)
691 if (is_pointer( hmem
))
695 volatile char *p
= hmem
;
706 RtlLockHeap( GetProcessHeap() );
709 struct local_header
*header
= get_header( hmem
);
710 if (header
->magic
== MAGIC_LOCAL_USED
)
713 if (!header
->ptr
) SetLastError( ERROR_DISCARDED
);
714 else if (header
->lock
< LMEM_LOCKCOUNT
) header
->lock
++;
718 WARN( "invalid handle %p (magic: 0x%04x)\n", hmem
, header
->magic
);
719 SetLastError( ERROR_INVALID_HANDLE
);
724 WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem
);
725 SetLastError( ERROR_INVALID_HANDLE
);
728 RtlUnlockHeap( GetProcessHeap() );
733 /***********************************************************************
734 * LocalReAlloc (kernelbase.@)
736 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalReAlloc( HLOCAL hmem
, SIZE_T size
, UINT flags
)
738 struct local_header
*header
;
741 DWORD heap_flags
= (flags
& LMEM_ZEROINIT
) ? HEAP_ZERO_MEMORY
: 0;
743 RtlLockHeap( GetProcessHeap() );
744 if (flags
& LMEM_MODIFY
) /* modify flags */
746 if (is_pointer( hmem
) && (flags
& LMEM_MOVEABLE
))
748 /* make a fixed block moveable
749 * actually only NT is able to do this. But it's soo simple
753 WARN( "null handle\n");
754 SetLastError( ERROR_NOACCESS
);
758 size
= RtlSizeHeap( GetProcessHeap(), 0, hmem
);
759 ret
= LocalAlloc( flags
, size
);
760 ptr
= LocalLock( ret
);
761 memcpy( ptr
, hmem
, size
);
766 else if (!is_pointer( hmem
) && (flags
& LMEM_DISCARDABLE
))
768 /* change the flags to make our block "discardable" */
769 header
= get_header( hmem
);
770 header
->flags
|= LMEM_DISCARDABLE
>> 8;
773 else SetLastError( ERROR_INVALID_PARAMETER
);
777 if (is_pointer( hmem
))
779 /* reallocate fixed memory */
780 if (!(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
781 ret
= HeapReAlloc( GetProcessHeap(), heap_flags
, hmem
, size
);
785 /* reallocate a moveable block */
786 header
= get_header( hmem
);
789 if (size
<= INT_MAX
- HLOCAL_STORAGE
)
793 if ((ptr
= HeapReAlloc( GetProcessHeap(), heap_flags
,
794 (char *)header
->ptr
- HLOCAL_STORAGE
,
795 size
+ HLOCAL_STORAGE
)))
797 header
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
803 if ((ptr
= HeapAlloc( GetProcessHeap(), heap_flags
, size
+ HLOCAL_STORAGE
)))
805 *(HLOCAL
*)ptr
= hmem
;
806 header
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
811 else SetLastError( ERROR_OUTOFMEMORY
);
815 if (header
->lock
== 0)
819 HeapFree( GetProcessHeap(), 0, (char *)header
->ptr
- HLOCAL_STORAGE
);
824 else WARN( "not freeing memory associated with locked handle\n" );
828 RtlUnlockHeap( GetProcessHeap() );
833 /***********************************************************************
834 * LocalUnlock (kernelbase.@)
836 BOOL WINAPI DECLSPEC_HOTPATCH
LocalUnlock( HLOCAL hmem
)
840 if (is_pointer( hmem
))
842 SetLastError( ERROR_NOT_LOCKED
);
846 RtlLockHeap( GetProcessHeap() );
849 struct local_header
*header
= get_header( hmem
);
850 if (header
->magic
== MAGIC_LOCAL_USED
)
855 ret
= (header
->lock
!= 0);
856 if (!ret
) SetLastError( NO_ERROR
);
860 WARN( "%p not locked\n", hmem
);
861 SetLastError( ERROR_NOT_LOCKED
);
866 WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem
, header
->magic
);
867 SetLastError( ERROR_INVALID_HANDLE
);
872 WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem
);
873 SetLastError( ERROR_INVALID_PARAMETER
);
876 RtlUnlockHeap( GetProcessHeap() );
881 /***********************************************************************
882 * Memory resource functions
883 ***********************************************************************/
886 /***********************************************************************
887 * CreateMemoryResourceNotification (kernelbase.@)
889 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type
)
892 UNICODE_STRING nameW
;
893 OBJECT_ATTRIBUTES attr
;
897 case LowMemoryResourceNotification
:
898 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\LowMemoryCondition" );
900 case HighMemoryResourceNotification
:
901 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\HighMemoryCondition" );
904 SetLastError( ERROR_INVALID_PARAMETER
);
908 InitializeObjectAttributes( &attr
, &nameW
, 0, 0, NULL
);
909 if (!set_ntstatus( NtOpenEvent( &ret
, EVENT_ALL_ACCESS
, &attr
))) return 0;
913 /***********************************************************************
914 * QueryMemoryResourceNotification (kernelbase.@)
916 BOOL WINAPI DECLSPEC_HOTPATCH
QueryMemoryResourceNotification( HANDLE handle
, BOOL
*state
)
918 switch (WaitForSingleObject( handle
, 0 ))
927 SetLastError( ERROR_INVALID_PARAMETER
);
932 /***********************************************************************
933 * Physical memory functions
934 ***********************************************************************/
937 /***********************************************************************
938 * AllocateUserPhysicalPages (kernelbase.@)
940 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
941 ULONG_PTR
*userarray
)
943 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
944 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
949 /***********************************************************************
950 * FreeUserPhysicalPages (kernelbase.@)
952 BOOL WINAPI DECLSPEC_HOTPATCH
FreeUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
953 ULONG_PTR
*userarray
)
955 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
957 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
962 /***********************************************************************
963 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
965 BOOL WINAPI DECLSPEC_HOTPATCH
GetPhysicallyInstalledSystemMemory( ULONGLONG
*memory
)
967 MEMORYSTATUSEX status
;
971 SetLastError( ERROR_INVALID_PARAMETER
);
974 status
.dwLength
= sizeof(status
);
975 GlobalMemoryStatusEx( &status
);
976 *memory
= status
.ullTotalPhys
/ 1024;
981 /***********************************************************************
982 * GlobalMemoryStatusEx (kernelbase.@)
984 BOOL WINAPI DECLSPEC_HOTPATCH
GlobalMemoryStatusEx( MEMORYSTATUSEX
*status
)
986 static MEMORYSTATUSEX cached_status
;
987 static DWORD last_check
;
988 SYSTEM_BASIC_INFORMATION basic_info
;
989 SYSTEM_PERFORMANCE_INFORMATION perf_info
;
991 if (status
->dwLength
!= sizeof(*status
))
993 SetLastError( ERROR_INVALID_PARAMETER
);
996 if ((NtGetTickCount() - last_check
) < 1000)
998 *status
= cached_status
;
1001 last_check
= NtGetTickCount();
1003 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
1004 &basic_info
, sizeof(basic_info
), NULL
)) ||
1005 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation
,
1006 &perf_info
, sizeof(perf_info
), NULL
)))
1009 status
->dwMemoryLoad
= 0;
1010 status
->ullTotalPhys
= perf_info
.TotalCommitLimit
;
1011 status
->ullAvailPhys
= perf_info
.AvailablePages
;
1012 status
->ullTotalPageFile
= perf_info
.TotalCommitLimit
+ 1; /* Titan Quest refuses to run if TotalPageFile <= TotalPhys */
1013 status
->ullAvailPageFile
= status
->ullTotalPageFile
- perf_info
.TotalCommittedPages
;
1014 status
->ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
;
1015 status
->ullAvailVirtual
= status
->ullTotalVirtual
- 64 * 1024; /* FIXME */
1016 status
->ullAvailExtendedVirtual
= 0;
1018 status
->ullTotalPhys
*= basic_info
.PageSize
;
1019 status
->ullAvailPhys
*= basic_info
.PageSize
;
1020 status
->ullTotalPageFile
*= basic_info
.PageSize
;
1021 status
->ullAvailPageFile
*= basic_info
.PageSize
;
1023 if (status
->ullTotalPhys
)
1024 status
->dwMemoryLoad
= (status
->ullTotalPhys
- status
->ullAvailPhys
) / (status
->ullTotalPhys
/ 100);
1026 TRACE_(virtual)( "MemoryLoad %d, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1027 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1028 status
->dwMemoryLoad
, wine_dbgstr_longlong(status
->ullTotalPhys
),
1029 wine_dbgstr_longlong(status
->ullAvailPhys
), wine_dbgstr_longlong(status
->ullTotalPageFile
),
1030 wine_dbgstr_longlong(status
->ullAvailPageFile
), wine_dbgstr_longlong(status
->ullTotalVirtual
),
1031 wine_dbgstr_longlong(status
->ullAvailVirtual
) );
1033 cached_status
= *status
;
1038 /***********************************************************************
1039 * MapUserPhysicalPages (kernelbase.@)
1041 BOOL WINAPI DECLSPEC_HOTPATCH
MapUserPhysicalPages( void *addr
, ULONG_PTR page_count
, ULONG_PTR
*pages
)
1043 FIXME( "stub: %p %lu %p\n", addr
, page_count
, pages
);
1045 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1050 /***********************************************************************
1052 ***********************************************************************/
1055 /***********************************************************************
1056 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1058 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPagesNuma( HANDLE process
, ULONG_PTR
*pages
,
1059 ULONG_PTR
*userarray
, DWORD node
)
1061 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1062 return AllocateUserPhysicalPages( process
, pages
, userarray
);
1066 /***********************************************************************
1067 * CreateFileMappingNumaW (kernelbase.@)
1069 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileMappingNumaW( HANDLE file
, LPSECURITY_ATTRIBUTES sa
,
1070 DWORD protect
, DWORD size_high
, DWORD size_low
,
1071 LPCWSTR name
, DWORD node
)
1073 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1074 return CreateFileMappingW( file
, sa
, protect
, size_high
, size_low
, name
);
1078 /***********************************************************************
1079 * GetLogicalProcessorInformation (kernelbase.@)
1081 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buffer
,
1088 SetLastError( ERROR_INVALID_PARAMETER
);
1091 status
= NtQuerySystemInformation( SystemLogicalProcessorInformation
, buffer
, *len
, len
);
1092 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1093 return set_ntstatus( status
);
1097 /***********************************************************************
1098 * GetLogicalProcessorInformationEx (kernelbase.@)
1100 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship
,
1101 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buffer
, DWORD
*len
)
1107 SetLastError( ERROR_INVALID_PARAMETER
);
1110 status
= NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx
, &relationship
,
1111 sizeof(relationship
), buffer
, *len
, len
);
1112 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1113 return set_ntstatus( status
);
1117 /**********************************************************************
1118 * GetNumaHighestNodeNumber (kernelbase.@)
1120 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaHighestNodeNumber( ULONG
*node
)
1122 FIXME( "semi-stub: %p\n", node
);
1128 /**********************************************************************
1129 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1131 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaNodeProcessorMaskEx( USHORT node
, GROUP_AFFINITY
*mask
)
1133 FIXME( "stub: %hu %p\n", node
, mask
);
1134 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1139 /***********************************************************************
1140 * GetNumaProximityNodeEx (kernelbase.@)
1142 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaProximityNodeEx( ULONG proximity_id
, USHORT
*node
)
1144 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1149 /***********************************************************************
1150 * MapViewOfFileExNuma (kernelbase.@)
1152 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileExNuma( HANDLE handle
, DWORD access
, DWORD offset_high
,
1153 DWORD offset_low
, SIZE_T count
, LPVOID addr
,
1156 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1157 return MapViewOfFileEx( handle
, access
, offset_high
, offset_low
, count
, addr
);
1161 /***********************************************************************
1162 * VirtualAllocExNuma (kernelbase.@)
1164 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocExNuma( HANDLE process
, void *addr
, SIZE_T size
,
1165 DWORD type
, DWORD protect
, DWORD node
)
1167 if (node
) FIXME( "Ignoring preferred node %u\n", node
);
1168 return VirtualAllocEx( process
, addr
, size
, type
, protect
);
1172 /***********************************************************************
1173 * Firmware functions
1174 ***********************************************************************/
1177 /***********************************************************************
1178 * EnumSystemFirmwareTable (kernelbase.@)
1180 UINT WINAPI
EnumSystemFirmwareTables( DWORD provider
, void *buffer
, DWORD size
)
1182 FIXME( "(0x%08x, %p, %d)\n", provider
, buffer
, size
);
1187 /***********************************************************************
1188 * GetSystemFirmwareTable (kernelbase.@)
1190 UINT WINAPI
GetSystemFirmwareTable( DWORD provider
, DWORD id
, void *buffer
, DWORD size
)
1192 SYSTEM_FIRMWARE_TABLE_INFORMATION
*info
;
1193 ULONG buffer_size
= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
) + size
;
1195 TRACE( "(0x%08x, 0x%08x, %p, %d)\n", provider
, id
, buffer
, size
);
1197 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, buffer_size
)))
1199 SetLastError( ERROR_OUTOFMEMORY
);
1203 info
->ProviderSignature
= provider
;
1204 info
->Action
= SystemFirmwareTable_Get
;
1207 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation
,
1208 info
, buffer_size
, &buffer_size
));
1209 buffer_size
-= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
1210 if (buffer_size
<= size
) memcpy( buffer
, info
->TableBuffer
, buffer_size
);
1212 HeapFree( GetProcessHeap(), 0, info
);