kernelbase: Implement internal KernelBaseGetGlobalData.
[wine.git] / dlls / kernelbase / memory.c
blob6d42316760b9bfe4370689c75896c855bd34a06f
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);
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;
80 GetSystemInfo( si );
81 RtlWow64GetProcessMachines( GetCurrentProcess(), &current_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;
88 break;
89 case IMAGE_FILE_MACHINE_ARM64:
90 si->u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64;
91 si->dwProcessorType = 0;
92 break;
93 default:
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 )))
111 return;
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;
131 case 5:
132 case 6: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
133 default: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
135 break;
136 case PROCESSOR_ARCHITECTURE_PPC:
137 switch (cpu_info.ProcessorLevel)
139 case 1: si->dwProcessorType = PROCESSOR_PPC_601; break;
140 case 3:
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;
147 break;
148 case PROCESSOR_ARCHITECTURE_AMD64:
149 si->dwProcessorType = PROCESSOR_AMD_X8664;
150 break;
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;
157 break;
158 case PROCESSOR_ARCHITECTURE_ARM64:
159 si->dwProcessorType = 0;
160 break;
161 default:
162 FIXME( "Unknown processor architecture %x\n", cpu_info.ProcessorArchitecture );
163 si->dwProcessorType = 0;
164 break;
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 );
176 return FALSE;
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 )))
188 return ~0u;
189 return 0;
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 )
209 NTSTATUS status;
210 LARGE_INTEGER offset;
211 ULONG protect;
212 BOOL exec;
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) );
232 addr = NULL;
234 return addr;
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 )))
254 return ~0u;
255 return 0;
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 );
266 return FALSE;
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 );
281 return FALSE;
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 )
303 LPVOID ret = addr;
305 if (!set_ntstatus( NtAllocateVirtualMemory( process, &ret, 0, &size, type, protect ))) return NULL;
306 return ret;
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 )
317 LPVOID ret = addr;
319 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process, &ret, &size, type, protect, parameters, count )))
320 return NULL;
321 return ret;
325 /***********************************************************************
326 * VirtualAllocFromApp (kernelbase.@)
328 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocFromApp( void *addr, SIZE_T size,
329 DWORD type, DWORD protect )
331 LPVOID ret = addr;
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 );
339 return NULL;
342 if (!set_ntstatus( NtAllocateVirtualMemory( GetCurrentProcess(), &ret, 0, &size, type, protect ))) return NULL;
343 return ret;
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 );
354 return TRUE;
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 )
400 DWORD 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 )
423 SIZE_T ret;
425 if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
426 return 0;
427 return 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;
454 __TRY
456 volatile const char *p = str;
457 while (p != str + max) if (!*p++) break;
459 __EXCEPT_PAGE_FAULT
461 return TRUE;
463 __ENDTRY
464 return FALSE;
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;
472 __TRY
474 volatile const WCHAR *p = str;
475 while (p != str + max) if (!*p++) break;
477 __EXCEPT_PAGE_FAULT
479 return TRUE;
481 __ENDTRY
482 return FALSE;
486 /***********************************************************************
487 * Heap functions
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 );
507 return ret;
511 /***********************************************************************
512 * HeapDestroy (kernelbase.@)
514 BOOL WINAPI DECLSPEC_HOTPATCH HeapDestroy( HANDLE heap )
516 if (!RtlDestroyHeap( heap )) return TRUE;
517 SetLastError( ERROR_INVALID_HANDLE );
518 return FALSE;
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"
590 struct mem_entry
592 WORD magic;
593 void *ptr;
594 BYTE flags;
595 BYTE lock;
598 #include "poppack.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;
615 return mem;
618 static inline HLOCAL HLOCAL_from_mem( struct mem_entry *mem )
620 return &mem->ptr;
623 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle )
625 if ((ULONG_PTR)handle & 2) return NULL;
626 return handle;
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;
671 void *ptr;
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 );
681 return ptr;
684 if (size > INT_MAX - HLOCAL_STORAGE)
686 SetLastError( ERROR_OUTOFMEMORY );
687 return 0;
689 if (!(mem = HeapAlloc( GetProcessHeap(), 0, sizeof(*mem) ))) return 0;
691 mem->magic = MAGIC_LOCAL_USED;
692 mem->flags = flags >> 8;
693 mem->lock = 0;
695 if (size)
697 if (!(ptr = HeapAlloc(GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
699 HeapFree( GetProcessHeap(), 0, mem );
700 return 0;
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;
718 HLOCAL ret;
719 void *ptr;
721 TRACE_(globalmem)( "handle %p\n", handle );
723 RtlLockHeap( GetProcessHeap() );
724 __TRY
726 ret = 0;
727 if ((ptr = unsafe_ptr_from_HLOCAL( handle )))
729 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, ptr ))
731 SetLastError( ERROR_INVALID_HANDLE );
732 ret = handle;
735 else /* HANDLE */
737 if ((mem = unsafe_mem_from_HLOCAL( handle )))
739 mem->magic = 0xdead;
740 if (mem->ptr)
742 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, (char *)mem->ptr - HLOCAL_STORAGE ))
743 ret = handle;
745 if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, mem )) ret = handle;
747 else
749 WARN_(globalmem)( "invalid handle %p\n", handle );
750 SetLastError( ERROR_INVALID_HANDLE );
751 ret = handle;
755 __EXCEPT_PAGE_FAULT
757 WARN_(globalmem)( "invalid handle %p\n", handle );
758 SetLastError( ERROR_INVALID_HANDLE );
759 ret = handle;
761 __ENDTRY
762 RtlUnlockHeap( GetProcessHeap() );
763 return ret;
767 /***********************************************************************
768 * LocalLock (kernelbase.@)
770 LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
772 struct mem_entry *mem;
773 void *ret = NULL;
775 TRACE_(globalmem)( "handle %p\n", handle );
777 if ((ret = unsafe_ptr_from_HLOCAL( handle )))
779 __TRY
781 volatile char *p = ret;
782 *p |= 0;
784 __EXCEPT_PAGE_FAULT
786 return NULL;
788 __ENDTRY
789 return ret;
792 RtlLockHeap( GetProcessHeap() );
793 __TRY
795 if ((mem = unsafe_mem_from_HLOCAL( handle )))
797 ret = mem->ptr;
798 if (!mem->ptr) SetLastError( ERROR_DISCARDED );
799 else if (mem->lock < LMEM_LOCKCOUNT) mem->lock++;
801 else
803 WARN_(globalmem)( "invalid handle %p\n", handle );
804 SetLastError( ERROR_INVALID_HANDLE );
807 __EXCEPT_PAGE_FAULT
809 WARN_(globalmem)( "(%p): Page fault occurred ! Caused by bug ?\n", handle );
810 SetLastError( ERROR_INVALID_HANDLE );
812 __ENDTRY
813 RtlUnlockHeap( GetProcessHeap() );
814 return ret;
818 /***********************************************************************
819 * LocalReAlloc (kernelbase.@)
821 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags )
823 struct mem_entry *mem;
824 HLOCAL ret = 0;
825 DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
826 void *ptr;
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
838 if (handle == 0)
840 WARN_(globalmem)( "null handle\n" );
841 SetLastError( ERROR_NOACCESS );
843 else
845 size = RtlSizeHeap( GetProcessHeap(), 0, handle );
846 ret = LocalAlloc( flags, size );
847 ptr = LocalLock( ret );
848 memcpy( ptr, handle, size );
849 LocalUnlock( ret );
850 LocalFree( handle );
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;
857 ret = handle;
859 else SetLastError( ERROR_INVALID_PARAMETER );
861 else
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 */
872 if (size != 0)
874 if (size <= INT_MAX - HLOCAL_STORAGE)
876 if (mem->ptr)
878 if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)mem->ptr - HLOCAL_STORAGE,
879 size + HLOCAL_STORAGE )))
881 mem->ptr = (char *)ptr + HLOCAL_STORAGE;
882 ret = handle;
885 else
887 if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
889 *(HLOCAL *)ptr = handle;
890 mem->ptr = (char *)ptr + HLOCAL_STORAGE;
891 ret = handle;
895 else SetLastError( ERROR_OUTOFMEMORY );
897 else
899 if (mem->lock == 0)
901 if (mem->ptr)
903 HeapFree( GetProcessHeap(), 0, (char *)mem->ptr - HLOCAL_STORAGE );
904 mem->ptr = NULL;
906 ret = handle;
908 else WARN_(globalmem)( "not freeing memory associated with locked handle\n" );
911 else SetLastError( ERROR_INVALID_HANDLE );
913 RtlUnlockHeap( GetProcessHeap() );
914 return ret;
918 /***********************************************************************
919 * LocalUnlock (kernelbase.@)
921 BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL handle )
923 struct mem_entry *mem;
924 BOOL ret = FALSE;
926 TRACE_(globalmem)( "handle %p\n", handle );
928 if (unsafe_ptr_from_HLOCAL( handle ))
930 SetLastError( ERROR_NOT_LOCKED );
931 return FALSE;
934 RtlLockHeap( GetProcessHeap() );
935 __TRY
937 if ((mem = unsafe_mem_from_HLOCAL( handle )))
939 if (mem->lock)
941 mem->lock--;
942 ret = (mem->lock != 0);
943 if (!ret) SetLastError( NO_ERROR );
945 else
947 WARN_(globalmem)( "%p not locked\n", handle );
948 SetLastError( ERROR_NOT_LOCKED );
951 else
953 WARN_(globalmem)( "invalid handle %p\n", handle );
954 SetLastError( ERROR_INVALID_HANDLE );
957 __EXCEPT_PAGE_FAULT
959 WARN_(globalmem)( "(%p): Page fault occurred ! Caused by bug ?\n", handle );
960 SetLastError( ERROR_INVALID_PARAMETER );
962 __ENDTRY
963 RtlUnlockHeap( GetProcessHeap() );
964 return ret;
968 /***********************************************************************
969 * Memory resource functions
970 ***********************************************************************/
973 /***********************************************************************
974 * CreateMemoryResourceNotification (kernelbase.@)
976 HANDLE WINAPI DECLSPEC_HOTPATCH CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type )
978 HANDLE ret;
979 UNICODE_STRING nameW;
980 OBJECT_ATTRIBUTES attr;
982 switch (type)
984 case LowMemoryResourceNotification:
985 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\LowMemoryCondition" );
986 break;
987 case HighMemoryResourceNotification:
988 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\HighMemoryCondition" );
989 break;
990 default:
991 SetLastError( ERROR_INVALID_PARAMETER );
992 return 0;
995 InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL );
996 if (!set_ntstatus( NtOpenEvent( &ret, EVENT_ALL_ACCESS, &attr ))) return 0;
997 return ret;
1000 /***********************************************************************
1001 * QueryMemoryResourceNotification (kernelbase.@)
1003 BOOL WINAPI DECLSPEC_HOTPATCH QueryMemoryResourceNotification( HANDLE handle, BOOL *state )
1005 switch (WaitForSingleObject( handle, 0 ))
1007 case WAIT_OBJECT_0:
1008 *state = TRUE;
1009 return TRUE;
1010 case WAIT_TIMEOUT:
1011 *state = FALSE;
1012 return TRUE;
1014 SetLastError( ERROR_INVALID_PARAMETER );
1015 return FALSE;
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 );
1032 return FALSE;
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 );
1043 *pages = 0;
1044 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1045 return FALSE;
1049 /***********************************************************************
1050 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1052 BOOL WINAPI DECLSPEC_HOTPATCH GetPhysicallyInstalledSystemMemory( ULONGLONG *memory )
1054 MEMORYSTATUSEX status;
1056 if (!memory)
1058 SetLastError( ERROR_INVALID_PARAMETER );
1059 return FALSE;
1061 status.dwLength = sizeof(status);
1062 GlobalMemoryStatusEx( &status );
1063 *memory = status.ullTotalPhys / 1024;
1064 return TRUE;
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;
1077 VM_COUNTERS_EX vmc;
1079 if (status->dwLength != sizeof(*status))
1081 SetLastError( ERROR_INVALID_PARAMETER );
1082 return FALSE;
1084 if ((NtGetTickCount() - last_check) < 1000)
1086 *status = cached_status;
1087 return TRUE;
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 )))
1097 return FALSE;
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;
1124 return TRUE;
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 );
1134 *pages = 0;
1135 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1136 return FALSE;
1140 /***********************************************************************
1141 * NUMA functions
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,
1172 DWORD *len )
1174 NTSTATUS status;
1176 if (!len)
1178 SetLastError( ERROR_INVALID_PARAMETER );
1179 return FALSE;
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 )
1193 NTSTATUS status;
1195 if (!len)
1197 SetLastError( ERROR_INVALID_PARAMETER );
1198 return FALSE;
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)
1213 if (flags)
1214 FIXME("Unsupported flags %#lx.\n", flags);
1216 *return_length = 0;
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 );
1230 return TRUE;
1234 /**********************************************************************
1235 * GetNumaHighestNodeNumber (kernelbase.@)
1237 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaHighestNodeNumber( ULONG *node )
1239 FIXME( "semi-stub: %p\n", node );
1240 *node = 0;
1241 return TRUE;
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 );
1252 return FALSE;
1256 /***********************************************************************
1257 * GetNumaProximityNodeEx (kernelbase.@)
1259 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaProximityNodeEx( ULONG proximity_id, USHORT *node )
1261 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1262 return FALSE;
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,
1271 DWORD node )
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 /***********************************************************************
1290 * CPU functions
1291 ***********************************************************************/
1294 #if defined(__i386__) || defined(__x86_64__)
1295 /***********************************************************************
1296 * GetEnabledXStateFeatures (kernelbase.@)
1298 DWORD64 WINAPI GetEnabledXStateFeatures(void)
1300 TRACE( "\n" );
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 )
1311 ULONG orig_length;
1312 NTSTATUS status;
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 );
1327 if (status)
1328 return set_ntstatus( status );
1331 if (!buffer || orig_length < *length)
1333 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1334 return FALSE;
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);
1342 return TRUE;
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 ));
1360 #endif
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))
1370 return NULL;
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)
1378 if (length)
1379 *length = sizeof(M128A) * 16;
1381 return &context->u.FltSave.XmmRegisters;
1384 if (length)
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))
1396 return FALSE;
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 );
1405 return TRUE;
1408 /***********************************************************************
1409 * GetXStateFeaturesMask (kernelbase.@)
1411 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1413 if (!(context->ContextFlags & CONTEXT_AMD64))
1414 return FALSE;
1416 *feature_mask = (context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT
1417 ? 3 : 0;
1419 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1420 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1422 return TRUE;
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))
1431 return NULL;
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)
1439 if (length)
1440 *length = sizeof(M128A) * 8;
1442 return (BYTE *)&context->ExtendedRegisters + offsetof(XSAVE_FORMAT, XmmRegisters);
1445 if (length)
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))
1457 return FALSE;
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 );
1466 return TRUE;
1469 /***********************************************************************
1470 * GetXStateFeaturesMask (kernelbase.@)
1472 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1474 if (!(context->ContextFlags & CONTEXT_i386))
1475 return FALSE;
1477 *feature_mask = (context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS
1478 ? 3 : 0;
1480 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1481 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1483 return TRUE;
1485 #endif
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 );
1498 return 0;
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 );
1515 return 0;
1518 info->ProviderSignature = provider;
1519 info->Action = SystemFirmwareTable_Get;
1520 info->TableID = id;
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 );
1528 return buffer_size;