kernelbase: Use RtlWow64GetProcessMachines() to get native system information.
[wine.git] / dlls / kernelbase / memory.c
blob4e03267cbb59715d3f77800329e6d71d18a015ee
1 /*
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
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <limits.h>
25 #include <sys/types.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "winternl.h"
35 #include "winerror.h"
36 #include "ddk/wdm.h"
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);
46 /***********************************************************************
47 * Virtual memory functions
48 ***********************************************************************/
51 /***********************************************************************
52 * FlushViewOfFile (kernelbase.@)
54 BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size )
56 NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
58 if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
59 return set_ntstatus( status );
63 /***********************************************************************
64 * GetLargePageMinimum (kernelbase.@)
66 SIZE_T WINAPI GetLargePageMinimum(void)
68 return 2 * 1024 * 1024;
72 /***********************************************************************
73 * GetNativeSystemInfo (kernelbase.@)
75 void WINAPI DECLSPEC_HOTPATCH GetNativeSystemInfo( SYSTEM_INFO *si )
77 USHORT current_machine, native_machine;
79 GetSystemInfo( si );
80 RtlWow64GetProcessMachines( GetCurrentProcess(), &current_machine, &native_machine );
81 if (!current_machine) return;
82 switch (native_machine)
84 case PROCESSOR_ARCHITECTURE_AMD64:
85 si->u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
86 si->dwProcessorType = PROCESSOR_AMD_X8664;
87 break;
88 case PROCESSOR_ARCHITECTURE_ARM64:
89 si->u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64;
90 si->dwProcessorType = 0;
91 break;
92 default:
93 FIXME( "Add the proper information for %d in wow64 mode\n", si->u.s.wProcessorArchitecture );
98 /***********************************************************************
99 * GetSystemInfo (kernelbase.@)
101 void WINAPI DECLSPEC_HOTPATCH GetSystemInfo( SYSTEM_INFO *si )
103 SYSTEM_BASIC_INFORMATION basic_info;
104 SYSTEM_CPU_INFORMATION cpu_info;
106 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
107 &basic_info, sizeof(basic_info), NULL )) ||
108 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation,
109 &cpu_info, sizeof(cpu_info), NULL )))
110 return;
112 si->u.s.wProcessorArchitecture = cpu_info.Architecture;
113 si->u.s.wReserved = 0;
114 si->dwPageSize = basic_info.PageSize;
115 si->lpMinimumApplicationAddress = basic_info.LowestUserAddress;
116 si->lpMaximumApplicationAddress = basic_info.HighestUserAddress;
117 si->dwActiveProcessorMask = basic_info.ActiveProcessorsAffinityMask;
118 si->dwNumberOfProcessors = basic_info.NumberOfProcessors;
119 si->dwAllocationGranularity = basic_info.AllocationGranularity;
120 si->wProcessorLevel = cpu_info.Level;
121 si->wProcessorRevision = cpu_info.Revision;
123 switch (cpu_info.Architecture)
125 case PROCESSOR_ARCHITECTURE_INTEL:
126 switch (cpu_info.Level)
128 case 3: si->dwProcessorType = PROCESSOR_INTEL_386; break;
129 case 4: si->dwProcessorType = PROCESSOR_INTEL_486; break;
130 case 5:
131 case 6: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
132 default: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
134 break;
135 case PROCESSOR_ARCHITECTURE_PPC:
136 switch (cpu_info.Level)
138 case 1: si->dwProcessorType = PROCESSOR_PPC_601; break;
139 case 3:
140 case 6: si->dwProcessorType = PROCESSOR_PPC_603; break;
141 case 4: si->dwProcessorType = PROCESSOR_PPC_604; break;
142 case 9: si->dwProcessorType = PROCESSOR_PPC_604; break;
143 case 20: si->dwProcessorType = PROCESSOR_PPC_620; break;
144 default: si->dwProcessorType = 0;
146 break;
147 case PROCESSOR_ARCHITECTURE_AMD64:
148 si->dwProcessorType = PROCESSOR_AMD_X8664;
149 break;
150 case PROCESSOR_ARCHITECTURE_ARM:
151 switch (cpu_info.Level)
153 case 4: si->dwProcessorType = PROCESSOR_ARM_7TDMI; break;
154 default: si->dwProcessorType = PROCESSOR_ARM920;
156 break;
157 case PROCESSOR_ARCHITECTURE_ARM64:
158 si->dwProcessorType = 0;
159 break;
160 default:
161 FIXME( "Unknown processor architecture %x\n", cpu_info.Architecture );
162 si->dwProcessorType = 0;
163 break;
168 /***********************************************************************
169 * GetSystemFileCacheSize (kernelbase.@)
171 BOOL WINAPI DECLSPEC_HOTPATCH GetSystemFileCacheSize( SIZE_T *mincache, SIZE_T *maxcache, DWORD *flags )
173 FIXME( "stub: %p %p %p\n", mincache, maxcache, flags );
174 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
175 return FALSE;
179 /***********************************************************************
180 * GetWriteWatch (kernelbase.@)
182 UINT WINAPI DECLSPEC_HOTPATCH GetWriteWatch( DWORD flags, void *base, SIZE_T size, void **addresses,
183 ULONG_PTR *count, ULONG *granularity )
185 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags, base, size,
186 addresses, count, granularity )))
187 return ~0u;
188 return 0;
192 /***********************************************************************
193 * MapViewOfFile (kernelbase.@)
195 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile( HANDLE mapping, DWORD access, DWORD offset_high,
196 DWORD offset_low, SIZE_T count )
198 return MapViewOfFileEx( mapping, access, offset_high, offset_low, count, NULL );
202 /***********************************************************************
203 * MapViewOfFileEx (kernelbase.@)
205 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileEx( HANDLE handle, DWORD access, DWORD offset_high,
206 DWORD offset_low, SIZE_T count, LPVOID addr )
208 NTSTATUS status;
209 LARGE_INTEGER offset;
210 ULONG protect;
211 BOOL exec;
213 offset.u.LowPart = offset_low;
214 offset.u.HighPart = offset_high;
216 exec = access & FILE_MAP_EXECUTE;
217 access &= ~FILE_MAP_EXECUTE;
219 if (access == FILE_MAP_COPY)
220 protect = exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY;
221 else if (access & FILE_MAP_WRITE)
222 protect = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
223 else if (access & FILE_MAP_READ)
224 protect = exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
225 else protect = PAGE_NOACCESS;
227 if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
228 &count, ViewShare, 0, protect )) < 0)
230 SetLastError( RtlNtStatusToDosError(status) );
231 addr = NULL;
233 return addr;
237 /***********************************************************************
238 * ReadProcessMemory (kernelbase.@)
240 BOOL WINAPI DECLSPEC_HOTPATCH ReadProcessMemory( HANDLE process, const void *addr, void *buffer,
241 SIZE_T size, SIZE_T *bytes_read )
243 return set_ntstatus( NtReadVirtualMemory( process, addr, buffer, size, bytes_read ));
247 /***********************************************************************
248 * ResetWriteWatch (kernelbase.@)
250 UINT WINAPI DECLSPEC_HOTPATCH ResetWriteWatch( void *base, SIZE_T size )
252 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base, size )))
253 return ~0u;
254 return 0;
258 /***********************************************************************
259 * SetSystemFileCacheSize (kernelbase.@)
261 BOOL WINAPI DECLSPEC_HOTPATCH SetSystemFileCacheSize( SIZE_T mincache, SIZE_T maxcache, DWORD flags )
263 FIXME( "stub: %ld %ld %d\n", mincache, maxcache, flags );
264 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
265 return FALSE;
269 /***********************************************************************
270 * UnmapViewOfFile (kernelbase.@)
272 BOOL WINAPI DECLSPEC_HOTPATCH UnmapViewOfFile( const void *addr )
274 if (GetVersion() & 0x80000000)
276 MEMORY_BASIC_INFORMATION info;
277 if (!VirtualQuery( addr, &info, sizeof(info) ) || info.AllocationBase != addr)
279 SetLastError( ERROR_INVALID_ADDRESS );
280 return FALSE;
283 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr ));
287 /***********************************************************************
288 * VirtualAlloc (kernelbase.@)
290 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc( void *addr, SIZE_T size, DWORD type, DWORD protect )
292 return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
296 /***********************************************************************
297 * VirtualAllocEx (kernelbase.@)
299 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocEx( HANDLE process, void *addr, SIZE_T size,
300 DWORD type, DWORD protect )
302 LPVOID ret = addr;
304 if (!set_ntstatus( NtAllocateVirtualMemory( process, &ret, 0, &size, type, protect ))) return NULL;
305 return ret;
309 /***********************************************************************
310 * VirtualAlloc2 (kernelbase.@)
312 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc2( HANDLE process, void *addr, SIZE_T size,
313 DWORD type, DWORD protect,
314 MEM_EXTENDED_PARAMETER *parameters, ULONG count )
316 LPVOID ret = addr;
318 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process, &ret, &size, type, protect, parameters, count )))
319 return NULL;
320 return ret;
324 /***********************************************************************
325 * VirtualAllocFromApp (kernelbase.@)
327 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocFromApp( void *addr, SIZE_T size,
328 DWORD type, DWORD protect )
330 LPVOID ret = addr;
332 TRACE_(virtual)( "addr %p, size %p, type %#x, protect %#x.\n", addr, (void *)size, type, protect );
334 if (protect == PAGE_EXECUTE || protect == PAGE_EXECUTE_READ || protect == PAGE_EXECUTE_READWRITE
335 || protect == PAGE_EXECUTE_WRITECOPY)
337 SetLastError( ERROR_INVALID_PARAMETER );
338 return NULL;
341 if (!set_ntstatus( NtAllocateVirtualMemory( GetCurrentProcess(), &ret, 0, &size, type, protect ))) return NULL;
342 return ret;
346 /***********************************************************************
347 * VirtualFree (kernelbase.@)
349 BOOL WINAPI DECLSPEC_HOTPATCH VirtualFree( void *addr, SIZE_T size, DWORD type )
351 return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
355 /***********************************************************************
356 * VirtualFreeEx (kernelbase.@)
358 BOOL WINAPI DECLSPEC_HOTPATCH VirtualFreeEx( HANDLE process, void *addr, SIZE_T size, DWORD type )
360 return set_ntstatus( NtFreeVirtualMemory( process, &addr, &size, type ));
364 /***********************************************************************
365 * VirtualLock (kernelbase.@)
367 BOOL WINAPI DECLSPEC_HOTPATCH VirtualLock( void *addr, SIZE_T size )
369 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 ));
373 /***********************************************************************
374 * VirtualProtect (kernelbase.@)
376 BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtect( void *addr, SIZE_T size, DWORD new_prot, DWORD *old_prot )
378 return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
382 /***********************************************************************
383 * VirtualProtectEx (kernelbase.@)
385 BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtectEx( HANDLE process, void *addr, SIZE_T size,
386 DWORD new_prot, DWORD *old_prot )
388 DWORD prot;
390 /* Win9x allows passing NULL as old_prot while this fails on NT */
391 if (!old_prot && (GetVersion() & 0x80000000)) old_prot = &prot;
392 return set_ntstatus( NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot ));
396 /***********************************************************************
397 * VirtualQuery (kernelbase.@)
399 SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len )
401 return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
405 /***********************************************************************
406 * VirtualQueryEx (kernelbase.@)
408 SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQueryEx( HANDLE process, LPCVOID addr,
409 PMEMORY_BASIC_INFORMATION info, SIZE_T len )
411 SIZE_T ret;
413 if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
414 return 0;
415 return ret;
419 /***********************************************************************
420 * VirtualUnlock (kernelbase.@)
422 BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size )
424 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 ));
428 /***********************************************************************
429 * WriteProcessMemory (kernelbase.@)
431 BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer,
432 SIZE_T size, SIZE_T *bytes_written )
434 return set_ntstatus( NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ));
438 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
439 BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
441 if (!str) return TRUE;
442 __TRY
444 volatile const char *p = str;
445 while (p != str + max) if (!*p++) break;
447 __EXCEPT_PAGE_FAULT
449 return TRUE;
451 __ENDTRY
452 return FALSE;
456 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
457 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT_PTR max )
459 if (!str) return TRUE;
460 __TRY
462 volatile const WCHAR *p = str;
463 while (p != str + max) if (!*p++) break;
465 __EXCEPT_PAGE_FAULT
467 return TRUE;
469 __ENDTRY
470 return FALSE;
474 /***********************************************************************
475 * Heap functions
476 ***********************************************************************/
479 /***********************************************************************
480 * HeapCompact (kernelbase.@)
482 SIZE_T WINAPI DECLSPEC_HOTPATCH HeapCompact( HANDLE heap, DWORD flags )
484 return RtlCompactHeap( heap, flags );
488 /***********************************************************************
489 * HeapCreate (kernelbase.@)
491 HANDLE WINAPI DECLSPEC_HOTPATCH HeapCreate( DWORD flags, SIZE_T init_size, SIZE_T max_size )
493 HANDLE ret = RtlCreateHeap( flags, NULL, max_size, init_size, NULL, NULL );
494 if (!ret) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
495 return ret;
499 /***********************************************************************
500 * HeapDestroy (kernelbase.@)
502 BOOL WINAPI DECLSPEC_HOTPATCH HeapDestroy( HANDLE heap )
504 if (!RtlDestroyHeap( heap )) return TRUE;
505 SetLastError( ERROR_INVALID_HANDLE );
506 return FALSE;
510 /***********************************************************************
511 * HeapLock (kernelbase.@)
513 BOOL WINAPI DECLSPEC_HOTPATCH HeapLock( HANDLE heap )
515 return RtlLockHeap( heap );
519 /***********************************************************************
520 * HeapQueryInformation (kernelbase.@)
522 BOOL WINAPI HeapQueryInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class,
523 PVOID info, SIZE_T size, PSIZE_T size_out )
525 return set_ntstatus( RtlQueryHeapInformation( heap, info_class, info, size, size_out ));
529 /***********************************************************************
530 * HeapSetInformation (kernelbase.@)
532 BOOL WINAPI HeapSetInformation( HANDLE heap, HEAP_INFORMATION_CLASS infoclass, PVOID info, SIZE_T size )
534 return set_ntstatus( RtlSetHeapInformation( heap, infoclass, info, size ));
538 /***********************************************************************
539 * HeapUnlock (kernelbase.@)
541 BOOL WINAPI HeapUnlock( HANDLE heap )
543 return RtlUnlockHeap( heap );
547 /***********************************************************************
548 * HeapValidate (kernelbase.@)
550 BOOL WINAPI DECLSPEC_HOTPATCH HeapValidate( HANDLE heap, DWORD flags, LPCVOID ptr )
552 return RtlValidateHeap( heap, flags, ptr );
556 /***********************************************************************
557 * HeapWalk (kernelbase.@)
559 BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
561 return set_ntstatus( RtlWalkHeap( heap, entry ));
565 /***********************************************************************
566 * Global/local heap functions
567 ***********************************************************************/
569 #include "pshpack1.h"
571 struct local_header
573 WORD magic;
574 void *ptr;
575 BYTE flags;
576 BYTE lock;
579 #include "poppack.h"
581 #define MAGIC_LOCAL_USED 0x5342
582 /* align the storage needed for the HLOCAL on an 8-byte boundary thus
583 * LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
584 * size = 8*k, where k=1,2,3,... allocs exactly the given size.
585 * The Minolta DiMAGE Image Viewer heavily relies on this, corrupting
586 * the output jpeg's > 1 MB if not */
587 #define HLOCAL_STORAGE (sizeof(HLOCAL) * 2)
589 static inline struct local_header *get_header( HLOCAL hmem )
591 return (struct local_header *)((char *)hmem - 2);
594 static inline HLOCAL get_handle( struct local_header *header )
596 return &header->ptr;
599 static inline BOOL is_pointer( HLOCAL hmem )
601 return !((ULONG_PTR)hmem & 2);
604 /***********************************************************************
605 * GlobalAlloc (kernelbase.@)
607 HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size )
609 /* mask out obsolete flags */
610 flags &= ~(GMEM_NOCOMPACT | GMEM_NOT_BANKED | GMEM_NOTIFY);
612 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
613 if (!(flags & GMEM_MOVEABLE) && !size) size = 1;
615 return LocalAlloc( flags, size );
619 /***********************************************************************
620 * GlobalFree (kernelbase.@)
622 HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL hmem )
624 return LocalFree( hmem );
628 /***********************************************************************
629 * LocalAlloc (kernelbase.@)
631 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
633 struct local_header *header;
634 DWORD heap_flags = 0;
635 void *ptr;
637 if (flags & LMEM_ZEROINIT) heap_flags = HEAP_ZERO_MEMORY;
639 if (!(flags & LMEM_MOVEABLE)) /* pointer */
641 ptr = HeapAlloc( GetProcessHeap(), heap_flags, size );
642 TRACE( "(flags=%04x) returning %p\n", flags, ptr );
643 return ptr;
646 if (size > INT_MAX - HLOCAL_STORAGE)
648 SetLastError( ERROR_OUTOFMEMORY );
649 return 0;
651 if (!(header = HeapAlloc( GetProcessHeap(), 0, sizeof(*header) ))) return 0;
653 header->magic = MAGIC_LOCAL_USED;
654 header->flags = flags >> 8;
655 header->lock = 0;
657 if (size)
659 if (!(ptr = HeapAlloc(GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
661 HeapFree( GetProcessHeap(), 0, header );
662 return 0;
664 *(HLOCAL *)ptr = get_handle( header );
665 header->ptr = (char *)ptr + HLOCAL_STORAGE;
667 else header->ptr = NULL;
669 TRACE( "(flags=%04x) returning handle %p pointer %p\n",
670 flags, get_handle( header ), header->ptr );
671 return get_handle( header );
675 /***********************************************************************
676 * LocalFree (kernelbase.@)
678 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL hmem )
680 struct local_header *header;
681 HLOCAL ret;
683 RtlLockHeap( GetProcessHeap() );
684 __TRY
686 ret = 0;
687 if (is_pointer(hmem)) /* POINTER */
689 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, hmem ))
691 SetLastError( ERROR_INVALID_HANDLE );
692 ret = hmem;
695 else /* HANDLE */
697 header = get_header( hmem );
698 if (header->magic == MAGIC_LOCAL_USED)
700 header->magic = 0xdead;
701 if (header->ptr)
703 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE,
704 (char *)header->ptr - HLOCAL_STORAGE ))
705 ret = hmem;
707 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, header )) ret = hmem;
709 else
711 WARN( "invalid handle %p (magic: 0x%04x)\n", hmem, header->magic );
712 SetLastError( ERROR_INVALID_HANDLE );
713 ret = hmem;
717 __EXCEPT_PAGE_FAULT
719 WARN( "invalid handle %p\n", hmem );
720 SetLastError( ERROR_INVALID_HANDLE );
721 ret = hmem;
723 __ENDTRY
724 RtlUnlockHeap( GetProcessHeap() );
725 return ret;
729 /***********************************************************************
730 * LocalLock (kernelbase.@)
732 LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL hmem )
734 void *ret = NULL;
736 if (is_pointer( hmem ))
738 __TRY
740 volatile char *p = hmem;
741 *p |= 0;
743 __EXCEPT_PAGE_FAULT
745 return NULL;
747 __ENDTRY
748 return hmem;
751 RtlLockHeap( GetProcessHeap() );
752 __TRY
754 struct local_header *header = get_header( hmem );
755 if (header->magic == MAGIC_LOCAL_USED)
757 ret = header->ptr;
758 if (!header->ptr) SetLastError( ERROR_DISCARDED );
759 else if (header->lock < LMEM_LOCKCOUNT) header->lock++;
761 else
763 WARN( "invalid handle %p (magic: 0x%04x)\n", hmem, header->magic );
764 SetLastError( ERROR_INVALID_HANDLE );
767 __EXCEPT_PAGE_FAULT
769 WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem);
770 SetLastError( ERROR_INVALID_HANDLE );
772 __ENDTRY
773 RtlUnlockHeap( GetProcessHeap() );
774 return ret;
778 /***********************************************************************
779 * LocalReAlloc (kernelbase.@)
781 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL hmem, SIZE_T size, UINT flags )
783 struct local_header *header;
784 void *ptr;
785 HLOCAL ret = 0;
786 DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
788 RtlLockHeap( GetProcessHeap() );
789 if (flags & LMEM_MODIFY) /* modify flags */
791 if (is_pointer( hmem ) && (flags & LMEM_MOVEABLE))
793 /* make a fixed block moveable
794 * actually only NT is able to do this. But it's soo simple
796 if (hmem == 0)
798 WARN( "null handle\n");
799 SetLastError( ERROR_NOACCESS );
801 else
803 size = RtlSizeHeap( GetProcessHeap(), 0, hmem );
804 ret = LocalAlloc( flags, size );
805 ptr = LocalLock( ret );
806 memcpy( ptr, hmem, size );
807 LocalUnlock( ret );
808 LocalFree( hmem );
811 else if (!is_pointer( hmem ) && (flags & LMEM_DISCARDABLE))
813 /* change the flags to make our block "discardable" */
814 header = get_header( hmem );
815 header->flags |= LMEM_DISCARDABLE >> 8;
816 ret = hmem;
818 else SetLastError( ERROR_INVALID_PARAMETER );
820 else
822 if (is_pointer( hmem ))
824 /* reallocate fixed memory */
825 if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
826 ret = HeapReAlloc( GetProcessHeap(), heap_flags, hmem, size );
828 else
830 /* reallocate a moveable block */
831 header = get_header( hmem );
832 if (size != 0)
834 if (size <= INT_MAX - HLOCAL_STORAGE)
836 if (header->ptr)
838 if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags,
839 (char *)header->ptr - HLOCAL_STORAGE,
840 size + HLOCAL_STORAGE )))
842 header->ptr = (char *)ptr + HLOCAL_STORAGE;
843 ret = hmem;
846 else
848 if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
850 *(HLOCAL *)ptr = hmem;
851 header->ptr = (char *)ptr + HLOCAL_STORAGE;
852 ret = hmem;
856 else SetLastError( ERROR_OUTOFMEMORY );
858 else
860 if (header->lock == 0)
862 if (header->ptr)
864 HeapFree( GetProcessHeap(), 0, (char *)header->ptr - HLOCAL_STORAGE );
865 header->ptr = NULL;
867 ret = hmem;
869 else WARN( "not freeing memory associated with locked handle\n" );
873 RtlUnlockHeap( GetProcessHeap() );
874 return ret;
878 /***********************************************************************
879 * LocalUnlock (kernelbase.@)
881 BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL hmem )
883 BOOL ret = FALSE;
885 if (is_pointer( hmem ))
887 SetLastError( ERROR_NOT_LOCKED );
888 return FALSE;
891 RtlLockHeap( GetProcessHeap() );
892 __TRY
894 struct local_header *header = get_header( hmem );
895 if (header->magic == MAGIC_LOCAL_USED)
897 if (header->lock)
899 header->lock--;
900 ret = (header->lock != 0);
901 if (!ret) SetLastError( NO_ERROR );
903 else
905 WARN( "%p not locked\n", hmem );
906 SetLastError( ERROR_NOT_LOCKED );
909 else
911 WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, header->magic );
912 SetLastError( ERROR_INVALID_HANDLE );
915 __EXCEPT_PAGE_FAULT
917 WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem);
918 SetLastError( ERROR_INVALID_PARAMETER );
920 __ENDTRY
921 RtlUnlockHeap( GetProcessHeap() );
922 return ret;
926 /***********************************************************************
927 * Memory resource functions
928 ***********************************************************************/
931 /***********************************************************************
932 * CreateMemoryResourceNotification (kernelbase.@)
934 HANDLE WINAPI DECLSPEC_HOTPATCH CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type )
936 HANDLE ret;
937 UNICODE_STRING nameW;
938 OBJECT_ATTRIBUTES attr;
940 switch (type)
942 case LowMemoryResourceNotification:
943 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\LowMemoryCondition" );
944 break;
945 case HighMemoryResourceNotification:
946 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\HighMemoryCondition" );
947 break;
948 default:
949 SetLastError( ERROR_INVALID_PARAMETER );
950 return 0;
953 InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL );
954 if (!set_ntstatus( NtOpenEvent( &ret, EVENT_ALL_ACCESS, &attr ))) return 0;
955 return ret;
958 /***********************************************************************
959 * QueryMemoryResourceNotification (kernelbase.@)
961 BOOL WINAPI DECLSPEC_HOTPATCH QueryMemoryResourceNotification( HANDLE handle, BOOL *state )
963 switch (WaitForSingleObject( handle, 0 ))
965 case WAIT_OBJECT_0:
966 *state = TRUE;
967 return TRUE;
968 case WAIT_TIMEOUT:
969 *state = FALSE;
970 return TRUE;
972 SetLastError( ERROR_INVALID_PARAMETER );
973 return FALSE;
977 /***********************************************************************
978 * Physical memory functions
979 ***********************************************************************/
982 /***********************************************************************
983 * AllocateUserPhysicalPages (kernelbase.@)
985 BOOL WINAPI DECLSPEC_HOTPATCH AllocateUserPhysicalPages( HANDLE process, ULONG_PTR *pages,
986 ULONG_PTR *userarray )
988 FIXME( "stub: %p %p %p\n", process, pages, userarray );
989 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
990 return FALSE;
994 /***********************************************************************
995 * FreeUserPhysicalPages (kernelbase.@)
997 BOOL WINAPI DECLSPEC_HOTPATCH FreeUserPhysicalPages( HANDLE process, ULONG_PTR *pages,
998 ULONG_PTR *userarray )
1000 FIXME( "stub: %p %p %p\n", process, pages, userarray );
1001 *pages = 0;
1002 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1003 return FALSE;
1007 /***********************************************************************
1008 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1010 BOOL WINAPI DECLSPEC_HOTPATCH GetPhysicallyInstalledSystemMemory( ULONGLONG *memory )
1012 MEMORYSTATUSEX status;
1014 if (!memory)
1016 SetLastError( ERROR_INVALID_PARAMETER );
1017 return FALSE;
1019 status.dwLength = sizeof(status);
1020 GlobalMemoryStatusEx( &status );
1021 *memory = status.ullTotalPhys / 1024;
1022 return TRUE;
1026 /***********************************************************************
1027 * GlobalMemoryStatusEx (kernelbase.@)
1029 BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status )
1031 static MEMORYSTATUSEX cached_status;
1032 static DWORD last_check;
1033 SYSTEM_BASIC_INFORMATION basic_info;
1034 SYSTEM_PERFORMANCE_INFORMATION perf_info;
1036 if (status->dwLength != sizeof(*status))
1038 SetLastError( ERROR_INVALID_PARAMETER );
1039 return FALSE;
1041 if ((NtGetTickCount() - last_check) < 1000)
1043 *status = cached_status;
1044 return TRUE;
1046 last_check = NtGetTickCount();
1048 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
1049 &basic_info, sizeof(basic_info), NULL )) ||
1050 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation,
1051 &perf_info, sizeof(perf_info), NULL)))
1052 return FALSE;
1054 status->dwMemoryLoad = 0;
1055 status->ullTotalPhys = perf_info.TotalCommitLimit;
1056 status->ullAvailPhys = perf_info.AvailablePages;
1057 status->ullTotalPageFile = perf_info.TotalCommitLimit + 1; /* Titan Quest refuses to run if TotalPageFile <= TotalPhys */
1058 status->ullAvailPageFile = status->ullTotalPageFile - perf_info.TotalCommittedPages;
1059 status->ullTotalVirtual = (ULONG_PTR)basic_info.HighestUserAddress - (ULONG_PTR)basic_info.LowestUserAddress;
1060 status->ullAvailVirtual = status->ullTotalVirtual - 64 * 1024; /* FIXME */
1061 status->ullAvailExtendedVirtual = 0;
1063 status->ullTotalPhys *= basic_info.PageSize;
1064 status->ullAvailPhys *= basic_info.PageSize;
1065 status->ullTotalPageFile *= basic_info.PageSize;
1066 status->ullAvailPageFile *= basic_info.PageSize;
1068 if (status->ullTotalPhys)
1069 status->dwMemoryLoad = (status->ullTotalPhys - status->ullAvailPhys) / (status->ullTotalPhys / 100);
1071 TRACE_(virtual)( "MemoryLoad %d, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1072 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1073 status->dwMemoryLoad, wine_dbgstr_longlong(status->ullTotalPhys),
1074 wine_dbgstr_longlong(status->ullAvailPhys), wine_dbgstr_longlong(status->ullTotalPageFile),
1075 wine_dbgstr_longlong(status->ullAvailPageFile), wine_dbgstr_longlong(status->ullTotalVirtual),
1076 wine_dbgstr_longlong(status->ullAvailVirtual) );
1078 cached_status = *status;
1079 return TRUE;
1083 /***********************************************************************
1084 * MapUserPhysicalPages (kernelbase.@)
1086 BOOL WINAPI DECLSPEC_HOTPATCH MapUserPhysicalPages( void *addr, ULONG_PTR page_count, ULONG_PTR *pages )
1088 FIXME( "stub: %p %lu %p\n", addr, page_count, pages );
1089 *pages = 0;
1090 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1091 return FALSE;
1095 /***********************************************************************
1096 * NUMA functions
1097 ***********************************************************************/
1100 /***********************************************************************
1101 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1103 BOOL WINAPI DECLSPEC_HOTPATCH AllocateUserPhysicalPagesNuma( HANDLE process, ULONG_PTR *pages,
1104 ULONG_PTR *userarray, DWORD node )
1106 if (node) FIXME( "Ignoring preferred node %u\n", node );
1107 return AllocateUserPhysicalPages( process, pages, userarray );
1111 /***********************************************************************
1112 * CreateFileMappingNumaW (kernelbase.@)
1114 HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileMappingNumaW( HANDLE file, LPSECURITY_ATTRIBUTES sa,
1115 DWORD protect, DWORD size_high, DWORD size_low,
1116 LPCWSTR name, DWORD node )
1118 if (node) FIXME( "Ignoring preferred node %u\n", node );
1119 return CreateFileMappingW( file, sa, protect, size_high, size_low, name );
1123 /***********************************************************************
1124 * GetLogicalProcessorInformation (kernelbase.@)
1126 BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buffer,
1127 DWORD *len )
1129 NTSTATUS status;
1131 if (!len)
1133 SetLastError( ERROR_INVALID_PARAMETER );
1134 return FALSE;
1136 status = NtQuerySystemInformation( SystemLogicalProcessorInformation, buffer, *len, len );
1137 if (status == STATUS_INFO_LENGTH_MISMATCH) status = STATUS_BUFFER_TOO_SMALL;
1138 return set_ntstatus( status );
1142 /***********************************************************************
1143 * GetLogicalProcessorInformationEx (kernelbase.@)
1145 BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship,
1146 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, DWORD *len )
1148 NTSTATUS status;
1150 if (!len)
1152 SetLastError( ERROR_INVALID_PARAMETER );
1153 return FALSE;
1155 status = NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx, &relationship,
1156 sizeof(relationship), buffer, *len, len );
1157 if (status == STATUS_INFO_LENGTH_MISMATCH) status = STATUS_BUFFER_TOO_SMALL;
1158 return set_ntstatus( status );
1162 /***********************************************************************
1163 * GetSystemCpuSetInformation (kernelbase.@)
1165 BOOL WINAPI GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION *info, ULONG buffer_length, ULONG *return_length,
1166 HANDLE process, ULONG flags)
1168 if (flags)
1169 FIXME("Unsupported flags %#x.\n", flags);
1171 *return_length = 0;
1173 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation, &process, sizeof(process), info,
1174 buffer_length, return_length ));
1178 /***********************************************************************
1179 * SetThreadSelectedCpuSets (kernelbase.@)
1181 BOOL WINAPI SetThreadSelectedCpuSets(HANDLE thread, const ULONG *cpu_set_ids, ULONG count)
1183 FIXME( "thread %p, cpu_set_ids %p, count %u stub.\n", thread, cpu_set_ids, count );
1185 return TRUE;
1189 /**********************************************************************
1190 * GetNumaHighestNodeNumber (kernelbase.@)
1192 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaHighestNodeNumber( ULONG *node )
1194 FIXME( "semi-stub: %p\n", node );
1195 *node = 0;
1196 return TRUE;
1200 /**********************************************************************
1201 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1203 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaNodeProcessorMaskEx( USHORT node, GROUP_AFFINITY *mask )
1205 FIXME( "stub: %hu %p\n", node, mask );
1206 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1207 return FALSE;
1211 /***********************************************************************
1212 * GetNumaProximityNodeEx (kernelbase.@)
1214 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaProximityNodeEx( ULONG proximity_id, USHORT *node )
1216 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1217 return FALSE;
1221 /***********************************************************************
1222 * MapViewOfFileExNuma (kernelbase.@)
1224 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileExNuma( HANDLE handle, DWORD access, DWORD offset_high,
1225 DWORD offset_low, SIZE_T count, LPVOID addr,
1226 DWORD node )
1228 if (node) FIXME( "Ignoring preferred node %u\n", node );
1229 return MapViewOfFileEx( handle, access, offset_high, offset_low, count, addr );
1233 /***********************************************************************
1234 * VirtualAllocExNuma (kernelbase.@)
1236 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocExNuma( HANDLE process, void *addr, SIZE_T size,
1237 DWORD type, DWORD protect, DWORD node )
1239 if (node) FIXME( "Ignoring preferred node %u\n", node );
1240 return VirtualAllocEx( process, addr, size, type, protect );
1244 /***********************************************************************
1245 * CPU functions
1246 ***********************************************************************/
1249 #if defined(__i386__) || defined(__x86_64__)
1250 /***********************************************************************
1251 * GetEnabledXStateFeatures (kernelbase.@)
1253 DWORD64 WINAPI GetEnabledXStateFeatures(void)
1255 TRACE( "\n" );
1256 return RtlGetEnabledExtendedFeatures( ~(ULONG64)0 );
1260 /***********************************************************************
1261 * InitializeContext2 (kernelbase.@)
1263 BOOL WINAPI InitializeContext2( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length,
1264 ULONG64 compaction_mask )
1266 ULONG orig_length;
1267 NTSTATUS status;
1269 TRACE( "buffer %p, context_flags %#x, context %p, ret_length %p, compaction_mask %s.\n",
1270 buffer, context_flags, context, length, wine_dbgstr_longlong(compaction_mask) );
1272 orig_length = *length;
1274 if ((status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask )))
1276 if (status == STATUS_NOT_SUPPORTED && context_flags & 0x40)
1278 context_flags &= ~0x40;
1279 status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask );
1282 if (status)
1283 return set_ntstatus( status );
1286 if (!buffer || orig_length < *length)
1288 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1289 return FALSE;
1292 if ((status = RtlInitializeExtendedContext2( buffer, context_flags, (CONTEXT_EX **)context, compaction_mask )))
1293 return set_ntstatus( status );
1295 *context = (CONTEXT *)((BYTE *)*context + (*(CONTEXT_EX **)context)->Legacy.Offset);
1297 return TRUE;
1300 /***********************************************************************
1301 * InitializeContext (kernelbase.@)
1303 BOOL WINAPI InitializeContext( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length )
1305 return InitializeContext2( buffer, context_flags, context, length, ~(ULONG64)0 );
1308 /***********************************************************************
1309 * CopyContext (kernelbase.@)
1311 BOOL WINAPI CopyContext( CONTEXT *dst, DWORD context_flags, CONTEXT *src )
1313 DWORD context_size, arch_flag, flags_offset, dst_flags, src_flags;
1314 static const DWORD arch_mask = 0x110000;
1315 NTSTATUS status;
1316 BYTE *d, *s;
1318 TRACE("dst %p, context_flags %#x, src %p.\n", dst, context_flags, src);
1320 if (context_flags & 0x40 && !RtlGetEnabledExtendedFeatures( ~(ULONG64)0 ))
1322 SetLastError(ERROR_NOT_SUPPORTED);
1323 return FALSE;
1326 arch_flag = context_flags & arch_mask;
1328 switch (arch_flag)
1330 case 0x10000: context_size = 0x2cc; flags_offset = 0; break;
1331 case 0x100000: context_size = 0x4d0; flags_offset = 0x30; break;
1332 default:
1333 SetLastError( ERROR_INVALID_PARAMETER );
1334 return FALSE;
1337 d = (BYTE *)dst;
1338 s = (BYTE *)src;
1339 dst_flags = *(DWORD *)(d + flags_offset);
1340 src_flags = *(DWORD *)(s + flags_offset);
1342 if ((dst_flags & arch_mask) != arch_flag
1343 || (src_flags & arch_mask) != arch_flag)
1345 SetLastError( ERROR_INVALID_PARAMETER );
1346 return FALSE;
1349 context_flags &= src_flags;
1351 if (context_flags & ~dst_flags & 0x40)
1353 SetLastError(ERROR_MORE_DATA);
1354 return FALSE;
1357 if ((status = RtlCopyExtendedContext( (CONTEXT_EX *)(d + context_size), context_flags,
1358 (CONTEXT_EX *)(s + context_size) )))
1359 return set_ntstatus( status );
1361 return TRUE;
1363 #endif
1366 #if defined(__x86_64__)
1367 /***********************************************************************
1368 * LocateXStateFeature (kernelbase.@)
1370 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
1372 if (!(context->ContextFlags & CONTEXT_AMD64))
1373 return NULL;
1375 if (feature_id >= 2)
1376 return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1377 ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
1379 if (feature_id == 1)
1381 if (length)
1382 *length = sizeof(M128A) * 16;
1384 return &context->u.FltSave.XmmRegisters;
1387 if (length)
1388 *length = offsetof(XSAVE_FORMAT, XmmRegisters);
1390 return &context->u.FltSave;
1393 /***********************************************************************
1394 * SetXStateFeaturesMask (kernelbase.@)
1396 BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
1398 if (!(context->ContextFlags & CONTEXT_AMD64))
1399 return FALSE;
1401 if (feature_mask & 0x3)
1402 context->ContextFlags |= CONTEXT_FLOATING_POINT;
1404 if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
1405 return !(feature_mask & ~(DWORD64)3);
1407 RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
1408 return TRUE;
1411 /***********************************************************************
1412 * GetXStateFeaturesMask (kernelbase.@)
1414 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1416 if (!(context->ContextFlags & CONTEXT_AMD64))
1417 return FALSE;
1419 *feature_mask = (context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT
1420 ? 3 : 0;
1422 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1423 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1425 return TRUE;
1427 #elif defined(__i386__)
1428 /***********************************************************************
1429 * LocateXStateFeature (kernelbase.@)
1431 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
1433 if (!(context->ContextFlags & CONTEXT_X86))
1434 return NULL;
1436 if (feature_id >= 2)
1437 return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1438 ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
1440 if (feature_id == 1)
1442 if (length)
1443 *length = sizeof(M128A) * 8;
1445 return (BYTE *)&context->ExtendedRegisters + offsetof(XSAVE_FORMAT, XmmRegisters);
1448 if (length)
1449 *length = offsetof(XSAVE_FORMAT, XmmRegisters);
1451 return &context->ExtendedRegisters;
1454 /***********************************************************************
1455 * SetXStateFeaturesMask (kernelbase.@)
1457 BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
1459 if (!(context->ContextFlags & CONTEXT_X86))
1460 return FALSE;
1462 if (feature_mask & 0x3)
1463 context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
1465 if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
1466 return !(feature_mask & ~(DWORD64)3);
1468 RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
1469 return TRUE;
1472 /***********************************************************************
1473 * GetXStateFeaturesMask (kernelbase.@)
1475 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1477 if (!(context->ContextFlags & CONTEXT_X86))
1478 return FALSE;
1480 *feature_mask = (context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS
1481 ? 3 : 0;
1483 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1484 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1486 return TRUE;
1488 #endif
1490 /***********************************************************************
1491 * Firmware functions
1492 ***********************************************************************/
1495 /***********************************************************************
1496 * EnumSystemFirmwareTable (kernelbase.@)
1498 UINT WINAPI EnumSystemFirmwareTables( DWORD provider, void *buffer, DWORD size )
1500 FIXME( "(0x%08x, %p, %d)\n", provider, buffer, size );
1501 return 0;
1505 /***********************************************************************
1506 * GetSystemFirmwareTable (kernelbase.@)
1508 UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWORD size )
1510 SYSTEM_FIRMWARE_TABLE_INFORMATION *info;
1511 ULONG buffer_size = offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer ) + size;
1513 TRACE( "(0x%08x, 0x%08x, %p, %d)\n", provider, id, buffer, size );
1515 if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, buffer_size )))
1517 SetLastError( ERROR_OUTOFMEMORY );
1518 return 0;
1521 info->ProviderSignature = provider;
1522 info->Action = SystemFirmwareTable_Get;
1523 info->TableID = id;
1525 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation,
1526 info, buffer_size, &buffer_size ));
1527 buffer_size -= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer );
1528 if (buffer_size <= size) memcpy( buffer, info->TableBuffer, buffer_size );
1530 HeapFree( GetProcessHeap(), 0, info );
1531 return buffer_size;