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);
44 WINE_DECLARE_DEBUG_CHANNEL(globalmem
);
47 BOOLEAN WINAPI
RtlSetUserValueHeap( HANDLE handle
, ULONG flags
, void *ptr
, void *user_value
);
50 /***********************************************************************
51 * Virtual memory functions
52 ***********************************************************************/
55 /***********************************************************************
56 * FlushViewOfFile (kernelbase.@)
58 BOOL WINAPI DECLSPEC_HOTPATCH
FlushViewOfFile( const void *base
, SIZE_T size
)
60 NTSTATUS status
= NtFlushVirtualMemory( GetCurrentProcess(), &base
, &size
, 0 );
62 if (status
== STATUS_NOT_MAPPED_DATA
) status
= STATUS_SUCCESS
;
63 return set_ntstatus( status
);
67 /***********************************************************************
68 * GetLargePageMinimum (kernelbase.@)
70 SIZE_T WINAPI
GetLargePageMinimum(void)
72 return 2 * 1024 * 1024;
76 /***********************************************************************
77 * GetNativeSystemInfo (kernelbase.@)
79 void WINAPI DECLSPEC_HOTPATCH
GetNativeSystemInfo( SYSTEM_INFO
*si
)
81 USHORT current_machine
, native_machine
;
84 RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine
, &native_machine
);
85 if (!current_machine
) return;
86 switch (native_machine
)
88 case IMAGE_FILE_MACHINE_AMD64
:
89 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_AMD64
;
90 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
92 case IMAGE_FILE_MACHINE_ARM64
:
93 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_ARM64
;
94 si
->dwProcessorType
= 0;
97 FIXME( "Add the proper information for %x in wow64 mode\n", native_machine
);
102 /***********************************************************************
103 * GetSystemInfo (kernelbase.@)
105 void WINAPI DECLSPEC_HOTPATCH
GetSystemInfo( SYSTEM_INFO
*si
)
107 SYSTEM_BASIC_INFORMATION basic_info
;
108 SYSTEM_CPU_INFORMATION cpu_info
;
110 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
111 &basic_info
, sizeof(basic_info
), NULL
)) ||
112 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation
,
113 &cpu_info
, sizeof(cpu_info
), NULL
)))
116 si
->u
.s
.wProcessorArchitecture
= cpu_info
.ProcessorArchitecture
;
117 si
->u
.s
.wReserved
= 0;
118 si
->dwPageSize
= basic_info
.PageSize
;
119 si
->lpMinimumApplicationAddress
= basic_info
.LowestUserAddress
;
120 si
->lpMaximumApplicationAddress
= basic_info
.HighestUserAddress
;
121 si
->dwActiveProcessorMask
= basic_info
.ActiveProcessorsAffinityMask
;
122 si
->dwNumberOfProcessors
= basic_info
.NumberOfProcessors
;
123 si
->dwAllocationGranularity
= basic_info
.AllocationGranularity
;
124 si
->wProcessorLevel
= cpu_info
.ProcessorLevel
;
125 si
->wProcessorRevision
= cpu_info
.ProcessorRevision
;
127 switch (cpu_info
.ProcessorArchitecture
)
129 case PROCESSOR_ARCHITECTURE_INTEL
:
130 switch (cpu_info
.ProcessorLevel
)
132 case 3: si
->dwProcessorType
= PROCESSOR_INTEL_386
; break;
133 case 4: si
->dwProcessorType
= PROCESSOR_INTEL_486
; break;
135 case 6: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
136 default: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
139 case PROCESSOR_ARCHITECTURE_PPC
:
140 switch (cpu_info
.ProcessorLevel
)
142 case 1: si
->dwProcessorType
= PROCESSOR_PPC_601
; break;
144 case 6: si
->dwProcessorType
= PROCESSOR_PPC_603
; break;
145 case 4: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
146 case 9: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
147 case 20: si
->dwProcessorType
= PROCESSOR_PPC_620
; break;
148 default: si
->dwProcessorType
= 0;
151 case PROCESSOR_ARCHITECTURE_AMD64
:
152 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
154 case PROCESSOR_ARCHITECTURE_ARM
:
155 switch (cpu_info
.ProcessorLevel
)
157 case 4: si
->dwProcessorType
= PROCESSOR_ARM_7TDMI
; break;
158 default: si
->dwProcessorType
= PROCESSOR_ARM920
;
161 case PROCESSOR_ARCHITECTURE_ARM64
:
162 si
->dwProcessorType
= 0;
165 FIXME( "Unknown processor architecture %x\n", cpu_info
.ProcessorArchitecture
);
166 si
->dwProcessorType
= 0;
172 /***********************************************************************
173 * GetSystemFileCacheSize (kernelbase.@)
175 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemFileCacheSize( SIZE_T
*mincache
, SIZE_T
*maxcache
, DWORD
*flags
)
177 FIXME( "stub: %p %p %p\n", mincache
, maxcache
, flags
);
178 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
183 /***********************************************************************
184 * GetWriteWatch (kernelbase.@)
186 UINT WINAPI DECLSPEC_HOTPATCH
GetWriteWatch( DWORD flags
, void *base
, SIZE_T size
, void **addresses
,
187 ULONG_PTR
*count
, ULONG
*granularity
)
189 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags
, base
, size
,
190 addresses
, count
, granularity
)))
196 /***********************************************************************
197 * MapViewOfFile (kernelbase.@)
199 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile( HANDLE mapping
, DWORD access
, DWORD offset_high
,
200 DWORD offset_low
, SIZE_T count
)
202 return MapViewOfFileEx( mapping
, access
, offset_high
, offset_low
, count
, NULL
);
206 /***********************************************************************
207 * MapViewOfFileEx (kernelbase.@)
209 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileEx( HANDLE handle
, DWORD access
, DWORD offset_high
,
210 DWORD offset_low
, SIZE_T count
, LPVOID addr
)
213 LARGE_INTEGER offset
;
217 offset
.u
.LowPart
= offset_low
;
218 offset
.u
.HighPart
= offset_high
;
220 exec
= access
& FILE_MAP_EXECUTE
;
221 access
&= ~FILE_MAP_EXECUTE
;
223 if (access
== FILE_MAP_COPY
)
224 protect
= exec
? PAGE_EXECUTE_WRITECOPY
: PAGE_WRITECOPY
;
225 else if (access
& FILE_MAP_WRITE
)
226 protect
= exec
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
227 else if (access
& FILE_MAP_READ
)
228 protect
= exec
? PAGE_EXECUTE_READ
: PAGE_READONLY
;
229 else protect
= PAGE_NOACCESS
;
231 if ((status
= NtMapViewOfSection( handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
232 &count
, ViewShare
, 0, protect
)) < 0)
234 SetLastError( RtlNtStatusToDosError(status
) );
241 /***********************************************************************
242 * MapViewOfFileFromApp (kernelbase.@)
244 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileFromApp( HANDLE handle
, ULONG access
, ULONG64 offset
, SIZE_T size
)
246 return MapViewOfFile( handle
, access
, offset
<< 32, offset
, size
);
249 /***********************************************************************
250 * MapViewOfFile3 (kernelbase.@)
252 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile3( HANDLE handle
, HANDLE process
, PVOID baseaddr
, ULONG64 offset
,
253 SIZE_T size
, ULONG alloc_type
, ULONG protection
, MEM_EXTENDED_PARAMETER
*params
, ULONG params_count
)
259 off
.QuadPart
= offset
;
260 if (!set_ntstatus( NtMapViewOfSectionEx( handle
, process
, &addr
, &off
, &size
, alloc_type
, protection
,
261 params
, params_count
)))
268 /***********************************************************************
269 * ReadProcessMemory (kernelbase.@)
271 BOOL WINAPI DECLSPEC_HOTPATCH
ReadProcessMemory( HANDLE process
, const void *addr
, void *buffer
,
272 SIZE_T size
, SIZE_T
*bytes_read
)
274 return set_ntstatus( NtReadVirtualMemory( process
, addr
, buffer
, size
, bytes_read
));
278 /***********************************************************************
279 * ResetWriteWatch (kernelbase.@)
281 UINT WINAPI DECLSPEC_HOTPATCH
ResetWriteWatch( void *base
, SIZE_T size
)
283 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base
, size
)))
289 /***********************************************************************
290 * SetSystemFileCacheSize (kernelbase.@)
292 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemFileCacheSize( SIZE_T mincache
, SIZE_T maxcache
, DWORD flags
)
294 FIXME( "stub: %Id %Id %ld\n", mincache
, maxcache
, flags
);
295 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
300 /***********************************************************************
301 * UnmapViewOfFile (kernelbase.@)
303 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile( const void *addr
)
305 if (GetVersion() & 0x80000000)
307 MEMORY_BASIC_INFORMATION info
;
308 if (!VirtualQuery( addr
, &info
, sizeof(info
) ) || info
.AllocationBase
!= addr
)
310 SetLastError( ERROR_INVALID_ADDRESS
);
314 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr
));
318 /***********************************************************************
319 * UnmapViewOfFile2 (kernelbase.@)
321 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile2( HANDLE process
, void *addr
, ULONG flags
)
323 return set_ntstatus( NtUnmapViewOfSectionEx( process
, addr
, flags
));
327 /***********************************************************************
328 * UnmapViewOfFileEx (kernelbase.@)
330 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFileEx( void *addr
, ULONG flags
)
332 return set_ntstatus( NtUnmapViewOfSectionEx( GetCurrentProcess(), addr
, flags
));
336 /***********************************************************************
337 * VirtualAlloc (kernelbase.@)
339 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc( void *addr
, SIZE_T size
, DWORD type
, DWORD protect
)
341 return VirtualAllocEx( GetCurrentProcess(), addr
, size
, type
, protect
);
345 /***********************************************************************
346 * VirtualAllocEx (kernelbase.@)
348 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocEx( HANDLE process
, void *addr
, SIZE_T size
,
349 DWORD type
, DWORD protect
)
353 if (!set_ntstatus( NtAllocateVirtualMemory( process
, &ret
, 0, &size
, type
, protect
))) return NULL
;
358 /***********************************************************************
359 * VirtualAlloc2 (kernelbase.@)
361 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc2( HANDLE process
, void *addr
, SIZE_T size
,
362 DWORD type
, DWORD protect
,
363 MEM_EXTENDED_PARAMETER
*parameters
, ULONG count
)
367 if (!process
) process
= GetCurrentProcess();
368 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process
, &ret
, &size
, type
, protect
, parameters
, count
)))
373 static BOOL
is_exec_prot( DWORD protect
)
375 return protect
== PAGE_EXECUTE
|| protect
== PAGE_EXECUTE_READ
|| protect
== PAGE_EXECUTE_READWRITE
376 || protect
== PAGE_EXECUTE_WRITECOPY
;
379 /***********************************************************************
380 * VirtualAlloc2FromApp (kernelbase.@)
382 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc2FromApp( HANDLE process
, void *addr
, SIZE_T size
,
383 DWORD type
, DWORD protect
, MEM_EXTENDED_PARAMETER
*parameters
, ULONG count
)
387 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx, params %p, count %lu.\n", addr
, (void *)size
, type
, protect
,
390 if (is_exec_prot( protect
))
392 SetLastError( ERROR_INVALID_PARAMETER
);
396 if (!process
) process
= GetCurrentProcess();
397 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process
, &ret
, &size
, type
, protect
, parameters
, count
)))
403 /***********************************************************************
404 * VirtualAllocFromApp (kernelbase.@)
406 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocFromApp( void *addr
, SIZE_T size
,
407 DWORD type
, DWORD protect
)
411 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx.\n", addr
, (void *)size
, type
, protect
);
413 if (is_exec_prot( protect
))
415 SetLastError( ERROR_INVALID_PARAMETER
);
419 if (!set_ntstatus( NtAllocateVirtualMemory( GetCurrentProcess(), &ret
, 0, &size
, type
, protect
))) return NULL
;
424 /***********************************************************************
425 * PrefetchVirtualMemory (kernelbase.@)
427 BOOL WINAPI DECLSPEC_HOTPATCH
PrefetchVirtualMemory( HANDLE process
, ULONG_PTR count
,
428 WIN32_MEMORY_RANGE_ENTRY
*addresses
, ULONG flags
)
430 return set_ntstatus( NtSetInformationVirtualMemory( process
, VmPrefetchInformation
,
431 count
, (PMEMORY_RANGE_ENTRY
)addresses
,
432 &flags
, sizeof(flags
) ));
436 /***********************************************************************
437 * VirtualFree (kernelbase.@)
439 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFree( void *addr
, SIZE_T size
, DWORD type
)
441 return VirtualFreeEx( GetCurrentProcess(), addr
, size
, type
);
445 /***********************************************************************
446 * VirtualFreeEx (kernelbase.@)
448 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFreeEx( HANDLE process
, void *addr
, SIZE_T size
, DWORD type
)
450 return set_ntstatus( NtFreeVirtualMemory( process
, &addr
, &size
, type
));
454 /***********************************************************************
455 * VirtualLock (kernelbase.@)
457 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualLock( void *addr
, SIZE_T size
)
459 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
463 /***********************************************************************
464 * VirtualProtect (kernelbase.@)
466 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtect( void *addr
, SIZE_T size
, DWORD new_prot
, DWORD
*old_prot
)
468 return VirtualProtectEx( GetCurrentProcess(), addr
, size
, new_prot
, old_prot
);
472 /***********************************************************************
473 * VirtualProtectEx (kernelbase.@)
475 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtectEx( HANDLE process
, void *addr
, SIZE_T size
,
476 DWORD new_prot
, DWORD
*old_prot
)
480 /* Win9x allows passing NULL as old_prot while this fails on NT */
481 if (!old_prot
&& (GetVersion() & 0x80000000)) old_prot
= &prot
;
482 return set_ntstatus( NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
));
486 /***********************************************************************
487 * VirtualQuery (kernelbase.@)
489 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQuery( LPCVOID addr
, PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
491 return VirtualQueryEx( GetCurrentProcess(), addr
, info
, len
);
495 /***********************************************************************
496 * VirtualQueryEx (kernelbase.@)
498 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQueryEx( HANDLE process
, LPCVOID addr
,
499 PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
503 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryBasicInformation
, info
, len
, &ret
)))
509 /***********************************************************************
510 * VirtualUnlock (kernelbase.@)
512 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualUnlock( void *addr
, SIZE_T size
)
514 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
518 /***********************************************************************
519 * WriteProcessMemory (kernelbase.@)
521 BOOL WINAPI DECLSPEC_HOTPATCH
WriteProcessMemory( HANDLE process
, void *addr
, const void *buffer
,
522 SIZE_T size
, SIZE_T
*bytes_written
)
524 return set_ntstatus( NtWriteVirtualMemory( process
, addr
, buffer
, size
, bytes_written
));
528 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
529 BOOL WINAPI
IsBadStringPtrA( LPCSTR str
, UINT_PTR max
)
531 if (!str
) return TRUE
;
534 volatile const char *p
= str
;
535 while (p
!= str
+ max
) if (!*p
++) break;
546 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
547 BOOL WINAPI
IsBadStringPtrW( LPCWSTR str
, UINT_PTR max
)
549 if (!str
) return TRUE
;
552 volatile const WCHAR
*p
= str
;
553 while (p
!= str
+ max
) if (!*p
++) break;
564 /***********************************************************************
566 ***********************************************************************/
569 /***********************************************************************
570 * HeapCompact (kernelbase.@)
572 SIZE_T WINAPI DECLSPEC_HOTPATCH
HeapCompact( HANDLE heap
, DWORD flags
)
574 return RtlCompactHeap( heap
, flags
);
578 /***********************************************************************
579 * HeapCreate (kernelbase.@)
581 HANDLE WINAPI DECLSPEC_HOTPATCH
HeapCreate( DWORD flags
, SIZE_T init_size
, SIZE_T max_size
)
583 HANDLE ret
= RtlCreateHeap( flags
, NULL
, max_size
, init_size
, NULL
, NULL
);
584 if (!ret
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
589 /***********************************************************************
590 * HeapDestroy (kernelbase.@)
592 BOOL WINAPI DECLSPEC_HOTPATCH
HeapDestroy( HANDLE heap
)
594 if (!RtlDestroyHeap( heap
)) return TRUE
;
595 SetLastError( ERROR_INVALID_HANDLE
);
600 /***********************************************************************
601 * HeapLock (kernelbase.@)
603 BOOL WINAPI DECLSPEC_HOTPATCH
HeapLock( HANDLE heap
)
605 return RtlLockHeap( heap
);
609 /***********************************************************************
610 * HeapQueryInformation (kernelbase.@)
612 BOOL WINAPI
HeapQueryInformation( HANDLE heap
, HEAP_INFORMATION_CLASS info_class
,
613 PVOID info
, SIZE_T size
, PSIZE_T size_out
)
615 return set_ntstatus( RtlQueryHeapInformation( heap
, info_class
, info
, size
, size_out
));
619 /***********************************************************************
620 * HeapSetInformation (kernelbase.@)
622 BOOL WINAPI
HeapSetInformation( HANDLE heap
, HEAP_INFORMATION_CLASS infoclass
, PVOID info
, SIZE_T size
)
624 return set_ntstatus( RtlSetHeapInformation( heap
, infoclass
, info
, size
));
628 /***********************************************************************
629 * HeapUnlock (kernelbase.@)
631 BOOL WINAPI
HeapUnlock( HANDLE heap
)
633 return RtlUnlockHeap( heap
);
637 /***********************************************************************
638 * HeapValidate (kernelbase.@)
640 BOOL WINAPI DECLSPEC_HOTPATCH
HeapValidate( HANDLE heap
, DWORD flags
, LPCVOID ptr
)
642 return RtlValidateHeap( heap
, flags
, ptr
);
646 /* undocumented RtlWalkHeap structure */
648 struct rtl_heap_entry
651 SIZE_T cbData
; /* differs from PROCESS_HEAP_ENTRY */
654 WORD wFlags
; /* value differs from PROCESS_HEAP_ENTRY */
661 DWORD dwCommittedSize
;
662 DWORD dwUnCommittedSize
;
669 /* rtl_heap_entry flags, names made up */
671 #define RTL_HEAP_ENTRY_BUSY 0x0001
672 #define RTL_HEAP_ENTRY_REGION 0x0002
673 #define RTL_HEAP_ENTRY_BLOCK 0x0010
674 #define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000
675 #define RTL_HEAP_ENTRY_COMMITTED 0x4000
676 #define RTL_HEAP_ENTRY_LFH 0x8000
679 /***********************************************************************
680 * HeapWalk (kernelbase.@)
682 BOOL WINAPI DECLSPEC_HOTPATCH
HeapWalk( HANDLE heap
, PROCESS_HEAP_ENTRY
*entry
)
684 struct rtl_heap_entry rtl_entry
= {0};
687 if (!entry
) return set_ntstatus( STATUS_INVALID_PARAMETER
);
689 rtl_entry
.lpData
= entry
->lpData
;
690 rtl_entry
.cbData
= entry
->cbData
;
691 rtl_entry
.cbOverhead
= entry
->cbOverhead
;
692 rtl_entry
.iRegionIndex
= entry
->iRegionIndex
;
694 if (entry
->wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
695 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_BUSY
;
696 if (entry
->wFlags
& PROCESS_HEAP_REGION
)
697 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_REGION
;
698 if (entry
->wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
699 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_UNCOMMITTED
;
700 memcpy( &rtl_entry
.Region
, &entry
->u
.Region
, sizeof(entry
->u
.Region
) );
702 if (!(status
= RtlWalkHeap( heap
, &rtl_entry
)))
704 entry
->lpData
= rtl_entry
.lpData
;
705 entry
->cbData
= rtl_entry
.cbData
;
706 entry
->cbOverhead
= rtl_entry
.cbOverhead
;
707 entry
->iRegionIndex
= rtl_entry
.iRegionIndex
;
709 if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_BUSY
)
710 entry
->wFlags
= PROCESS_HEAP_ENTRY_BUSY
;
711 else if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_REGION
)
712 entry
->wFlags
= PROCESS_HEAP_REGION
;
713 else if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_UNCOMMITTED
)
714 entry
->wFlags
= PROCESS_HEAP_UNCOMMITTED_RANGE
;
718 memcpy( &entry
->u
.Region
, &rtl_entry
.Region
, sizeof(entry
->u
.Region
) );
721 return set_ntstatus( status
);
725 /***********************************************************************
726 * Global/local heap functions
727 ***********************************************************************/
729 /* some undocumented flags (names are made up) */
730 #define HEAP_ADD_USER_INFO 0x00000100
732 /* not compatible with windows */
733 struct kernelbase_global_data
735 struct mem_entry
*mem_entries
;
736 struct mem_entry
*mem_entries_end
;
739 #define MEM_FLAG_USED 1
740 #define MEM_FLAG_MOVEABLE 2
741 #define MEM_FLAG_DISCARDABLE 4
742 #define MEM_FLAG_DISCARDED 8
743 #define MEM_FLAG_DDESHARE 0x8000
759 C_ASSERT(sizeof(struct mem_entry
) == 2 * sizeof(void *));
761 #define MAX_MEM_HANDLES 0x10000
762 static struct mem_entry
*next_free_mem
;
763 static struct kernelbase_global_data global_data
= {0};
765 static inline struct mem_entry
*unsafe_mem_from_HLOCAL( HLOCAL handle
)
767 struct mem_entry
*mem
= CONTAINING_RECORD( *(volatile HANDLE
*)&handle
, struct mem_entry
, ptr
);
768 struct kernelbase_global_data
*data
= &global_data
;
769 if (((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL
;
770 if (mem
< data
->mem_entries
|| mem
>= data
->mem_entries_end
) return NULL
;
771 if (!(mem
->flags
& MEM_FLAG_USED
)) return NULL
;
775 static inline HLOCAL
HLOCAL_from_mem( struct mem_entry
*mem
)
781 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle
)
783 if (((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1))) return NULL
;
787 void init_global_data(void)
789 global_data
.mem_entries
= VirtualAlloc( NULL
, MAX_MEM_HANDLES
* sizeof(struct mem_entry
), MEM_COMMIT
, PAGE_READWRITE
);
790 if (!(next_free_mem
= global_data
.mem_entries
)) ERR( "Failed to allocate kernelbase global handle table\n" );
791 global_data
.mem_entries_end
= global_data
.mem_entries
+ MAX_MEM_HANDLES
;
794 /***********************************************************************
795 * KernelBaseGetGlobalData (kernelbase.@)
797 void *WINAPI
KernelBaseGetGlobalData(void)
799 WARN_(globalmem
)( "semi-stub!\n" );
804 /***********************************************************************
805 * GlobalAlloc (kernelbase.@)
807 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalAlloc( UINT flags
, SIZE_T size
)
809 struct mem_entry
*mem
;
812 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
813 if (!(flags
& GMEM_MOVEABLE
) && !size
) size
= 1;
815 handle
= LocalAlloc( flags
, size
);
817 if ((mem
= unsafe_mem_from_HLOCAL( handle
)) && (flags
& GMEM_DDESHARE
))
818 mem
->flags
|= MEM_FLAG_DDESHARE
;
824 /***********************************************************************
825 * GlobalFree (kernelbase.@)
827 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalFree( HLOCAL handle
)
829 return LocalFree( handle
);
833 /***********************************************************************
834 * LocalAlloc (kernelbase.@)
836 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalAlloc( UINT flags
, SIZE_T size
)
838 DWORD heap_flags
= 0x200 | HEAP_ADD_USER_INFO
;
839 HANDLE heap
= GetProcessHeap();
840 struct mem_entry
*mem
;
844 TRACE_(globalmem
)( "flags %#x, size %#Ix\n", flags
, size
);
846 if (flags
& LMEM_ZEROINIT
) heap_flags
|= HEAP_ZERO_MEMORY
;
848 if (!(flags
& LMEM_MOVEABLE
)) /* pointer */
850 ptr
= HeapAlloc( heap
, heap_flags
, size
);
851 if (ptr
) RtlSetUserValueHeap( heap
, heap_flags
, ptr
, ptr
);
852 TRACE_(globalmem
)( "return %p\n", ptr
);
857 if ((mem
= next_free_mem
) < global_data
.mem_entries
|| mem
>= global_data
.mem_entries_end
)
861 if (!mem
->next_free
) next_free_mem
++;
862 else next_free_mem
= mem
->next_free
;
863 mem
->next_free
= NULL
;
865 RtlUnlockHeap( heap
);
867 if (!mem
) goto failed
;
868 handle
= HLOCAL_from_mem( mem
);
870 mem
->flags
= MEM_FLAG_USED
| MEM_FLAG_MOVEABLE
;
871 if (flags
& LMEM_DISCARDABLE
) mem
->flags
|= MEM_FLAG_DISCARDABLE
;
875 if (!size
) mem
->flags
|= MEM_FLAG_DISCARDED
;
878 if (!(ptr
= HeapAlloc( heap
, heap_flags
, size
))) goto failed
;
879 RtlSetUserValueHeap( heap
, heap_flags
, ptr
, handle
);
883 TRACE_(globalmem
)( "return handle %p, ptr %p\n", handle
, mem
->ptr
);
887 if (mem
) LocalFree( *(volatile HANDLE
*)&handle
);
888 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
893 /***********************************************************************
894 * LocalFree (kernelbase.@)
896 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalFree( HLOCAL handle
)
898 HANDLE heap
= GetProcessHeap();
899 struct mem_entry
*mem
;
903 TRACE_(globalmem
)( "handle %p\n", handle
);
906 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)) &&
907 HeapValidate( heap
, HEAP_NO_SERIALIZE
, ptr
))
909 if (HeapFree( heap
, HEAP_NO_SERIALIZE
, ptr
)) ret
= 0;
911 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
913 if (HeapFree( heap
, HEAP_NO_SERIALIZE
, mem
->ptr
)) ret
= 0;
915 mem
->next_free
= next_free_mem
;
918 RtlUnlockHeap( heap
);
922 WARN_(globalmem
)( "invalid handle %p\n", handle
);
923 SetLastError( ERROR_INVALID_HANDLE
);
929 /***********************************************************************
930 * LocalLock (kernelbase.@)
932 LPVOID WINAPI DECLSPEC_HOTPATCH
LocalLock( HLOCAL handle
)
934 HANDLE heap
= GetProcessHeap();
935 struct mem_entry
*mem
;
938 TRACE_(globalmem
)( "handle %p\n", handle
);
940 if (!handle
) return NULL
;
941 if ((ret
= unsafe_ptr_from_HLOCAL( handle
)))
945 volatile char *p
= ret
;
957 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
959 if (!(ret
= mem
->ptr
)) SetLastError( ERROR_DISCARDED
);
960 else if (!++mem
->lock
) mem
->lock
--;
964 WARN_(globalmem
)( "invalid handle %p\n", handle
);
965 SetLastError( ERROR_INVALID_HANDLE
);
967 RtlUnlockHeap( heap
);
973 /***********************************************************************
974 * LocalReAlloc (kernelbase.@)
976 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalReAlloc( HLOCAL handle
, SIZE_T size
, UINT flags
)
978 DWORD heap_flags
= 0x200 | HEAP_ADD_USER_INFO
| HEAP_NO_SERIALIZE
;
979 HANDLE heap
= GetProcessHeap();
980 struct mem_entry
*mem
;
984 TRACE_(globalmem
)( "handle %p, size %#Ix, flags %#x\n", handle
, size
, flags
);
986 if (flags
& LMEM_ZEROINIT
) heap_flags
|= HEAP_ZERO_MEMORY
;
989 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)) &&
990 HeapValidate( heap
, HEAP_NO_SERIALIZE
, ptr
))
992 if (flags
& LMEM_MODIFY
) ret
= handle
;
993 else if (flags
& LMEM_DISCARDABLE
) SetLastError( ERROR_INVALID_PARAMETER
);
994 else if (flags
& LMEM_MOVEABLE
)
996 ret
= HeapReAlloc( heap
, heap_flags
, ptr
, size
);
997 if (ret
) RtlSetUserValueHeap( heap
, heap_flags
, ret
, ret
);
998 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1000 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1002 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
1004 if (flags
& LMEM_MODIFY
)
1006 if (flags
& LMEM_DISCARDABLE
) mem
->flags
|= MEM_FLAG_DISCARDABLE
;
1009 else if (flags
& LMEM_DISCARDABLE
) SetLastError( ERROR_INVALID_PARAMETER
);
1014 if (mem
->lock
&& !(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
1015 if (!mem
->ptr
) ptr
= HeapAlloc( heap
, heap_flags
, size
);
1016 else ptr
= HeapReAlloc( heap
, heap_flags
, mem
->ptr
, size
);
1018 if (!ptr
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1021 RtlSetUserValueHeap( heap
, heap_flags
, ptr
, handle
);
1022 mem
->flags
&= ~MEM_FLAG_DISCARDED
;
1027 else if ((flags
& LMEM_MOVEABLE
) && !mem
->lock
)
1029 HeapFree( heap
, heap_flags
, mem
->ptr
);
1030 mem
->flags
|= MEM_FLAG_DISCARDED
;
1034 else SetLastError( ERROR_INVALID_PARAMETER
);
1037 else SetLastError( ERROR_INVALID_HANDLE
);
1038 RtlUnlockHeap( heap
);
1044 /***********************************************************************
1045 * LocalUnlock (kernelbase.@)
1047 BOOL WINAPI DECLSPEC_HOTPATCH
LocalUnlock( HLOCAL handle
)
1049 HANDLE heap
= GetProcessHeap();
1050 struct mem_entry
*mem
;
1053 TRACE_(globalmem
)( "handle %p\n", handle
);
1055 if (unsafe_ptr_from_HLOCAL( handle
))
1057 SetLastError( ERROR_NOT_LOCKED
);
1061 RtlLockHeap( heap
);
1062 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
1066 ret
= (--mem
->lock
!= 0);
1067 if (!ret
) SetLastError( NO_ERROR
);
1071 WARN_(globalmem
)( "handle %p not locked\n", handle
);
1072 SetLastError( ERROR_NOT_LOCKED
);
1077 WARN_(globalmem
)( "invalid handle %p\n", handle
);
1078 SetLastError( ERROR_INVALID_HANDLE
);
1080 RtlUnlockHeap( heap
);
1086 /***********************************************************************
1087 * Memory resource functions
1088 ***********************************************************************/
1091 /***********************************************************************
1092 * CreateMemoryResourceNotification (kernelbase.@)
1094 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type
)
1097 UNICODE_STRING nameW
;
1098 OBJECT_ATTRIBUTES attr
;
1102 case LowMemoryResourceNotification
:
1103 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\LowMemoryCondition" );
1105 case HighMemoryResourceNotification
:
1106 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\HighMemoryCondition" );
1109 SetLastError( ERROR_INVALID_PARAMETER
);
1113 InitializeObjectAttributes( &attr
, &nameW
, 0, 0, NULL
);
1114 if (!set_ntstatus( NtOpenEvent( &ret
, EVENT_ALL_ACCESS
, &attr
))) return 0;
1118 /***********************************************************************
1119 * QueryMemoryResourceNotification (kernelbase.@)
1121 BOOL WINAPI DECLSPEC_HOTPATCH
QueryMemoryResourceNotification( HANDLE handle
, BOOL
*state
)
1123 switch (WaitForSingleObject( handle
, 0 ))
1132 SetLastError( ERROR_INVALID_PARAMETER
);
1137 /***********************************************************************
1138 * Physical memory functions
1139 ***********************************************************************/
1142 /***********************************************************************
1143 * AllocateUserPhysicalPages (kernelbase.@)
1145 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1146 ULONG_PTR
*userarray
)
1148 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1149 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1154 /***********************************************************************
1155 * FreeUserPhysicalPages (kernelbase.@)
1157 BOOL WINAPI DECLSPEC_HOTPATCH
FreeUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1158 ULONG_PTR
*userarray
)
1160 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1162 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1167 /***********************************************************************
1168 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1170 BOOL WINAPI DECLSPEC_HOTPATCH
GetPhysicallyInstalledSystemMemory( ULONGLONG
*memory
)
1172 MEMORYSTATUSEX status
;
1176 SetLastError( ERROR_INVALID_PARAMETER
);
1179 status
.dwLength
= sizeof(status
);
1180 GlobalMemoryStatusEx( &status
);
1181 *memory
= status
.ullTotalPhys
/ 1024;
1186 /***********************************************************************
1187 * GlobalMemoryStatusEx (kernelbase.@)
1189 BOOL WINAPI DECLSPEC_HOTPATCH
GlobalMemoryStatusEx( MEMORYSTATUSEX
*status
)
1191 static MEMORYSTATUSEX cached_status
;
1192 static DWORD last_check
;
1193 SYSTEM_BASIC_INFORMATION basic_info
;
1194 SYSTEM_PERFORMANCE_INFORMATION perf_info
;
1197 if (status
->dwLength
!= sizeof(*status
))
1199 SetLastError( ERROR_INVALID_PARAMETER
);
1202 if ((NtGetTickCount() - last_check
) < 1000)
1204 *status
= cached_status
;
1207 last_check
= NtGetTickCount();
1209 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
1210 &basic_info
, sizeof(basic_info
), NULL
)) ||
1211 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation
,
1212 &perf_info
, sizeof(perf_info
), NULL
)) ||
1213 !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
,
1214 &vmc
, sizeof(vmc
), NULL
)))
1217 status
->dwMemoryLoad
= 0;
1218 status
->ullTotalPhys
= basic_info
.MmNumberOfPhysicalPages
;
1219 status
->ullAvailPhys
= perf_info
.AvailablePages
;
1220 status
->ullTotalPageFile
= perf_info
.TotalCommitLimit
;
1221 status
->ullAvailPageFile
= status
->ullTotalPageFile
- perf_info
.TotalCommittedPages
;
1222 status
->ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
+ 1;
1223 status
->ullAvailVirtual
= status
->ullTotalVirtual
- (ULONGLONG
)vmc
.WorkingSetSize
/* approximate */;
1224 status
->ullAvailExtendedVirtual
= 0;
1226 status
->ullTotalPhys
*= basic_info
.PageSize
;
1227 status
->ullAvailPhys
*= basic_info
.PageSize
;
1228 status
->ullTotalPageFile
*= basic_info
.PageSize
;
1229 status
->ullAvailPageFile
*= basic_info
.PageSize
;
1231 if (status
->ullTotalPhys
)
1232 status
->dwMemoryLoad
= (status
->ullTotalPhys
- status
->ullAvailPhys
) / (status
->ullTotalPhys
/ 100);
1234 TRACE_(virtual)( "MemoryLoad %ld, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1235 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1236 status
->dwMemoryLoad
, wine_dbgstr_longlong(status
->ullTotalPhys
),
1237 wine_dbgstr_longlong(status
->ullAvailPhys
), wine_dbgstr_longlong(status
->ullTotalPageFile
),
1238 wine_dbgstr_longlong(status
->ullAvailPageFile
), wine_dbgstr_longlong(status
->ullTotalVirtual
),
1239 wine_dbgstr_longlong(status
->ullAvailVirtual
) );
1241 cached_status
= *status
;
1246 /***********************************************************************
1247 * MapUserPhysicalPages (kernelbase.@)
1249 BOOL WINAPI DECLSPEC_HOTPATCH
MapUserPhysicalPages( void *addr
, ULONG_PTR page_count
, ULONG_PTR
*pages
)
1251 FIXME( "stub: %p %Iu %p\n", addr
, page_count
, pages
);
1253 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1258 /***********************************************************************
1260 ***********************************************************************/
1263 /***********************************************************************
1264 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1266 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPagesNuma( HANDLE process
, ULONG_PTR
*pages
,
1267 ULONG_PTR
*userarray
, DWORD node
)
1269 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1270 return AllocateUserPhysicalPages( process
, pages
, userarray
);
1274 /***********************************************************************
1275 * CreateFileMappingNumaW (kernelbase.@)
1277 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileMappingNumaW( HANDLE file
, LPSECURITY_ATTRIBUTES sa
,
1278 DWORD protect
, DWORD size_high
, DWORD size_low
,
1279 LPCWSTR name
, DWORD node
)
1281 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1282 return CreateFileMappingW( file
, sa
, protect
, size_high
, size_low
, name
);
1286 /***********************************************************************
1287 * GetLogicalProcessorInformation (kernelbase.@)
1289 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buffer
,
1296 SetLastError( ERROR_INVALID_PARAMETER
);
1299 status
= NtQuerySystemInformation( SystemLogicalProcessorInformation
, buffer
, *len
, len
);
1300 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1301 return set_ntstatus( status
);
1305 /***********************************************************************
1306 * GetLogicalProcessorInformationEx (kernelbase.@)
1308 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship
,
1309 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buffer
, DWORD
*len
)
1315 SetLastError( ERROR_INVALID_PARAMETER
);
1318 status
= NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx
, &relationship
,
1319 sizeof(relationship
), buffer
, *len
, len
);
1320 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1321 return set_ntstatus( status
);
1325 /***********************************************************************
1326 * GetSystemCpuSetInformation (kernelbase.@)
1328 BOOL WINAPI
GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION
*info
, ULONG buffer_length
, ULONG
*return_length
,
1329 HANDLE process
, ULONG flags
)
1332 FIXME("Unsupported flags %#lx.\n", flags
);
1336 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation
, &process
, sizeof(process
), info
,
1337 buffer_length
, return_length
));
1341 /***********************************************************************
1342 * SetThreadSelectedCpuSets (kernelbase.@)
1344 BOOL WINAPI
SetThreadSelectedCpuSets(HANDLE thread
, const ULONG
*cpu_set_ids
, ULONG count
)
1346 FIXME( "thread %p, cpu_set_ids %p, count %lu stub.\n", thread
, cpu_set_ids
, count
);
1352 /***********************************************************************
1353 * SetProcessDefaultCpuSets (kernelbase.@)
1355 BOOL WINAPI
SetProcessDefaultCpuSets(HANDLE process
, const ULONG
*cpu_set_ids
, ULONG count
)
1357 FIXME( "process %p, cpu_set_ids %p, count %lu stub.\n", process
, cpu_set_ids
, count
);
1363 /**********************************************************************
1364 * GetNumaHighestNodeNumber (kernelbase.@)
1366 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaHighestNodeNumber( ULONG
*node
)
1368 FIXME( "semi-stub: %p\n", node
);
1374 /**********************************************************************
1375 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1377 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaNodeProcessorMaskEx( USHORT node
, GROUP_AFFINITY
*mask
)
1379 FIXME( "stub: %hu %p\n", node
, mask
);
1380 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1385 /***********************************************************************
1386 * GetNumaProximityNodeEx (kernelbase.@)
1388 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaProximityNodeEx( ULONG proximity_id
, USHORT
*node
)
1390 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1395 /***********************************************************************
1396 * MapViewOfFileExNuma (kernelbase.@)
1398 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileExNuma( HANDLE handle
, DWORD access
, DWORD offset_high
,
1399 DWORD offset_low
, SIZE_T count
, LPVOID addr
,
1402 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1403 return MapViewOfFileEx( handle
, access
, offset_high
, offset_low
, count
, addr
);
1407 /***********************************************************************
1408 * VirtualAllocExNuma (kernelbase.@)
1410 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocExNuma( HANDLE process
, void *addr
, SIZE_T size
,
1411 DWORD type
, DWORD protect
, DWORD node
)
1413 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1414 return VirtualAllocEx( process
, addr
, size
, type
, protect
);
1418 /***********************************************************************
1419 * QueryVirtualMemoryInformation (kernelbase.@)
1421 BOOL WINAPI DECLSPEC_HOTPATCH
QueryVirtualMemoryInformation( HANDLE process
, const void *addr
,
1422 WIN32_MEMORY_INFORMATION_CLASS info_class
, void *info
, SIZE_T size
, SIZE_T
*ret_size
)
1426 case MemoryRegionInfo
:
1427 return set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryRegionInformation
, info
, size
, ret_size
));
1429 FIXME("Unsupported info class %u.\n", info_class
);
1435 /***********************************************************************
1437 ***********************************************************************/
1440 #if defined(__i386__) || defined(__x86_64__)
1441 /***********************************************************************
1442 * GetEnabledXStateFeatures (kernelbase.@)
1444 DWORD64 WINAPI
GetEnabledXStateFeatures(void)
1447 return RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 );
1451 /***********************************************************************
1452 * InitializeContext2 (kernelbase.@)
1454 BOOL WINAPI
InitializeContext2( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
,
1455 ULONG64 compaction_mask
)
1460 TRACE( "buffer %p, context_flags %#lx, context %p, ret_length %p, compaction_mask %s.\n",
1461 buffer
, context_flags
, context
, length
, wine_dbgstr_longlong(compaction_mask
) );
1463 orig_length
= *length
;
1465 if ((status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
)))
1467 if (status
== STATUS_NOT_SUPPORTED
&& context_flags
& 0x40)
1469 context_flags
&= ~0x40;
1470 status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
);
1474 return set_ntstatus( status
);
1477 if (!buffer
|| orig_length
< *length
)
1479 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1483 if ((status
= RtlInitializeExtendedContext2( buffer
, context_flags
, (CONTEXT_EX
**)context
, compaction_mask
)))
1484 return set_ntstatus( status
);
1486 *context
= (CONTEXT
*)((BYTE
*)*context
+ (*(CONTEXT_EX
**)context
)->Legacy
.Offset
);
1491 /***********************************************************************
1492 * InitializeContext (kernelbase.@)
1494 BOOL WINAPI
InitializeContext( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
)
1496 return InitializeContext2( buffer
, context_flags
, context
, length
, ~(ULONG64
)0 );
1499 /***********************************************************************
1500 * CopyContext (kernelbase.@)
1502 BOOL WINAPI
CopyContext( CONTEXT
*dst
, DWORD context_flags
, CONTEXT
*src
)
1504 return set_ntstatus( RtlCopyContext( dst
, context_flags
, src
));
1509 #if defined(__x86_64__)
1510 /***********************************************************************
1511 * LocateXStateFeature (kernelbase.@)
1513 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1515 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1518 if (feature_id
>= 2)
1519 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1520 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1522 if (feature_id
== 1)
1525 *length
= sizeof(M128A
) * 16;
1527 return &context
->u
.FltSave
.XmmRegisters
;
1531 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1533 return &context
->u
.FltSave
;
1536 /***********************************************************************
1537 * SetXStateFeaturesMask (kernelbase.@)
1539 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1541 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1544 if (feature_mask
& 0x3)
1545 context
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
1547 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1548 return !(feature_mask
& ~(DWORD64
)3);
1550 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1554 /***********************************************************************
1555 * GetXStateFeaturesMask (kernelbase.@)
1557 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1559 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1562 *feature_mask
= (context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
1565 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1566 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1570 #elif defined(__i386__)
1571 /***********************************************************************
1572 * LocateXStateFeature (kernelbase.@)
1574 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1576 if (!(context
->ContextFlags
& CONTEXT_i386
))
1579 if (feature_id
>= 2)
1580 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1581 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1583 if (feature_id
== 1)
1586 *length
= sizeof(M128A
) * 8;
1588 return (BYTE
*)&context
->ExtendedRegisters
+ offsetof(XSAVE_FORMAT
, XmmRegisters
);
1592 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1594 return &context
->ExtendedRegisters
;
1597 /***********************************************************************
1598 * SetXStateFeaturesMask (kernelbase.@)
1600 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1602 if (!(context
->ContextFlags
& CONTEXT_i386
))
1605 if (feature_mask
& 0x3)
1606 context
->ContextFlags
|= CONTEXT_EXTENDED_REGISTERS
;
1608 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1609 return !(feature_mask
& ~(DWORD64
)3);
1611 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1615 /***********************************************************************
1616 * GetXStateFeaturesMask (kernelbase.@)
1618 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1620 if (!(context
->ContextFlags
& CONTEXT_i386
))
1623 *feature_mask
= (context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
1626 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1627 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1633 /***********************************************************************
1634 * Firmware functions
1635 ***********************************************************************/
1638 /***********************************************************************
1639 * EnumSystemFirmwareTable (kernelbase.@)
1641 UINT WINAPI
EnumSystemFirmwareTables( DWORD provider
, void *buffer
, DWORD size
)
1643 FIXME( "(0x%08lx, %p, %ld)\n", provider
, buffer
, size
);
1648 /***********************************************************************
1649 * GetSystemFirmwareTable (kernelbase.@)
1651 UINT WINAPI
GetSystemFirmwareTable( DWORD provider
, DWORD id
, void *buffer
, DWORD size
)
1653 SYSTEM_FIRMWARE_TABLE_INFORMATION
*info
;
1654 ULONG buffer_size
= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
) + size
;
1656 TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider
, id
, buffer
, size
);
1658 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, buffer_size
)))
1660 SetLastError( ERROR_OUTOFMEMORY
);
1664 info
->ProviderSignature
= provider
;
1665 info
->Action
= SystemFirmwareTable_Get
;
1668 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation
,
1669 info
, buffer_size
, &buffer_size
));
1670 buffer_size
-= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
1671 if (buffer_size
<= size
) memcpy( buffer
, info
->TableBuffer
, buffer_size
);
1673 HeapFree( GetProcessHeap(), 0, info
);