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