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 /***********************************************************************
48 * Virtual memory functions
49 ***********************************************************************/
52 /***********************************************************************
53 * DiscardVirtualMemory (kernelbase.@)
55 DWORD WINAPI DECLSPEC_HOTPATCH
DiscardVirtualMemory( void *addr
, SIZE_T size
)
60 status
= NtAllocateVirtualMemory( GetCurrentProcess(), &ret
, 0, &size
, MEM_RESET
, PAGE_NOACCESS
);
61 return RtlNtStatusToDosError( status
);
65 /***********************************************************************
66 * FlushViewOfFile (kernelbase.@)
68 BOOL WINAPI DECLSPEC_HOTPATCH
FlushViewOfFile( const void *base
, SIZE_T size
)
70 NTSTATUS status
= NtFlushVirtualMemory( GetCurrentProcess(), &base
, &size
, 0 );
72 if (status
== STATUS_NOT_MAPPED_DATA
) status
= STATUS_SUCCESS
;
73 return set_ntstatus( status
);
77 /***********************************************************************
78 * GetLargePageMinimum (kernelbase.@)
80 SIZE_T WINAPI
GetLargePageMinimum(void)
82 return 2 * 1024 * 1024;
86 static void fill_system_info( SYSTEM_INFO
*si
, const SYSTEM_BASIC_INFORMATION
*basic_info
,
87 const SYSTEM_CPU_INFORMATION
*cpu_info
)
89 si
->u
.s
.wProcessorArchitecture
= cpu_info
->ProcessorArchitecture
;
90 si
->u
.s
.wReserved
= 0;
91 si
->dwPageSize
= basic_info
->PageSize
;
92 si
->lpMinimumApplicationAddress
= basic_info
->LowestUserAddress
;
93 si
->lpMaximumApplicationAddress
= basic_info
->HighestUserAddress
;
94 si
->dwActiveProcessorMask
= basic_info
->ActiveProcessorsAffinityMask
;
95 si
->dwNumberOfProcessors
= basic_info
->NumberOfProcessors
;
96 si
->dwAllocationGranularity
= basic_info
->AllocationGranularity
;
97 si
->wProcessorLevel
= cpu_info
->ProcessorLevel
;
98 si
->wProcessorRevision
= cpu_info
->ProcessorRevision
;
100 switch (cpu_info
->ProcessorArchitecture
)
102 case PROCESSOR_ARCHITECTURE_INTEL
:
103 switch (cpu_info
->ProcessorLevel
)
105 case 3: si
->dwProcessorType
= PROCESSOR_INTEL_386
; break;
106 case 4: si
->dwProcessorType
= PROCESSOR_INTEL_486
; break;
108 case 6: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
109 default: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
112 case PROCESSOR_ARCHITECTURE_AMD64
:
113 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
115 case PROCESSOR_ARCHITECTURE_ARM
:
116 switch (cpu_info
->ProcessorLevel
)
118 case 4: si
->dwProcessorType
= PROCESSOR_ARM_7TDMI
; break;
119 default: si
->dwProcessorType
= PROCESSOR_ARM920
;
122 case PROCESSOR_ARCHITECTURE_ARM64
:
123 si
->dwProcessorType
= 0;
126 FIXME( "Unknown processor architecture %x\n", cpu_info
->ProcessorArchitecture
);
127 si
->dwProcessorType
= 0;
133 /***********************************************************************
134 * GetNativeSystemInfo (kernelbase.@)
136 void WINAPI DECLSPEC_HOTPATCH
GetNativeSystemInfo( SYSTEM_INFO
*si
)
138 SYSTEM_BASIC_INFORMATION basic_info
;
139 SYSTEM_CPU_INFORMATION cpu_info
;
143 USHORT current_machine
, native_machine
;
145 RtlWow64GetProcessMachines( 0, ¤t_machine
, &native_machine
);
146 if (native_machine
!= IMAGE_FILE_MACHINE_AMD64
)
149 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_AMD64
;
154 if (!set_ntstatus( RtlGetNativeSystemInformation( SystemBasicInformation
,
155 &basic_info
, sizeof(basic_info
), NULL
)) ||
156 !set_ntstatus( RtlGetNativeSystemInformation( SystemCpuInformation
,
157 &cpu_info
, sizeof(cpu_info
), NULL
)))
160 fill_system_info( si
, &basic_info
, &cpu_info
);
164 /***********************************************************************
165 * GetSystemInfo (kernelbase.@)
167 void WINAPI DECLSPEC_HOTPATCH
GetSystemInfo( SYSTEM_INFO
*si
)
169 SYSTEM_BASIC_INFORMATION basic_info
;
170 SYSTEM_CPU_INFORMATION cpu_info
;
172 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
173 &basic_info
, sizeof(basic_info
), NULL
)) ||
174 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation
,
175 &cpu_info
, sizeof(cpu_info
), NULL
)))
178 fill_system_info( si
, &basic_info
, &cpu_info
);
182 /***********************************************************************
183 * GetSystemFileCacheSize (kernelbase.@)
185 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemFileCacheSize( SIZE_T
*mincache
, SIZE_T
*maxcache
, DWORD
*flags
)
187 FIXME( "stub: %p %p %p\n", mincache
, maxcache
, flags
);
188 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
193 /***********************************************************************
194 * GetWriteWatch (kernelbase.@)
196 UINT WINAPI DECLSPEC_HOTPATCH
GetWriteWatch( DWORD flags
, void *base
, SIZE_T size
, void **addresses
,
197 ULONG_PTR
*count
, ULONG
*granularity
)
199 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags
, base
, size
,
200 addresses
, count
, granularity
)))
206 /***********************************************************************
207 * MapViewOfFile (kernelbase.@)
209 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile( HANDLE mapping
, DWORD access
, DWORD offset_high
,
210 DWORD offset_low
, SIZE_T count
)
212 return MapViewOfFileEx( mapping
, access
, offset_high
, offset_low
, count
, NULL
);
216 /***********************************************************************
217 * MapViewOfFileEx (kernelbase.@)
219 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileEx( HANDLE handle
, DWORD access
, DWORD offset_high
,
220 DWORD offset_low
, SIZE_T count
, LPVOID addr
)
223 LARGE_INTEGER offset
;
227 offset
.u
.LowPart
= offset_low
;
228 offset
.u
.HighPart
= offset_high
;
230 exec
= access
& FILE_MAP_EXECUTE
;
231 access
&= ~FILE_MAP_EXECUTE
;
233 if (access
== FILE_MAP_COPY
)
234 protect
= exec
? PAGE_EXECUTE_WRITECOPY
: PAGE_WRITECOPY
;
235 else if (access
& FILE_MAP_WRITE
)
236 protect
= exec
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
237 else if (access
& FILE_MAP_READ
)
238 protect
= exec
? PAGE_EXECUTE_READ
: PAGE_READONLY
;
239 else protect
= PAGE_NOACCESS
;
241 if ((status
= NtMapViewOfSection( handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
242 &count
, ViewShare
, 0, protect
)) < 0)
244 SetLastError( RtlNtStatusToDosError(status
) );
251 /***********************************************************************
252 * MapViewOfFileFromApp (kernelbase.@)
254 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileFromApp( HANDLE handle
, ULONG access
, ULONG64 offset
, SIZE_T size
)
256 return MapViewOfFile( handle
, access
, offset
<< 32, offset
, size
);
259 /***********************************************************************
260 * MapViewOfFile3 (kernelbase.@)
262 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile3( HANDLE handle
, HANDLE process
, PVOID baseaddr
, ULONG64 offset
,
263 SIZE_T size
, ULONG alloc_type
, ULONG protection
, MEM_EXTENDED_PARAMETER
*params
, ULONG params_count
)
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 return set_ntstatus( NtFreeVirtualMemory( process
, &addr
, &size
, type
));
464 /***********************************************************************
465 * VirtualLock (kernelbase.@)
467 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualLock( void *addr
, SIZE_T size
)
469 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
473 /***********************************************************************
474 * VirtualProtect (kernelbase.@)
476 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtect( void *addr
, SIZE_T size
, DWORD new_prot
, DWORD
*old_prot
)
478 return VirtualProtectEx( GetCurrentProcess(), addr
, size
, new_prot
, old_prot
);
482 /***********************************************************************
483 * VirtualProtectEx (kernelbase.@)
485 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtectEx( HANDLE process
, void *addr
, SIZE_T size
,
486 DWORD new_prot
, DWORD
*old_prot
)
490 /* Win9x allows passing NULL as old_prot while this fails on NT */
491 if (!old_prot
&& (GetVersion() & 0x80000000)) old_prot
= &prot
;
492 return set_ntstatus( NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
));
496 /***********************************************************************
497 * VirtualQuery (kernelbase.@)
499 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQuery( LPCVOID addr
, PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
501 return VirtualQueryEx( GetCurrentProcess(), addr
, info
, len
);
505 /***********************************************************************
506 * VirtualQueryEx (kernelbase.@)
508 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQueryEx( HANDLE process
, LPCVOID addr
,
509 PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
513 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryBasicInformation
, info
, len
, &ret
)))
519 /***********************************************************************
520 * VirtualUnlock (kernelbase.@)
522 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualUnlock( void *addr
, SIZE_T size
)
524 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
528 /***********************************************************************
529 * WriteProcessMemory (kernelbase.@)
531 BOOL WINAPI DECLSPEC_HOTPATCH
WriteProcessMemory( HANDLE process
, void *addr
, const void *buffer
,
532 SIZE_T size
, SIZE_T
*bytes_written
)
534 return set_ntstatus( NtWriteVirtualMemory( process
, addr
, buffer
, size
, bytes_written
));
538 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
539 BOOL WINAPI
IsBadStringPtrA( LPCSTR str
, UINT_PTR max
)
541 if (!str
) return TRUE
;
544 volatile const char *p
= str
;
545 while (p
!= str
+ max
) if (!*p
++) break;
556 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
557 BOOL WINAPI
IsBadStringPtrW( LPCWSTR str
, UINT_PTR max
)
559 if (!str
) return TRUE
;
562 volatile const WCHAR
*p
= str
;
563 while (p
!= str
+ max
) if (!*p
++) break;
574 /***********************************************************************
576 ***********************************************************************/
579 /***********************************************************************
580 * HeapCompact (kernelbase.@)
582 SIZE_T WINAPI DECLSPEC_HOTPATCH
HeapCompact( HANDLE heap
, DWORD flags
)
584 return RtlCompactHeap( heap
, flags
);
588 /***********************************************************************
589 * HeapCreate (kernelbase.@)
591 HANDLE WINAPI DECLSPEC_HOTPATCH
HeapCreate( DWORD flags
, SIZE_T init_size
, SIZE_T max_size
)
593 HANDLE ret
= RtlCreateHeap( flags
, NULL
, max_size
, init_size
, NULL
, NULL
);
594 if (!ret
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
599 /***********************************************************************
600 * HeapDestroy (kernelbase.@)
602 BOOL WINAPI DECLSPEC_HOTPATCH
HeapDestroy( HANDLE heap
)
604 if (!RtlDestroyHeap( heap
)) return TRUE
;
605 SetLastError( ERROR_INVALID_HANDLE
);
610 /***********************************************************************
611 * HeapLock (kernelbase.@)
613 BOOL WINAPI DECLSPEC_HOTPATCH
HeapLock( HANDLE heap
)
615 return RtlLockHeap( heap
);
619 /***********************************************************************
620 * HeapQueryInformation (kernelbase.@)
622 BOOL WINAPI
HeapQueryInformation( HANDLE heap
, HEAP_INFORMATION_CLASS info_class
,
623 PVOID info
, SIZE_T size
, PSIZE_T size_out
)
625 return set_ntstatus( RtlQueryHeapInformation( heap
, info_class
, info
, size
, size_out
));
629 /***********************************************************************
630 * HeapSetInformation (kernelbase.@)
632 BOOL WINAPI
HeapSetInformation( HANDLE heap
, HEAP_INFORMATION_CLASS infoclass
, PVOID info
, SIZE_T size
)
634 return set_ntstatus( RtlSetHeapInformation( heap
, infoclass
, info
, size
));
638 /***********************************************************************
639 * HeapUnlock (kernelbase.@)
641 BOOL WINAPI
HeapUnlock( HANDLE heap
)
643 return RtlUnlockHeap( heap
);
647 /***********************************************************************
648 * HeapValidate (kernelbase.@)
650 BOOL WINAPI DECLSPEC_HOTPATCH
HeapValidate( HANDLE heap
, DWORD flags
, LPCVOID ptr
)
652 return RtlValidateHeap( heap
, flags
, ptr
);
656 /* undocumented RtlWalkHeap structure */
658 struct rtl_heap_entry
661 SIZE_T cbData
; /* differs from PROCESS_HEAP_ENTRY */
664 WORD wFlags
; /* value differs from PROCESS_HEAP_ENTRY */
671 DWORD dwCommittedSize
;
672 DWORD dwUnCommittedSize
;
679 /* rtl_heap_entry flags, names made up */
681 #define RTL_HEAP_ENTRY_BUSY 0x0001
682 #define RTL_HEAP_ENTRY_REGION 0x0002
683 #define RTL_HEAP_ENTRY_BLOCK 0x0010
684 #define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000
685 #define RTL_HEAP_ENTRY_COMMITTED 0x4000
686 #define RTL_HEAP_ENTRY_LFH 0x8000
689 /***********************************************************************
690 * HeapWalk (kernelbase.@)
692 BOOL WINAPI DECLSPEC_HOTPATCH
HeapWalk( HANDLE heap
, PROCESS_HEAP_ENTRY
*entry
)
694 struct rtl_heap_entry rtl_entry
= {0};
697 if (!entry
) return set_ntstatus( STATUS_INVALID_PARAMETER
);
699 rtl_entry
.lpData
= entry
->lpData
;
700 rtl_entry
.cbData
= entry
->cbData
;
701 rtl_entry
.cbOverhead
= entry
->cbOverhead
;
702 rtl_entry
.iRegionIndex
= entry
->iRegionIndex
;
704 if (entry
->wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
705 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_BUSY
;
706 if (entry
->wFlags
& PROCESS_HEAP_REGION
)
707 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_REGION
;
708 if (entry
->wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
709 rtl_entry
.wFlags
|= RTL_HEAP_ENTRY_UNCOMMITTED
;
710 memcpy( &rtl_entry
.Region
, &entry
->u
.Region
, sizeof(entry
->u
.Region
) );
712 if (!(status
= RtlWalkHeap( heap
, &rtl_entry
)))
714 entry
->lpData
= rtl_entry
.lpData
;
715 entry
->cbData
= rtl_entry
.cbData
;
716 entry
->cbOverhead
= rtl_entry
.cbOverhead
;
717 entry
->iRegionIndex
= rtl_entry
.iRegionIndex
;
719 if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_BUSY
)
720 entry
->wFlags
= PROCESS_HEAP_ENTRY_BUSY
;
721 else if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_REGION
)
722 entry
->wFlags
= PROCESS_HEAP_REGION
;
723 else if (rtl_entry
.wFlags
& RTL_HEAP_ENTRY_UNCOMMITTED
)
724 entry
->wFlags
= PROCESS_HEAP_UNCOMMITTED_RANGE
;
728 memcpy( &entry
->u
.Region
, &rtl_entry
.Region
, sizeof(entry
->u
.Region
) );
731 return set_ntstatus( status
);
735 /***********************************************************************
736 * Global/local heap functions
737 ***********************************************************************/
739 /* some undocumented flags (names are made up) */
740 #define HEAP_ADD_USER_INFO 0x00000100
742 /* not compatible with windows */
743 struct kernelbase_global_data
745 struct mem_entry
*mem_entries
;
746 struct mem_entry
*mem_entries_end
;
749 #define MEM_FLAG_USED 1
750 #define MEM_FLAG_MOVEABLE 2
751 #define MEM_FLAG_DISCARDABLE 4
752 #define MEM_FLAG_DISCARDED 8
753 #define MEM_FLAG_DDESHARE 0x8000
769 C_ASSERT(sizeof(struct mem_entry
) == 2 * sizeof(void *));
771 #define MAX_MEM_HANDLES 0x10000
772 static struct mem_entry
*next_free_mem
;
773 static struct kernelbase_global_data global_data
= {0};
775 static inline struct mem_entry
*unsafe_mem_from_HLOCAL( HLOCAL handle
)
777 struct mem_entry
*mem
= CONTAINING_RECORD( *(volatile HANDLE
*)&handle
, struct mem_entry
, ptr
);
778 struct kernelbase_global_data
*data
= &global_data
;
779 if (((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL
;
780 if (mem
< data
->mem_entries
|| mem
>= data
->mem_entries_end
) return NULL
;
781 if (!(mem
->flags
& MEM_FLAG_USED
)) return NULL
;
785 static inline HLOCAL
HLOCAL_from_mem( struct mem_entry
*mem
)
791 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle
)
793 if (((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1))) return NULL
;
797 void init_global_data(void)
799 global_data
.mem_entries
= VirtualAlloc( NULL
, MAX_MEM_HANDLES
* sizeof(struct mem_entry
), MEM_COMMIT
, PAGE_READWRITE
);
800 if (!(next_free_mem
= global_data
.mem_entries
)) ERR( "Failed to allocate kernelbase global handle table\n" );
801 global_data
.mem_entries_end
= global_data
.mem_entries
+ MAX_MEM_HANDLES
;
804 /***********************************************************************
805 * KernelBaseGetGlobalData (kernelbase.@)
807 void *WINAPI
KernelBaseGetGlobalData(void)
809 WARN_(globalmem
)( "semi-stub!\n" );
814 /***********************************************************************
815 * GlobalAlloc (kernelbase.@)
817 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalAlloc( UINT flags
, SIZE_T size
)
819 struct mem_entry
*mem
;
822 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
823 if (!(flags
& GMEM_MOVEABLE
) && !size
) size
= 1;
825 handle
= LocalAlloc( flags
, size
);
827 if ((mem
= unsafe_mem_from_HLOCAL( handle
)) && (flags
& GMEM_DDESHARE
))
828 mem
->flags
|= MEM_FLAG_DDESHARE
;
834 /***********************************************************************
835 * GlobalFree (kernelbase.@)
837 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalFree( HLOCAL handle
)
839 return LocalFree( handle
);
843 /***********************************************************************
844 * LocalAlloc (kernelbase.@)
846 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalAlloc( UINT flags
, SIZE_T size
)
848 DWORD heap_flags
= 0x200 | HEAP_ADD_USER_INFO
;
849 HANDLE heap
= GetProcessHeap();
850 struct mem_entry
*mem
;
854 TRACE_(globalmem
)( "flags %#x, size %#Ix\n", flags
, size
);
856 if (flags
& LMEM_ZEROINIT
) heap_flags
|= HEAP_ZERO_MEMORY
;
858 if (!(flags
& LMEM_MOVEABLE
)) /* pointer */
860 ptr
= HeapAlloc( heap
, heap_flags
, size
);
861 if (ptr
) RtlSetUserValueHeap( heap
, heap_flags
, ptr
, ptr
);
862 TRACE_(globalmem
)( "return %p\n", ptr
);
867 if ((mem
= next_free_mem
) < global_data
.mem_entries
|| mem
>= global_data
.mem_entries_end
)
871 if (!mem
->next_free
) next_free_mem
++;
872 else next_free_mem
= mem
->next_free
;
873 mem
->next_free
= NULL
;
875 RtlUnlockHeap( heap
);
877 if (!mem
) goto failed
;
878 handle
= HLOCAL_from_mem( mem
);
880 mem
->flags
= MEM_FLAG_USED
| MEM_FLAG_MOVEABLE
;
881 if (flags
& LMEM_DISCARDABLE
) mem
->flags
|= MEM_FLAG_DISCARDABLE
;
885 if (!size
) mem
->flags
|= MEM_FLAG_DISCARDED
;
888 if (!(ptr
= HeapAlloc( heap
, heap_flags
, size
))) goto failed
;
889 RtlSetUserValueHeap( heap
, heap_flags
, ptr
, handle
);
893 TRACE_(globalmem
)( "return handle %p, ptr %p\n", handle
, mem
->ptr
);
897 if (mem
) LocalFree( *(volatile HANDLE
*)&handle
);
898 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
903 /***********************************************************************
904 * LocalFree (kernelbase.@)
906 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalFree( HLOCAL handle
)
908 HANDLE heap
= GetProcessHeap();
909 struct mem_entry
*mem
;
913 TRACE_(globalmem
)( "handle %p\n", handle
);
916 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)) &&
917 HeapValidate( heap
, HEAP_NO_SERIALIZE
, ptr
))
919 if (HeapFree( heap
, HEAP_NO_SERIALIZE
, ptr
)) ret
= 0;
921 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
923 if (HeapFree( heap
, HEAP_NO_SERIALIZE
, mem
->ptr
)) ret
= 0;
925 mem
->next_free
= next_free_mem
;
928 RtlUnlockHeap( heap
);
932 WARN_(globalmem
)( "invalid handle %p\n", handle
);
933 SetLastError( ERROR_INVALID_HANDLE
);
939 /***********************************************************************
940 * LocalLock (kernelbase.@)
942 LPVOID WINAPI DECLSPEC_HOTPATCH
LocalLock( HLOCAL handle
)
944 HANDLE heap
= GetProcessHeap();
945 struct mem_entry
*mem
;
948 TRACE_(globalmem
)( "handle %p\n", handle
);
950 if (!handle
) return NULL
;
951 if ((ret
= unsafe_ptr_from_HLOCAL( handle
)))
955 volatile char *p
= ret
;
967 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
969 if (!(ret
= mem
->ptr
)) SetLastError( ERROR_DISCARDED
);
970 else if (!++mem
->lock
) mem
->lock
--;
974 WARN_(globalmem
)( "invalid handle %p\n", handle
);
975 SetLastError( ERROR_INVALID_HANDLE
);
977 RtlUnlockHeap( heap
);
983 /***********************************************************************
984 * LocalReAlloc (kernelbase.@)
986 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalReAlloc( HLOCAL handle
, SIZE_T size
, UINT flags
)
988 DWORD heap_flags
= 0x200 | HEAP_ADD_USER_INFO
| HEAP_NO_SERIALIZE
;
989 HANDLE heap
= GetProcessHeap();
990 struct mem_entry
*mem
;
994 TRACE_(globalmem
)( "handle %p, size %#Ix, flags %#x\n", handle
, size
, flags
);
996 if (flags
& LMEM_ZEROINIT
) heap_flags
|= HEAP_ZERO_MEMORY
;
999 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)) &&
1000 HeapValidate( heap
, HEAP_NO_SERIALIZE
, ptr
))
1002 if (flags
& LMEM_MODIFY
) ret
= handle
;
1003 else if (flags
& LMEM_DISCARDABLE
) SetLastError( ERROR_INVALID_PARAMETER
);
1006 if (!(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
1007 ret
= HeapReAlloc( heap
, heap_flags
, ptr
, size
);
1008 if (ret
) RtlSetUserValueHeap( heap
, heap_flags
, ret
, ret
);
1009 else SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1012 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
1014 if (flags
& LMEM_MODIFY
)
1016 if (flags
& LMEM_DISCARDABLE
) mem
->flags
|= MEM_FLAG_DISCARDABLE
;
1019 else if (flags
& LMEM_DISCARDABLE
) SetLastError( ERROR_INVALID_PARAMETER
);
1024 if (mem
->lock
&& !(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
1025 if (!mem
->ptr
) ptr
= HeapAlloc( heap
, heap_flags
, size
);
1026 else ptr
= HeapReAlloc( heap
, heap_flags
, mem
->ptr
, size
);
1028 if (!ptr
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1031 RtlSetUserValueHeap( heap
, heap_flags
, ptr
, handle
);
1032 mem
->flags
&= ~MEM_FLAG_DISCARDED
;
1037 else if ((flags
& LMEM_MOVEABLE
) && !mem
->lock
)
1039 HeapFree( heap
, heap_flags
, mem
->ptr
);
1040 mem
->flags
|= MEM_FLAG_DISCARDED
;
1044 else SetLastError( ERROR_INVALID_PARAMETER
);
1047 else SetLastError( ERROR_INVALID_HANDLE
);
1048 RtlUnlockHeap( heap
);
1054 /***********************************************************************
1055 * LocalUnlock (kernelbase.@)
1057 BOOL WINAPI DECLSPEC_HOTPATCH
LocalUnlock( HLOCAL handle
)
1059 HANDLE heap
= GetProcessHeap();
1060 struct mem_entry
*mem
;
1063 TRACE_(globalmem
)( "handle %p\n", handle
);
1065 if (unsafe_ptr_from_HLOCAL( handle
))
1067 SetLastError( ERROR_NOT_LOCKED
);
1071 RtlLockHeap( heap
);
1072 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
1076 ret
= (--mem
->lock
!= 0);
1077 if (!ret
) SetLastError( NO_ERROR
);
1081 WARN_(globalmem
)( "handle %p not locked\n", handle
);
1082 SetLastError( ERROR_NOT_LOCKED
);
1087 WARN_(globalmem
)( "invalid handle %p\n", handle
);
1088 SetLastError( ERROR_INVALID_HANDLE
);
1090 RtlUnlockHeap( heap
);
1096 /***********************************************************************
1097 * Memory resource functions
1098 ***********************************************************************/
1101 /***********************************************************************
1102 * CreateMemoryResourceNotification (kernelbase.@)
1104 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type
)
1107 UNICODE_STRING nameW
;
1108 OBJECT_ATTRIBUTES attr
;
1112 case LowMemoryResourceNotification
:
1113 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\LowMemoryCondition" );
1115 case HighMemoryResourceNotification
:
1116 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\HighMemoryCondition" );
1119 SetLastError( ERROR_INVALID_PARAMETER
);
1123 InitializeObjectAttributes( &attr
, &nameW
, 0, 0, NULL
);
1124 if (!set_ntstatus( NtOpenEvent( &ret
, EVENT_ALL_ACCESS
, &attr
))) return 0;
1128 /***********************************************************************
1129 * QueryMemoryResourceNotification (kernelbase.@)
1131 BOOL WINAPI DECLSPEC_HOTPATCH
QueryMemoryResourceNotification( HANDLE handle
, BOOL
*state
)
1133 switch (WaitForSingleObject( handle
, 0 ))
1142 SetLastError( ERROR_INVALID_PARAMETER
);
1147 /***********************************************************************
1148 * Physical memory functions
1149 ***********************************************************************/
1152 /***********************************************************************
1153 * AllocateUserPhysicalPages (kernelbase.@)
1155 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1156 ULONG_PTR
*userarray
)
1158 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1159 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1164 /***********************************************************************
1165 * FreeUserPhysicalPages (kernelbase.@)
1167 BOOL WINAPI DECLSPEC_HOTPATCH
FreeUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1168 ULONG_PTR
*userarray
)
1170 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1172 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1177 /***********************************************************************
1178 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1180 BOOL WINAPI DECLSPEC_HOTPATCH
GetPhysicallyInstalledSystemMemory( ULONGLONG
*memory
)
1182 MEMORYSTATUSEX status
;
1186 SetLastError( ERROR_INVALID_PARAMETER
);
1189 status
.dwLength
= sizeof(status
);
1190 GlobalMemoryStatusEx( &status
);
1191 *memory
= status
.ullTotalPhys
/ 1024;
1196 /***********************************************************************
1197 * GlobalMemoryStatusEx (kernelbase.@)
1199 BOOL WINAPI DECLSPEC_HOTPATCH
GlobalMemoryStatusEx( MEMORYSTATUSEX
*status
)
1201 static MEMORYSTATUSEX cached_status
;
1202 static DWORD last_check
;
1203 SYSTEM_BASIC_INFORMATION basic_info
;
1204 SYSTEM_PERFORMANCE_INFORMATION perf_info
;
1207 if (status
->dwLength
!= sizeof(*status
))
1209 SetLastError( ERROR_INVALID_PARAMETER
);
1212 if ((NtGetTickCount() - last_check
) < 1000)
1214 *status
= cached_status
;
1217 last_check
= NtGetTickCount();
1219 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
1220 &basic_info
, sizeof(basic_info
), NULL
)) ||
1221 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation
,
1222 &perf_info
, sizeof(perf_info
), NULL
)) ||
1223 !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
,
1224 &vmc
, sizeof(vmc
), NULL
)))
1227 status
->dwMemoryLoad
= 0;
1228 status
->ullTotalPhys
= basic_info
.MmNumberOfPhysicalPages
;
1229 status
->ullAvailPhys
= perf_info
.AvailablePages
;
1230 status
->ullTotalPageFile
= perf_info
.TotalCommitLimit
;
1231 status
->ullAvailPageFile
= status
->ullTotalPageFile
- perf_info
.TotalCommittedPages
;
1232 status
->ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
+ 1;
1233 status
->ullAvailVirtual
= status
->ullTotalVirtual
- (ULONGLONG
)vmc
.WorkingSetSize
/* approximate */;
1234 status
->ullAvailExtendedVirtual
= 0;
1236 status
->ullTotalPhys
*= basic_info
.PageSize
;
1237 status
->ullAvailPhys
*= basic_info
.PageSize
;
1238 status
->ullTotalPageFile
*= basic_info
.PageSize
;
1239 status
->ullAvailPageFile
*= basic_info
.PageSize
;
1241 if (status
->ullTotalPhys
)
1242 status
->dwMemoryLoad
= (status
->ullTotalPhys
- status
->ullAvailPhys
) / (status
->ullTotalPhys
/ 100);
1244 TRACE_(virtual)( "MemoryLoad %ld, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1245 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1246 status
->dwMemoryLoad
, wine_dbgstr_longlong(status
->ullTotalPhys
),
1247 wine_dbgstr_longlong(status
->ullAvailPhys
), wine_dbgstr_longlong(status
->ullTotalPageFile
),
1248 wine_dbgstr_longlong(status
->ullAvailPageFile
), wine_dbgstr_longlong(status
->ullTotalVirtual
),
1249 wine_dbgstr_longlong(status
->ullAvailVirtual
) );
1251 cached_status
= *status
;
1256 /***********************************************************************
1257 * MapUserPhysicalPages (kernelbase.@)
1259 BOOL WINAPI DECLSPEC_HOTPATCH
MapUserPhysicalPages( void *addr
, ULONG_PTR page_count
, ULONG_PTR
*pages
)
1261 FIXME( "stub: %p %Iu %p\n", addr
, page_count
, pages
);
1263 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1268 /***********************************************************************
1270 ***********************************************************************/
1273 /***********************************************************************
1274 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1276 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPagesNuma( HANDLE process
, ULONG_PTR
*pages
,
1277 ULONG_PTR
*userarray
, DWORD node
)
1279 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1280 return AllocateUserPhysicalPages( process
, pages
, userarray
);
1284 /***********************************************************************
1285 * CreateFileMappingNumaW (kernelbase.@)
1287 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileMappingNumaW( HANDLE file
, LPSECURITY_ATTRIBUTES sa
,
1288 DWORD protect
, DWORD size_high
, DWORD size_low
,
1289 LPCWSTR name
, DWORD node
)
1291 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1292 return CreateFileMappingW( file
, sa
, protect
, size_high
, size_low
, name
);
1296 /***********************************************************************
1297 * GetLogicalProcessorInformation (kernelbase.@)
1299 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buffer
,
1306 SetLastError( ERROR_INVALID_PARAMETER
);
1309 status
= NtQuerySystemInformation( SystemLogicalProcessorInformation
, buffer
, *len
, len
);
1310 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1311 return set_ntstatus( status
);
1315 /***********************************************************************
1316 * GetLogicalProcessorInformationEx (kernelbase.@)
1318 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship
,
1319 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buffer
, DWORD
*len
)
1325 SetLastError( ERROR_INVALID_PARAMETER
);
1328 status
= NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx
, &relationship
,
1329 sizeof(relationship
), buffer
, *len
, len
);
1330 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1331 return set_ntstatus( status
);
1335 /***********************************************************************
1336 * GetSystemCpuSetInformation (kernelbase.@)
1338 BOOL WINAPI
GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION
*info
, ULONG buffer_length
, ULONG
*return_length
,
1339 HANDLE process
, ULONG flags
)
1342 FIXME("Unsupported flags %#lx.\n", flags
);
1346 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation
, &process
, sizeof(process
), info
,
1347 buffer_length
, return_length
));
1351 /***********************************************************************
1352 * SetThreadSelectedCpuSets (kernelbase.@)
1354 BOOL WINAPI
SetThreadSelectedCpuSets(HANDLE thread
, const ULONG
*cpu_set_ids
, ULONG count
)
1356 FIXME( "thread %p, cpu_set_ids %p, count %lu stub.\n", thread
, cpu_set_ids
, count
);
1362 /***********************************************************************
1363 * SetProcessDefaultCpuSets (kernelbase.@)
1365 BOOL WINAPI
SetProcessDefaultCpuSets(HANDLE process
, const ULONG
*cpu_set_ids
, ULONG count
)
1367 FIXME( "process %p, cpu_set_ids %p, count %lu stub.\n", process
, cpu_set_ids
, count
);
1373 /**********************************************************************
1374 * GetNumaHighestNodeNumber (kernelbase.@)
1376 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaHighestNodeNumber( ULONG
*node
)
1378 FIXME( "semi-stub: %p\n", node
);
1384 /**********************************************************************
1385 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1387 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaNodeProcessorMaskEx( USHORT node
, GROUP_AFFINITY
*mask
)
1389 FIXME( "stub: %hu %p\n", node
, mask
);
1390 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1395 /***********************************************************************
1396 * GetNumaProximityNodeEx (kernelbase.@)
1398 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaProximityNodeEx( ULONG proximity_id
, USHORT
*node
)
1400 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1405 /***********************************************************************
1406 * MapViewOfFileExNuma (kernelbase.@)
1408 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileExNuma( HANDLE handle
, DWORD access
, DWORD offset_high
,
1409 DWORD offset_low
, SIZE_T count
, LPVOID addr
,
1412 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1413 return MapViewOfFileEx( handle
, access
, offset_high
, offset_low
, count
, addr
);
1417 /***********************************************************************
1418 * VirtualAllocExNuma (kernelbase.@)
1420 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocExNuma( HANDLE process
, void *addr
, SIZE_T size
,
1421 DWORD type
, DWORD protect
, DWORD node
)
1423 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1424 return VirtualAllocEx( process
, addr
, size
, type
, protect
);
1428 /***********************************************************************
1429 * QueryVirtualMemoryInformation (kernelbase.@)
1431 BOOL WINAPI DECLSPEC_HOTPATCH
QueryVirtualMemoryInformation( HANDLE process
, const void *addr
,
1432 WIN32_MEMORY_INFORMATION_CLASS info_class
, void *info
, SIZE_T size
, SIZE_T
*ret_size
)
1436 case MemoryRegionInfo
:
1437 return set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryRegionInformation
, info
, size
, ret_size
));
1439 FIXME("Unsupported info class %u.\n", info_class
);
1445 /***********************************************************************
1447 ***********************************************************************/
1450 #if defined(__i386__) || defined(__x86_64__)
1451 /***********************************************************************
1452 * GetEnabledXStateFeatures (kernelbase.@)
1454 DWORD64 WINAPI
GetEnabledXStateFeatures(void)
1457 return RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 );
1461 /***********************************************************************
1462 * InitializeContext2 (kernelbase.@)
1464 BOOL WINAPI
InitializeContext2( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
,
1465 ULONG64 compaction_mask
)
1470 TRACE( "buffer %p, context_flags %#lx, context %p, ret_length %p, compaction_mask %s.\n",
1471 buffer
, context_flags
, context
, length
, wine_dbgstr_longlong(compaction_mask
) );
1473 orig_length
= *length
;
1475 if ((status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
)))
1477 if (status
== STATUS_NOT_SUPPORTED
&& context_flags
& 0x40)
1479 context_flags
&= ~0x40;
1480 status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
);
1484 return set_ntstatus( status
);
1487 if (!buffer
|| orig_length
< *length
)
1489 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1493 if ((status
= RtlInitializeExtendedContext2( buffer
, context_flags
, (CONTEXT_EX
**)context
, compaction_mask
)))
1494 return set_ntstatus( status
);
1496 *context
= (CONTEXT
*)((BYTE
*)*context
+ (*(CONTEXT_EX
**)context
)->Legacy
.Offset
);
1501 /***********************************************************************
1502 * InitializeContext (kernelbase.@)
1504 BOOL WINAPI
InitializeContext( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
)
1506 return InitializeContext2( buffer
, context_flags
, context
, length
, ~(ULONG64
)0 );
1509 /***********************************************************************
1510 * CopyContext (kernelbase.@)
1512 BOOL WINAPI
CopyContext( CONTEXT
*dst
, DWORD context_flags
, CONTEXT
*src
)
1514 return set_ntstatus( RtlCopyContext( dst
, context_flags
, src
));
1519 #if defined(__x86_64__)
1520 /***********************************************************************
1521 * LocateXStateFeature (kernelbase.@)
1523 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1525 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1528 if (feature_id
>= 2)
1529 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1530 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1532 if (feature_id
== 1)
1535 *length
= sizeof(M128A
) * 16;
1537 return &context
->u
.FltSave
.XmmRegisters
;
1541 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1543 return &context
->u
.FltSave
;
1546 /***********************************************************************
1547 * SetXStateFeaturesMask (kernelbase.@)
1549 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1551 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1554 if (feature_mask
& 0x3)
1555 context
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
1557 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1558 return !(feature_mask
& ~(DWORD64
)3);
1560 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1564 /***********************************************************************
1565 * GetXStateFeaturesMask (kernelbase.@)
1567 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1569 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1572 *feature_mask
= (context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
1575 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1576 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1580 #elif defined(__i386__)
1581 /***********************************************************************
1582 * LocateXStateFeature (kernelbase.@)
1584 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1586 if (!(context
->ContextFlags
& CONTEXT_i386
))
1589 if (feature_id
>= 2)
1590 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1591 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1593 if (feature_id
== 1)
1596 *length
= sizeof(M128A
) * 8;
1598 return (BYTE
*)&context
->ExtendedRegisters
+ offsetof(XSAVE_FORMAT
, XmmRegisters
);
1602 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1604 return &context
->ExtendedRegisters
;
1607 /***********************************************************************
1608 * SetXStateFeaturesMask (kernelbase.@)
1610 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1612 if (!(context
->ContextFlags
& CONTEXT_i386
))
1615 if (feature_mask
& 0x3)
1616 context
->ContextFlags
|= CONTEXT_EXTENDED_REGISTERS
;
1618 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1619 return !(feature_mask
& ~(DWORD64
)3);
1621 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1625 /***********************************************************************
1626 * GetXStateFeaturesMask (kernelbase.@)
1628 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1630 if (!(context
->ContextFlags
& CONTEXT_i386
))
1633 *feature_mask
= (context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
1636 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1637 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1643 /***********************************************************************
1644 * Firmware functions
1645 ***********************************************************************/
1648 /***********************************************************************
1649 * EnumSystemFirmwareTable (kernelbase.@)
1651 UINT WINAPI
EnumSystemFirmwareTables( DWORD provider
, void *buffer
, DWORD size
)
1653 FIXME( "(0x%08lx, %p, %ld)\n", provider
, buffer
, size
);
1658 /***********************************************************************
1659 * GetSystemFirmwareTable (kernelbase.@)
1661 UINT WINAPI
GetSystemFirmwareTable( DWORD provider
, DWORD id
, void *buffer
, DWORD size
)
1663 SYSTEM_FIRMWARE_TABLE_INFORMATION
*info
;
1664 ULONG buffer_size
= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
) + size
;
1666 TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider
, id
, buffer
, size
);
1668 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, buffer_size
)))
1670 SetLastError( ERROR_OUTOFMEMORY
);
1674 info
->ProviderSignature
= provider
;
1675 info
->Action
= SystemFirmwareTable_Get
;
1678 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation
,
1679 info
, buffer_size
, &buffer_size
));
1680 buffer_size
-= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
1681 if (buffer_size
<= size
) memcpy( buffer
, info
->TableBuffer
, buffer_size
);
1683 HeapFree( GetProcessHeap(), 0, info
);