kernelbase: Only discard HLOCAL with LMEM_MOVEABLE and if not locked.
[wine.git] / dlls / kernelbase / memory.c
blobdf7c07c270010c00f98361481e43fb9e6254ae54
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 BOOLEAN WINAPI RtlSetUserValueHeap( HANDLE handle, ULONG flags, void *ptr, void *user_value );
50 /***********************************************************************
51 * Virtual memory functions
52 ***********************************************************************/
55 /***********************************************************************
56 * FlushViewOfFile (kernelbase.@)
58 BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size )
60 NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
62 if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
63 return set_ntstatus( status );
67 /***********************************************************************
68 * GetLargePageMinimum (kernelbase.@)
70 SIZE_T WINAPI GetLargePageMinimum(void)
72 return 2 * 1024 * 1024;
76 /***********************************************************************
77 * GetNativeSystemInfo (kernelbase.@)
79 void WINAPI DECLSPEC_HOTPATCH GetNativeSystemInfo( SYSTEM_INFO *si )
81 USHORT current_machine, native_machine;
83 GetSystemInfo( si );
84 RtlWow64GetProcessMachines( GetCurrentProcess(), &current_machine, &native_machine );
85 if (!current_machine) return;
86 switch (native_machine)
88 case IMAGE_FILE_MACHINE_AMD64:
89 si->u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
90 si->dwProcessorType = PROCESSOR_AMD_X8664;
91 break;
92 case IMAGE_FILE_MACHINE_ARM64:
93 si->u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64;
94 si->dwProcessorType = 0;
95 break;
96 default:
97 FIXME( "Add the proper information for %x in wow64 mode\n", native_machine );
102 /***********************************************************************
103 * GetSystemInfo (kernelbase.@)
105 void WINAPI DECLSPEC_HOTPATCH GetSystemInfo( SYSTEM_INFO *si )
107 SYSTEM_BASIC_INFORMATION basic_info;
108 SYSTEM_CPU_INFORMATION cpu_info;
110 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
111 &basic_info, sizeof(basic_info), NULL )) ||
112 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation,
113 &cpu_info, sizeof(cpu_info), NULL )))
114 return;
116 si->u.s.wProcessorArchitecture = cpu_info.ProcessorArchitecture;
117 si->u.s.wReserved = 0;
118 si->dwPageSize = basic_info.PageSize;
119 si->lpMinimumApplicationAddress = basic_info.LowestUserAddress;
120 si->lpMaximumApplicationAddress = basic_info.HighestUserAddress;
121 si->dwActiveProcessorMask = basic_info.ActiveProcessorsAffinityMask;
122 si->dwNumberOfProcessors = basic_info.NumberOfProcessors;
123 si->dwAllocationGranularity = basic_info.AllocationGranularity;
124 si->wProcessorLevel = cpu_info.ProcessorLevel;
125 si->wProcessorRevision = cpu_info.ProcessorRevision;
127 switch (cpu_info.ProcessorArchitecture)
129 case PROCESSOR_ARCHITECTURE_INTEL:
130 switch (cpu_info.ProcessorLevel)
132 case 3: si->dwProcessorType = PROCESSOR_INTEL_386; break;
133 case 4: si->dwProcessorType = PROCESSOR_INTEL_486; break;
134 case 5:
135 case 6: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
136 default: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
138 break;
139 case PROCESSOR_ARCHITECTURE_PPC:
140 switch (cpu_info.ProcessorLevel)
142 case 1: si->dwProcessorType = PROCESSOR_PPC_601; break;
143 case 3:
144 case 6: si->dwProcessorType = PROCESSOR_PPC_603; break;
145 case 4: si->dwProcessorType = PROCESSOR_PPC_604; break;
146 case 9: si->dwProcessorType = PROCESSOR_PPC_604; break;
147 case 20: si->dwProcessorType = PROCESSOR_PPC_620; break;
148 default: si->dwProcessorType = 0;
150 break;
151 case PROCESSOR_ARCHITECTURE_AMD64:
152 si->dwProcessorType = PROCESSOR_AMD_X8664;
153 break;
154 case PROCESSOR_ARCHITECTURE_ARM:
155 switch (cpu_info.ProcessorLevel)
157 case 4: si->dwProcessorType = PROCESSOR_ARM_7TDMI; break;
158 default: si->dwProcessorType = PROCESSOR_ARM920;
160 break;
161 case PROCESSOR_ARCHITECTURE_ARM64:
162 si->dwProcessorType = 0;
163 break;
164 default:
165 FIXME( "Unknown processor architecture %x\n", cpu_info.ProcessorArchitecture );
166 si->dwProcessorType = 0;
167 break;
172 /***********************************************************************
173 * GetSystemFileCacheSize (kernelbase.@)
175 BOOL WINAPI DECLSPEC_HOTPATCH GetSystemFileCacheSize( SIZE_T *mincache, SIZE_T *maxcache, DWORD *flags )
177 FIXME( "stub: %p %p %p\n", mincache, maxcache, flags );
178 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
179 return FALSE;
183 /***********************************************************************
184 * GetWriteWatch (kernelbase.@)
186 UINT WINAPI DECLSPEC_HOTPATCH GetWriteWatch( DWORD flags, void *base, SIZE_T size, void **addresses,
187 ULONG_PTR *count, ULONG *granularity )
189 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags, base, size,
190 addresses, count, granularity )))
191 return ~0u;
192 return 0;
196 /***********************************************************************
197 * MapViewOfFile (kernelbase.@)
199 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile( HANDLE mapping, DWORD access, DWORD offset_high,
200 DWORD offset_low, SIZE_T count )
202 return MapViewOfFileEx( mapping, access, offset_high, offset_low, count, NULL );
206 /***********************************************************************
207 * MapViewOfFileEx (kernelbase.@)
209 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileEx( HANDLE handle, DWORD access, DWORD offset_high,
210 DWORD offset_low, SIZE_T count, LPVOID addr )
212 NTSTATUS status;
213 LARGE_INTEGER offset;
214 ULONG protect;
215 BOOL exec;
217 offset.u.LowPart = offset_low;
218 offset.u.HighPart = offset_high;
220 exec = access & FILE_MAP_EXECUTE;
221 access &= ~FILE_MAP_EXECUTE;
223 if (access == FILE_MAP_COPY)
224 protect = exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY;
225 else if (access & FILE_MAP_WRITE)
226 protect = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
227 else if (access & FILE_MAP_READ)
228 protect = exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
229 else protect = PAGE_NOACCESS;
231 if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
232 &count, ViewShare, 0, protect )) < 0)
234 SetLastError( RtlNtStatusToDosError(status) );
235 addr = NULL;
237 return addr;
241 /***********************************************************************
242 * MapViewOfFileFromApp (kernelbase.@)
244 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileFromApp( HANDLE handle, ULONG access, ULONG64 offset, SIZE_T size )
246 return MapViewOfFile( handle, access, offset << 32, offset, size );
249 /***********************************************************************
250 * MapViewOfFile3 (kernelbase.@)
252 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile3( HANDLE handle, HANDLE process, PVOID baseaddr, ULONG64 offset,
253 SIZE_T size, ULONG alloc_type, ULONG protection, MEM_EXTENDED_PARAMETER *params, ULONG params_count )
255 LARGE_INTEGER off;
256 void *addr;
258 addr = baseaddr;
259 off.QuadPart = offset;
260 if (!set_ntstatus( NtMapViewOfSectionEx( handle, process, &addr, &off, &size, alloc_type, protection,
261 params, params_count )))
263 return NULL;
265 return addr;
268 /***********************************************************************
269 * ReadProcessMemory (kernelbase.@)
271 BOOL WINAPI DECLSPEC_HOTPATCH ReadProcessMemory( HANDLE process, const void *addr, void *buffer,
272 SIZE_T size, SIZE_T *bytes_read )
274 return set_ntstatus( NtReadVirtualMemory( process, addr, buffer, size, bytes_read ));
278 /***********************************************************************
279 * ResetWriteWatch (kernelbase.@)
281 UINT WINAPI DECLSPEC_HOTPATCH ResetWriteWatch( void *base, SIZE_T size )
283 if (!set_ntstatus( NtResetWriteWatch( GetCurrentProcess(), base, size )))
284 return ~0u;
285 return 0;
289 /***********************************************************************
290 * SetSystemFileCacheSize (kernelbase.@)
292 BOOL WINAPI DECLSPEC_HOTPATCH SetSystemFileCacheSize( SIZE_T mincache, SIZE_T maxcache, DWORD flags )
294 FIXME( "stub: %Id %Id %ld\n", mincache, maxcache, flags );
295 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
296 return FALSE;
300 /***********************************************************************
301 * UnmapViewOfFile (kernelbase.@)
303 BOOL WINAPI DECLSPEC_HOTPATCH UnmapViewOfFile( const void *addr )
305 if (GetVersion() & 0x80000000)
307 MEMORY_BASIC_INFORMATION info;
308 if (!VirtualQuery( addr, &info, sizeof(info) ) || info.AllocationBase != addr)
310 SetLastError( ERROR_INVALID_ADDRESS );
311 return FALSE;
314 return set_ntstatus( NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr ));
318 /***********************************************************************
319 * UnmapViewOfFile2 (kernelbase.@)
321 BOOL WINAPI DECLSPEC_HOTPATCH UnmapViewOfFile2( HANDLE process, void *addr, ULONG flags )
323 return set_ntstatus( NtUnmapViewOfSectionEx( process, addr, flags ));
327 /***********************************************************************
328 * UnmapViewOfFileEx (kernelbase.@)
330 BOOL WINAPI DECLSPEC_HOTPATCH UnmapViewOfFileEx( void *addr, ULONG flags )
332 return set_ntstatus( NtUnmapViewOfSectionEx( GetCurrentProcess(), addr, flags ));
336 /***********************************************************************
337 * VirtualAlloc (kernelbase.@)
339 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc( void *addr, SIZE_T size, DWORD type, DWORD protect )
341 return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
345 /***********************************************************************
346 * VirtualAllocEx (kernelbase.@)
348 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocEx( HANDLE process, void *addr, SIZE_T size,
349 DWORD type, DWORD protect )
351 LPVOID ret = addr;
353 if (!set_ntstatus( NtAllocateVirtualMemory( process, &ret, 0, &size, type, protect ))) return NULL;
354 return ret;
358 /***********************************************************************
359 * VirtualAlloc2 (kernelbase.@)
361 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc2( HANDLE process, void *addr, SIZE_T size,
362 DWORD type, DWORD protect,
363 MEM_EXTENDED_PARAMETER *parameters, ULONG count )
365 LPVOID ret = addr;
367 if (!process) process = GetCurrentProcess();
368 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process, &ret, &size, type, protect, parameters, count )))
369 return NULL;
370 return ret;
373 static BOOL is_exec_prot( DWORD protect )
375 return protect == PAGE_EXECUTE || protect == PAGE_EXECUTE_READ || protect == PAGE_EXECUTE_READWRITE
376 || protect == PAGE_EXECUTE_WRITECOPY;
379 /***********************************************************************
380 * VirtualAlloc2FromApp (kernelbase.@)
382 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc2FromApp( HANDLE process, void *addr, SIZE_T size,
383 DWORD type, DWORD protect, MEM_EXTENDED_PARAMETER *parameters, ULONG count )
385 LPVOID ret = addr;
387 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx, params %p, count %lu.\n", addr, (void *)size, type, protect,
388 parameters, count );
390 if (is_exec_prot( protect ))
392 SetLastError( ERROR_INVALID_PARAMETER );
393 return NULL;
396 if (!process) process = GetCurrentProcess();
397 if (!set_ntstatus( NtAllocateVirtualMemoryEx( process, &ret, &size, type, protect, parameters, count )))
398 return NULL;
399 return ret;
403 /***********************************************************************
404 * VirtualAllocFromApp (kernelbase.@)
406 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocFromApp( void *addr, SIZE_T size,
407 DWORD type, DWORD protect )
409 LPVOID ret = addr;
411 TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx.\n", addr, (void *)size, type, protect );
413 if (is_exec_prot( protect ))
415 SetLastError( ERROR_INVALID_PARAMETER );
416 return NULL;
419 if (!set_ntstatus( NtAllocateVirtualMemory( GetCurrentProcess(), &ret, 0, &size, type, protect ))) return NULL;
420 return ret;
424 /***********************************************************************
425 * PrefetchVirtualMemory (kernelbase.@)
427 BOOL WINAPI DECLSPEC_HOTPATCH PrefetchVirtualMemory( HANDLE process, ULONG_PTR count,
428 WIN32_MEMORY_RANGE_ENTRY *addresses, ULONG flags )
430 return set_ntstatus( NtSetInformationVirtualMemory( process, VmPrefetchInformation,
431 count, (PMEMORY_RANGE_ENTRY)addresses,
432 &flags, sizeof(flags) ));
436 /***********************************************************************
437 * VirtualFree (kernelbase.@)
439 BOOL WINAPI DECLSPEC_HOTPATCH VirtualFree( void *addr, SIZE_T size, DWORD type )
441 return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
445 /***********************************************************************
446 * VirtualFreeEx (kernelbase.@)
448 BOOL WINAPI DECLSPEC_HOTPATCH VirtualFreeEx( HANDLE process, void *addr, SIZE_T size, DWORD type )
450 return set_ntstatus( NtFreeVirtualMemory( process, &addr, &size, type ));
454 /***********************************************************************
455 * VirtualLock (kernelbase.@)
457 BOOL WINAPI DECLSPEC_HOTPATCH VirtualLock( void *addr, SIZE_T size )
459 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 ));
463 /***********************************************************************
464 * VirtualProtect (kernelbase.@)
466 BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtect( void *addr, SIZE_T size, DWORD new_prot, DWORD *old_prot )
468 return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
472 /***********************************************************************
473 * VirtualProtectEx (kernelbase.@)
475 BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtectEx( HANDLE process, void *addr, SIZE_T size,
476 DWORD new_prot, DWORD *old_prot )
478 DWORD prot;
480 /* Win9x allows passing NULL as old_prot while this fails on NT */
481 if (!old_prot && (GetVersion() & 0x80000000)) old_prot = &prot;
482 return set_ntstatus( NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot ));
486 /***********************************************************************
487 * VirtualQuery (kernelbase.@)
489 SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len )
491 return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
495 /***********************************************************************
496 * VirtualQueryEx (kernelbase.@)
498 SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQueryEx( HANDLE process, LPCVOID addr,
499 PMEMORY_BASIC_INFORMATION info, SIZE_T len )
501 SIZE_T ret;
503 if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
504 return 0;
505 return ret;
509 /***********************************************************************
510 * VirtualUnlock (kernelbase.@)
512 BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size )
514 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 ));
518 /***********************************************************************
519 * WriteProcessMemory (kernelbase.@)
521 BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer,
522 SIZE_T size, SIZE_T *bytes_written )
524 return set_ntstatus( NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ));
528 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
529 BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
531 if (!str) return TRUE;
532 __TRY
534 volatile const char *p = str;
535 while (p != str + max) if (!*p++) break;
537 __EXCEPT_PAGE_FAULT
539 return TRUE;
541 __ENDTRY
542 return FALSE;
546 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
547 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT_PTR max )
549 if (!str) return TRUE;
550 __TRY
552 volatile const WCHAR *p = str;
553 while (p != str + max) if (!*p++) break;
555 __EXCEPT_PAGE_FAULT
557 return TRUE;
559 __ENDTRY
560 return FALSE;
564 /***********************************************************************
565 * Heap functions
566 ***********************************************************************/
569 /***********************************************************************
570 * HeapCompact (kernelbase.@)
572 SIZE_T WINAPI DECLSPEC_HOTPATCH HeapCompact( HANDLE heap, DWORD flags )
574 return RtlCompactHeap( heap, flags );
578 /***********************************************************************
579 * HeapCreate (kernelbase.@)
581 HANDLE WINAPI DECLSPEC_HOTPATCH HeapCreate( DWORD flags, SIZE_T init_size, SIZE_T max_size )
583 HANDLE ret = RtlCreateHeap( flags, NULL, max_size, init_size, NULL, NULL );
584 if (!ret) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
585 return ret;
589 /***********************************************************************
590 * HeapDestroy (kernelbase.@)
592 BOOL WINAPI DECLSPEC_HOTPATCH HeapDestroy( HANDLE heap )
594 if (!RtlDestroyHeap( heap )) return TRUE;
595 SetLastError( ERROR_INVALID_HANDLE );
596 return FALSE;
600 /***********************************************************************
601 * HeapLock (kernelbase.@)
603 BOOL WINAPI DECLSPEC_HOTPATCH HeapLock( HANDLE heap )
605 return RtlLockHeap( heap );
609 /***********************************************************************
610 * HeapQueryInformation (kernelbase.@)
612 BOOL WINAPI HeapQueryInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class,
613 PVOID info, SIZE_T size, PSIZE_T size_out )
615 return set_ntstatus( RtlQueryHeapInformation( heap, info_class, info, size, size_out ));
619 /***********************************************************************
620 * HeapSetInformation (kernelbase.@)
622 BOOL WINAPI HeapSetInformation( HANDLE heap, HEAP_INFORMATION_CLASS infoclass, PVOID info, SIZE_T size )
624 return set_ntstatus( RtlSetHeapInformation( heap, infoclass, info, size ));
628 /***********************************************************************
629 * HeapUnlock (kernelbase.@)
631 BOOL WINAPI HeapUnlock( HANDLE heap )
633 return RtlUnlockHeap( heap );
637 /***********************************************************************
638 * HeapValidate (kernelbase.@)
640 BOOL WINAPI DECLSPEC_HOTPATCH HeapValidate( HANDLE heap, DWORD flags, LPCVOID ptr )
642 return RtlValidateHeap( heap, flags, ptr );
646 /* undocumented RtlWalkHeap structure */
648 struct rtl_heap_entry
650 LPVOID lpData;
651 SIZE_T cbData; /* differs from PROCESS_HEAP_ENTRY */
652 BYTE cbOverhead;
653 BYTE iRegionIndex;
654 WORD wFlags; /* value differs from PROCESS_HEAP_ENTRY */
655 union {
656 struct {
657 HANDLE hMem;
658 DWORD dwReserved[3];
659 } Block;
660 struct {
661 DWORD dwCommittedSize;
662 DWORD dwUnCommittedSize;
663 LPVOID lpFirstBlock;
664 LPVOID lpLastBlock;
665 } Region;
669 /* rtl_heap_entry flags, names made up */
671 #define RTL_HEAP_ENTRY_BUSY 0x0001
672 #define RTL_HEAP_ENTRY_REGION 0x0002
673 #define RTL_HEAP_ENTRY_BLOCK 0x0010
674 #define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000
675 #define RTL_HEAP_ENTRY_COMMITTED 0x4000
676 #define RTL_HEAP_ENTRY_LFH 0x8000
679 /***********************************************************************
680 * HeapWalk (kernelbase.@)
682 BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
684 struct rtl_heap_entry rtl_entry = {0};
685 NTSTATUS status;
687 if (!entry) return set_ntstatus( STATUS_INVALID_PARAMETER );
689 rtl_entry.lpData = entry->lpData;
690 rtl_entry.cbData = entry->cbData;
691 rtl_entry.cbOverhead = entry->cbOverhead;
692 rtl_entry.iRegionIndex = entry->iRegionIndex;
694 if (entry->wFlags & PROCESS_HEAP_ENTRY_BUSY)
695 rtl_entry.wFlags |= RTL_HEAP_ENTRY_BUSY;
696 if (entry->wFlags & PROCESS_HEAP_REGION)
697 rtl_entry.wFlags |= RTL_HEAP_ENTRY_REGION;
698 if (entry->wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
699 rtl_entry.wFlags |= RTL_HEAP_ENTRY_UNCOMMITTED;
700 memcpy( &rtl_entry.Region, &entry->u.Region, sizeof(entry->u.Region) );
702 if (!(status = RtlWalkHeap( heap, &rtl_entry )))
704 entry->lpData = rtl_entry.lpData;
705 entry->cbData = rtl_entry.cbData;
706 entry->cbOverhead = rtl_entry.cbOverhead;
707 entry->iRegionIndex = rtl_entry.iRegionIndex;
709 if (rtl_entry.wFlags & RTL_HEAP_ENTRY_BUSY)
710 entry->wFlags = PROCESS_HEAP_ENTRY_BUSY;
711 else if (rtl_entry.wFlags & RTL_HEAP_ENTRY_REGION)
712 entry->wFlags = PROCESS_HEAP_REGION;
713 else if (rtl_entry.wFlags & RTL_HEAP_ENTRY_UNCOMMITTED)
714 entry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE;
715 else
716 entry->wFlags = 0;
718 memcpy( &entry->u.Region, &rtl_entry.Region, sizeof(entry->u.Region) );
721 return set_ntstatus( status );
725 /***********************************************************************
726 * Global/local heap functions
727 ***********************************************************************/
729 /* some undocumented flags (names are made up) */
730 #define HEAP_ADD_USER_INFO 0x00000100
732 /* not compatible with windows */
733 struct kernelbase_global_data
735 struct mem_entry *mem_entries;
736 struct mem_entry *mem_entries_end;
739 #define MEM_FLAG_USED 1
740 #define MEM_FLAG_MOVEABLE 2
741 #define MEM_FLAG_DISCARDABLE 4
742 #define MEM_FLAG_DISCARDED 8
743 #define MEM_FLAG_DDESHARE 0x8000
745 struct mem_entry
747 union
749 struct
751 WORD flags;
752 BYTE lock;
754 void *next_free;
756 void *ptr;
759 C_ASSERT(sizeof(struct mem_entry) == 2 * sizeof(void *));
761 #define MAX_MEM_HANDLES 0x10000
762 static struct mem_entry *next_free_mem;
763 static struct kernelbase_global_data global_data = {0};
765 static inline struct mem_entry *unsafe_mem_from_HLOCAL( HLOCAL handle )
767 struct mem_entry *mem = CONTAINING_RECORD( *(volatile HANDLE *)&handle, struct mem_entry, ptr );
768 struct kernelbase_global_data *data = &global_data;
769 if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL;
770 if (mem < data->mem_entries || mem >= data->mem_entries_end) return NULL;
771 if (!(mem->flags & MEM_FLAG_USED)) return NULL;
772 return mem;
775 static inline HLOCAL HLOCAL_from_mem( struct mem_entry *mem )
777 if (!mem) return 0;
778 return &mem->ptr;
781 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle )
783 if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1))) return NULL;
784 return handle;
787 void init_global_data(void)
789 global_data.mem_entries = VirtualAlloc( NULL, MAX_MEM_HANDLES * sizeof(struct mem_entry), MEM_COMMIT, PAGE_READWRITE );
790 if (!(next_free_mem = global_data.mem_entries)) ERR( "Failed to allocate kernelbase global handle table\n" );
791 global_data.mem_entries_end = global_data.mem_entries + MAX_MEM_HANDLES;
794 /***********************************************************************
795 * KernelBaseGetGlobalData (kernelbase.@)
797 void *WINAPI KernelBaseGetGlobalData(void)
799 WARN_(globalmem)( "semi-stub!\n" );
800 return &global_data;
804 /***********************************************************************
805 * GlobalAlloc (kernelbase.@)
807 HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size )
809 struct mem_entry *mem;
810 HGLOBAL handle;
812 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
813 if (!(flags & GMEM_MOVEABLE) && !size) size = 1;
815 handle = LocalAlloc( flags, size );
817 if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & GMEM_DDESHARE))
818 mem->flags |= MEM_FLAG_DDESHARE;
820 return handle;
824 /***********************************************************************
825 * GlobalFree (kernelbase.@)
827 HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL handle )
829 return LocalFree( handle );
833 /***********************************************************************
834 * LocalAlloc (kernelbase.@)
836 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
838 DWORD heap_flags = 0x200 | HEAP_ADD_USER_INFO;
839 HANDLE heap = GetProcessHeap();
840 struct mem_entry *mem;
841 HLOCAL handle;
842 void *ptr;
844 TRACE_(globalmem)( "flags %#x, size %#Ix\n", flags, size );
846 if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
848 if (!(flags & LMEM_MOVEABLE)) /* pointer */
850 ptr = HeapAlloc( heap, heap_flags, size );
851 if (ptr) RtlSetUserValueHeap( heap, heap_flags, ptr, ptr );
852 TRACE_(globalmem)( "return %p\n", ptr );
853 return ptr;
856 RtlLockHeap( heap );
857 if ((mem = next_free_mem) < global_data.mem_entries || mem >= global_data.mem_entries_end)
858 mem = NULL;
859 else
861 if (!mem->next_free) next_free_mem++;
862 else next_free_mem = mem->next_free;
863 mem->next_free = NULL;
865 RtlUnlockHeap( heap );
867 if (!mem) goto failed;
868 handle = HLOCAL_from_mem( mem );
870 mem->flags = MEM_FLAG_USED | MEM_FLAG_MOVEABLE;
871 if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE;
872 mem->lock = 0;
873 mem->ptr = NULL;
875 if (!size) mem->flags |= MEM_FLAG_DISCARDED;
876 else
878 if (!(ptr = HeapAlloc( heap, heap_flags, size ))) goto failed;
879 RtlSetUserValueHeap( heap, heap_flags, ptr, handle );
880 mem->ptr = ptr;
883 TRACE_(globalmem)( "return handle %p, ptr %p\n", handle, mem->ptr );
884 return handle;
886 failed:
887 if (mem) LocalFree( *(volatile HANDLE *)&handle );
888 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
889 return 0;
893 /***********************************************************************
894 * LocalFree (kernelbase.@)
896 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL handle )
898 HANDLE heap = GetProcessHeap();
899 struct mem_entry *mem;
900 HLOCAL ret = handle;
901 void *ptr;
903 TRACE_(globalmem)( "handle %p\n", handle );
905 RtlLockHeap( heap );
906 if ((ptr = unsafe_ptr_from_HLOCAL( handle )) &&
907 HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
909 if (HeapFree( heap, HEAP_NO_SERIALIZE, ptr )) ret = 0;
911 else if ((mem = unsafe_mem_from_HLOCAL( handle )))
913 if (HeapFree( heap, HEAP_NO_SERIALIZE, mem->ptr )) ret = 0;
914 mem->ptr = NULL;
915 mem->next_free = next_free_mem;
916 next_free_mem = mem;
918 RtlUnlockHeap( heap );
920 if (ret)
922 WARN_(globalmem)( "invalid handle %p\n", handle );
923 SetLastError( ERROR_INVALID_HANDLE );
925 return ret;
929 /***********************************************************************
930 * LocalLock (kernelbase.@)
932 LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
934 HANDLE heap = GetProcessHeap();
935 struct mem_entry *mem;
936 void *ret = NULL;
938 TRACE_(globalmem)( "handle %p\n", handle );
940 if (!handle) return NULL;
941 if ((ret = unsafe_ptr_from_HLOCAL( handle )))
943 __TRY
945 volatile char *p = ret;
946 *p |= 0;
948 __EXCEPT_PAGE_FAULT
950 return NULL;
952 __ENDTRY
953 return ret;
956 RtlLockHeap( heap );
957 if ((mem = unsafe_mem_from_HLOCAL( handle )))
959 if (!(ret = mem->ptr)) SetLastError( ERROR_DISCARDED );
960 else if (!++mem->lock) mem->lock--;
962 else
964 WARN_(globalmem)( "invalid handle %p\n", handle );
965 SetLastError( ERROR_INVALID_HANDLE );
967 RtlUnlockHeap( heap );
969 return ret;
973 /***********************************************************************
974 * LocalReAlloc (kernelbase.@)
976 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags )
978 DWORD heap_flags = 0x200 | HEAP_ADD_USER_INFO | HEAP_NO_SERIALIZE;
979 HANDLE heap = GetProcessHeap();
980 struct mem_entry *mem;
981 HLOCAL ret = 0;
982 void *ptr;
984 TRACE_(globalmem)( "handle %p, size %#Ix, flags %#x\n", handle, size, flags );
986 if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
988 RtlLockHeap( heap );
989 if ((ptr = unsafe_ptr_from_HLOCAL( handle )) &&
990 HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
992 if (flags & LMEM_MODIFY) ret = handle;
993 else if (flags & LMEM_DISCARDABLE) SetLastError( ERROR_INVALID_PARAMETER );
994 else if (flags & LMEM_MOVEABLE)
996 ret = HeapReAlloc( heap, heap_flags, ptr, size );
997 if (ret) RtlSetUserValueHeap( heap, heap_flags, ret, ret );
998 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1000 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1002 else if ((mem = unsafe_mem_from_HLOCAL( handle )))
1004 if (flags & LMEM_MODIFY)
1006 if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE;
1007 ret = handle;
1009 else if (flags & LMEM_DISCARDABLE) SetLastError( ERROR_INVALID_PARAMETER );
1010 else
1012 if (size)
1014 if (mem->lock && !(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
1015 if (!mem->ptr) ptr = HeapAlloc( heap, heap_flags, size );
1016 else ptr = HeapReAlloc( heap, heap_flags, mem->ptr, size );
1018 if (!ptr) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1019 else
1021 RtlSetUserValueHeap( heap, heap_flags, ptr, handle );
1022 mem->flags &= ~MEM_FLAG_DISCARDED;
1023 mem->ptr = ptr;
1024 ret = handle;
1027 else if ((flags & LMEM_MOVEABLE) && !mem->lock)
1029 HeapFree( heap, heap_flags, mem->ptr );
1030 mem->flags |= MEM_FLAG_DISCARDED;
1031 mem->ptr = NULL;
1032 ret = handle;
1034 else SetLastError( ERROR_INVALID_PARAMETER );
1037 else SetLastError( ERROR_INVALID_HANDLE );
1038 RtlUnlockHeap( heap );
1040 return ret;
1044 /***********************************************************************
1045 * LocalUnlock (kernelbase.@)
1047 BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL handle )
1049 HANDLE heap = GetProcessHeap();
1050 struct mem_entry *mem;
1051 BOOL ret = FALSE;
1053 TRACE_(globalmem)( "handle %p\n", handle );
1055 if (unsafe_ptr_from_HLOCAL( handle ))
1057 SetLastError( ERROR_NOT_LOCKED );
1058 return FALSE;
1061 RtlLockHeap( heap );
1062 if ((mem = unsafe_mem_from_HLOCAL( handle )))
1064 if (mem->lock)
1066 ret = (--mem->lock != 0);
1067 if (!ret) SetLastError( NO_ERROR );
1069 else
1071 WARN_(globalmem)( "handle %p not locked\n", handle );
1072 SetLastError( ERROR_NOT_LOCKED );
1075 else
1077 WARN_(globalmem)( "invalid handle %p\n", handle );
1078 SetLastError( ERROR_INVALID_HANDLE );
1080 RtlUnlockHeap( heap );
1082 return ret;
1086 /***********************************************************************
1087 * Memory resource functions
1088 ***********************************************************************/
1091 /***********************************************************************
1092 * CreateMemoryResourceNotification (kernelbase.@)
1094 HANDLE WINAPI DECLSPEC_HOTPATCH CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type )
1096 HANDLE ret;
1097 UNICODE_STRING nameW;
1098 OBJECT_ATTRIBUTES attr;
1100 switch (type)
1102 case LowMemoryResourceNotification:
1103 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\LowMemoryCondition" );
1104 break;
1105 case HighMemoryResourceNotification:
1106 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\HighMemoryCondition" );
1107 break;
1108 default:
1109 SetLastError( ERROR_INVALID_PARAMETER );
1110 return 0;
1113 InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL );
1114 if (!set_ntstatus( NtOpenEvent( &ret, EVENT_ALL_ACCESS, &attr ))) return 0;
1115 return ret;
1118 /***********************************************************************
1119 * QueryMemoryResourceNotification (kernelbase.@)
1121 BOOL WINAPI DECLSPEC_HOTPATCH QueryMemoryResourceNotification( HANDLE handle, BOOL *state )
1123 switch (WaitForSingleObject( handle, 0 ))
1125 case WAIT_OBJECT_0:
1126 *state = TRUE;
1127 return TRUE;
1128 case WAIT_TIMEOUT:
1129 *state = FALSE;
1130 return TRUE;
1132 SetLastError( ERROR_INVALID_PARAMETER );
1133 return FALSE;
1137 /***********************************************************************
1138 * Physical memory functions
1139 ***********************************************************************/
1142 /***********************************************************************
1143 * AllocateUserPhysicalPages (kernelbase.@)
1145 BOOL WINAPI DECLSPEC_HOTPATCH AllocateUserPhysicalPages( HANDLE process, ULONG_PTR *pages,
1146 ULONG_PTR *userarray )
1148 FIXME( "stub: %p %p %p\n", process, pages, userarray );
1149 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1150 return FALSE;
1154 /***********************************************************************
1155 * FreeUserPhysicalPages (kernelbase.@)
1157 BOOL WINAPI DECLSPEC_HOTPATCH FreeUserPhysicalPages( HANDLE process, ULONG_PTR *pages,
1158 ULONG_PTR *userarray )
1160 FIXME( "stub: %p %p %p\n", process, pages, userarray );
1161 *pages = 0;
1162 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1163 return FALSE;
1167 /***********************************************************************
1168 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1170 BOOL WINAPI DECLSPEC_HOTPATCH GetPhysicallyInstalledSystemMemory( ULONGLONG *memory )
1172 MEMORYSTATUSEX status;
1174 if (!memory)
1176 SetLastError( ERROR_INVALID_PARAMETER );
1177 return FALSE;
1179 status.dwLength = sizeof(status);
1180 GlobalMemoryStatusEx( &status );
1181 *memory = status.ullTotalPhys / 1024;
1182 return TRUE;
1186 /***********************************************************************
1187 * GlobalMemoryStatusEx (kernelbase.@)
1189 BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status )
1191 static MEMORYSTATUSEX cached_status;
1192 static DWORD last_check;
1193 SYSTEM_BASIC_INFORMATION basic_info;
1194 SYSTEM_PERFORMANCE_INFORMATION perf_info;
1195 VM_COUNTERS_EX vmc;
1197 if (status->dwLength != sizeof(*status))
1199 SetLastError( ERROR_INVALID_PARAMETER );
1200 return FALSE;
1202 if ((NtGetTickCount() - last_check) < 1000)
1204 *status = cached_status;
1205 return TRUE;
1207 last_check = NtGetTickCount();
1209 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
1210 &basic_info, sizeof(basic_info), NULL )) ||
1211 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation,
1212 &perf_info, sizeof(perf_info), NULL)) ||
1213 !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters,
1214 &vmc, sizeof(vmc), NULL )))
1215 return FALSE;
1217 status->dwMemoryLoad = 0;
1218 status->ullTotalPhys = basic_info.MmNumberOfPhysicalPages;
1219 status->ullAvailPhys = perf_info.AvailablePages;
1220 status->ullTotalPageFile = perf_info.TotalCommitLimit;
1221 status->ullAvailPageFile = status->ullTotalPageFile - perf_info.TotalCommittedPages;
1222 status->ullTotalVirtual = (ULONG_PTR)basic_info.HighestUserAddress - (ULONG_PTR)basic_info.LowestUserAddress + 1;
1223 status->ullAvailVirtual = status->ullTotalVirtual - (ULONGLONG)vmc.WorkingSetSize /* approximate */;
1224 status->ullAvailExtendedVirtual = 0;
1226 status->ullTotalPhys *= basic_info.PageSize;
1227 status->ullAvailPhys *= basic_info.PageSize;
1228 status->ullTotalPageFile *= basic_info.PageSize;
1229 status->ullAvailPageFile *= basic_info.PageSize;
1231 if (status->ullTotalPhys)
1232 status->dwMemoryLoad = (status->ullTotalPhys - status->ullAvailPhys) / (status->ullTotalPhys / 100);
1234 TRACE_(virtual)( "MemoryLoad %ld, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1235 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1236 status->dwMemoryLoad, wine_dbgstr_longlong(status->ullTotalPhys),
1237 wine_dbgstr_longlong(status->ullAvailPhys), wine_dbgstr_longlong(status->ullTotalPageFile),
1238 wine_dbgstr_longlong(status->ullAvailPageFile), wine_dbgstr_longlong(status->ullTotalVirtual),
1239 wine_dbgstr_longlong(status->ullAvailVirtual) );
1241 cached_status = *status;
1242 return TRUE;
1246 /***********************************************************************
1247 * MapUserPhysicalPages (kernelbase.@)
1249 BOOL WINAPI DECLSPEC_HOTPATCH MapUserPhysicalPages( void *addr, ULONG_PTR page_count, ULONG_PTR *pages )
1251 FIXME( "stub: %p %Iu %p\n", addr, page_count, pages );
1252 *pages = 0;
1253 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1254 return FALSE;
1258 /***********************************************************************
1259 * NUMA functions
1260 ***********************************************************************/
1263 /***********************************************************************
1264 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1266 BOOL WINAPI DECLSPEC_HOTPATCH AllocateUserPhysicalPagesNuma( HANDLE process, ULONG_PTR *pages,
1267 ULONG_PTR *userarray, DWORD node )
1269 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1270 return AllocateUserPhysicalPages( process, pages, userarray );
1274 /***********************************************************************
1275 * CreateFileMappingNumaW (kernelbase.@)
1277 HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileMappingNumaW( HANDLE file, LPSECURITY_ATTRIBUTES sa,
1278 DWORD protect, DWORD size_high, DWORD size_low,
1279 LPCWSTR name, DWORD node )
1281 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1282 return CreateFileMappingW( file, sa, protect, size_high, size_low, name );
1286 /***********************************************************************
1287 * GetLogicalProcessorInformation (kernelbase.@)
1289 BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buffer,
1290 DWORD *len )
1292 NTSTATUS status;
1294 if (!len)
1296 SetLastError( ERROR_INVALID_PARAMETER );
1297 return FALSE;
1299 status = NtQuerySystemInformation( SystemLogicalProcessorInformation, buffer, *len, len );
1300 if (status == STATUS_INFO_LENGTH_MISMATCH) status = STATUS_BUFFER_TOO_SMALL;
1301 return set_ntstatus( status );
1305 /***********************************************************************
1306 * GetLogicalProcessorInformationEx (kernelbase.@)
1308 BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship,
1309 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, DWORD *len )
1311 NTSTATUS status;
1313 if (!len)
1315 SetLastError( ERROR_INVALID_PARAMETER );
1316 return FALSE;
1318 status = NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx, &relationship,
1319 sizeof(relationship), buffer, *len, len );
1320 if (status == STATUS_INFO_LENGTH_MISMATCH) status = STATUS_BUFFER_TOO_SMALL;
1321 return set_ntstatus( status );
1325 /***********************************************************************
1326 * GetSystemCpuSetInformation (kernelbase.@)
1328 BOOL WINAPI GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION *info, ULONG buffer_length, ULONG *return_length,
1329 HANDLE process, ULONG flags)
1331 if (flags)
1332 FIXME("Unsupported flags %#lx.\n", flags);
1334 *return_length = 0;
1336 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation, &process, sizeof(process), info,
1337 buffer_length, return_length ));
1341 /***********************************************************************
1342 * SetThreadSelectedCpuSets (kernelbase.@)
1344 BOOL WINAPI SetThreadSelectedCpuSets(HANDLE thread, const ULONG *cpu_set_ids, ULONG count)
1346 FIXME( "thread %p, cpu_set_ids %p, count %lu stub.\n", thread, cpu_set_ids, count );
1348 return TRUE;
1352 /***********************************************************************
1353 * SetProcessDefaultCpuSets (kernelbase.@)
1355 BOOL WINAPI SetProcessDefaultCpuSets(HANDLE process, const ULONG *cpu_set_ids, ULONG count)
1357 FIXME( "process %p, cpu_set_ids %p, count %lu stub.\n", process, cpu_set_ids, count );
1359 return TRUE;
1363 /**********************************************************************
1364 * GetNumaHighestNodeNumber (kernelbase.@)
1366 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaHighestNodeNumber( ULONG *node )
1368 FIXME( "semi-stub: %p\n", node );
1369 *node = 0;
1370 return TRUE;
1374 /**********************************************************************
1375 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1377 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaNodeProcessorMaskEx( USHORT node, GROUP_AFFINITY *mask )
1379 FIXME( "stub: %hu %p\n", node, mask );
1380 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1381 return FALSE;
1385 /***********************************************************************
1386 * GetNumaProximityNodeEx (kernelbase.@)
1388 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaProximityNodeEx( ULONG proximity_id, USHORT *node )
1390 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1391 return FALSE;
1395 /***********************************************************************
1396 * MapViewOfFileExNuma (kernelbase.@)
1398 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileExNuma( HANDLE handle, DWORD access, DWORD offset_high,
1399 DWORD offset_low, SIZE_T count, LPVOID addr,
1400 DWORD node )
1402 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1403 return MapViewOfFileEx( handle, access, offset_high, offset_low, count, addr );
1407 /***********************************************************************
1408 * VirtualAllocExNuma (kernelbase.@)
1410 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocExNuma( HANDLE process, void *addr, SIZE_T size,
1411 DWORD type, DWORD protect, DWORD node )
1413 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1414 return VirtualAllocEx( process, addr, size, type, protect );
1418 /***********************************************************************
1419 * QueryVirtualMemoryInformation (kernelbase.@)
1421 BOOL WINAPI DECLSPEC_HOTPATCH QueryVirtualMemoryInformation( HANDLE process, const void *addr,
1422 WIN32_MEMORY_INFORMATION_CLASS info_class, void *info, SIZE_T size, SIZE_T *ret_size)
1424 switch (info_class)
1426 case MemoryRegionInfo:
1427 return set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryRegionInformation, info, size, ret_size ));
1428 default:
1429 FIXME("Unsupported info class %u.\n", info_class);
1430 return FALSE;
1435 /***********************************************************************
1436 * CPU functions
1437 ***********************************************************************/
1440 #if defined(__i386__) || defined(__x86_64__)
1441 /***********************************************************************
1442 * GetEnabledXStateFeatures (kernelbase.@)
1444 DWORD64 WINAPI GetEnabledXStateFeatures(void)
1446 TRACE( "\n" );
1447 return RtlGetEnabledExtendedFeatures( ~(ULONG64)0 );
1451 /***********************************************************************
1452 * InitializeContext2 (kernelbase.@)
1454 BOOL WINAPI InitializeContext2( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length,
1455 ULONG64 compaction_mask )
1457 ULONG orig_length;
1458 NTSTATUS status;
1460 TRACE( "buffer %p, context_flags %#lx, context %p, ret_length %p, compaction_mask %s.\n",
1461 buffer, context_flags, context, length, wine_dbgstr_longlong(compaction_mask) );
1463 orig_length = *length;
1465 if ((status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask )))
1467 if (status == STATUS_NOT_SUPPORTED && context_flags & 0x40)
1469 context_flags &= ~0x40;
1470 status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask );
1473 if (status)
1474 return set_ntstatus( status );
1477 if (!buffer || orig_length < *length)
1479 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1480 return FALSE;
1483 if ((status = RtlInitializeExtendedContext2( buffer, context_flags, (CONTEXT_EX **)context, compaction_mask )))
1484 return set_ntstatus( status );
1486 *context = (CONTEXT *)((BYTE *)*context + (*(CONTEXT_EX **)context)->Legacy.Offset);
1488 return TRUE;
1491 /***********************************************************************
1492 * InitializeContext (kernelbase.@)
1494 BOOL WINAPI InitializeContext( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length )
1496 return InitializeContext2( buffer, context_flags, context, length, ~(ULONG64)0 );
1499 /***********************************************************************
1500 * CopyContext (kernelbase.@)
1502 BOOL WINAPI CopyContext( CONTEXT *dst, DWORD context_flags, CONTEXT *src )
1504 return set_ntstatus( RtlCopyContext( dst, context_flags, src ));
1506 #endif
1509 #if defined(__x86_64__)
1510 /***********************************************************************
1511 * LocateXStateFeature (kernelbase.@)
1513 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
1515 if (!(context->ContextFlags & CONTEXT_AMD64))
1516 return NULL;
1518 if (feature_id >= 2)
1519 return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1520 ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
1522 if (feature_id == 1)
1524 if (length)
1525 *length = sizeof(M128A) * 16;
1527 return &context->u.FltSave.XmmRegisters;
1530 if (length)
1531 *length = offsetof(XSAVE_FORMAT, XmmRegisters);
1533 return &context->u.FltSave;
1536 /***********************************************************************
1537 * SetXStateFeaturesMask (kernelbase.@)
1539 BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
1541 if (!(context->ContextFlags & CONTEXT_AMD64))
1542 return FALSE;
1544 if (feature_mask & 0x3)
1545 context->ContextFlags |= CONTEXT_FLOATING_POINT;
1547 if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
1548 return !(feature_mask & ~(DWORD64)3);
1550 RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
1551 return TRUE;
1554 /***********************************************************************
1555 * GetXStateFeaturesMask (kernelbase.@)
1557 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1559 if (!(context->ContextFlags & CONTEXT_AMD64))
1560 return FALSE;
1562 *feature_mask = (context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT
1563 ? 3 : 0;
1565 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1566 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1568 return TRUE;
1570 #elif defined(__i386__)
1571 /***********************************************************************
1572 * LocateXStateFeature (kernelbase.@)
1574 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
1576 if (!(context->ContextFlags & CONTEXT_i386))
1577 return NULL;
1579 if (feature_id >= 2)
1580 return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1581 ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
1583 if (feature_id == 1)
1585 if (length)
1586 *length = sizeof(M128A) * 8;
1588 return (BYTE *)&context->ExtendedRegisters + offsetof(XSAVE_FORMAT, XmmRegisters);
1591 if (length)
1592 *length = offsetof(XSAVE_FORMAT, XmmRegisters);
1594 return &context->ExtendedRegisters;
1597 /***********************************************************************
1598 * SetXStateFeaturesMask (kernelbase.@)
1600 BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
1602 if (!(context->ContextFlags & CONTEXT_i386))
1603 return FALSE;
1605 if (feature_mask & 0x3)
1606 context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
1608 if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
1609 return !(feature_mask & ~(DWORD64)3);
1611 RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
1612 return TRUE;
1615 /***********************************************************************
1616 * GetXStateFeaturesMask (kernelbase.@)
1618 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1620 if (!(context->ContextFlags & CONTEXT_i386))
1621 return FALSE;
1623 *feature_mask = (context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS
1624 ? 3 : 0;
1626 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1627 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1629 return TRUE;
1631 #endif
1633 /***********************************************************************
1634 * Firmware functions
1635 ***********************************************************************/
1638 /***********************************************************************
1639 * EnumSystemFirmwareTable (kernelbase.@)
1641 UINT WINAPI EnumSystemFirmwareTables( DWORD provider, void *buffer, DWORD size )
1643 FIXME( "(0x%08lx, %p, %ld)\n", provider, buffer, size );
1644 return 0;
1648 /***********************************************************************
1649 * GetSystemFirmwareTable (kernelbase.@)
1651 UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWORD size )
1653 SYSTEM_FIRMWARE_TABLE_INFORMATION *info;
1654 ULONG buffer_size = offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer ) + size;
1656 TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider, id, buffer, size );
1658 if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, buffer_size )))
1660 SetLastError( ERROR_OUTOFMEMORY );
1661 return 0;
1664 info->ProviderSignature = provider;
1665 info->Action = SystemFirmwareTable_Get;
1666 info->TableID = id;
1668 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation,
1669 info, buffer_size, &buffer_size ));
1670 buffer_size -= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer );
1671 if (buffer_size <= size) memcpy( buffer, info->TableBuffer, buffer_size );
1673 HeapFree( GetProcessHeap(), 0, info );
1674 return buffer_size;