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 * FlushViewOfFile (kernelbase.@)
55 BOOL WINAPI DECLSPEC_HOTPATCH
FlushViewOfFile( const void *base
, SIZE_T size
)
57 NTSTATUS status
= NtFlushVirtualMemory( GetCurrentProcess(), &base
, &size
, 0 );
59 if (status
== STATUS_NOT_MAPPED_DATA
) status
= STATUS_SUCCESS
;
60 return set_ntstatus( status
);
64 /***********************************************************************
65 * GetLargePageMinimum (kernelbase.@)
67 SIZE_T WINAPI
GetLargePageMinimum(void)
69 return 2 * 1024 * 1024;
73 /***********************************************************************
74 * GetNativeSystemInfo (kernelbase.@)
76 void WINAPI DECLSPEC_HOTPATCH
GetNativeSystemInfo( SYSTEM_INFO
*si
)
78 USHORT current_machine
, native_machine
;
81 RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine
, &native_machine
);
82 if (!current_machine
) return;
83 switch (native_machine
)
85 case IMAGE_FILE_MACHINE_AMD64
:
86 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_AMD64
;
87 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
89 case IMAGE_FILE_MACHINE_ARM64
:
90 si
->u
.s
.wProcessorArchitecture
= PROCESSOR_ARCHITECTURE_ARM64
;
91 si
->dwProcessorType
= 0;
94 FIXME( "Add the proper information for %x in wow64 mode\n", native_machine
);
99 /***********************************************************************
100 * GetSystemInfo (kernelbase.@)
102 void WINAPI DECLSPEC_HOTPATCH
GetSystemInfo( SYSTEM_INFO
*si
)
104 SYSTEM_BASIC_INFORMATION basic_info
;
105 SYSTEM_CPU_INFORMATION cpu_info
;
107 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
108 &basic_info
, sizeof(basic_info
), NULL
)) ||
109 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation
,
110 &cpu_info
, sizeof(cpu_info
), NULL
)))
113 si
->u
.s
.wProcessorArchitecture
= cpu_info
.ProcessorArchitecture
;
114 si
->u
.s
.wReserved
= 0;
115 si
->dwPageSize
= basic_info
.PageSize
;
116 si
->lpMinimumApplicationAddress
= basic_info
.LowestUserAddress
;
117 si
->lpMaximumApplicationAddress
= basic_info
.HighestUserAddress
;
118 si
->dwActiveProcessorMask
= basic_info
.ActiveProcessorsAffinityMask
;
119 si
->dwNumberOfProcessors
= basic_info
.NumberOfProcessors
;
120 si
->dwAllocationGranularity
= basic_info
.AllocationGranularity
;
121 si
->wProcessorLevel
= cpu_info
.ProcessorLevel
;
122 si
->wProcessorRevision
= cpu_info
.ProcessorRevision
;
124 switch (cpu_info
.ProcessorArchitecture
)
126 case PROCESSOR_ARCHITECTURE_INTEL
:
127 switch (cpu_info
.ProcessorLevel
)
129 case 3: si
->dwProcessorType
= PROCESSOR_INTEL_386
; break;
130 case 4: si
->dwProcessorType
= PROCESSOR_INTEL_486
; break;
132 case 6: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
133 default: si
->dwProcessorType
= PROCESSOR_INTEL_PENTIUM
; break;
136 case PROCESSOR_ARCHITECTURE_PPC
:
137 switch (cpu_info
.ProcessorLevel
)
139 case 1: si
->dwProcessorType
= PROCESSOR_PPC_601
; break;
141 case 6: si
->dwProcessorType
= PROCESSOR_PPC_603
; break;
142 case 4: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
143 case 9: si
->dwProcessorType
= PROCESSOR_PPC_604
; break;
144 case 20: si
->dwProcessorType
= PROCESSOR_PPC_620
; break;
145 default: si
->dwProcessorType
= 0;
148 case PROCESSOR_ARCHITECTURE_AMD64
:
149 si
->dwProcessorType
= PROCESSOR_AMD_X8664
;
151 case PROCESSOR_ARCHITECTURE_ARM
:
152 switch (cpu_info
.ProcessorLevel
)
154 case 4: si
->dwProcessorType
= PROCESSOR_ARM_7TDMI
; break;
155 default: si
->dwProcessorType
= PROCESSOR_ARM920
;
158 case PROCESSOR_ARCHITECTURE_ARM64
:
159 si
->dwProcessorType
= 0;
162 FIXME( "Unknown processor architecture %x\n", cpu_info
.ProcessorArchitecture
);
163 si
->dwProcessorType
= 0;
169 /***********************************************************************
170 * GetSystemFileCacheSize (kernelbase.@)
172 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemFileCacheSize( SIZE_T
*mincache
, SIZE_T
*maxcache
, DWORD
*flags
)
174 FIXME( "stub: %p %p %p\n", mincache
, maxcache
, flags
);
175 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
180 /***********************************************************************
181 * GetWriteWatch (kernelbase.@)
183 UINT WINAPI DECLSPEC_HOTPATCH
GetWriteWatch( DWORD flags
, void *base
, SIZE_T size
, void **addresses
,
184 ULONG_PTR
*count
, ULONG
*granularity
)
186 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags
, base
, size
,
187 addresses
, count
, granularity
)))
193 /***********************************************************************
194 * MapViewOfFile (kernelbase.@)
196 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFile( HANDLE mapping
, DWORD access
, DWORD offset_high
,
197 DWORD offset_low
, SIZE_T count
)
199 return MapViewOfFileEx( mapping
, access
, offset_high
, offset_low
, count
, NULL
);
203 /***********************************************************************
204 * MapViewOfFileEx (kernelbase.@)
206 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileEx( HANDLE handle
, DWORD access
, DWORD offset_high
,
207 DWORD offset_low
, SIZE_T count
, LPVOID addr
)
210 LARGE_INTEGER offset
;
214 offset
.u
.LowPart
= offset_low
;
215 offset
.u
.HighPart
= offset_high
;
217 exec
= access
& FILE_MAP_EXECUTE
;
218 access
&= ~FILE_MAP_EXECUTE
;
220 if (access
== FILE_MAP_COPY
)
221 protect
= exec
? PAGE_EXECUTE_WRITECOPY
: PAGE_WRITECOPY
;
222 else if (access
& FILE_MAP_WRITE
)
223 protect
= exec
? PAGE_EXECUTE_READWRITE
: PAGE_READWRITE
;
224 else if (access
& FILE_MAP_READ
)
225 protect
= exec
? PAGE_EXECUTE_READ
: PAGE_READONLY
;
226 else protect
= PAGE_NOACCESS
;
228 if ((status
= NtMapViewOfSection( handle
, GetCurrentProcess(), &addr
, 0, 0, &offset
,
229 &count
, ViewShare
, 0, protect
)) < 0)
231 SetLastError( RtlNtStatusToDosError(status
) );
238 /***********************************************************************
239 * ReadProcessMemory (kernelbase.@)
241 BOOL WINAPI DECLSPEC_HOTPATCH
ReadProcessMemory( HANDLE process
, const void *addr
, void *buffer
,
242 SIZE_T size
, SIZE_T
*bytes_read
)
244 return set_ntstatus( NtReadVirtualMemory( process
, addr
, buffer
, size
, bytes_read
));
248 /***********************************************************************
249 * ResetWriteWatch (kernelbase.@)
251 UINT WINAPI DECLSPEC_HOTPATCH
ResetWriteWatch( void *base
, SIZE_T size
)
253 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base
, size
)))
259 /***********************************************************************
260 * SetSystemFileCacheSize (kernelbase.@)
262 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemFileCacheSize( SIZE_T mincache
, SIZE_T maxcache
, DWORD flags
)
264 FIXME( "stub: %Id %Id %ld\n", mincache
, maxcache
, flags
);
265 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
270 /***********************************************************************
271 * UnmapViewOfFile (kernelbase.@)
273 BOOL WINAPI DECLSPEC_HOTPATCH
UnmapViewOfFile( const void *addr
)
275 if (GetVersion() & 0x80000000)
277 MEMORY_BASIC_INFORMATION info
;
278 if (!VirtualQuery( addr
, &info
, sizeof(info
) ) || info
.AllocationBase
!= addr
)
280 SetLastError( ERROR_INVALID_ADDRESS
);
284 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr
));
288 /***********************************************************************
289 * VirtualAlloc (kernelbase.@)
291 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc( void *addr
, SIZE_T size
, DWORD type
, DWORD protect
)
293 return VirtualAllocEx( GetCurrentProcess(), addr
, size
, type
, protect
);
297 /***********************************************************************
298 * VirtualAllocEx (kernelbase.@)
300 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocEx( HANDLE process
, void *addr
, SIZE_T size
,
301 DWORD type
, DWORD protect
)
305 if (!set_ntstatus( NtAllocateVirtualMemory( process
, &ret
, 0, &size
, type
, protect
))) return NULL
;
310 /***********************************************************************
311 * VirtualAlloc2 (kernelbase.@)
313 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAlloc2( HANDLE process
, void *addr
, SIZE_T size
,
314 DWORD type
, DWORD protect
,
315 MEM_EXTENDED_PARAMETER
*parameters
, ULONG count
)
319 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process
, &ret
, &size
, type
, protect
, parameters
, count
)))
325 /***********************************************************************
326 * VirtualAllocFromApp (kernelbase.@)
328 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocFromApp( void *addr
, SIZE_T size
,
329 DWORD type
, DWORD protect
)
333 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx.\n", addr
, (void *)size
, type
, protect
);
335 if (protect
== PAGE_EXECUTE
|| protect
== PAGE_EXECUTE_READ
|| protect
== PAGE_EXECUTE_READWRITE
336 || protect
== PAGE_EXECUTE_WRITECOPY
)
338 SetLastError( ERROR_INVALID_PARAMETER
);
342 if (!set_ntstatus( NtAllocateVirtualMemory( GetCurrentProcess(), &ret
, 0, &size
, type
, protect
))) return NULL
;
347 /***********************************************************************
348 * PrefetchVirtualMemory (kernelbase.@)
350 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ PrefetchVirtualMemory( HANDLE process
, ULONG_PTR count
,
351 WIN32_MEMORY_RANGE_ENTRY
*addresses
, ULONG flags
)
353 FIXME( "process %p, count %p, addresses %p, flags %#lx stub.\n", process
, (void *)count
, addresses
, flags
);
358 /***********************************************************************
359 * VirtualFree (kernelbase.@)
361 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFree( void *addr
, SIZE_T size
, DWORD type
)
363 return VirtualFreeEx( GetCurrentProcess(), addr
, size
, type
);
367 /***********************************************************************
368 * VirtualFreeEx (kernelbase.@)
370 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualFreeEx( HANDLE process
, void *addr
, SIZE_T size
, DWORD type
)
372 return set_ntstatus( NtFreeVirtualMemory( process
, &addr
, &size
, type
));
376 /***********************************************************************
377 * VirtualLock (kernelbase.@)
379 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualLock( void *addr
, SIZE_T size
)
381 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
385 /***********************************************************************
386 * VirtualProtect (kernelbase.@)
388 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtect( void *addr
, SIZE_T size
, DWORD new_prot
, DWORD
*old_prot
)
390 return VirtualProtectEx( GetCurrentProcess(), addr
, size
, new_prot
, old_prot
);
394 /***********************************************************************
395 * VirtualProtectEx (kernelbase.@)
397 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualProtectEx( HANDLE process
, void *addr
, SIZE_T size
,
398 DWORD new_prot
, DWORD
*old_prot
)
402 /* Win9x allows passing NULL as old_prot while this fails on NT */
403 if (!old_prot
&& (GetVersion() & 0x80000000)) old_prot
= &prot
;
404 return set_ntstatus( NtProtectVirtualMemory( process
, &addr
, &size
, new_prot
, old_prot
));
408 /***********************************************************************
409 * VirtualQuery (kernelbase.@)
411 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQuery( LPCVOID addr
, PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
413 return VirtualQueryEx( GetCurrentProcess(), addr
, info
, len
);
417 /***********************************************************************
418 * VirtualQueryEx (kernelbase.@)
420 SIZE_T WINAPI DECLSPEC_HOTPATCH
VirtualQueryEx( HANDLE process
, LPCVOID addr
,
421 PMEMORY_BASIC_INFORMATION info
, SIZE_T len
)
425 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryBasicInformation
, info
, len
, &ret
)))
431 /***********************************************************************
432 * VirtualUnlock (kernelbase.@)
434 BOOL WINAPI DECLSPEC_HOTPATCH
VirtualUnlock( void *addr
, SIZE_T size
)
436 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr
, &size
, 1 ));
440 /***********************************************************************
441 * WriteProcessMemory (kernelbase.@)
443 BOOL WINAPI DECLSPEC_HOTPATCH
WriteProcessMemory( HANDLE process
, void *addr
, const void *buffer
,
444 SIZE_T size
, SIZE_T
*bytes_written
)
446 return set_ntstatus( NtWriteVirtualMemory( process
, addr
, buffer
, size
, bytes_written
));
450 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
451 BOOL WINAPI
IsBadStringPtrA( LPCSTR str
, UINT_PTR max
)
453 if (!str
) return TRUE
;
456 volatile const char *p
= str
;
457 while (p
!= str
+ max
) if (!*p
++) break;
468 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
469 BOOL WINAPI
IsBadStringPtrW( LPCWSTR str
, UINT_PTR max
)
471 if (!str
) return TRUE
;
474 volatile const WCHAR
*p
= str
;
475 while (p
!= str
+ max
) if (!*p
++) break;
486 /***********************************************************************
488 ***********************************************************************/
491 /***********************************************************************
492 * HeapCompact (kernelbase.@)
494 SIZE_T WINAPI DECLSPEC_HOTPATCH
HeapCompact( HANDLE heap
, DWORD flags
)
496 return RtlCompactHeap( heap
, flags
);
500 /***********************************************************************
501 * HeapCreate (kernelbase.@)
503 HANDLE WINAPI DECLSPEC_HOTPATCH
HeapCreate( DWORD flags
, SIZE_T init_size
, SIZE_T max_size
)
505 HANDLE ret
= RtlCreateHeap( flags
, NULL
, max_size
, init_size
, NULL
, NULL
);
506 if (!ret
) SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
511 /***********************************************************************
512 * HeapDestroy (kernelbase.@)
514 BOOL WINAPI DECLSPEC_HOTPATCH
HeapDestroy( HANDLE heap
)
516 if (!RtlDestroyHeap( heap
)) return TRUE
;
517 SetLastError( ERROR_INVALID_HANDLE
);
522 /***********************************************************************
523 * HeapLock (kernelbase.@)
525 BOOL WINAPI DECLSPEC_HOTPATCH
HeapLock( HANDLE heap
)
527 return RtlLockHeap( heap
);
531 /***********************************************************************
532 * HeapQueryInformation (kernelbase.@)
534 BOOL WINAPI
HeapQueryInformation( HANDLE heap
, HEAP_INFORMATION_CLASS info_class
,
535 PVOID info
, SIZE_T size
, PSIZE_T size_out
)
537 return set_ntstatus( RtlQueryHeapInformation( heap
, info_class
, info
, size
, size_out
));
541 /***********************************************************************
542 * HeapSetInformation (kernelbase.@)
544 BOOL WINAPI
HeapSetInformation( HANDLE heap
, HEAP_INFORMATION_CLASS infoclass
, PVOID info
, SIZE_T size
)
546 return set_ntstatus( RtlSetHeapInformation( heap
, infoclass
, info
, size
));
550 /***********************************************************************
551 * HeapUnlock (kernelbase.@)
553 BOOL WINAPI
HeapUnlock( HANDLE heap
)
555 return RtlUnlockHeap( heap
);
559 /***********************************************************************
560 * HeapValidate (kernelbase.@)
562 BOOL WINAPI DECLSPEC_HOTPATCH
HeapValidate( HANDLE heap
, DWORD flags
, LPCVOID ptr
)
564 return RtlValidateHeap( heap
, flags
, ptr
);
568 /***********************************************************************
569 * HeapWalk (kernelbase.@)
571 BOOL WINAPI DECLSPEC_HOTPATCH
HeapWalk( HANDLE heap
, PROCESS_HEAP_ENTRY
*entry
)
573 return set_ntstatus( RtlWalkHeap( heap
, entry
));
577 /***********************************************************************
578 * Global/local heap functions
579 ***********************************************************************/
581 /* not compatible with windows */
582 struct kernelbase_global_data
584 struct mem_entry
*mem_entries
;
585 struct mem_entry
*mem_entries_end
;
588 #include "pshpack1.h"
600 static struct kernelbase_global_data kernelbase_global_data
= {0};
602 #define MAGIC_LOCAL_USED 0x5342
603 /* align the storage needed for the HLOCAL on an 8-byte boundary thus
604 * LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
605 * size = 8*k, where k=1,2,3,... allocs exactly the given size.
606 * The Minolta DiMAGE Image Viewer heavily relies on this, corrupting
607 * the output jpeg's > 1 MB if not */
608 #define HLOCAL_STORAGE (sizeof(HLOCAL) * 2)
610 static inline struct mem_entry
*unsafe_mem_from_HLOCAL( HLOCAL handle
)
612 struct mem_entry
*mem
= CONTAINING_RECORD( handle
, struct mem_entry
, ptr
);
613 if (!((ULONG_PTR
)handle
& 2)) return NULL
;
614 if (mem
->magic
!= MAGIC_LOCAL_USED
) return NULL
;
618 static inline HLOCAL
HLOCAL_from_mem( struct mem_entry
*mem
)
623 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle
)
625 if ((ULONG_PTR
)handle
& 2) return NULL
;
630 /***********************************************************************
631 * KernelBaseGetGlobalData (kernelbase.@)
633 void *WINAPI
KernelBaseGetGlobalData(void)
635 WARN_(globalmem
)( "semi-stub!\n" );
636 return &kernelbase_global_data
;
640 /***********************************************************************
641 * GlobalAlloc (kernelbase.@)
643 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalAlloc( UINT flags
, SIZE_T size
)
645 /* mask out obsolete flags */
646 flags
&= ~(GMEM_NOCOMPACT
| GMEM_NOT_BANKED
| GMEM_NOTIFY
);
648 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
649 if (!(flags
& GMEM_MOVEABLE
) && !size
) size
= 1;
651 return LocalAlloc( flags
, size
);
655 /***********************************************************************
656 * GlobalFree (kernelbase.@)
658 HGLOBAL WINAPI DECLSPEC_HOTPATCH
GlobalFree( HLOCAL handle
)
660 return LocalFree( handle
);
664 /***********************************************************************
665 * LocalAlloc (kernelbase.@)
667 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalAlloc( UINT flags
, SIZE_T size
)
669 struct mem_entry
*mem
;
670 DWORD heap_flags
= 0;
673 TRACE_(globalmem
)( "flags %#x, size %#Ix\n", flags
, size
);
675 if (flags
& LMEM_ZEROINIT
) heap_flags
= HEAP_ZERO_MEMORY
;
677 if (!(flags
& LMEM_MOVEABLE
)) /* pointer */
679 ptr
= HeapAlloc( GetProcessHeap(), heap_flags
, size
);
680 TRACE_(globalmem
)( "return %p\n", ptr
);
684 if (size
> INT_MAX
- HLOCAL_STORAGE
)
686 SetLastError( ERROR_OUTOFMEMORY
);
689 if (!(mem
= HeapAlloc( GetProcessHeap(), 0, sizeof(*mem
) ))) return 0;
691 mem
->magic
= MAGIC_LOCAL_USED
;
692 mem
->flags
= flags
>> 8;
697 if (!(ptr
= HeapAlloc(GetProcessHeap(), heap_flags
, size
+ HLOCAL_STORAGE
)))
699 HeapFree( GetProcessHeap(), 0, mem
);
702 *(HLOCAL
*)ptr
= HLOCAL_from_mem( mem
);
703 mem
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
705 else mem
->ptr
= NULL
;
707 TRACE_(globalmem
)( "return handle %p, ptr %p\n", HLOCAL_from_mem( mem
), mem
->ptr
);
708 return HLOCAL_from_mem( mem
);
712 /***********************************************************************
713 * LocalFree (kernelbase.@)
715 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalFree( HLOCAL handle
)
717 struct mem_entry
*mem
;
721 TRACE_(globalmem
)( "handle %p\n", handle
);
723 RtlLockHeap( GetProcessHeap() );
727 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)))
729 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, ptr
))
731 SetLastError( ERROR_INVALID_HANDLE
);
737 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
742 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, (char *)mem
->ptr
- HLOCAL_STORAGE
))
745 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE
, mem
)) ret
= handle
;
749 WARN_(globalmem
)( "invalid handle %p\n", handle
);
750 SetLastError( ERROR_INVALID_HANDLE
);
757 WARN_(globalmem
)( "invalid handle %p\n", handle
);
758 SetLastError( ERROR_INVALID_HANDLE
);
762 RtlUnlockHeap( GetProcessHeap() );
767 /***********************************************************************
768 * LocalLock (kernelbase.@)
770 LPVOID WINAPI DECLSPEC_HOTPATCH
LocalLock( HLOCAL handle
)
772 struct mem_entry
*mem
;
775 TRACE_(globalmem
)( "handle %p\n", handle
);
777 if ((ret
= unsafe_ptr_from_HLOCAL( handle
)))
781 volatile char *p
= ret
;
792 RtlLockHeap( GetProcessHeap() );
795 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
798 if (!mem
->ptr
) SetLastError( ERROR_DISCARDED
);
799 else if (mem
->lock
< LMEM_LOCKCOUNT
) mem
->lock
++;
803 WARN_(globalmem
)( "invalid handle %p\n", handle
);
804 SetLastError( ERROR_INVALID_HANDLE
);
809 WARN_(globalmem
)( "(%p): Page fault occurred ! Caused by bug ?\n", handle
);
810 SetLastError( ERROR_INVALID_HANDLE
);
813 RtlUnlockHeap( GetProcessHeap() );
818 /***********************************************************************
819 * LocalReAlloc (kernelbase.@)
821 HLOCAL WINAPI DECLSPEC_HOTPATCH
LocalReAlloc( HLOCAL handle
, SIZE_T size
, UINT flags
)
823 struct mem_entry
*mem
;
825 DWORD heap_flags
= (flags
& LMEM_ZEROINIT
) ? HEAP_ZERO_MEMORY
: 0;
828 TRACE_(globalmem
)( "handle %p, size %#Ix, flags %#x\n", handle
, size
, flags
);
830 RtlLockHeap( GetProcessHeap() );
831 if (flags
& LMEM_MODIFY
) /* modify flags */
833 if (unsafe_ptr_from_HLOCAL( handle
) && (flags
& LMEM_MOVEABLE
))
835 /* make a fixed block moveable
836 * actually only NT is able to do this. But it's soo simple
840 WARN_(globalmem
)( "null handle\n" );
841 SetLastError( ERROR_NOACCESS
);
845 size
= RtlSizeHeap( GetProcessHeap(), 0, handle
);
846 ret
= LocalAlloc( flags
, size
);
847 ptr
= LocalLock( ret
);
848 memcpy( ptr
, handle
, size
);
853 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)) && (flags
& LMEM_DISCARDABLE
))
855 /* change the flags to make our block "discardable" */
856 mem
->flags
|= LMEM_DISCARDABLE
>> 8;
859 else SetLastError( ERROR_INVALID_PARAMETER
);
863 if ((ptr
= unsafe_ptr_from_HLOCAL( handle
)))
865 /* reallocate fixed memory */
866 if (!(flags
& LMEM_MOVEABLE
)) heap_flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
867 ret
= HeapReAlloc( GetProcessHeap(), heap_flags
, ptr
, size
);
869 else if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
871 /* reallocate a moveable block */
874 if (size
<= INT_MAX
- HLOCAL_STORAGE
)
878 if ((ptr
= HeapReAlloc( GetProcessHeap(), heap_flags
, (char *)mem
->ptr
- HLOCAL_STORAGE
,
879 size
+ HLOCAL_STORAGE
)))
881 mem
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
887 if ((ptr
= HeapAlloc( GetProcessHeap(), heap_flags
, size
+ HLOCAL_STORAGE
)))
889 *(HLOCAL
*)ptr
= handle
;
890 mem
->ptr
= (char *)ptr
+ HLOCAL_STORAGE
;
895 else SetLastError( ERROR_OUTOFMEMORY
);
903 HeapFree( GetProcessHeap(), 0, (char *)mem
->ptr
- HLOCAL_STORAGE
);
908 else WARN_(globalmem
)( "not freeing memory associated with locked handle\n" );
911 else SetLastError( ERROR_INVALID_HANDLE
);
913 RtlUnlockHeap( GetProcessHeap() );
918 /***********************************************************************
919 * LocalUnlock (kernelbase.@)
921 BOOL WINAPI DECLSPEC_HOTPATCH
LocalUnlock( HLOCAL handle
)
923 struct mem_entry
*mem
;
926 TRACE_(globalmem
)( "handle %p\n", handle
);
928 if (unsafe_ptr_from_HLOCAL( handle
))
930 SetLastError( ERROR_NOT_LOCKED
);
934 RtlLockHeap( GetProcessHeap() );
937 if ((mem
= unsafe_mem_from_HLOCAL( handle
)))
942 ret
= (mem
->lock
!= 0);
943 if (!ret
) SetLastError( NO_ERROR
);
947 WARN_(globalmem
)( "%p not locked\n", handle
);
948 SetLastError( ERROR_NOT_LOCKED
);
953 WARN_(globalmem
)( "invalid handle %p\n", handle
);
954 SetLastError( ERROR_INVALID_HANDLE
);
959 WARN_(globalmem
)( "(%p): Page fault occurred ! Caused by bug ?\n", handle
);
960 SetLastError( ERROR_INVALID_PARAMETER
);
963 RtlUnlockHeap( GetProcessHeap() );
968 /***********************************************************************
969 * Memory resource functions
970 ***********************************************************************/
973 /***********************************************************************
974 * CreateMemoryResourceNotification (kernelbase.@)
976 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type
)
979 UNICODE_STRING nameW
;
980 OBJECT_ATTRIBUTES attr
;
984 case LowMemoryResourceNotification
:
985 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\LowMemoryCondition" );
987 case HighMemoryResourceNotification
:
988 RtlInitUnicodeString( &nameW
, L
"\\KernelObjects\\HighMemoryCondition" );
991 SetLastError( ERROR_INVALID_PARAMETER
);
995 InitializeObjectAttributes( &attr
, &nameW
, 0, 0, NULL
);
996 if (!set_ntstatus( NtOpenEvent( &ret
, EVENT_ALL_ACCESS
, &attr
))) return 0;
1000 /***********************************************************************
1001 * QueryMemoryResourceNotification (kernelbase.@)
1003 BOOL WINAPI DECLSPEC_HOTPATCH
QueryMemoryResourceNotification( HANDLE handle
, BOOL
*state
)
1005 switch (WaitForSingleObject( handle
, 0 ))
1014 SetLastError( ERROR_INVALID_PARAMETER
);
1019 /***********************************************************************
1020 * Physical memory functions
1021 ***********************************************************************/
1024 /***********************************************************************
1025 * AllocateUserPhysicalPages (kernelbase.@)
1027 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1028 ULONG_PTR
*userarray
)
1030 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1031 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1036 /***********************************************************************
1037 * FreeUserPhysicalPages (kernelbase.@)
1039 BOOL WINAPI DECLSPEC_HOTPATCH
FreeUserPhysicalPages( HANDLE process
, ULONG_PTR
*pages
,
1040 ULONG_PTR
*userarray
)
1042 FIXME( "stub: %p %p %p\n", process
, pages
, userarray
);
1044 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1049 /***********************************************************************
1050 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1052 BOOL WINAPI DECLSPEC_HOTPATCH
GetPhysicallyInstalledSystemMemory( ULONGLONG
*memory
)
1054 MEMORYSTATUSEX status
;
1058 SetLastError( ERROR_INVALID_PARAMETER
);
1061 status
.dwLength
= sizeof(status
);
1062 GlobalMemoryStatusEx( &status
);
1063 *memory
= status
.ullTotalPhys
/ 1024;
1068 /***********************************************************************
1069 * GlobalMemoryStatusEx (kernelbase.@)
1071 BOOL WINAPI DECLSPEC_HOTPATCH
GlobalMemoryStatusEx( MEMORYSTATUSEX
*status
)
1073 static MEMORYSTATUSEX cached_status
;
1074 static DWORD last_check
;
1075 SYSTEM_BASIC_INFORMATION basic_info
;
1076 SYSTEM_PERFORMANCE_INFORMATION perf_info
;
1079 if (status
->dwLength
!= sizeof(*status
))
1081 SetLastError( ERROR_INVALID_PARAMETER
);
1084 if ((NtGetTickCount() - last_check
) < 1000)
1086 *status
= cached_status
;
1089 last_check
= NtGetTickCount();
1091 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation
,
1092 &basic_info
, sizeof(basic_info
), NULL
)) ||
1093 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation
,
1094 &perf_info
, sizeof(perf_info
), NULL
)) ||
1095 !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
,
1096 &vmc
, sizeof(vmc
), NULL
)))
1099 status
->dwMemoryLoad
= 0;
1100 status
->ullTotalPhys
= basic_info
.MmNumberOfPhysicalPages
;
1101 status
->ullAvailPhys
= perf_info
.AvailablePages
;
1102 status
->ullTotalPageFile
= perf_info
.TotalCommitLimit
;
1103 status
->ullAvailPageFile
= status
->ullTotalPageFile
- perf_info
.TotalCommittedPages
;
1104 status
->ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
+ 1;
1105 status
->ullAvailVirtual
= status
->ullTotalVirtual
- (ULONGLONG
)vmc
.WorkingSetSize
/* approximate */;
1106 status
->ullAvailExtendedVirtual
= 0;
1108 status
->ullTotalPhys
*= basic_info
.PageSize
;
1109 status
->ullAvailPhys
*= basic_info
.PageSize
;
1110 status
->ullTotalPageFile
*= basic_info
.PageSize
;
1111 status
->ullAvailPageFile
*= basic_info
.PageSize
;
1113 if (status
->ullTotalPhys
)
1114 status
->dwMemoryLoad
= (status
->ullTotalPhys
- status
->ullAvailPhys
) / (status
->ullTotalPhys
/ 100);
1116 TRACE_(virtual)( "MemoryLoad %ld, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1117 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1118 status
->dwMemoryLoad
, wine_dbgstr_longlong(status
->ullTotalPhys
),
1119 wine_dbgstr_longlong(status
->ullAvailPhys
), wine_dbgstr_longlong(status
->ullTotalPageFile
),
1120 wine_dbgstr_longlong(status
->ullAvailPageFile
), wine_dbgstr_longlong(status
->ullTotalVirtual
),
1121 wine_dbgstr_longlong(status
->ullAvailVirtual
) );
1123 cached_status
= *status
;
1128 /***********************************************************************
1129 * MapUserPhysicalPages (kernelbase.@)
1131 BOOL WINAPI DECLSPEC_HOTPATCH
MapUserPhysicalPages( void *addr
, ULONG_PTR page_count
, ULONG_PTR
*pages
)
1133 FIXME( "stub: %p %Iu %p\n", addr
, page_count
, pages
);
1135 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1140 /***********************************************************************
1142 ***********************************************************************/
1145 /***********************************************************************
1146 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1148 BOOL WINAPI DECLSPEC_HOTPATCH
AllocateUserPhysicalPagesNuma( HANDLE process
, ULONG_PTR
*pages
,
1149 ULONG_PTR
*userarray
, DWORD node
)
1151 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1152 return AllocateUserPhysicalPages( process
, pages
, userarray
);
1156 /***********************************************************************
1157 * CreateFileMappingNumaW (kernelbase.@)
1159 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileMappingNumaW( HANDLE file
, LPSECURITY_ATTRIBUTES sa
,
1160 DWORD protect
, DWORD size_high
, DWORD size_low
,
1161 LPCWSTR name
, DWORD node
)
1163 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1164 return CreateFileMappingW( file
, sa
, protect
, size_high
, size_low
, name
);
1168 /***********************************************************************
1169 * GetLogicalProcessorInformation (kernelbase.@)
1171 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buffer
,
1178 SetLastError( ERROR_INVALID_PARAMETER
);
1181 status
= NtQuerySystemInformation( SystemLogicalProcessorInformation
, buffer
, *len
, len
);
1182 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1183 return set_ntstatus( status
);
1187 /***********************************************************************
1188 * GetLogicalProcessorInformationEx (kernelbase.@)
1190 BOOL WINAPI DECLSPEC_HOTPATCH
GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship
,
1191 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buffer
, DWORD
*len
)
1197 SetLastError( ERROR_INVALID_PARAMETER
);
1200 status
= NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx
, &relationship
,
1201 sizeof(relationship
), buffer
, *len
, len
);
1202 if (status
== STATUS_INFO_LENGTH_MISMATCH
) status
= STATUS_BUFFER_TOO_SMALL
;
1203 return set_ntstatus( status
);
1207 /***********************************************************************
1208 * GetSystemCpuSetInformation (kernelbase.@)
1210 BOOL WINAPI
GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION
*info
, ULONG buffer_length
, ULONG
*return_length
,
1211 HANDLE process
, ULONG flags
)
1214 FIXME("Unsupported flags %#lx.\n", flags
);
1218 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation
, &process
, sizeof(process
), info
,
1219 buffer_length
, return_length
));
1223 /***********************************************************************
1224 * SetThreadSelectedCpuSets (kernelbase.@)
1226 BOOL WINAPI
SetThreadSelectedCpuSets(HANDLE thread
, const ULONG
*cpu_set_ids
, ULONG count
)
1228 FIXME( "thread %p, cpu_set_ids %p, count %lu stub.\n", thread
, cpu_set_ids
, count
);
1234 /**********************************************************************
1235 * GetNumaHighestNodeNumber (kernelbase.@)
1237 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaHighestNodeNumber( ULONG
*node
)
1239 FIXME( "semi-stub: %p\n", node
);
1245 /**********************************************************************
1246 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1248 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaNodeProcessorMaskEx( USHORT node
, GROUP_AFFINITY
*mask
)
1250 FIXME( "stub: %hu %p\n", node
, mask
);
1251 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1256 /***********************************************************************
1257 * GetNumaProximityNodeEx (kernelbase.@)
1259 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumaProximityNodeEx( ULONG proximity_id
, USHORT
*node
)
1261 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1266 /***********************************************************************
1267 * MapViewOfFileExNuma (kernelbase.@)
1269 LPVOID WINAPI DECLSPEC_HOTPATCH
MapViewOfFileExNuma( HANDLE handle
, DWORD access
, DWORD offset_high
,
1270 DWORD offset_low
, SIZE_T count
, LPVOID addr
,
1273 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1274 return MapViewOfFileEx( handle
, access
, offset_high
, offset_low
, count
, addr
);
1278 /***********************************************************************
1279 * VirtualAllocExNuma (kernelbase.@)
1281 LPVOID WINAPI DECLSPEC_HOTPATCH
VirtualAllocExNuma( HANDLE process
, void *addr
, SIZE_T size
,
1282 DWORD type
, DWORD protect
, DWORD node
)
1284 if (node
) FIXME( "Ignoring preferred node %lu\n", node
);
1285 return VirtualAllocEx( process
, addr
, size
, type
, protect
);
1289 /***********************************************************************
1291 ***********************************************************************/
1294 #if defined(__i386__) || defined(__x86_64__)
1295 /***********************************************************************
1296 * GetEnabledXStateFeatures (kernelbase.@)
1298 DWORD64 WINAPI
GetEnabledXStateFeatures(void)
1301 return RtlGetEnabledExtendedFeatures( ~(ULONG64
)0 );
1305 /***********************************************************************
1306 * InitializeContext2 (kernelbase.@)
1308 BOOL WINAPI
InitializeContext2( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
,
1309 ULONG64 compaction_mask
)
1314 TRACE( "buffer %p, context_flags %#lx, context %p, ret_length %p, compaction_mask %s.\n",
1315 buffer
, context_flags
, context
, length
, wine_dbgstr_longlong(compaction_mask
) );
1317 orig_length
= *length
;
1319 if ((status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
)))
1321 if (status
== STATUS_NOT_SUPPORTED
&& context_flags
& 0x40)
1323 context_flags
&= ~0x40;
1324 status
= RtlGetExtendedContextLength2( context_flags
, length
, compaction_mask
);
1328 return set_ntstatus( status
);
1331 if (!buffer
|| orig_length
< *length
)
1333 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1337 if ((status
= RtlInitializeExtendedContext2( buffer
, context_flags
, (CONTEXT_EX
**)context
, compaction_mask
)))
1338 return set_ntstatus( status
);
1340 *context
= (CONTEXT
*)((BYTE
*)*context
+ (*(CONTEXT_EX
**)context
)->Legacy
.Offset
);
1345 /***********************************************************************
1346 * InitializeContext (kernelbase.@)
1348 BOOL WINAPI
InitializeContext( void *buffer
, DWORD context_flags
, CONTEXT
**context
, DWORD
*length
)
1350 return InitializeContext2( buffer
, context_flags
, context
, length
, ~(ULONG64
)0 );
1353 /***********************************************************************
1354 * CopyContext (kernelbase.@)
1356 BOOL WINAPI
CopyContext( CONTEXT
*dst
, DWORD context_flags
, CONTEXT
*src
)
1358 return set_ntstatus( RtlCopyContext( dst
, context_flags
, src
));
1363 #if defined(__x86_64__)
1364 /***********************************************************************
1365 * LocateXStateFeature (kernelbase.@)
1367 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1369 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1372 if (feature_id
>= 2)
1373 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1374 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1376 if (feature_id
== 1)
1379 *length
= sizeof(M128A
) * 16;
1381 return &context
->u
.FltSave
.XmmRegisters
;
1385 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1387 return &context
->u
.FltSave
;
1390 /***********************************************************************
1391 * SetXStateFeaturesMask (kernelbase.@)
1393 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1395 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1398 if (feature_mask
& 0x3)
1399 context
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
1401 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1402 return !(feature_mask
& ~(DWORD64
)3);
1404 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1408 /***********************************************************************
1409 * GetXStateFeaturesMask (kernelbase.@)
1411 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1413 if (!(context
->ContextFlags
& CONTEXT_AMD64
))
1416 *feature_mask
= (context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
1419 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1420 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1424 #elif defined(__i386__)
1425 /***********************************************************************
1426 * LocateXStateFeature (kernelbase.@)
1428 void * WINAPI
LocateXStateFeature( CONTEXT
*context
, DWORD feature_id
, DWORD
*length
)
1430 if (!(context
->ContextFlags
& CONTEXT_i386
))
1433 if (feature_id
>= 2)
1434 return ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1435 ? RtlLocateExtendedFeature( (CONTEXT_EX
*)(context
+ 1), feature_id
, length
) : NULL
;
1437 if (feature_id
== 1)
1440 *length
= sizeof(M128A
) * 8;
1442 return (BYTE
*)&context
->ExtendedRegisters
+ offsetof(XSAVE_FORMAT
, XmmRegisters
);
1446 *length
= offsetof(XSAVE_FORMAT
, XmmRegisters
);
1448 return &context
->ExtendedRegisters
;
1451 /***********************************************************************
1452 * SetXStateFeaturesMask (kernelbase.@)
1454 BOOL WINAPI
SetXStateFeaturesMask( CONTEXT
*context
, DWORD64 feature_mask
)
1456 if (!(context
->ContextFlags
& CONTEXT_i386
))
1459 if (feature_mask
& 0x3)
1460 context
->ContextFlags
|= CONTEXT_EXTENDED_REGISTERS
;
1462 if ((context
->ContextFlags
& CONTEXT_XSTATE
) != CONTEXT_XSTATE
)
1463 return !(feature_mask
& ~(DWORD64
)3);
1465 RtlSetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1), feature_mask
);
1469 /***********************************************************************
1470 * GetXStateFeaturesMask (kernelbase.@)
1472 BOOL WINAPI
GetXStateFeaturesMask( CONTEXT
*context
, DWORD64
*feature_mask
)
1474 if (!(context
->ContextFlags
& CONTEXT_i386
))
1477 *feature_mask
= (context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
1480 if ((context
->ContextFlags
& CONTEXT_XSTATE
) == CONTEXT_XSTATE
)
1481 *feature_mask
|= RtlGetExtendedFeaturesMask( (CONTEXT_EX
*)(context
+ 1) );
1487 /***********************************************************************
1488 * Firmware functions
1489 ***********************************************************************/
1492 /***********************************************************************
1493 * EnumSystemFirmwareTable (kernelbase.@)
1495 UINT WINAPI
EnumSystemFirmwareTables( DWORD provider
, void *buffer
, DWORD size
)
1497 FIXME( "(0x%08lx, %p, %ld)\n", provider
, buffer
, size
);
1502 /***********************************************************************
1503 * GetSystemFirmwareTable (kernelbase.@)
1505 UINT WINAPI
GetSystemFirmwareTable( DWORD provider
, DWORD id
, void *buffer
, DWORD size
)
1507 SYSTEM_FIRMWARE_TABLE_INFORMATION
*info
;
1508 ULONG buffer_size
= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
) + size
;
1510 TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider
, id
, buffer
, size
);
1512 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, buffer_size
)))
1514 SetLastError( ERROR_OUTOFMEMORY
);
1518 info
->ProviderSignature
= provider
;
1519 info
->Action
= SystemFirmwareTable_Get
;
1522 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation
,
1523 info
, buffer_size
, &buffer_size
));
1524 buffer_size
-= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
1525 if (buffer_size
<= size
) memcpy( buffer
, info
->TableBuffer
, buffer_size
);
1527 HeapFree( GetProcessHeap(), 0, info
);