NT4/private/windows/base/client/gmem.c
2020-09-30 17:12:29 +02:00

1193 lines
31 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
atom.c
Abstract:
This module contains the Win32 Global Memory Management APIs
Author:
Steve Wood (stevewo) 24-Sep-1990
Revision History:
--*/
#include "basedll.h"
#pragma hdrstop
#include "winuserp.h"
#include "wowuserp.h"
PFNWOWGLOBALFREEHOOK pfnWowGlobalFreeHook = NULL;
VOID
WINAPI
RegisterWowBaseHandlers(
PFNWOWGLOBALFREEHOOK pfn)
{
pfnWowGlobalFreeHook = pfn;
}
#if i386
#pragma optimize("y",off)
#endif
HGLOBAL
WINAPI
GlobalAlloc(
UINT uFlags,
DWORD dwBytes
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
HANDLE hMem;
LPSTR p;
ULONG Flags;
if (uFlags & ~GMEM_VALID_FLAGS) {
SetLastError( ERROR_INVALID_PARAMETER );
return( NULL );
}
Flags = 0;
if (uFlags & GMEM_ZEROINIT) {
Flags |= HEAP_ZERO_MEMORY;
}
if (!(uFlags & GMEM_MOVEABLE)) {
if (uFlags & GMEM_DDESHARE) {
Flags |= BASE_HEAP_FLAG_DDESHARE;
}
p = RtlAllocateHeap( BaseHeap,
MAKE_TAG( GMEM_TAG ) | Flags,
dwBytes ? dwBytes : 1
);
if (p == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
return p;
}
p = NULL;
RtlLockHeap( BaseHeap );
Flags |= HEAP_NO_SERIALIZE | HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
try {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &BaseHeapHandleTable, NULL );
if (HandleEntry == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto Fail;
}
hMem = (HANDLE)&HandleEntry->Object;
if (dwBytes != 0) {
p = (LPSTR)RtlAllocateHeap( BaseHeap, MAKE_TAG( GMEM_TAG ) | Flags, dwBytes );
if (p == NULL) {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
HandleEntry = NULL;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
else {
RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );
}
}
Fail: ;
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
if (HandleEntry != NULL) {
HandleEntry->Object = p;
if (p != NULL) {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
}
else {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED | BASE_HANDLE_DISCARDED;
}
if (uFlags & GMEM_DISCARDABLE) {
HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
}
if (uFlags & GMEM_MOVEABLE) {
HandleEntry->Flags |= BASE_HANDLE_MOVEABLE;
}
if (uFlags & GMEM_DDESHARE) {
HandleEntry->Flags |= BASE_HANDLE_SHARED;
}
p = (LPSTR)hMem;
}
return( (HANDLE)p );
}
HGLOBAL
WINAPI
GlobalReAlloc(
HANDLE hMem,
DWORD dwBytes,
UINT uFlags
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
HANDLE Handle;
LPSTR p;
ULONG Flags;
if ((uFlags & ~(GMEM_VALID_FLAGS | GMEM_MODIFY)) ||
((uFlags & GMEM_DISCARDABLE) && !(uFlags & GMEM_MODIFY))
) {
#if DBG
DbgPrint( "*** GlobalReAlloc( %lx ) - invalid flags\n", uFlags );
BaseHeapBreakPoint();
#endif
SetLastError( ERROR_INVALID_PARAMETER );
return( NULL );
}
Flags = 0;
if (uFlags & GMEM_ZEROINIT) {
Flags |= HEAP_ZERO_MEMORY;
}
if (!(uFlags & GMEM_MOVEABLE)) {
Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
}
RtlLockHeap( BaseHeap );
Flags |= HEAP_NO_SERIALIZE;
try {
if ((ULONG)hMem & BASE_HANDLE_MARK_BIT) {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
#if DBG
DbgPrint( "*** GlobalReAlloc( %lx ) - invalid handle\n", hMem );
BaseHeapBreakPoint();
#endif
SetLastError( ERROR_INVALID_HANDLE );
hMem = NULL;
}
else
if (uFlags & GMEM_MODIFY) {
if (uFlags & GMEM_DISCARDABLE) {
HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
}
else {
HandleEntry->Flags &= ~BASE_HANDLE_DISCARDABLE;
}
}
else {
p = HandleEntry->Object;
if (dwBytes == 0) {
hMem = NULL;
if (p != NULL) {
if ((uFlags & GMEM_MOVEABLE) && HandleEntry->LockCount == 0) {
if (RtlFreeHeap( BaseHeap, Flags, p )) {
HandleEntry->Object = NULL;
HandleEntry->Flags |= BASE_HANDLE_DISCARDED;
hMem = (HANDLE)&HandleEntry->Object;
}
}
else {
#if DBG
DbgPrint( "*** GlobalReAlloc( %lx ) - failing with locked handle\n", &HandleEntry->Object );
BaseHeapBreakPoint();
#endif
}
}
else {
hMem = (HANDLE)&HandleEntry->Object;
}
}
else {
Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
if (p == NULL) {
p = RtlAllocateHeap( BaseHeap, MAKE_TAG( GMEM_TAG ) | Flags, dwBytes );
if (p != NULL) {
RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );
}
}
else {
if (!(uFlags & GMEM_MOVEABLE) &&
HandleEntry->LockCount != 0
) {
Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
}
else {
Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;
}
p = RtlReAllocateHeap( BaseHeap, MAKE_TAG( GMEM_TAG ) | Flags, p, dwBytes );
}
if (p != NULL) {
HandleEntry->Object = p;
HandleEntry->Flags &= ~BASE_HANDLE_DISCARDED;
}
else {
hMem = NULL;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
}
}
}
else
if (uFlags & GMEM_MODIFY) {
if (uFlags & GMEM_MOVEABLE) {
Handle = hMem;
if (RtlGetUserInfoHeap( BaseHeap, HEAP_NO_SERIALIZE, (PVOID)hMem, &Handle, NULL )) {
if (Handle == hMem || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &BaseHeapHandleTable,
NULL
);
if (HandleEntry == NULL) {
hMem = NULL;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
else {
dwBytes = RtlSizeHeap( BaseHeap, HEAP_NO_SERIALIZE, hMem );
Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
HandleEntry->Object = (PVOID)RtlAllocateHeap( BaseHeap,
MAKE_TAG( GMEM_TAG ) | Flags,
dwBytes
);
if (HandleEntry->Object == NULL) {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
hMem = NULL;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
else {
RtlMoveMemory( HandleEntry->Object, hMem, dwBytes );
RtlFreeHeap( BaseHeap, HEAP_NO_SERIALIZE, hMem );
hMem = (HANDLE)&HandleEntry->Object;
HandleEntry->LockCount = 0;
HandleEntry->Flags = RTL_HANDLE_ALLOCATED | BASE_HANDLE_MOVEABLE;
if (uFlags & GMEM_DISCARDABLE) {
HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
}
if ((ULONG)Handle & GMEM_DDESHARE) {
HandleEntry->Flags |= BASE_HANDLE_SHARED;
}
RtlSetUserValueHeap( BaseHeap,
HEAP_NO_SERIALIZE,
HandleEntry->Object,
hMem
);
}
}
}
}
}
}
else {
hMem = RtlReAllocateHeap( BaseHeap,
MAKE_TAG( GMEM_TAG ) | Flags | HEAP_NO_SERIALIZE,
(PVOID)hMem,
dwBytes
);
if (hMem == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
hMem = NULL;
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
return( (LPSTR)hMem );
}
LPVOID
WINAPI
GlobalLock(
HGLOBAL hMem
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
LPSTR p;
if ((ULONG)hMem & BASE_HANDLE_MARK_BIT) {
RtlLockHeap( BaseHeap );
try {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
#if DBG
DbgPrint( "*** GlobalLock( %lx ) - invalid handle\n", hMem );
BaseHeapBreakPoint();
#endif
SetLastError( ERROR_INVALID_HANDLE );
p = NULL;
}
else {
p = HandleEntry->Object;
if (p != NULL) {
if (HandleEntry->LockCount++ == GMEM_LOCKCOUNT) {
HandleEntry->LockCount--;
}
}
else {
SetLastError( ERROR_DISCARDED );
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
p = NULL;
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
return( p );
}
else {
if ( (ULONG)hMem & 0x80000000 ) {
return NULL;
}
return( (LPSTR)hMem );
}
}
HANDLE
WINAPI
GlobalHandle(
LPCVOID pMem
)
{
HANDLE Handle;
ULONG Flags;
RtlLockHeap( BaseHeap );
try {
Handle = NULL;
if (!RtlGetUserInfoHeap( BaseHeap, HEAP_NO_SERIALIZE, (LPVOID)pMem, &Handle, &Flags )) {
SetLastError( ERROR_INVALID_HANDLE );
}
else
if (Handle == NULL || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
Handle = (HANDLE)pMem;
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
return( Handle );
}
BOOL
WINAPI
GlobalUnlock(
HANDLE hMem
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
BOOL Result;
Result = TRUE;
if ((ULONG)hMem & BASE_HANDLE_MARK_BIT) {
RtlLockHeap( BaseHeap );
try {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
#if DBG
PVOID ImageBase;
//
// If passed address is NOT part of an image file, then display
// a debug message. This prevents apps that call GlobalUnlock
// with the return value of LockResource from displaying the
// message.
//
if (!RtlPcToFileHeader( (PVOID)hMem, &ImageBase)) {
DbgPrint( "*** GlobalUnlock( %lx ) - invalid handle\n", hMem );
BaseHeapBreakPoint();
}
#endif
SetLastError( ERROR_INVALID_HANDLE );
}
else
if (HandleEntry->LockCount-- == 0) {
HandleEntry->LockCount++;
SetLastError( ERROR_NOT_LOCKED );
Result = FALSE;
}
else
if (HandleEntry->LockCount == 0) {
SetLastError( NO_ERROR );
Result = FALSE;
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
}
return( Result );
}
DWORD
WINAPI
GlobalSize(
HANDLE hMem
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
PVOID Handle;
ULONG Flags;
DWORD dwSize;
dwSize = 0xFFFFFFFF;
Flags = 0;
RtlLockHeap( BaseHeap );
try {
if (!((ULONG)hMem & BASE_HANDLE_MARK_BIT)) {
Handle = NULL;
if (!RtlGetUserInfoHeap( BaseHeap, Flags, hMem, &Handle, &Flags )) {
}
else
if (Handle == NULL || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
dwSize = RtlSizeHeap( BaseHeap, HEAP_NO_SERIALIZE, (PVOID)hMem );
}
else {
hMem = Handle;
}
}
if ((ULONG)hMem & BASE_HANDLE_MARK_BIT) {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
#if DBG
DbgPrint( "*** GlobalSize( %lx ) - invalid handle\n", hMem );
BaseHeapBreakPoint();
#endif
SetLastError( ERROR_INVALID_HANDLE );
}
else
if (HandleEntry->Flags & BASE_HANDLE_DISCARDED) {
dwSize = HandleEntry->Size;
}
else {
dwSize = RtlSizeHeap( BaseHeap, HEAP_NO_SERIALIZE, HandleEntry->Object );
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
if (dwSize == 0xFFFFFFFF) {
SetLastError( ERROR_INVALID_HANDLE );
return 0;
}
else {
return dwSize;
}
}
UINT
WINAPI
GlobalFlags(
HANDLE hMem
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
HANDLE Handle;
ULONG Flags;
UINT uFlags;
uFlags = GMEM_INVALID_HANDLE;
RtlLockHeap( BaseHeap );
try {
if (!((ULONG)hMem & BASE_HANDLE_MARK_BIT)) {
Handle = NULL;
Flags = 0;
if (!RtlGetUserInfoHeap( BaseHeap, Flags, hMem, &Handle, &Flags )) {
}
else
if (Handle == NULL || !(Flags & BASE_HEAP_FLAG_MOVEABLE)) {
uFlags = 0;
}
else {
hMem = Handle;
}
}
if ((ULONG)hMem & BASE_HANDLE_MARK_BIT) {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
if (RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;
if (HandleEntry->Flags & BASE_HANDLE_DISCARDED) {
uFlags |= GMEM_DISCARDED;
}
if (HandleEntry->Flags & BASE_HANDLE_DISCARDABLE) {
uFlags |= GMEM_DISCARDABLE;
}
if (HandleEntry->Flags & BASE_HANDLE_SHARED) {
uFlags |= GMEM_DDESHARE;
}
}
}
if (uFlags == GMEM_INVALID_HANDLE) {
#if DBG
DbgPrint( "*** GlobalFlags( %lx ) - invalid handle\n", hMem );
BaseHeapBreakPoint();
#endif
SetLastError( ERROR_INVALID_HANDLE );
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
return( uFlags );
}
HGLOBAL
WINAPI
GlobalFree(
HGLOBAL hMem
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
LPSTR p;
if (pfnWowGlobalFreeHook != NULL) {
if (!(*pfnWowGlobalFreeHook)(hMem)) {
return NULL;
}
}
if (!((ULONG)hMem & BASE_HANDLE_MARK_BIT)) {
if (RtlFreeHeap( BaseHeap, 0, (PVOID)hMem )) {
return NULL;
}
else {
SetLastError( ERROR_INVALID_HANDLE );
return hMem;
}
}
RtlLockHeap( BaseHeap );
try {
if ((ULONG)hMem & BASE_HANDLE_MARK_BIT) {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)
CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );
if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {
#if DBG
DbgPrint( "*** GlobalFree( %lx ) - invalid handle\n", hMem );
BaseHeapBreakPoint();
#endif
SetLastError( ERROR_INVALID_HANDLE );
p = NULL;
}
else {
#if DBG
if (HandleEntry->LockCount != 0) {
DbgPrint( "BASE: GlobalFree called with a locked object.\n" );
BaseHeapBreakPoint();
}
#endif
p = HandleEntry->Object;
RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
if (p == NULL) {
hMem = NULL;
}
}
}
else {
p = (LPSTR)hMem;
}
if (p != NULL) {
if (RtlFreeHeap( BaseHeap, HEAP_NO_SERIALIZE, p )) {
hMem = NULL;
}
else {
SetLastError( ERROR_INVALID_HANDLE );
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}
RtlUnlockHeap( BaseHeap );
return( hMem );
}
UINT
WINAPI
GlobalCompact(
DWORD dwMinFree
)
{
return RtlCompactHeap( BaseHeap, 0 );
}
VOID
WINAPI
GlobalFix(
HGLOBAL hMem
)
{
if (hMem != (HGLOBAL)-1) {
GlobalLock( hMem );
}
return;
}
VOID
WINAPI
GlobalUnfix(
HGLOBAL hMem
)
{
if (hMem != (HGLOBAL)-1) {
GlobalUnlock( hMem );
}
return;
}
LPVOID
WINAPI
GlobalWire(
HGLOBAL hMem
)
{
return GlobalLock( hMem );
}
BOOL
WINAPI
GlobalUnWire(
HGLOBAL hMem
)
{
return GlobalUnlock( hMem );
}
VOID
WINAPI
GlobalMemoryStatus(
LPMEMORYSTATUS lpBuffer
)
{
SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
VM_COUNTERS VmCounters;
QUOTA_LIMITS QuotaLimits;
DWORD AvailPageFile;
DWORD PhysicalMemory;
NTSTATUS Status;
Status = NtQuerySystemInformation(
SystemPerformanceInformation,
&PerfInfo,
sizeof(PerfInfo),
NULL
);
ASSERT(NT_SUCCESS(Status));
PhysicalMemory = BaseStaticServerData->SysInfo.NumberOfPhysicalPages * BaseStaticServerData->SysInfo.PageSize;
lpBuffer->dwLength = sizeof( *lpBuffer );
//
// Determine the memory load. < 100 available pages is 100
// > 1100 available pages is 0
//
if (PerfInfo.AvailablePages < 100) {
lpBuffer->dwMemoryLoad = 100;
} else {
(long)lpBuffer->dwMemoryLoad = 100 - (long)((PerfInfo.AvailablePages - 100) / 10);
if ((long)lpBuffer->dwMemoryLoad < 0) {
lpBuffer->dwMemoryLoad = 0;
}
}
lpBuffer->dwTotalPhys = PhysicalMemory;
PhysicalMemory = PerfInfo.AvailablePages;
PhysicalMemory *= BaseStaticServerData->SysInfo.PageSize;
lpBuffer->dwAvailPhys = PhysicalMemory;
//
// Zero returned values in case the query process fails.
//
RtlZeroMemory (&QuotaLimits, sizeof (QUOTA_LIMITS));
RtlZeroMemory (&VmCounters, sizeof (VM_COUNTERS));
Status = NtQueryInformationProcess (NtCurrentProcess(),
ProcessQuotaLimits,
&QuotaLimits,
sizeof(QUOTA_LIMITS),
NULL );
Status = NtQueryInformationProcess (NtCurrentProcess(),
ProcessVmCounters,
&VmCounters,
sizeof(VM_COUNTERS),
NULL );
//
// Determine the total page file space with respect to this process.
//
lpBuffer->dwTotalPageFile = PerfInfo.CommitLimit;
if (QuotaLimits.PagefileLimit < PerfInfo.CommitLimit) {
lpBuffer->dwTotalPageFile = QuotaLimits.PagefileLimit;
}
lpBuffer->dwTotalPageFile *= BaseStaticServerData->SysInfo.PageSize;
//
// Determine remaining page file space with respect to this process.
//
AvailPageFile = PerfInfo.CommitLimit - PerfInfo.CommittedPages;
lpBuffer->dwAvailPageFile =
QuotaLimits.PagefileLimit - VmCounters.PagefileUsage;
if ((ULONG)lpBuffer->dwTotalPageFile > (ULONG)AvailPageFile) {
lpBuffer->dwAvailPageFile = AvailPageFile;
}
lpBuffer->dwAvailPageFile *= BaseStaticServerData->SysInfo.PageSize;
lpBuffer->dwTotalVirtual = (BaseStaticServerData->SysInfo.MaximumUserModeAddress -
BaseStaticServerData->SysInfo.MinimumUserModeAddress) + 1;
lpBuffer->dwAvailVirtual = lpBuffer->dwTotalVirtual - VmCounters.VirtualSize;
return;
}
PVOID
WINAPI
VirtualAlloc(
PVOID lpAddress,
DWORD dwSize,
DWORD flAllocationType,
DWORD flProtect
)
{
return VirtualAllocEx(
NtCurrentProcess(),
lpAddress,
dwSize,
flAllocationType,
flProtect
);
}
BOOL
WINAPI
VirtualFree(
LPVOID lpAddress,
DWORD dwSize,
DWORD dwFreeType
)
{
return VirtualFreeEx(NtCurrentProcess(),lpAddress,dwSize,dwFreeType);
}
PVOID
WINAPI
VirtualAllocEx(
HANDLE hProcess,
PVOID lpAddress,
DWORD dwSize,
DWORD flAllocationType,
DWORD flProtect
)
{
NTSTATUS Status;
if (lpAddress != NULL && (ULONG)lpAddress < BaseStaticServerData->SysInfo.AllocationGranularity) {
SetLastError( ERROR_INVALID_PARAMETER );
return( NULL );
}
try {
Status = NtAllocateVirtualMemory( hProcess,
&lpAddress,
0,
&dwSize,
flAllocationType,
flProtect
);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Status = GetExceptionCode();
}
if (NT_SUCCESS( Status )) {
return( lpAddress );
}
else {
BaseSetLastNTError( Status );
return( NULL );
}
}
BOOL
WINAPI
VirtualFreeEx(
HANDLE hProcess,
LPVOID lpAddress,
DWORD dwSize,
DWORD dwFreeType
)
{
NTSTATUS Status;
if ( (dwFreeType & MEM_RELEASE ) && dwSize != 0 ) {
BaseSetLastNTError( STATUS_INVALID_PARAMETER );
return FALSE;
}
Status = NtFreeVirtualMemory( hProcess,
&lpAddress,
&dwSize,
dwFreeType
);
if (NT_SUCCESS( Status )) {
return( TRUE );
}
else {
BaseSetLastNTError( Status );
return( FALSE );
}
}
BOOL
WINAPI
VirtualProtect(
PVOID lpAddress,
DWORD dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
)
{
return VirtualProtectEx( NtCurrentProcess(),
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect
);
}
BOOL
WINAPI
VirtualProtectEx(
HANDLE hProcess,
PVOID lpAddress,
DWORD dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
)
{
NTSTATUS Status;
Status = NtProtectVirtualMemory( hProcess,
&lpAddress,
&dwSize,
flNewProtect,
lpflOldProtect
);
if (NT_SUCCESS( Status )) {
return( TRUE );
}
else {
BaseSetLastNTError( Status );
return( FALSE );
}
}
DWORD
WINAPI
VirtualQuery(
LPCVOID lpAddress,
PMEMORY_BASIC_INFORMATION lpBuffer,
DWORD dwLength
)
{
return VirtualQueryEx( NtCurrentProcess(),
lpAddress,
(PMEMORY_BASIC_INFORMATION)lpBuffer,
dwLength
);
}
DWORD
WINAPI
VirtualQueryEx(
HANDLE hProcess,
LPCVOID lpAddress,
PMEMORY_BASIC_INFORMATION lpBuffer,
DWORD dwLength
)
{
NTSTATUS Status;
ULONG ReturnLength;
Status = NtQueryVirtualMemory( hProcess,
(LPVOID)lpAddress,
MemoryBasicInformation,
(PMEMORY_BASIC_INFORMATION)lpBuffer,
dwLength,
&ReturnLength
);
if (NT_SUCCESS( Status )) {
return( ReturnLength );
}
else {
BaseSetLastNTError( Status );
return( 0 );
}
}
BOOL
WINAPI
VirtualLock(
LPVOID lpAddress,
DWORD dwSize
)
/*++
Routine Description:
This API may be used to lock the specified range of the processes
address space into memory. This range is present whenever the
application is running. All pages covered by the range must be
commited. VirtialLock is in now way related to LocalLock or
GlobalLock. It does not perform a handle translation. Its function
is to lock memory in the "working set" of the calling process.
Note that the specified range is used to compute the range of pages
covered by the lock. A 2 byte lock that straddles a page boundry
ends up locking both of the pages covered by the range. Also note
that calls to VirtualLock do not nest.
Arguments:
lpAddress - Supplies the base address of the region being locked.
dwSize - Supplies the number of bytes being locked.
Return Value:
TRUE - The operation was was successful.
FALSE - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS Status;
PVOID BaseAddress;
ULONG RegionSize;
BOOL ReturnValue;
ReturnValue = TRUE;
BaseAddress = lpAddress;
RegionSize = dwSize;
Status = NtLockVirtualMemory(
NtCurrentProcess(),
&lpAddress,
&RegionSize,
MAP_PROCESS
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
}
return ReturnValue;
}
BOOL
WINAPI
VirtualUnlock(
LPVOID lpAddress,
DWORD dwSize
)
/*++
Routine Description:
This API may be used to unlock the specified range of the processes
address space from memory. This call is used to reveres the effects of
a previous call to VirtualLock. The range specified need not match
a range passed to a previous VirtualLock call, but it must specify
a locked range" for this API to be successful.
Note that the specified range is used to compute the range of pages
covered by the unlock. A 2 byte unlock that straddles a page boundry
ends up unlocking both of the pages covered by the range.
Arguments:
lpAddress - Supplies the base address of the region being unlocked.
dwSize - Supplies the number of bytes being unlocked.
Return Value:
TRUE - The operation was was successful.
FALSE - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS Status;
PVOID BaseAddress;
ULONG RegionSize;
BOOL ReturnValue;
ReturnValue = TRUE;
BaseAddress = lpAddress;
RegionSize = dwSize;
Status = NtUnlockVirtualMemory(
NtCurrentProcess(),
&lpAddress,
&RegionSize,
MAP_PROCESS
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
}
return ReturnValue;
}
BOOL
WINAPI
FlushInstructionCache(
HANDLE hProcess,
LPCVOID lpBaseAddress,
DWORD dwSize
)
/*++
Routine Description:
This function flushes the instruction cache for the specified process.
Arguments:
hProcess - Supplies a handle to the process in which the instruction
cache is to be flushed.
lpBaseAddress - Supplies an optional pointer to base of the region that
is flushed.
dwSize - Supplies the length of the region that is flushed if the base
address is specified.
Return Value:
TRUE - The operation was was successful.
FALSE - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS Status;
BOOL ReturnValue = TRUE;
Status = NtFlushInstructionCache(
hProcess,
(LPVOID)lpBaseAddress,
dwSize
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
}
return ReturnValue;
}