include: Add some new ProcThreadAttribute definitions.
[wine.git] / dlls / kernelbase / memory.c
blobc4a484b5a308f7e50ffea074c7c53521593c9f52
1 /*
2 * Win32 memory management functions
4 * Copyright 1997 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <limits.h>
25 #include <sys/types.h>
27 #include "ntstatus.h"
28 #define WIN32_NO_STATUS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "winternl.h"
35 #include "winerror.h"
36 #include "ddk/wdm.h"
38 #include "kernelbase.h"
39 #include "wine/exception.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(heap);
43 WINE_DECLARE_DEBUG_CHANNEL(virtual);
44 WINE_DECLARE_DEBUG_CHANNEL(globalmem);
47 /***********************************************************************
48 * Virtual memory functions
49 ***********************************************************************/
52 /***********************************************************************
53 * DiscardVirtualMemory (kernelbase.@)
55 DWORD WINAPI DECLSPEC_HOTPATCH DiscardVirtualMemory( void *addr, SIZE_T size )
57 NTSTATUS status;
58 LPVOID ret = addr;
60 status = NtAllocateVirtualMemory( GetCurrentProcess(), &ret, 0, &size, MEM_RESET, PAGE_NOACCESS );
61 return RtlNtStatusToDosError( status );
65 /***********************************************************************
66 * FlushViewOfFile (kernelbase.@)
68 BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size )
70 NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
72 if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
73 return set_ntstatus( status );
77 /***********************************************************************
78 * GetLargePageMinimum (kernelbase.@)
80 SIZE_T WINAPI GetLargePageMinimum(void)
82 return 2 * 1024 * 1024;
86 static void fill_system_info( SYSTEM_INFO *si, const SYSTEM_BASIC_INFORMATION *basic_info,
87 const SYSTEM_CPU_INFORMATION *cpu_info )
89 si->u.s.wProcessorArchitecture = cpu_info->ProcessorArchitecture;
90 si->u.s.wReserved = 0;
91 si->dwPageSize = basic_info->PageSize;
92 si->lpMinimumApplicationAddress = basic_info->LowestUserAddress;
93 si->lpMaximumApplicationAddress = basic_info->HighestUserAddress;
94 si->dwActiveProcessorMask = basic_info->ActiveProcessorsAffinityMask;
95 si->dwNumberOfProcessors = basic_info->NumberOfProcessors;
96 si->dwAllocationGranularity = basic_info->AllocationGranularity;
97 si->wProcessorLevel = cpu_info->ProcessorLevel;
98 si->wProcessorRevision = cpu_info->ProcessorRevision;
100 switch (cpu_info->ProcessorArchitecture)
102 case PROCESSOR_ARCHITECTURE_INTEL:
103 switch (cpu_info->ProcessorLevel)
105 case 3: si->dwProcessorType = PROCESSOR_INTEL_386; break;
106 case 4: si->dwProcessorType = PROCESSOR_INTEL_486; break;
107 case 5:
108 case 6: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
109 default: si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; break;
111 break;
112 case PROCESSOR_ARCHITECTURE_AMD64:
113 si->dwProcessorType = PROCESSOR_AMD_X8664;
114 break;
115 case PROCESSOR_ARCHITECTURE_ARM:
116 switch (cpu_info->ProcessorLevel)
118 case 4: si->dwProcessorType = PROCESSOR_ARM_7TDMI; break;
119 default: si->dwProcessorType = PROCESSOR_ARM920;
121 break;
122 case PROCESSOR_ARCHITECTURE_ARM64:
123 si->dwProcessorType = 0;
124 break;
125 default:
126 FIXME( "Unknown processor architecture %x\n", cpu_info->ProcessorArchitecture );
127 si->dwProcessorType = 0;
128 break;
133 /***********************************************************************
134 * GetNativeSystemInfo (kernelbase.@)
136 void WINAPI DECLSPEC_HOTPATCH GetNativeSystemInfo( SYSTEM_INFO *si )
138 SYSTEM_BASIC_INFORMATION basic_info;
139 SYSTEM_CPU_INFORMATION cpu_info;
141 if (is_wow64)
143 USHORT current_machine, native_machine;
145 RtlWow64GetProcessMachines( 0, &current_machine, &native_machine );
146 if (native_machine != IMAGE_FILE_MACHINE_AMD64)
148 GetSystemInfo( si );
149 si->u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
150 return;
154 if (!set_ntstatus( RtlGetNativeSystemInformation( SystemBasicInformation,
155 &basic_info, sizeof(basic_info), NULL )) ||
156 !set_ntstatus( RtlGetNativeSystemInformation( SystemCpuInformation,
157 &cpu_info, sizeof(cpu_info), NULL )))
158 return;
160 fill_system_info( si, &basic_info, &cpu_info );
164 /***********************************************************************
165 * GetSystemInfo (kernelbase.@)
167 void WINAPI DECLSPEC_HOTPATCH GetSystemInfo( SYSTEM_INFO *si )
169 SYSTEM_BASIC_INFORMATION basic_info;
170 SYSTEM_CPU_INFORMATION cpu_info;
172 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
173 &basic_info, sizeof(basic_info), NULL )) ||
174 !set_ntstatus( NtQuerySystemInformation( SystemCpuInformation,
175 &cpu_info, sizeof(cpu_info), NULL )))
176 return;
178 fill_system_info( si, &basic_info, &cpu_info );
182 /***********************************************************************
183 * GetSystemFileCacheSize (kernelbase.@)
185 BOOL WINAPI DECLSPEC_HOTPATCH GetSystemFileCacheSize( SIZE_T *mincache, SIZE_T *maxcache, DWORD *flags )
187 FIXME( "stub: %p %p %p\n", mincache, maxcache, flags );
188 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
189 return FALSE;
193 /***********************************************************************
194 * GetWriteWatch (kernelbase.@)
196 UINT WINAPI DECLSPEC_HOTPATCH GetWriteWatch( DWORD flags, void *base, SIZE_T size, void **addresses,
197 ULONG_PTR *count, ULONG *granularity )
199 if (!set_ntstatus( NtGetWriteWatch( GetCurrentProcess(), flags, base, size,
200 addresses, count, granularity )))
201 return ~0u;
202 return 0;
206 /***********************************************************************
207 * MapViewOfFile (kernelbase.@)
209 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile( HANDLE mapping, DWORD access, DWORD offset_high,
210 DWORD offset_low, SIZE_T count )
212 return MapViewOfFileEx( mapping, access, offset_high, offset_low, count, NULL );
216 /***********************************************************************
217 * MapViewOfFileEx (kernelbase.@)
219 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileEx( HANDLE handle, DWORD access, DWORD offset_high,
220 DWORD offset_low, SIZE_T count, LPVOID addr )
222 NTSTATUS status;
223 LARGE_INTEGER offset;
224 ULONG protect;
225 BOOL exec;
227 offset.u.LowPart = offset_low;
228 offset.u.HighPart = offset_high;
230 exec = access & FILE_MAP_EXECUTE;
231 access &= ~FILE_MAP_EXECUTE;
233 if (access == FILE_MAP_COPY)
234 protect = exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY;
235 else if (access & FILE_MAP_WRITE)
236 protect = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
237 else if (access & FILE_MAP_READ)
238 protect = exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
239 else protect = PAGE_NOACCESS;
241 if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
242 &count, ViewShare, 0, protect )) < 0)
244 SetLastError( RtlNtStatusToDosError(status) );
245 addr = NULL;
247 return addr;
251 /***********************************************************************
252 * MapViewOfFileFromApp (kernelbase.@)
254 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileFromApp( HANDLE handle, ULONG access, ULONG64 offset, SIZE_T size )
256 return MapViewOfFile( handle, access, offset << 32, offset, size );
259 /***********************************************************************
260 * MapViewOfFile3 (kernelbase.@)
262 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile3( HANDLE handle, HANDLE process, PVOID baseaddr, ULONG64 offset,
263 SIZE_T size, ULONG alloc_type, ULONG protection, MEM_EXTENDED_PARAMETER *params, ULONG params_count )
265 LARGE_INTEGER off;
266 void *addr;
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 return set_ntstatus( NtFreeVirtualMemory( process, &addr, &size, type ));
464 /***********************************************************************
465 * VirtualLock (kernelbase.@)
467 BOOL WINAPI DECLSPEC_HOTPATCH VirtualLock( void *addr, SIZE_T size )
469 return set_ntstatus( NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 ));
473 /***********************************************************************
474 * VirtualProtect (kernelbase.@)
476 BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtect( void *addr, SIZE_T size, DWORD new_prot, DWORD *old_prot )
478 return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
482 /***********************************************************************
483 * VirtualProtectEx (kernelbase.@)
485 BOOL WINAPI DECLSPEC_HOTPATCH VirtualProtectEx( HANDLE process, void *addr, SIZE_T size,
486 DWORD new_prot, DWORD *old_prot )
488 DWORD prot;
490 /* Win9x allows passing NULL as old_prot while this fails on NT */
491 if (!old_prot && (GetVersion() & 0x80000000)) old_prot = &prot;
492 return set_ntstatus( NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot ));
496 /***********************************************************************
497 * VirtualQuery (kernelbase.@)
499 SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len )
501 return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
505 /***********************************************************************
506 * VirtualQueryEx (kernelbase.@)
508 SIZE_T WINAPI DECLSPEC_HOTPATCH VirtualQueryEx( HANDLE process, LPCVOID addr,
509 PMEMORY_BASIC_INFORMATION info, SIZE_T len )
511 SIZE_T ret;
513 if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
514 return 0;
515 return ret;
519 /***********************************************************************
520 * VirtualUnlock (kernelbase.@)
522 BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size )
524 return set_ntstatus( NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 ));
528 /***********************************************************************
529 * WriteProcessMemory (kernelbase.@)
531 BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer,
532 SIZE_T size, SIZE_T *bytes_written )
534 return set_ntstatus( NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ));
538 /* IsBadStringPtrA replacement for kernelbase, to catch exception in debug traces. */
539 BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
541 if (!str) return TRUE;
542 __TRY
544 volatile const char *p = str;
545 while (p != str + max) if (!*p++) break;
547 __EXCEPT_PAGE_FAULT
549 return TRUE;
551 __ENDTRY
552 return FALSE;
556 /* IsBadStringPtrW replacement for kernelbase, to catch exception in debug traces. */
557 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT_PTR max )
559 if (!str) return TRUE;
560 __TRY
562 volatile const WCHAR *p = str;
563 while (p != str + max) if (!*p++) break;
565 __EXCEPT_PAGE_FAULT
567 return TRUE;
569 __ENDTRY
570 return FALSE;
574 /***********************************************************************
575 * Heap functions
576 ***********************************************************************/
579 /***********************************************************************
580 * HeapCompact (kernelbase.@)
582 SIZE_T WINAPI DECLSPEC_HOTPATCH HeapCompact( HANDLE heap, DWORD flags )
584 return RtlCompactHeap( heap, flags );
588 /***********************************************************************
589 * HeapCreate (kernelbase.@)
591 HANDLE WINAPI DECLSPEC_HOTPATCH HeapCreate( DWORD flags, SIZE_T init_size, SIZE_T max_size )
593 HANDLE ret = RtlCreateHeap( flags, NULL, max_size, init_size, NULL, NULL );
594 if (!ret) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
595 return ret;
599 /***********************************************************************
600 * HeapDestroy (kernelbase.@)
602 BOOL WINAPI DECLSPEC_HOTPATCH HeapDestroy( HANDLE heap )
604 if (!RtlDestroyHeap( heap )) return TRUE;
605 SetLastError( ERROR_INVALID_HANDLE );
606 return FALSE;
610 /***********************************************************************
611 * HeapLock (kernelbase.@)
613 BOOL WINAPI DECLSPEC_HOTPATCH HeapLock( HANDLE heap )
615 return RtlLockHeap( heap );
619 /***********************************************************************
620 * HeapQueryInformation (kernelbase.@)
622 BOOL WINAPI HeapQueryInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class,
623 PVOID info, SIZE_T size, PSIZE_T size_out )
625 return set_ntstatus( RtlQueryHeapInformation( heap, info_class, info, size, size_out ));
629 /***********************************************************************
630 * HeapSetInformation (kernelbase.@)
632 BOOL WINAPI HeapSetInformation( HANDLE heap, HEAP_INFORMATION_CLASS infoclass, PVOID info, SIZE_T size )
634 return set_ntstatus( RtlSetHeapInformation( heap, infoclass, info, size ));
638 /***********************************************************************
639 * HeapUnlock (kernelbase.@)
641 BOOL WINAPI HeapUnlock( HANDLE heap )
643 return RtlUnlockHeap( heap );
647 /***********************************************************************
648 * HeapValidate (kernelbase.@)
650 BOOL WINAPI DECLSPEC_HOTPATCH HeapValidate( HANDLE heap, DWORD flags, LPCVOID ptr )
652 return RtlValidateHeap( heap, flags, ptr );
656 /* undocumented RtlWalkHeap structure */
658 struct rtl_heap_entry
660 LPVOID lpData;
661 SIZE_T cbData; /* differs from PROCESS_HEAP_ENTRY */
662 BYTE cbOverhead;
663 BYTE iRegionIndex;
664 WORD wFlags; /* value differs from PROCESS_HEAP_ENTRY */
665 union {
666 struct {
667 HANDLE hMem;
668 DWORD dwReserved[3];
669 } Block;
670 struct {
671 DWORD dwCommittedSize;
672 DWORD dwUnCommittedSize;
673 LPVOID lpFirstBlock;
674 LPVOID lpLastBlock;
675 } Region;
679 /* rtl_heap_entry flags, names made up */
681 #define RTL_HEAP_ENTRY_BUSY 0x0001
682 #define RTL_HEAP_ENTRY_REGION 0x0002
683 #define RTL_HEAP_ENTRY_BLOCK 0x0010
684 #define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000
685 #define RTL_HEAP_ENTRY_COMMITTED 0x4000
686 #define RTL_HEAP_ENTRY_LFH 0x8000
689 /***********************************************************************
690 * HeapWalk (kernelbase.@)
692 BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
694 struct rtl_heap_entry rtl_entry = {0};
695 NTSTATUS status;
697 if (!entry) return set_ntstatus( STATUS_INVALID_PARAMETER );
699 rtl_entry.lpData = entry->lpData;
700 rtl_entry.cbData = entry->cbData;
701 rtl_entry.cbOverhead = entry->cbOverhead;
702 rtl_entry.iRegionIndex = entry->iRegionIndex;
704 if (entry->wFlags & PROCESS_HEAP_ENTRY_BUSY)
705 rtl_entry.wFlags |= RTL_HEAP_ENTRY_BUSY;
706 if (entry->wFlags & PROCESS_HEAP_REGION)
707 rtl_entry.wFlags |= RTL_HEAP_ENTRY_REGION;
708 if (entry->wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
709 rtl_entry.wFlags |= RTL_HEAP_ENTRY_UNCOMMITTED;
710 memcpy( &rtl_entry.Region, &entry->u.Region, sizeof(entry->u.Region) );
712 if (!(status = RtlWalkHeap( heap, &rtl_entry )))
714 entry->lpData = rtl_entry.lpData;
715 entry->cbData = rtl_entry.cbData;
716 entry->cbOverhead = rtl_entry.cbOverhead;
717 entry->iRegionIndex = rtl_entry.iRegionIndex;
719 if (rtl_entry.wFlags & RTL_HEAP_ENTRY_BUSY)
720 entry->wFlags = PROCESS_HEAP_ENTRY_BUSY;
721 else if (rtl_entry.wFlags & RTL_HEAP_ENTRY_REGION)
722 entry->wFlags = PROCESS_HEAP_REGION;
723 else if (rtl_entry.wFlags & RTL_HEAP_ENTRY_UNCOMMITTED)
724 entry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE;
725 else
726 entry->wFlags = 0;
728 memcpy( &entry->u.Region, &rtl_entry.Region, sizeof(entry->u.Region) );
731 return set_ntstatus( status );
735 /***********************************************************************
736 * Global/local heap functions
737 ***********************************************************************/
739 /* some undocumented flags (names are made up) */
740 #define HEAP_ADD_USER_INFO 0x00000100
742 /* not compatible with windows */
743 struct kernelbase_global_data
745 struct mem_entry *mem_entries;
746 struct mem_entry *mem_entries_end;
749 #define MEM_FLAG_USED 1
750 #define MEM_FLAG_MOVEABLE 2
751 #define MEM_FLAG_DISCARDABLE 4
752 #define MEM_FLAG_DISCARDED 8
753 #define MEM_FLAG_DDESHARE 0x8000
755 struct mem_entry
757 union
759 struct
761 WORD flags;
762 BYTE lock;
764 void *next_free;
766 void *ptr;
769 C_ASSERT(sizeof(struct mem_entry) == 2 * sizeof(void *));
771 #define MAX_MEM_HANDLES 0x10000
772 static struct mem_entry *next_free_mem;
773 static struct kernelbase_global_data global_data = {0};
775 static inline struct mem_entry *unsafe_mem_from_HLOCAL( HLOCAL handle )
777 struct mem_entry *mem = CONTAINING_RECORD( *(volatile HANDLE *)&handle, struct mem_entry, ptr );
778 struct kernelbase_global_data *data = &global_data;
779 if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL;
780 if (mem < data->mem_entries || mem >= data->mem_entries_end) return NULL;
781 if (!(mem->flags & MEM_FLAG_USED)) return NULL;
782 return mem;
785 static inline HLOCAL HLOCAL_from_mem( struct mem_entry *mem )
787 if (!mem) return 0;
788 return &mem->ptr;
791 static inline void *unsafe_ptr_from_HLOCAL( HLOCAL handle )
793 if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1))) return NULL;
794 return handle;
797 void init_global_data(void)
799 global_data.mem_entries = VirtualAlloc( NULL, MAX_MEM_HANDLES * sizeof(struct mem_entry), MEM_COMMIT, PAGE_READWRITE );
800 if (!(next_free_mem = global_data.mem_entries)) ERR( "Failed to allocate kernelbase global handle table\n" );
801 global_data.mem_entries_end = global_data.mem_entries + MAX_MEM_HANDLES;
804 /***********************************************************************
805 * KernelBaseGetGlobalData (kernelbase.@)
807 void *WINAPI KernelBaseGetGlobalData(void)
809 WARN_(globalmem)( "semi-stub!\n" );
810 return &global_data;
814 /***********************************************************************
815 * GlobalAlloc (kernelbase.@)
817 HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size )
819 struct mem_entry *mem;
820 HGLOBAL handle;
822 /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
823 if (!(flags & GMEM_MOVEABLE) && !size) size = 1;
825 handle = LocalAlloc( flags, size );
827 if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & GMEM_DDESHARE))
828 mem->flags |= MEM_FLAG_DDESHARE;
830 return handle;
834 /***********************************************************************
835 * GlobalFree (kernelbase.@)
837 HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL handle )
839 return LocalFree( handle );
843 /***********************************************************************
844 * LocalAlloc (kernelbase.@)
846 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
848 DWORD heap_flags = 0x200 | HEAP_ADD_USER_INFO;
849 HANDLE heap = GetProcessHeap();
850 struct mem_entry *mem;
851 HLOCAL handle;
852 void *ptr;
854 TRACE_(globalmem)( "flags %#x, size %#Ix\n", flags, size );
856 if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
858 if (!(flags & LMEM_MOVEABLE)) /* pointer */
860 ptr = HeapAlloc( heap, heap_flags, size );
861 if (ptr) RtlSetUserValueHeap( heap, heap_flags, ptr, ptr );
862 TRACE_(globalmem)( "return %p\n", ptr );
863 return ptr;
866 RtlLockHeap( heap );
867 if ((mem = next_free_mem) < global_data.mem_entries || mem >= global_data.mem_entries_end)
868 mem = NULL;
869 else
871 if (!mem->next_free) next_free_mem++;
872 else next_free_mem = mem->next_free;
873 mem->next_free = NULL;
875 RtlUnlockHeap( heap );
877 if (!mem) goto failed;
878 handle = HLOCAL_from_mem( mem );
880 mem->flags = MEM_FLAG_USED | MEM_FLAG_MOVEABLE;
881 if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE;
882 mem->lock = 0;
883 mem->ptr = NULL;
885 if (!size) mem->flags |= MEM_FLAG_DISCARDED;
886 else
888 if (!(ptr = HeapAlloc( heap, heap_flags, size ))) goto failed;
889 RtlSetUserValueHeap( heap, heap_flags, ptr, handle );
890 mem->ptr = ptr;
893 TRACE_(globalmem)( "return handle %p, ptr %p\n", handle, mem->ptr );
894 return handle;
896 failed:
897 if (mem) LocalFree( *(volatile HANDLE *)&handle );
898 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
899 return 0;
903 /***********************************************************************
904 * LocalFree (kernelbase.@)
906 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL handle )
908 HANDLE heap = GetProcessHeap();
909 struct mem_entry *mem;
910 HLOCAL ret = handle;
911 void *ptr;
913 TRACE_(globalmem)( "handle %p\n", handle );
915 RtlLockHeap( heap );
916 if ((ptr = unsafe_ptr_from_HLOCAL( handle )) &&
917 HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
919 if (HeapFree( heap, HEAP_NO_SERIALIZE, ptr )) ret = 0;
921 else if ((mem = unsafe_mem_from_HLOCAL( handle )))
923 if (HeapFree( heap, HEAP_NO_SERIALIZE, mem->ptr )) ret = 0;
924 mem->ptr = NULL;
925 mem->next_free = next_free_mem;
926 next_free_mem = mem;
928 RtlUnlockHeap( heap );
930 if (ret)
932 WARN_(globalmem)( "invalid handle %p\n", handle );
933 SetLastError( ERROR_INVALID_HANDLE );
935 return ret;
939 /***********************************************************************
940 * LocalLock (kernelbase.@)
942 LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
944 HANDLE heap = GetProcessHeap();
945 struct mem_entry *mem;
946 void *ret = NULL;
948 TRACE_(globalmem)( "handle %p\n", handle );
950 if (!handle) return NULL;
951 if ((ret = unsafe_ptr_from_HLOCAL( handle )))
953 __TRY
955 volatile char *p = ret;
956 *p |= 0;
958 __EXCEPT_PAGE_FAULT
960 return NULL;
962 __ENDTRY
963 return ret;
966 RtlLockHeap( heap );
967 if ((mem = unsafe_mem_from_HLOCAL( handle )))
969 if (!(ret = mem->ptr)) SetLastError( ERROR_DISCARDED );
970 else if (!++mem->lock) mem->lock--;
972 else
974 WARN_(globalmem)( "invalid handle %p\n", handle );
975 SetLastError( ERROR_INVALID_HANDLE );
977 RtlUnlockHeap( heap );
979 return ret;
983 /***********************************************************************
984 * LocalReAlloc (kernelbase.@)
986 HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags )
988 DWORD heap_flags = 0x200 | HEAP_ADD_USER_INFO | HEAP_NO_SERIALIZE;
989 HANDLE heap = GetProcessHeap();
990 struct mem_entry *mem;
991 HLOCAL ret = 0;
992 void *ptr;
994 TRACE_(globalmem)( "handle %p, size %#Ix, flags %#x\n", handle, size, flags );
996 if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
998 RtlLockHeap( heap );
999 if ((ptr = unsafe_ptr_from_HLOCAL( handle )) &&
1000 HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
1002 if (flags & LMEM_MODIFY) ret = handle;
1003 else if (flags & LMEM_DISCARDABLE) SetLastError( ERROR_INVALID_PARAMETER );
1004 else
1006 if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
1007 ret = HeapReAlloc( heap, heap_flags, ptr, size );
1008 if (ret) RtlSetUserValueHeap( heap, heap_flags, ret, ret );
1009 else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1012 else if ((mem = unsafe_mem_from_HLOCAL( handle )))
1014 if (flags & LMEM_MODIFY)
1016 if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE;
1017 ret = handle;
1019 else if (flags & LMEM_DISCARDABLE) SetLastError( ERROR_INVALID_PARAMETER );
1020 else
1022 if (size)
1024 if (mem->lock && !(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
1025 if (!mem->ptr) ptr = HeapAlloc( heap, heap_flags, size );
1026 else ptr = HeapReAlloc( heap, heap_flags, mem->ptr, size );
1028 if (!ptr) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1029 else
1031 RtlSetUserValueHeap( heap, heap_flags, ptr, handle );
1032 mem->flags &= ~MEM_FLAG_DISCARDED;
1033 mem->ptr = ptr;
1034 ret = handle;
1037 else if ((flags & LMEM_MOVEABLE) && !mem->lock)
1039 HeapFree( heap, heap_flags, mem->ptr );
1040 mem->flags |= MEM_FLAG_DISCARDED;
1041 mem->ptr = NULL;
1042 ret = handle;
1044 else SetLastError( ERROR_INVALID_PARAMETER );
1047 else SetLastError( ERROR_INVALID_HANDLE );
1048 RtlUnlockHeap( heap );
1050 return ret;
1054 /***********************************************************************
1055 * LocalUnlock (kernelbase.@)
1057 BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL handle )
1059 HANDLE heap = GetProcessHeap();
1060 struct mem_entry *mem;
1061 BOOL ret = FALSE;
1063 TRACE_(globalmem)( "handle %p\n", handle );
1065 if (unsafe_ptr_from_HLOCAL( handle ))
1067 SetLastError( ERROR_NOT_LOCKED );
1068 return FALSE;
1071 RtlLockHeap( heap );
1072 if ((mem = unsafe_mem_from_HLOCAL( handle )))
1074 if (mem->lock)
1076 ret = (--mem->lock != 0);
1077 if (!ret) SetLastError( NO_ERROR );
1079 else
1081 WARN_(globalmem)( "handle %p not locked\n", handle );
1082 SetLastError( ERROR_NOT_LOCKED );
1085 else
1087 WARN_(globalmem)( "invalid handle %p\n", handle );
1088 SetLastError( ERROR_INVALID_HANDLE );
1090 RtlUnlockHeap( heap );
1092 return ret;
1096 /***********************************************************************
1097 * Memory resource functions
1098 ***********************************************************************/
1101 /***********************************************************************
1102 * CreateMemoryResourceNotification (kernelbase.@)
1104 HANDLE WINAPI DECLSPEC_HOTPATCH CreateMemoryResourceNotification( MEMORY_RESOURCE_NOTIFICATION_TYPE type )
1106 HANDLE ret;
1107 UNICODE_STRING nameW;
1108 OBJECT_ATTRIBUTES attr;
1110 switch (type)
1112 case LowMemoryResourceNotification:
1113 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\LowMemoryCondition" );
1114 break;
1115 case HighMemoryResourceNotification:
1116 RtlInitUnicodeString( &nameW, L"\\KernelObjects\\HighMemoryCondition" );
1117 break;
1118 default:
1119 SetLastError( ERROR_INVALID_PARAMETER );
1120 return 0;
1123 InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL );
1124 if (!set_ntstatus( NtOpenEvent( &ret, EVENT_ALL_ACCESS, &attr ))) return 0;
1125 return ret;
1128 /***********************************************************************
1129 * QueryMemoryResourceNotification (kernelbase.@)
1131 BOOL WINAPI DECLSPEC_HOTPATCH QueryMemoryResourceNotification( HANDLE handle, BOOL *state )
1133 switch (WaitForSingleObject( handle, 0 ))
1135 case WAIT_OBJECT_0:
1136 *state = TRUE;
1137 return TRUE;
1138 case WAIT_TIMEOUT:
1139 *state = FALSE;
1140 return TRUE;
1142 SetLastError( ERROR_INVALID_PARAMETER );
1143 return FALSE;
1147 /***********************************************************************
1148 * Physical memory functions
1149 ***********************************************************************/
1152 /***********************************************************************
1153 * AllocateUserPhysicalPages (kernelbase.@)
1155 BOOL WINAPI DECLSPEC_HOTPATCH AllocateUserPhysicalPages( HANDLE process, ULONG_PTR *pages,
1156 ULONG_PTR *userarray )
1158 FIXME( "stub: %p %p %p\n", process, pages, userarray );
1159 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1160 return FALSE;
1164 /***********************************************************************
1165 * FreeUserPhysicalPages (kernelbase.@)
1167 BOOL WINAPI DECLSPEC_HOTPATCH FreeUserPhysicalPages( HANDLE process, ULONG_PTR *pages,
1168 ULONG_PTR *userarray )
1170 FIXME( "stub: %p %p %p\n", process, pages, userarray );
1171 *pages = 0;
1172 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1173 return FALSE;
1177 /***********************************************************************
1178 * GetPhysicallyInstalledSystemMemory (kernelbase.@)
1180 BOOL WINAPI DECLSPEC_HOTPATCH GetPhysicallyInstalledSystemMemory( ULONGLONG *memory )
1182 MEMORYSTATUSEX status;
1184 if (!memory)
1186 SetLastError( ERROR_INVALID_PARAMETER );
1187 return FALSE;
1189 status.dwLength = sizeof(status);
1190 GlobalMemoryStatusEx( &status );
1191 *memory = status.ullTotalPhys / 1024;
1192 return TRUE;
1196 /***********************************************************************
1197 * GlobalMemoryStatusEx (kernelbase.@)
1199 BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status )
1201 static MEMORYSTATUSEX cached_status;
1202 static DWORD last_check;
1203 SYSTEM_BASIC_INFORMATION basic_info;
1204 SYSTEM_PERFORMANCE_INFORMATION perf_info;
1205 VM_COUNTERS_EX vmc;
1207 if (status->dwLength != sizeof(*status))
1209 SetLastError( ERROR_INVALID_PARAMETER );
1210 return FALSE;
1212 if ((NtGetTickCount() - last_check) < 1000)
1214 *status = cached_status;
1215 return TRUE;
1217 last_check = NtGetTickCount();
1219 if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
1220 &basic_info, sizeof(basic_info), NULL )) ||
1221 !set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation,
1222 &perf_info, sizeof(perf_info), NULL)) ||
1223 !set_ntstatus( NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters,
1224 &vmc, sizeof(vmc), NULL )))
1225 return FALSE;
1227 status->dwMemoryLoad = 0;
1228 status->ullTotalPhys = basic_info.MmNumberOfPhysicalPages;
1229 status->ullAvailPhys = perf_info.AvailablePages;
1230 status->ullTotalPageFile = perf_info.TotalCommitLimit;
1231 status->ullAvailPageFile = status->ullTotalPageFile - perf_info.TotalCommittedPages;
1232 status->ullTotalVirtual = (ULONG_PTR)basic_info.HighestUserAddress - (ULONG_PTR)basic_info.LowestUserAddress + 1;
1233 status->ullAvailVirtual = status->ullTotalVirtual - (ULONGLONG)vmc.WorkingSetSize /* approximate */;
1234 status->ullAvailExtendedVirtual = 0;
1236 status->ullTotalPhys *= basic_info.PageSize;
1237 status->ullAvailPhys *= basic_info.PageSize;
1238 status->ullTotalPageFile *= basic_info.PageSize;
1239 status->ullAvailPageFile *= basic_info.PageSize;
1241 if (status->ullTotalPhys)
1242 status->dwMemoryLoad = (status->ullTotalPhys - status->ullAvailPhys) / (status->ullTotalPhys / 100);
1244 TRACE_(virtual)( "MemoryLoad %ld, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
1245 "AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
1246 status->dwMemoryLoad, wine_dbgstr_longlong(status->ullTotalPhys),
1247 wine_dbgstr_longlong(status->ullAvailPhys), wine_dbgstr_longlong(status->ullTotalPageFile),
1248 wine_dbgstr_longlong(status->ullAvailPageFile), wine_dbgstr_longlong(status->ullTotalVirtual),
1249 wine_dbgstr_longlong(status->ullAvailVirtual) );
1251 cached_status = *status;
1252 return TRUE;
1256 /***********************************************************************
1257 * MapUserPhysicalPages (kernelbase.@)
1259 BOOL WINAPI DECLSPEC_HOTPATCH MapUserPhysicalPages( void *addr, ULONG_PTR page_count, ULONG_PTR *pages )
1261 FIXME( "stub: %p %Iu %p\n", addr, page_count, pages );
1262 *pages = 0;
1263 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1264 return FALSE;
1268 /***********************************************************************
1269 * NUMA functions
1270 ***********************************************************************/
1273 /***********************************************************************
1274 * AllocateUserPhysicalPagesNuma (kernelbase.@)
1276 BOOL WINAPI DECLSPEC_HOTPATCH AllocateUserPhysicalPagesNuma( HANDLE process, ULONG_PTR *pages,
1277 ULONG_PTR *userarray, DWORD node )
1279 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1280 return AllocateUserPhysicalPages( process, pages, userarray );
1284 /***********************************************************************
1285 * CreateFileMappingNumaW (kernelbase.@)
1287 HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileMappingNumaW( HANDLE file, LPSECURITY_ATTRIBUTES sa,
1288 DWORD protect, DWORD size_high, DWORD size_low,
1289 LPCWSTR name, DWORD node )
1291 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1292 return CreateFileMappingW( file, sa, protect, size_high, size_low, name );
1296 /***********************************************************************
1297 * GetLogicalProcessorInformation (kernelbase.@)
1299 BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformation( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buffer,
1300 DWORD *len )
1302 NTSTATUS status;
1304 if (!len)
1306 SetLastError( ERROR_INVALID_PARAMETER );
1307 return FALSE;
1309 status = NtQuerySystemInformation( SystemLogicalProcessorInformation, buffer, *len, len );
1310 if (status == STATUS_INFO_LENGTH_MISMATCH) status = STATUS_BUFFER_TOO_SMALL;
1311 return set_ntstatus( status );
1315 /***********************************************************************
1316 * GetLogicalProcessorInformationEx (kernelbase.@)
1318 BOOL WINAPI DECLSPEC_HOTPATCH GetLogicalProcessorInformationEx( LOGICAL_PROCESSOR_RELATIONSHIP relationship,
1319 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, DWORD *len )
1321 NTSTATUS status;
1323 if (!len)
1325 SetLastError( ERROR_INVALID_PARAMETER );
1326 return FALSE;
1328 status = NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx, &relationship,
1329 sizeof(relationship), buffer, *len, len );
1330 if (status == STATUS_INFO_LENGTH_MISMATCH) status = STATUS_BUFFER_TOO_SMALL;
1331 return set_ntstatus( status );
1335 /***********************************************************************
1336 * GetSystemCpuSetInformation (kernelbase.@)
1338 BOOL WINAPI GetSystemCpuSetInformation(SYSTEM_CPU_SET_INFORMATION *info, ULONG buffer_length, ULONG *return_length,
1339 HANDLE process, ULONG flags)
1341 if (flags)
1342 FIXME("Unsupported flags %#lx.\n", flags);
1344 *return_length = 0;
1346 return set_ntstatus( NtQuerySystemInformationEx( SystemCpuSetInformation, &process, sizeof(process), info,
1347 buffer_length, return_length ));
1351 /***********************************************************************
1352 * SetThreadSelectedCpuSets (kernelbase.@)
1354 BOOL WINAPI SetThreadSelectedCpuSets(HANDLE thread, const ULONG *cpu_set_ids, ULONG count)
1356 FIXME( "thread %p, cpu_set_ids %p, count %lu stub.\n", thread, cpu_set_ids, count );
1358 return TRUE;
1362 /***********************************************************************
1363 * SetProcessDefaultCpuSets (kernelbase.@)
1365 BOOL WINAPI SetProcessDefaultCpuSets(HANDLE process, const ULONG *cpu_set_ids, ULONG count)
1367 FIXME( "process %p, cpu_set_ids %p, count %lu stub.\n", process, cpu_set_ids, count );
1369 return TRUE;
1373 /**********************************************************************
1374 * GetNumaHighestNodeNumber (kernelbase.@)
1376 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaHighestNodeNumber( ULONG *node )
1378 FIXME( "semi-stub: %p\n", node );
1379 *node = 0;
1380 return TRUE;
1384 /**********************************************************************
1385 * GetNumaNodeProcessorMaskEx (kernelbase.@)
1387 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaNodeProcessorMaskEx( USHORT node, GROUP_AFFINITY *mask )
1389 FIXME( "stub: %hu %p\n", node, mask );
1390 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1391 return FALSE;
1395 /***********************************************************************
1396 * GetNumaProximityNodeEx (kernelbase.@)
1398 BOOL WINAPI DECLSPEC_HOTPATCH GetNumaProximityNodeEx( ULONG proximity_id, USHORT *node )
1400 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1401 return FALSE;
1405 /***********************************************************************
1406 * MapViewOfFileExNuma (kernelbase.@)
1408 LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFileExNuma( HANDLE handle, DWORD access, DWORD offset_high,
1409 DWORD offset_low, SIZE_T count, LPVOID addr,
1410 DWORD node )
1412 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1413 return MapViewOfFileEx( handle, access, offset_high, offset_low, count, addr );
1417 /***********************************************************************
1418 * VirtualAllocExNuma (kernelbase.@)
1420 LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocExNuma( HANDLE process, void *addr, SIZE_T size,
1421 DWORD type, DWORD protect, DWORD node )
1423 if (node) FIXME( "Ignoring preferred node %lu\n", node );
1424 return VirtualAllocEx( process, addr, size, type, protect );
1428 /***********************************************************************
1429 * QueryVirtualMemoryInformation (kernelbase.@)
1431 BOOL WINAPI DECLSPEC_HOTPATCH QueryVirtualMemoryInformation( HANDLE process, const void *addr,
1432 WIN32_MEMORY_INFORMATION_CLASS info_class, void *info, SIZE_T size, SIZE_T *ret_size)
1434 switch (info_class)
1436 case MemoryRegionInfo:
1437 return set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryRegionInformation, info, size, ret_size ));
1438 default:
1439 FIXME("Unsupported info class %u.\n", info_class);
1440 return FALSE;
1445 /***********************************************************************
1446 * CPU functions
1447 ***********************************************************************/
1450 #if defined(__i386__) || defined(__x86_64__)
1451 /***********************************************************************
1452 * GetEnabledXStateFeatures (kernelbase.@)
1454 DWORD64 WINAPI GetEnabledXStateFeatures(void)
1456 TRACE( "\n" );
1457 return RtlGetEnabledExtendedFeatures( ~(ULONG64)0 );
1461 /***********************************************************************
1462 * InitializeContext2 (kernelbase.@)
1464 BOOL WINAPI InitializeContext2( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length,
1465 ULONG64 compaction_mask )
1467 ULONG orig_length;
1468 NTSTATUS status;
1470 TRACE( "buffer %p, context_flags %#lx, context %p, ret_length %p, compaction_mask %s.\n",
1471 buffer, context_flags, context, length, wine_dbgstr_longlong(compaction_mask) );
1473 orig_length = *length;
1475 if ((status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask )))
1477 if (status == STATUS_NOT_SUPPORTED && context_flags & 0x40)
1479 context_flags &= ~0x40;
1480 status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask );
1483 if (status)
1484 return set_ntstatus( status );
1487 if (!buffer || orig_length < *length)
1489 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1490 return FALSE;
1493 if ((status = RtlInitializeExtendedContext2( buffer, context_flags, (CONTEXT_EX **)context, compaction_mask )))
1494 return set_ntstatus( status );
1496 *context = (CONTEXT *)((BYTE *)*context + (*(CONTEXT_EX **)context)->Legacy.Offset);
1498 return TRUE;
1501 /***********************************************************************
1502 * InitializeContext (kernelbase.@)
1504 BOOL WINAPI InitializeContext( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length )
1506 return InitializeContext2( buffer, context_flags, context, length, ~(ULONG64)0 );
1509 /***********************************************************************
1510 * CopyContext (kernelbase.@)
1512 BOOL WINAPI CopyContext( CONTEXT *dst, DWORD context_flags, CONTEXT *src )
1514 return set_ntstatus( RtlCopyContext( dst, context_flags, src ));
1516 #endif
1519 #if defined(__x86_64__)
1520 /***********************************************************************
1521 * LocateXStateFeature (kernelbase.@)
1523 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
1525 if (!(context->ContextFlags & CONTEXT_AMD64))
1526 return NULL;
1528 if (feature_id >= 2)
1529 return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1530 ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
1532 if (feature_id == 1)
1534 if (length)
1535 *length = sizeof(M128A) * 16;
1537 return &context->u.FltSave.XmmRegisters;
1540 if (length)
1541 *length = offsetof(XSAVE_FORMAT, XmmRegisters);
1543 return &context->u.FltSave;
1546 /***********************************************************************
1547 * SetXStateFeaturesMask (kernelbase.@)
1549 BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
1551 if (!(context->ContextFlags & CONTEXT_AMD64))
1552 return FALSE;
1554 if (feature_mask & 0x3)
1555 context->ContextFlags |= CONTEXT_FLOATING_POINT;
1557 if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
1558 return !(feature_mask & ~(DWORD64)3);
1560 RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
1561 return TRUE;
1564 /***********************************************************************
1565 * GetXStateFeaturesMask (kernelbase.@)
1567 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1569 if (!(context->ContextFlags & CONTEXT_AMD64))
1570 return FALSE;
1572 *feature_mask = (context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT
1573 ? 3 : 0;
1575 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1576 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1578 return TRUE;
1580 #elif defined(__i386__)
1581 /***********************************************************************
1582 * LocateXStateFeature (kernelbase.@)
1584 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
1586 if (!(context->ContextFlags & CONTEXT_i386))
1587 return NULL;
1589 if (feature_id >= 2)
1590 return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1591 ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
1593 if (feature_id == 1)
1595 if (length)
1596 *length = sizeof(M128A) * 8;
1598 return (BYTE *)&context->ExtendedRegisters + offsetof(XSAVE_FORMAT, XmmRegisters);
1601 if (length)
1602 *length = offsetof(XSAVE_FORMAT, XmmRegisters);
1604 return &context->ExtendedRegisters;
1607 /***********************************************************************
1608 * SetXStateFeaturesMask (kernelbase.@)
1610 BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
1612 if (!(context->ContextFlags & CONTEXT_i386))
1613 return FALSE;
1615 if (feature_mask & 0x3)
1616 context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
1618 if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
1619 return !(feature_mask & ~(DWORD64)3);
1621 RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
1622 return TRUE;
1625 /***********************************************************************
1626 * GetXStateFeaturesMask (kernelbase.@)
1628 BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
1630 if (!(context->ContextFlags & CONTEXT_i386))
1631 return FALSE;
1633 *feature_mask = (context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS
1634 ? 3 : 0;
1636 if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
1637 *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
1639 return TRUE;
1641 #endif
1643 /***********************************************************************
1644 * Firmware functions
1645 ***********************************************************************/
1648 /***********************************************************************
1649 * EnumSystemFirmwareTable (kernelbase.@)
1651 UINT WINAPI EnumSystemFirmwareTables( DWORD provider, void *buffer, DWORD size )
1653 FIXME( "(0x%08lx, %p, %ld)\n", provider, buffer, size );
1654 return 0;
1658 /***********************************************************************
1659 * GetSystemFirmwareTable (kernelbase.@)
1661 UINT WINAPI GetSystemFirmwareTable( DWORD provider, DWORD id, void *buffer, DWORD size )
1663 SYSTEM_FIRMWARE_TABLE_INFORMATION *info;
1664 ULONG buffer_size = offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer ) + size;
1666 TRACE( "(0x%08lx, 0x%08lx, %p, %ld)\n", provider, id, buffer, size );
1668 if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, buffer_size )))
1670 SetLastError( ERROR_OUTOFMEMORY );
1671 return 0;
1674 info->ProviderSignature = provider;
1675 info->Action = SystemFirmwareTable_Get;
1676 info->TableID = id;
1678 set_ntstatus( NtQuerySystemInformation( SystemFirmwareTableInformation,
1679 info, buffer_size, &buffer_size ));
1680 buffer_size -= offsetof( SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer );
1681 if (buffer_size <= size) memcpy( buffer, info->TableBuffer, buffer_size );
1683 HeapFree( GetProcessHeap(), 0, info );
1684 return buffer_size;