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
36 #include "kernelbase.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(heap
);
41 WINE_DECLARE_DEBUG_CHANNEL(virtual);
42 WINE_DECLARE_DEBUG_CHANNEL(globalmem
);
45 /***********************************************************************
46 * Virtual memory functions
47 ***********************************************************************/
50 /***********************************************************************
51 * DiscardVirtualMemory (kernelbase.@)
53 DWORD WINAPI DECLSPEC_HOTPATCH
DiscardVirtualMemory( void *addr
, SIZE_T size
)
58 status
= NtAllocateVirtualMemory( GetCurrentProcess(), &ret
, 0, &size
, MEM_RESET
, PAGE_NOACCESS
);
59 return RtlNtStatusToDosError( status
);
63 /***********************************************************************
64 * FlushViewOfFile (kernelbase.@)
66 BOOL WINAPI DECLSPEC_HOTPATCH
FlushViewOfFile( const void *base
, SIZE_T size
)
68 NTSTATUS status
= NtFlushVirtualMemory( GetCurrentProcess(), &base
, &size
, 0 );
70 if (status
== STATUS_NOT_MAPPED_DATA
) status
= STATUS_SUCCESS
;
71 return set_ntstatus( status
);
75 /***********************************************************************
76 * GetLargePageMinimum (kernelbase.@)
78 SIZE_T WINAPI
GetLargePageMinimum(void)
80 return 2 * 1024 * 1024;
84 static void fill_system_info( SYSTEM_INFO
*si
, const SYSTEM_BASIC_INFORMATION
*basic_info
,
85 const SYSTEM_CPU_INFORMATION
*cpu_info
)
87 si
->wProcessorArchitecture
= cpu_info
->ProcessorArchitecture
;
89 si
->dwPageSize
= basic_info
->PageSize
;
90 si
->lpMinimumApplicationAddress
= basic_info
->LowestUserAddress
;
91 si
->lpMaximumApplicationAddress
= basic_info
->HighestUserAddress
;
92 si
->dwActiveProcessorMask
= basic_info
->ActiveProcessorsAffinityMask
;
93 si
->dwNumberOfProcessors
= basic_info
->NumberOfProcessors
;
94 si
->dwAllocationGranularity
= basic_info
->AllocationGranularity
;
95 si
->wProcessorLevel
= cpu_info
->ProcessorLevel
;
96 si
->wProcessorRevision
= cpu_info
->ProcessorRevision
;
98 switch (cpu_info
->ProcessorArchitecture
)
100 case PROCESSOR_ARCHITECTURE_INTEL
:
101 switch (cpu_info
->ProcessorLevel
)
103 case 3: si
->dwProcessorType
= PROCESSOR_INTEL_386
; break;
104 case 4: si
->dwProcessorType
= PROCESSOR_INTEL_486
; break;
106 case 6: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
107 default: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
110 case PROCESSOR_ARCHITECTURE_AMD64
:
111 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
113 case PROCESSOR_ARCHITECTURE_ARM
:
114 switch (cpu_info
->ProcessorLevel
)
116 case 4: si
->dwProcessorType
= PROCESSOR_ARM_7TDMI
; break;
117 default: si
->dwProcessorType
= PROCESSOR_ARM920
;
120 case PROCESSOR_ARCHITECTURE_ARM64
:
121 si
->dwProcessorType
= 0;
124 FIXME( "Unknown processor architecture %x\n", cpu_info
->ProcessorArchitecture
);
125 si
->dwProcessorType
= 0;
131 /***********************************************************************
132 * GetNativeSystemInfo (kernelbase.@)
134 void WINAPI DECLSPEC_HOTPATCH
GetNativeSystemInfo( SYSTEM_INFO
*si
)
136 SYSTEM_BASIC_INFORMATION basic_info
;
137 SYSTEM_CPU_INFORMATION cpu_info
;
141 USHORT current_machine
, native_machine
;
143 RtlWow64GetProcessMachines( 0, ¤t_machine
, &native_machine
);
144 if (native_machine
!= IMAGE_FILE_MACHINE_AMD64
)
147 si
->wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_AMD64
;
152 if (!set_ntstatus( RtlGetNativeSystemInformation( SystemBasicInformation
,
153 &basic_info
, sizeof(basic_info
), NULL
)) ||
154 !set_ntstatus( RtlGetNativeSystemInformation( SystemCpuInformation
,
155 &cpu_info
, sizeof(cpu_info
), NULL
)))
158 fill_system_info( si
, &basic_info
, &cpu_info
);
162 /***********************************************************************
163 * GetSystemInfo (kernelbase.@)
165 void WINAPI DECLSPEC_HOTPATCH
GetSystemInfo( SYSTEM_INFO
*si
)
167 SYSTEM_BASIC_INFORMATION basic_info
;
168 SYSTEM_CPU_INFORMATION cpu_info
;
170 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
171 &basic_info
, sizeof(basic_info
), NULL
)) ||
172 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation
,
173 &cpu_info
, sizeof(cpu_info
), NULL
)))
176 fill_system_info( si
, &basic_info
, &cpu_info
);
180 /***********************************************************************
181 * GetSystemFileCacheSize (kernelbase.@)
183 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemFileCacheSize( SIZE_T
*mincache
, SIZE_T
*maxcache
, DWORD
*flags
)
185 FIXME( "stub: %p %p %p\n", mincache
, maxcache
, flags
);
186 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
191 /***********************************************************************
192 * GetWriteWatch (kernelbase.@)
194 UINT WINAPI DECLSPEC_HOTPATCH
GetWriteWatch( DWORD flags
, void *base
, SIZE_T size
, void **addresses
,
195 ULONG_PTR
*count
, ULONG
*granularity
)
197 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags
, base
, size
,
198 addresses
, count
, granularity
)))
204 /***********************************************************************
205 * MapViewOfFile (kernelbase.@)
207 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile( HANDLE mapping
, DWORD access
, DWORD offset_high
,
208 DWORD offset_low
, SIZE_T count
)
210 return MapViewOfFileEx( mapping
, access
, offset_high
, offset_low
, count
, NULL
);
214 /***********************************************************************
215 * MapViewOfFileEx (kernelbase.@)
217 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileEx( HANDLE handle
, DWORD access
, DWORD offset_high
,
218 DWORD offset_low
, SIZE_T count
, LPVOID addr
)
221 LARGE_INTEGER offset
;
225 offset
.u
.LowPart
= offset_low
;
226 offset
.u
.HighPart
= offset_high
;
228 exec
= access
& FILE_MAP_EXECUTE
;
229 access
&= ~FILE_MAP_EXECUTE
;
231 if (access
== FILE_MAP_COPY
)
232 protect
= exec
? PAGE_EXECUTE_WRITECOPY
: PAGE_WRITECOPY
;
233 else if (access
& FILE_MAP_WRITE
)
234 protect
= exec
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
235 else if (access
& FILE_MAP_READ
)
236 protect
= exec
? PAGE_EXECUTE_READ
: PAGE_READONLY
;
237 else protect
= PAGE_NOACCESS
;
239 if ((status
= NtMapViewOfSection( handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
240 &count
, ViewShare
, 0, protect
)) < 0)
242 SetLastError( RtlNtStatusToDosError(status
) );
249 /***********************************************************************
250 * MapViewOfFileFromApp (kernelbase.@)
252 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileFromApp( HANDLE handle
, ULONG access
, ULONG64 offset
, SIZE_T size
)
254 return MapViewOfFile( handle
, access
, offset
<< 32, offset
, size
);
257 /***********************************************************************
258 * MapViewOfFile3 (kernelbase.@)
260 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile3( HANDLE handle
, HANDLE process
, PVOID baseaddr
, ULONG64 offset
,
261 SIZE_T size
, ULONG alloc_type
, ULONG protection
, MEM_EXTENDED_PARAMETER
*params
, ULONG params_count
)
266 if (!process
) process
= GetCurrentProcess();
269 off
.QuadPart
= offset
;
270 if (!set_ntstatus( NtMapViewOfSectionEx( handle
, process
, &addr
, &off
, &size
, alloc_type
, protection
,
271 params
, params_count
)))
278 /***********************************************************************
279 * ReadProcessMemory (kernelbase.@)
281 BOOL WINAPI DECLSPEC_HOTPATCH
ReadProcessMemory( HANDLE process
, const void *addr
, void *buffer
,
282 SIZE_T size
, SIZE_T
*bytes_read
)
284 return set_ntstatus( NtReadVirtualMemory( process
, addr
, buffer
, size
, bytes_read
));
288 /***********************************************************************
289 * ResetWriteWatch (kernelbase.@)
291 UINT WINAPI DECLSPEC_HOTPATCH
ResetWriteWatch( void *base
, SIZE_T size
)
293 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base
, size
)))
299 /***********************************************************************
300 * SetSystemFileCacheSize (kernelbase.@)
302 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemFileCacheSize( SIZE_T mincache
, SIZE_T maxcache
, DWORD flags
)
304 FIXME( "stub: %Id %Id %ld\n", mincache
, maxcache
, flags
);
305 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
310 /***********************************************************************
311 * UnmapViewOfFile (kernelbase.@)
313 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile( const void *addr
)
315 if (GetVersion() & 0x80000000)
317 MEMORY_BASIC_INFORMATION info
;
318 if (!VirtualQuery( addr
, &info
, sizeof(info
) ) || info
.AllocationBase
!= addr
)
320 SetLastError( ERROR_INVALID_ADDRESS
);
324 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr
));
328 /***********************************************************************
329 * UnmapViewOfFile2 (kernelbase.@)
331 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile2( HANDLE process
, void *addr
, ULONG flags
)
333 return set_ntstatus( NtUnmapViewOfSectionEx( process
, addr
, flags
));
337 /***********************************************************************
338 * UnmapViewOfFileEx (kernelbase.@)
340 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFileEx( void *addr
, ULONG flags
)
342 return set_ntstatus( NtUnmapViewOfSectionEx( GetCurrentProcess(), addr
, flags
));
346 /***********************************************************************
347 * VirtualAlloc (kernelbase.@)
349 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc( void *addr
, SIZE_T size
, DWORD type
, DWORD protect
)
351 return VirtualAllocEx( GetCurrentProcess(), addr
, size
, type
, protect
);
355 /***********************************************************************
356 * VirtualAllocEx (kernelbase.@)
358 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocEx( HANDLE process
, void *addr
, SIZE_T size
,
359 DWORD type
, DWORD protect
)
363 if (!set_ntstatus( NtAllocateVirtualMemory( process
, &ret
, 0, &size
, type
, protect
))) return NULL
;
368 /***********************************************************************
369 * VirtualAlloc2 (kernelbase.@)
371 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc2( HANDLE process
, void *addr
, SIZE_T size
,
372 DWORD type
, DWORD protect
,
373 MEM_EXTENDED_PARAMETER
*parameters
, ULONG count
)
377 if (!process
) process
= GetCurrentProcess();
378 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process
, &ret
, &size
, type
, protect
, parameters
, count
)))
383 static BOOL
is_exec_prot( DWORD protect
)
385 return protect
== PAGE_EXECUTE
|| protect
== PAGE_EXECUTE_READ
|| protect
== PAGE_EXECUTE_READWRITE
386 || protect
== PAGE_EXECUTE_WRITECOPY
;
389 /***********************************************************************
390 * VirtualAlloc2FromApp (kernelbase.@)
392 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc2FromApp( HANDLE process
, void *addr
, SIZE_T size
,
393 DWORD type
, DWORD protect
, MEM_EXTENDED_PARAMETER
*parameters
, ULONG count
)
397 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx, params %p, count %lu.\n", addr
, (void *)size
, type
, protect
,
400 if (is_exec_prot( protect
))
402 SetLastError( ERROR_INVALID_PARAMETER
);
406 if (!process
) process
= GetCurrentProcess();
407 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process
, &ret
, &size
, type
, protect
, parameters
, count
)))
413 /***********************************************************************
414 * VirtualAllocFromApp (kernelbase.@)
416 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocFromApp( void *addr
, SIZE_T size
,
417 DWORD type
, DWORD protect
)
421 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx.\n", addr
, (void *)size
, type
, protect
);
423 if (is_exec_prot( protect
))
425 SetLastError( ERROR_INVALID_PARAMETER
);
429 if (!set_ntstatus( NtAllocateVirtualMemory( GetCurrentProcess(), &ret
, 0, &size
, type
, protect
))) return NULL
;
434 /***********************************************************************
435 * PrefetchVirtualMemory (kernelbase.@)
437 BOOL WINAPI DECLSPEC_HOTPATCH
PrefetchVirtualMemory( HANDLE process
, ULONG_PTR count
,
438 WIN32_MEMORY_RANGE_ENTRY
*addresses
, ULONG flags
)
440 return set_ntstatus( NtSetInformationVirtualMemory( process
, VmPrefetchInformation
,
441 count
, (PMEMORY_RANGE_ENTRY
)addresses
,
442 &flags
, sizeof(flags
) ));
446 /***********************************************************************
447 * VirtualFree (kernelbase.@)
449 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFree( void *addr
, SIZE_T size
, DWORD type
)
451 return VirtualFreeEx( GetCurrentProcess(), addr
, size
, type
);
455 /***********************************************************************
456 * VirtualFreeEx (kernelbase.@)
458 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFreeEx( HANDLE process
, void *addr
, SIZE_T size
, DWORD type
)
460 if (type
== MEM_RELEASE
&& size
)
462 WARN( "Trying to release memory with specified size.\n" );
463 SetLastError( ERROR_INVALID_PARAMETER
);
466 return set_ntstatus( NtFreeVirtualMemory( process
, &addr
, &size
, type
));
470 /***********************************************************************
471 * VirtualLock (kernelbase.@)
473 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualLock( void *addr
, SIZE_T size
)
475 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
479 /***********************************************************************
480 * VirtualProtect (kernelbase.@)
482 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtect( void *addr
, SIZE_T size
, DWORD new_prot
, DWORD
*old_prot
)
484 return VirtualProtectEx( GetCurrentProcess(), addr
, size
, new_prot
, old_prot
);
488 /***********************************************************************
489 * VirtualProtectEx (kernelbase.@)
491 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtectEx( HANDLE process
, void *addr
, SIZE_T size
,
492 DWORD new_prot
, DWORD
*old_prot
)
496 /* Win9x allows passing NULL as old_prot while this fails on NT */
497 if (!old_prot
&& (GetVersion() & 0x80000000)) old_prot
= &prot
;
498 return set_ntstatus( NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
));
502 /***********************************************************************
503 * VirtualQuery (kernelbase.@)
505 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQuery( LPCVOID addr
, PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
507 return VirtualQueryEx( GetCurrentProcess(), addr
, info
, len
);
511 /***********************************************************************
512 * VirtualQueryEx (kernelbase.@)
514 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQueryEx( HANDLE process
, LPCVOID addr
,
515 PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
519 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryBasicInformation
, info
, len
, &ret
)))
525 /***********************************************************************
526 * VirtualUnlock (kernelbase.@)
528 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualUnlock( void *addr
, SIZE_T size
)
530 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
534 /***********************************************************************
535 * WriteProcessMemory (kernelbase.@)
537 BOOL WINAPI DECLSPEC_HOTPATCH
WriteProcessMemory( HANDLE process
, void *addr
, const void *buffer
,
538 SIZE_T size
, SIZE_T
*bytes_written
)
540 return set_ntstatus( NtWriteVirtualMemory( process
, addr
, buffer
, size
, bytes_written
));
544 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
545 BOOL WINAPI
IsBadStringPtrA( LPCSTR str
, UINT_PTR max
)
547 if (!str
) return TRUE
;
550 volatile const char *p
= str
;
551 while (p
!= str
+ max
) if (!*p
++) break;
562 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
563 BOOL WINAPI
IsBadStringPtrW( LPCWSTR str
, UINT_PTR max
)
565 if (!str
) return TRUE
;
568 volatile const WCHAR
*p
= str
;
569 while (p
!= str
+ max
) if (!*p
++) break;
580 /***********************************************************************
582 ***********************************************************************/
585 /***********************************************************************
586 * HeapCompact (kernelbase.@)
588 SIZE_T WINAPI DECLSPEC_HOTPATCH
HeapCompact( HANDLE heap
, DWORD flags
)
590 return RtlCompactHeap( heap
, flags
);
594 /***********************************************************************
595 * HeapCreate (kernelbase.@)
597 HANDLE WINAPI DECLSPEC_HOTPATCH
HeapCreate( DWORD flags
, SIZE_T init_size
, SIZE_T max_size
)
599 HANDLE ret
= RtlCreateHeap( flags
, NULL
, max_size
, init_size
, NULL
, NULL
);
600 if (!ret
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
605 /***********************************************************************
606 * HeapDestroy (kernelbase.@)
608 BOOL WINAPI DECLSPEC_HOTPATCH
HeapDestroy( HANDLE heap
)
610 if (!RtlDestroyHeap( heap
)) return TRUE
;
611 SetLastError( ERROR_INVALID_HANDLE
);
616 /***********************************************************************
617 * HeapLock (kernelbase.@)
619 BOOL WINAPI DECLSPEC_HOTPATCH
HeapLock( HANDLE heap
)
621 return RtlLockHeap( heap
);
625 /***********************************************************************
626 * HeapQueryInformation (kernelbase.@)
628 BOOL WINAPI
HeapQueryInformation( HANDLE heap
, HEAP_INFORMATION_CLASS info_class
,
629 PVOID info
, SIZE_T size
, PSIZE_T size_out
)
631 return set_ntstatus( RtlQueryHeapInformation( heap
, info_class
, info
, size
, size_out
));
635 /***********************************************************************
636 * HeapSetInformation (kernelbase.@)
638 BOOL WINAPI
HeapSetInformation( HANDLE heap
, HEAP_INFORMATION_CLASS infoclass
, PVOID info
, SIZE_T size
)
640 return set_ntstatus( RtlSetHeapInformation( heap
, infoclass
, info
, size
));
644 /***********************************************************************
645 * HeapUnlock (kernelbase.@)
647 BOOL WINAPI
HeapUnlock( HANDLE heap
)
649 return RtlUnlockHeap( heap
);
653 /***********************************************************************
654 * HeapValidate (kernelbase.@)
656 BOOL WINAPI DECLSPEC_HOTPATCH
HeapValidate( HANDLE heap
, DWORD flags
, LPCVOID ptr
)
658 return RtlValidateHeap( heap
, flags
, ptr
);
662 /* undocumented RtlWalkHeap structure */
664 struct rtl_heap_entry
667 SIZE_T cbData
; /* differs from PROCESS_HEAP_ENTRY */
670 WORD wFlags
; /* value differs from PROCESS_HEAP_ENTRY */
677 DWORD dwCommittedSize
;
678 DWORD dwUnCommittedSize
;
685 /* rtl_heap_entry flags, names made up */
687 #define RTL_HEAP_ENTRY_BUSY 0x0001
688 #define RTL_HEAP_ENTRY_REGION 0x0002
689 #define RTL_HEAP_ENTRY_BLOCK 0x0010
690 #define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000
691 #define RTL_HEAP_ENTRY_COMMITTED 0x4000
692 #define RTL_HEAP_ENTRY_LFH 0x8000
695 /***********************************************************************
696 * HeapWalk (kernelbase.@)
698 BOOL WINAPI DECLSPEC_HOTPATCH
HeapWalk( HANDLE heap
, PROCESS_HEAP_ENTRY
*entry
)
700 struct rtl_heap_entry rtl_entry
= {0};
703 if (!entry
) return set_ntstatus( STATUS_INVALID_PARAMETER
);
705 rtl_entry
.lpData
= entry
->lpData
;
706 rtl_entry
.cbData
= entry
->cbData
;
707 rtl_entry
.cbOverhead
= entry
->cbOverhead
;
708 rtl_entry
.iRegionIndex
= entry
->iRegionIndex
;
710 if (entry
->wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
711 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_BUSY
;
712 if (entry
->wFlags
& PROCESS_HEAP_REGION
)
713 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_REGION
;
714 if (entry
->wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
715 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_UNCOMMITTED
;
716 memcpy( &rtl_entry
.Region
, &entry
->Region
, sizeof(entry
->Region
) );
718 if (!(status
= RtlWalkHeap( heap
, &rtl_entry
)))
720 entry
->lpData
= rtl_entry
.lpData
;
721 entry
->cbData
= rtl_entry
.cbData
;
722 entry
->cbOverhead
= rtl_entry
.cbOverhead
;
723 entry
->iRegionIndex
= rtl_entry
.iRegionIndex
;
725 if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_BUSY
)
726 entry
->wFlags
= PROCESS_HEAP_ENTRY_BUSY
;
727 else if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_REGION
)
728 entry
->wFlags
= PROCESS_HEAP_REGION
;
729 else if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_UNCOMMITTED
)
730 entry
->wFlags
= PROCESS_HEAP_UNCOMMITTED_RANGE
;
734 memcpy( &entry
->Region
, &rtl_entry
.Region
, sizeof(entry
->Region
) );
737 return set_ntstatus( status
);
741 /***********************************************************************
742 * Global/local heap functions
743 ***********************************************************************/
745 /* some undocumented flags (names are made up) */
746 #define HEAP_ADD_USER_INFO 0x00000100
748 /* not compatible with windows */
749 struct kernelbase_global_data
751 struct mem_entry
*mem_entries
;
752 struct mem_entry
*mem_entries_end
;
755 #define MEM_FLAG_USED 1
756 #define MEM_FLAG_MOVEABLE 2
757 #define MEM_FLAG_DISCARDABLE 4
758 #define MEM_FLAG_DISCARDED 8
759 #define MEM_FLAG_DDESHARE 0x8000
775 C_ASSERT(sizeof(struct mem_entry
) == 2 * sizeof(void *));
777 #define MAX_MEM_HANDLES 0x10000
778 static struct mem_entry
*next_free_mem
;
779 static struct kernelbase_global_data global_data
= {0};
781 static inline struct mem_entry
*unsafe_mem_from_HLOCAL( HLOCAL handle
)
783 struct mem_entry
*mem
= CONTAINING_RECORD( *(volatile HANDLE
*)&handle
, struct mem_entry
, ptr
);
784 struct kernelbase_global_data
*data
= &global_data
;
785 if (((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL
;
786 if (mem
< data
->mem_entries
|| mem
>= data
->mem_entries_end
) return NULL
;
787 if (!(mem
->flags
& MEM_FLAG_USED
)) return NULL
;
791 static inline HLOCAL
HLOCAL_from_mem( struct mem_entry
*mem
)
797 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle
)
799 if (((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1))) return NULL
;
803 void init_global_data(void)
805 global_data
.mem_entries
= VirtualAlloc( NULL
, MAX_MEM_HANDLES
* sizeof(struct mem_entry
), MEM_COMMIT
, PAGE_READWRITE
);
806 if (!(next_free_mem
= global_data
.mem_entries
)) ERR( "Failed to allocate kernelbase global handle table\n" );
807 global_data
.mem_entries_end
= global_data
.mem_entries
+ MAX_MEM_HANDLES
;
810 /***********************************************************************
811 * KernelBaseGetGlobalData (kernelbase.@)
813 void *WINAPI
KernelBaseGetGlobalData(void)
815 WARN_(globalmem
)( "semi-stub!\n" );
820 /***********************************************************************
821 * GlobalAlloc (kernelbase.@)
823 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalAlloc( UINT flags
, SIZE_T size
)
825 struct mem_entry
*mem
;
828 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
829 if (!(flags
& GMEM_MOVEABLE
) && !size
) size
= 1;
831 handle
= LocalAlloc( flags
, size
);
833 if ((mem
= unsafe_mem_from_HLOCAL( handle
)) && (flags
& GMEM_DDESHARE
))
834 mem
->flags
|= MEM_FLAG_DDESHARE
;
840 /***********************************************************************
841 * GlobalFree (kernelbase.@)
843 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalFree( HLOCAL handle
)
845 return LocalFree( handle
);
849 /***********************************************************************
850 * LocalAlloc (kernelbase.@)
852 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalAlloc( UINT flags
, SIZE_T size
)
854 DWORD heap_flags
= 0x200 | HEAP_ADD_USER_INFO
;
855 HANDLE heap
= GetProcessHeap();
856 struct mem_entry
*mem
;
860 TRACE_(globalmem
)( "flags %#x, size %#Ix\n", flags
, size
);
862 if (flags
& LMEM_ZEROINIT
) heap_flags
|= HEAP_ZERO_MEMORY
;
864 if (!(flags
& LMEM_MOVEABLE
)) /* pointer */
866 ptr
= HeapAlloc( heap
, heap_flags
, size
);
867 if (ptr
) RtlSetUserValueHeap( heap
, heap_flags
, ptr
, ptr
);
868 TRACE_(globalmem
)( "return %p\n", ptr
);
873 if ((mem
= next_free_mem
) < global_data
.mem_entries
|| mem
>= global_data
.mem_entries_end
)
877 if (!mem
->next_free
) next_free_mem
++;
878 else next_free_mem
= mem
->next_free
;
879 mem
->next_free
= NULL
;
881 RtlUnlockHeap( heap
);
883 if (!mem
) goto failed
;
884 handle
= HLOCAL_from_mem( mem
);
886 mem
->flags
= MEM_FLAG_USED
| MEM_FLAG_MOVEABLE
;
887 if (flags
& LMEM_DISCARDABLE
) mem
->flags
|= MEM_FLAG_DISCARDABLE
;
891 if (!size
) mem
->flags
|= MEM_FLAG_DISCARDED
;
894 if (!(ptr
= HeapAlloc( heap
, heap_flags
, size
))) goto failed
;
895 RtlSetUserValueHeap( heap
, heap_flags
, ptr
, handle
);
899 TRACE_(globalmem
)( "return handle %p, ptr %p\n", handle
, mem
->ptr
);
903 if (mem
) LocalFree( *(volatile HANDLE
*)&handle
);
904 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
909 /***********************************************************************
910 * LocalFree (kernelbase.@)
912 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalFree( HLOCAL handle
)
914 HANDLE heap
= GetProcessHeap();
915 struct mem_entry
*mem
;
919 TRACE_(globalmem
)( "handle %p\n", handle
);
922 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)) &&
923 HeapValidate( heap
, HEAP_NO_SERIALIZE
, ptr
))
925 if (HeapFree( heap
, HEAP_NO_SERIALIZE
, ptr
)) ret
= 0;
927 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
929 if (HeapFree( heap
, HEAP_NO_SERIALIZE
, mem
->ptr
)) ret
= 0;
931 mem
->next_free
= next_free_mem
;
934 RtlUnlockHeap( heap
);
938 WARN_(globalmem
)( "invalid handle %p\n", handle
);
939 SetLastError( ERROR_INVALID_HANDLE
);
945 /***********************************************************************
946 * LocalLock (kernelbase.@)
948 LPVOID WINAPI DECLSPEC_HOTPATCH
LocalLock( HLOCAL handle
)
950 HANDLE heap
= GetProcessHeap();
951 struct mem_entry
*mem
;
954 TRACE_(globalmem
)( "handle %p\n", handle
);
956 if (!handle
) return NULL
;
957 if ((ret
= unsafe_ptr_from_HLOCAL( handle
)))
961 volatile char *p
= ret
;
973 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
975 if (!(ret
= mem
->ptr
)) SetLastError( ERROR_DISCARDED
);
976 else if (!++mem
->lock
) mem
->lock
--;
980 WARN_(globalmem
)( "invalid handle %p\n", handle
);
981 SetLastError( ERROR_INVALID_HANDLE
);
983 RtlUnlockHeap( heap
);
989 /***********************************************************************
990 * LocalReAlloc (kernelbase.@)
992 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalReAlloc( HLOCAL handle
, SIZE_T size
, UINT flags
)
994 DWORD heap_flags
= 0x200 | HEAP_ADD_USER_INFO
| HEAP_NO_SERIALIZE
;
995 HANDLE heap
= GetProcessHeap();
996 struct mem_entry
*mem
;
1000 TRACE_(globalmem
)( "handle %p, size %#Ix, flags %#x\n", handle
, size
, flags
);
1002 if (flags
& LMEM_ZEROINIT
) heap_flags
|= HEAP_ZERO_MEMORY
;
1004 RtlLockHeap( heap
);
1005 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)) &&
1006 HeapValidate( heap
, HEAP_NO_SERIALIZE
, ptr
))
1008 if (flags
& LMEM_MODIFY
) ret
= handle
;
1009 else if (flags
& LMEM_DISCARDABLE
) SetLastError( ERROR_INVALID_PARAMETER
);
1012 if (!(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
1013 ret
= HeapReAlloc( heap
, heap_flags
, ptr
, size
);
1014 if (ret
) RtlSetUserValueHeap( heap
, heap_flags
, ret
, ret
);
1015 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1018 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
1020 if (flags
& LMEM_MODIFY
)
1022 if (flags
& LMEM_DISCARDABLE
) mem
->flags
|= MEM_FLAG_DISCARDABLE
;
1025 else if (flags
& LMEM_DISCARDABLE
) SetLastError( ERROR_INVALID_PARAMETER
);
1030 if (mem
->lock
&& !(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
1031 if (!mem
->ptr
) ptr
= HeapAlloc( heap
, heap_flags
, size
);
1032 else ptr
= HeapReAlloc( heap
, heap_flags
, mem
->ptr
, size
);
1034 if (!ptr
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1037 RtlSetUserValueHeap( heap
, heap_flags
, ptr
, handle
);
1038 mem
->flags
&= ~MEM_FLAG_DISCARDED
;
1043 else if ((flags
& LMEM_MOVEABLE
) && !mem
->lock
)
1045 HeapFree( heap
, heap_flags
, mem
->ptr
);
1046 mem
->flags
|= MEM_FLAG_DISCARDED
;
1050 else SetLastError( ERROR_INVALID_PARAMETER
);
1053 else SetLastError( ERROR_INVALID_HANDLE
);
1054 RtlUnlockHeap( heap
);
1060 /***********************************************************************
1061 * LocalUnlock (kernelbase.@)
1063 BOOL WINAPI DECLSPEC_HOTPATCH
LocalUnlock( HLOCAL handle
)
1065 HANDLE heap
= GetProcessHeap();
1066 struct mem_entry
*mem
;
1069 TRACE_(globalmem
)( "handle %p\n", handle
);
1071 if (unsafe_ptr_from_HLOCAL( handle
))
1073 SetLastError( ERROR_NOT_LOCKED
);
1077 RtlLockHeap( heap
);
1078 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
1082 ret
= (--mem
->lock
!= 0);
1083 if (!ret
) SetLastError( NO_ERROR
);
1087 WARN_(globalmem
)( "handle %p not locked\n", handle
);
1088 SetLastError( ERROR_NOT_LOCKED
);
1093 WARN_(globalmem
)( "invalid handle %p\n", handle
);
1094 SetLastError( ERROR_INVALID_HANDLE
);
1096 RtlUnlockHeap( heap
);
1102 /***********************************************************************
1103 * Memory resource functions
1104 ***********************************************************************/
1107 /***********************************************************************
1108 * CreateMemoryResourceNotification (kernelbase.@)
1110 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type
)
1113 UNICODE_STRING nameW
;
1114 OBJECT_ATTRIBUTES attr
;
1118 case LowMemoryResourceNotification
:
1119 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\LowMemoryCondition" );
1121 case HighMemoryResourceNotification
:
1122 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\HighMemoryCondition" );
1125 SetLastError( ERROR_INVALID_PARAMETER
);
1129 InitializeObjectAttributes( &attr
, &nameW
, 0, 0, NULL
);
1130 if (!set_ntstatus( NtOpenEvent( &ret
, EVENT_ALL_ACCESS
, &attr
))) return 0;
1134 /***********************************************************************
1135 * QueryMemoryResourceNotification (kernelbase.@)
1137 BOOL WINAPI DECLSPEC_HOTPATCH
QueryMemoryResourceNotification( HANDLE handle
, BOOL
*state
)
1139 switch (WaitForSingleObject( handle
, 0 ))
1148 SetLastError( ERROR_INVALID_PARAMETER
);
1153 /***********************************************************************
1154 * Physical memory functions
1155 ***********************************************************************/
1158 /***********************************************************************
1159 * AllocateUserPhysicalPages (kernelbase.@)
1161 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1162 ULONG_PTR
*userarray
)
1164 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1165 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1170 /***********************************************************************
1171 * FreeUserPhysicalPages (kernelbase.@)
1173 BOOL WINAPI DECLSPEC_HOTPATCH
FreeUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1174 ULONG_PTR
*userarray
)
1176 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1178 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1183 /***********************************************************************
1184 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1186 BOOL WINAPI DECLSPEC_HOTPATCH
GetPhysicallyInstalledSystemMemory( ULONGLONG
*memory
)
1188 MEMORYSTATUSEX status
;
1192 SetLastError( ERROR_INVALID_PARAMETER
);
1195 status
.dwLength
= sizeof(status
);
1196 GlobalMemoryStatusEx( &status
);
1197 *memory
= status
.ullTotalPhys
/ 1024;
1202 /***********************************************************************
1203 * GlobalMemoryStatusEx (kernelbase.@)
1205 BOOL WINAPI DECLSPEC_HOTPATCH
GlobalMemoryStatusEx( MEMORYSTATUSEX
*status
)
1207 static MEMORYSTATUSEX cached_status
;
1208 static DWORD last_check
;
1209 SYSTEM_BASIC_INFORMATION basic_info
;
1210 SYSTEM_PERFORMANCE_INFORMATION perf_info
;
1213 if (status
->dwLength
!= sizeof(*status
))
1215 SetLastError( ERROR_INVALID_PARAMETER
);
1218 if ((NtGetTickCount() - last_check
) < 1000)
1220 *status
= cached_status
;
1223 last_check
= NtGetTickCount();
1225 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
1226 &basic_info
, sizeof(basic_info
), NULL
)) ||
1227 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation
,
1228 &perf_info
, sizeof(perf_info
), NULL
)) ||
1229 !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
,
1230 &vmc
, sizeof(vmc
), NULL
)))
1233 status
->dwMemoryLoad
= 0;
1234 status
->ullTotalPhys
= basic_info
.MmNumberOfPhysicalPages
;
1235 status
->ullAvailPhys
= perf_info
.AvailablePages
;
1236 status
->ullTotalPageFile
= perf_info
.TotalCommitLimit
;
1237 status
->ullAvailPageFile
= status
->ullTotalPageFile
- perf_info
.TotalCommittedPages
;
1238 status
->ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
+ 1;
1239 status
->ullAvailVirtual
= status
->ullTotalVirtual
- (ULONGLONG
)vmc
.WorkingSetSize
/* approximate */;
1240 status
->ullAvailExtendedVirtual
= 0;
1242 status
->ullTotalPhys
*= basic_info
.PageSize
;
1243 status
->ullAvailPhys
*= basic_info
.PageSize
;
1244 status
->ullTotalPageFile
*= basic_info
.PageSize
;
1245 status
->ullAvailPageFile
*= basic_info
.PageSize
;
1247 if (status
->ullTotalPhys
)
1248 status
->dwMemoryLoad
= (status
->ullTotalPhys
- status
->ullAvailPhys
) / (status
->ullTotalPhys
/ 100);
1250 TRACE_(virtual)( "MemoryLoad %lu, TotalPhys %I64u, AvailPhys %I64u, TotalPageFile %I64u, "
1251 "AvailPageFile %I64u, TotalVirtual %I64u, AvailVirtual %I64u\n",
1252 status
->dwMemoryLoad
, status
->ullTotalPhys
, status
->ullAvailPhys
, status
->ullTotalPageFile
,
1253 status
->ullAvailPageFile
, status
->ullTotalVirtual
, status
->ullAvailVirtual
);
1255 cached_status
= *status
;
1260 /***********************************************************************
1261 * MapUserPhysicalPages (kernelbase.@)
1263 BOOL WINAPI DECLSPEC_HOTPATCH
MapUserPhysicalPages( void *addr
, ULONG_PTR page_count
, ULONG_PTR
*pages
)
1265 FIXME( "stub: %p %Iu %p\n", addr
, page_count
, pages
);
1267 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1272 /***********************************************************************
1274 ***********************************************************************/
1277 /***********************************************************************
1278 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1280 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPagesNuma( HANDLE process
, ULONG_PTR
*pages
,
1281 ULONG_PTR
*userarray
, DWORD node
)
1283 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1284 return AllocateUserPhysicalPages( process
, pages
, userarray
);
1288 /***********************************************************************
1289 * CreateFileMappingNumaW (kernelbase.@)
1291 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileMappingNumaW( HANDLE file
, LPSECURITY_ATTRIBUTES sa
,
1292 DWORD protect
, DWORD size_high
, DWORD size_low
,
1293 LPCWSTR name
, DWORD node
)
1295 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1296 return CreateFileMappingW( file
, sa
, protect
, size_high
, size_low
, name
);
1300 /***********************************************************************
1301 * GetLogicalProcessorInformation (kernelbase.@)
1303 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buffer
,
1310 SetLastError( ERROR_INVALID_PARAMETER
);
1313 status
= NtQuerySystemInformation( SystemLogicalProcessorInformation
, buffer
, *len
, len
);
1314 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1315 return set_ntstatus( status
);
1319 /***********************************************************************
1320 * GetLogicalProcessorInformationEx (kernelbase.@)
1322 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship
,
1323 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buffer
, DWORD
*len
)
1329 SetLastError( ERROR_INVALID_PARAMETER
);
1332 status
= NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx
, &relationship
,
1333 sizeof(relationship
), buffer
, *len
, len
);
1334 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1335 return set_ntstatus( status
);
1339 /***********************************************************************
1340 * GetSystemCpuSetInformation (kernelbase.@)
1342 BOOL WINAPI
GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION
*info
, ULONG buffer_length
, ULONG
*return_length
,
1343 HANDLE process
, ULONG flags
)
1346 FIXME("Unsupported flags %#lx.\n", flags
);
1350 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation
, &process
, sizeof(process
), info
,
1351 buffer_length
, return_length
));
1355 /***********************************************************************
1356 * SetThreadSelectedCpuSets (kernelbase.@)
1358 BOOL WINAPI
SetThreadSelectedCpuSets(HANDLE thread
, const ULONG
*cpu_set_ids
, ULONG count
)
1360 FIXME( "thread %p, cpu_set_ids %p, count %lu stub.\n", thread
, cpu_set_ids
, count
);
1366 /***********************************************************************
1367 * SetProcessDefaultCpuSets (kernelbase.@)
1369 BOOL WINAPI
SetProcessDefaultCpuSets(HANDLE process
, const ULONG
*cpu_set_ids
, ULONG count
)
1371 FIXME( "process %p, cpu_set_ids %p, count %lu stub.\n", process
, cpu_set_ids
, count
);
1377 /**********************************************************************
1378 * GetNumaHighestNodeNumber (kernelbase.@)
1380 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaHighestNodeNumber( ULONG
*node
)
1382 FIXME( "semi-stub: %p\n", node
);
1388 /**********************************************************************
1389 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1391 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaNodeProcessorMaskEx( USHORT node
, GROUP_AFFINITY
*mask
)
1393 FIXME( "stub: %hu %p\n", node
, mask
);
1394 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1399 /***********************************************************************
1400 * GetNumaProximityNodeEx (kernelbase.@)
1402 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaProximityNodeEx( ULONG proximity_id
, USHORT
*node
)
1404 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1409 /***********************************************************************
1410 * MapViewOfFileExNuma (kernelbase.@)
1412 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileExNuma( HANDLE handle
, DWORD access
, DWORD offset_high
,
1413 DWORD offset_low
, SIZE_T count
, LPVOID addr
,
1416 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1417 return MapViewOfFileEx( handle
, access
, offset_high
, offset_low
, count
, addr
);
1421 /***********************************************************************
1422 * VirtualAllocExNuma (kernelbase.@)
1424 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocExNuma( HANDLE process
, void *addr
, SIZE_T size
,
1425 DWORD type
, DWORD protect
, DWORD node
)
1427 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1428 return VirtualAllocEx( process
, addr
, size
, type
, protect
);
1432 /***********************************************************************
1433 * QueryVirtualMemoryInformation (kernelbase.@)
1435 BOOL WINAPI DECLSPEC_HOTPATCH
QueryVirtualMemoryInformation( HANDLE process
, const void *addr
,
1436 WIN32_MEMORY_INFORMATION_CLASS info_class
, void *info
, SIZE_T size
, SIZE_T
*ret_size
)
1440 case MemoryRegionInfo
:
1441 return set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryRegionInformation
, info
, size
, ret_size
));
1443 FIXME("Unsupported info class %u.\n", info_class
);
1449 /***********************************************************************
1451 ***********************************************************************/
1454 /***********************************************************************
1455 * InitializeContext2 (kernelbase.@)
1457 BOOL WINAPI
InitializeContext2( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
,
1458 ULONG64 compaction_mask
)
1463 TRACE( "buffer %p, context_flags %#lx, context %p, ret_length %p, compaction_mask %s.\n",
1464 buffer
, context_flags
, context
, length
, wine_dbgstr_longlong(compaction_mask
) );
1466 orig_length
= *length
;
1468 if ((status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
)))
1470 if (status
== STATUS_NOT_SUPPORTED
&& context_flags
& 0x40)
1472 context_flags
&= ~0x40;
1473 status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
);
1477 return set_ntstatus( status
);
1480 if (!buffer
|| orig_length
< *length
)
1482 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1486 if ((status
= RtlInitializeExtendedContext2( buffer
, context_flags
, (CONTEXT_EX
**)context
, compaction_mask
)))
1487 return set_ntstatus( status
);
1489 *context
= (CONTEXT
*)((BYTE
*)*context
+ (*(CONTEXT_EX
**)context
)->Legacy
.Offset
);
1494 /***********************************************************************
1495 * InitializeContext (kernelbase.@)
1497 BOOL WINAPI
InitializeContext( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
)
1499 return InitializeContext2( buffer
, context_flags
, context
, length
, ~(ULONG64
)0 );
1502 /***********************************************************************
1503 * CopyContext (kernelbase.@)
1505 BOOL WINAPI
CopyContext( CONTEXT
*dst
, DWORD context_flags
, CONTEXT
*src
)
1507 return set_ntstatus( RtlCopyContext( dst
, context_flags
, src
));
1511 #if defined(__x86_64__)
1513 /***********************************************************************
1514 * GetEnabledXStateFeatures (kernelbase.@)
1516 DWORD64 WINAPI
GetEnabledXStateFeatures(void)
1519 return RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 );
1522 /***********************************************************************
1523 * LocateXStateFeature (kernelbase.@)
1525 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1527 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1530 if (feature_id
>= 2)
1531 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1532 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1534 if (feature_id
== 1)
1537 *length
= sizeof(M128A
) * 16;
1539 return &context
->FltSave
.XmmRegisters
;
1543 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1545 return &context
->FltSave
;
1548 /***********************************************************************
1549 * SetXStateFeaturesMask (kernelbase.@)
1551 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1553 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1556 if (feature_mask
& 0x3)
1557 context
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
1559 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1560 return !(feature_mask
& ~(DWORD64
)3);
1562 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1566 /***********************************************************************
1567 * GetXStateFeaturesMask (kernelbase.@)
1569 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1571 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1574 *feature_mask
= (context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
1577 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1578 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1583 #elif defined(__i386__)
1585 /***********************************************************************
1586 * GetEnabledXStateFeatures (kernelbase.@)
1588 DWORD64 WINAPI
GetEnabledXStateFeatures(void)
1591 return RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 );
1594 /***********************************************************************
1595 * LocateXStateFeature (kernelbase.@)
1597 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1599 if (!(context
->ContextFlags
& CONTEXT_i386
))
1602 if (feature_id
>= 2)
1603 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1604 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1606 if (feature_id
== 1)
1609 *length
= sizeof(M128A
) * 8;
1611 return (BYTE
*)&context
->ExtendedRegisters
+ offsetof(XSAVE_FORMAT
, XmmRegisters
);
1615 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1617 return &context
->ExtendedRegisters
;
1620 /***********************************************************************
1621 * SetXStateFeaturesMask (kernelbase.@)
1623 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1625 if (!(context
->ContextFlags
& CONTEXT_i386
))
1628 if (feature_mask
& 0x3)
1629 context
->ContextFlags
|= CONTEXT_EXTENDED_REGISTERS
;
1631 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1632 return !(feature_mask
& ~(DWORD64
)3);
1634 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1638 /***********************************************************************
1639 * GetXStateFeaturesMask (kernelbase.@)
1641 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1643 if (!(context
->ContextFlags
& CONTEXT_i386
))
1646 *feature_mask
= (context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
1649 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1650 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1656 /***********************************************************************
1657 * Firmware functions
1658 ***********************************************************************/
1661 /***********************************************************************
1662 * EnumSystemFirmwareTable (kernelbase.@)
1664 UINT WINAPI
EnumSystemFirmwareTables( DWORD provider
, void *buffer
, DWORD size
)
1666 FIXME( "(0x%08lx, %p, %ld)\n", provider
, buffer
, size
);
1671 /***********************************************************************
1672 * GetSystemFirmwareTable (kernelbase.@)
1674 UINT WINAPI
GetSystemFirmwareTable( DWORD provider
, DWORD id
, void *buffer
, DWORD size
)
1676 SYSTEM_FIRMWARE_TABLE_INFORMATION
*info
;
1677 ULONG buffer_size
= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
) + size
;
1679 TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider
, id
, buffer
, size
);
1681 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, buffer_size
)))
1683 SetLastError( ERROR_OUTOFMEMORY
);
1687 info
->ProviderSignature
= provider
;
1688 info
->Action
= SystemFirmwareTable_Get
;
1691 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation
,
1692 info
, buffer_size
, &buffer_size
));
1693 buffer_size
-= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
1694 if (buffer_size
<= size
) memcpy( buffer
, info
->TableBuffer
, buffer_size
);
1696 HeapFree( GetProcessHeap(), 0, info
);