📄 global.c
字号:
/*
* PROJECT: ReactOS Win32 Base API
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/win32/kernel32/mem/global.c
* PURPOSE: Global Memory APIs (sits on top of Heap*)
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <k32.h>
#define NDEBUG
#include "debug.h"
/* TYPES *********************************************************************/
extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
RTL_HANDLE_TABLE BaseHeapHandleTable;
/* FUNCTIONS ***************************************************************/
/*
* @implemented
*/
HGLOBAL
NTAPI
GlobalAlloc(UINT uFlags,
DWORD dwBytes)
{
ULONG Flags = 0;
PVOID Ptr = NULL;
HANDLE hMemory;
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
BASE_TRACE_ALLOC(dwBytes, uFlags);
ASSERT(hProcessHeap);
/* Make sure the flags are valid */
if (uFlags & ~GMEM_VALID_FLAGS)
{
/* They aren't, fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Convert ZEROINIT */
if (uFlags & GMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;
/* Check if we're not movable, which means pointer-based heap */
if (!(uFlags & GMEM_MOVEABLE))
{
/* Check if this is DDESHARE (deprecated) */
if (uFlags & GMEM_DDESHARE) Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
/* Allocate heap for it */
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
BASE_TRACE_ALLOC2(Ptr);
return Ptr;
}
/* This is heap based, so lock it in first */
RtlLockHeap(hProcessHeap);
/*
* Disable locking, enable custom flags, and write the
* movable flag (deprecated)
*/
Flags |= HEAP_NO_SERIALIZE |
HEAP_SETTABLE_USER_VALUE |
BASE_HEAP_FLAG_MOVABLE;
/* Allocate the handle */
HandleEntry = BaseHeapAllocEntry();
if (!HandleEntry)
{
/* Fail */
hMemory = NULL;
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
BASE_TRACE_FAILURE();
goto Quickie;
}
/* Get the object and make sure we have size */
hMemory = &HandleEntry->Object;
if (dwBytes)
{
/* Allocate the actual memory for it */
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
BASE_TRACE_PTR(HandleEntry, Ptr);
if (!Ptr)
{
/* We failed, manually set the allocate flag and free the handle */
HandleEntry->Flags = RTL_HANDLE_VALID;
BaseHeapFreeEntry(HandleEntry);
/* For the cleanup case */
HandleEntry = NULL;
}
else
{
/* All worked well, save our heap entry */
RtlSetUserValueHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, hMemory);
}
}
Quickie:
/* Cleanup! First unlock the heap */
RtlUnlockHeap(hProcessHeap);
/* Check if a handle was allocated */
if (HandleEntry)
{
/* Set the pointer and allocated flag */
HandleEntry->Object = Ptr;
HandleEntry->Flags = RTL_HANDLE_VALID;
if (!Ptr)
{
/* We don't have a valid pointer, but so reuse this handle */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;
}
/* Check if the handle is discardable */
if (uFlags & GMEM_DISCARDABLE)
{
/* Save it in the handle entry */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
}
/* Check if the handle is moveable */
if (uFlags & GMEM_MOVEABLE)
{
/* Save it in the handle entry */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE;
}
/* Check if the handle is DDE Shared */
if (uFlags & GMEM_DDESHARE)
{
/* Save it in the handle entry */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
}
/* Set the pointer */
Ptr = hMemory;
}
/* Return the pointer */
return Ptr;
}
/*
* @implemented
*/
SIZE_T
NTAPI
GlobalCompact(DWORD dwMinFree)
{
/* Call the RTL Heap Manager */
return RtlCompactHeap(hProcessHeap, 0);
}
/*
* @implemented
*/
VOID
NTAPI
GlobalFix(HGLOBAL hMem)
{
/* Lock the memory if it the handle is valid */
if (INVALID_HANDLE_VALUE != hMem) GlobalLock(hMem);
}
/*
* @implemented
*/
UINT
NTAPI
GlobalFlags(HGLOBAL hMem)
{
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
HANDLE Handle = NULL;
ULONG Flags = 0;
UINT uFlags = GMEM_INVALID_HANDLE;
/* Start by locking the heap */
RtlLockHeap(hProcessHeap);
/* Check if this is a simple RTL Heap Managed block */
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{
/* Then we'll query RTL Heap */
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
BASE_TRACE_PTR(Handle, hMem);
/*
* Check if RTL Heap didn't find a handle associated with us or
* said that this heap isn't movable, which means something we're
* really not a handle-based heap.
*/
if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{
/* Then set the flags to 0 */
uFlags = 0;
}
else
{
/* Otherwise we're handle-based, so get the internal handle */
hMem = Handle;
}
}
/* Check if the handle is actually an entry in our table */
if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
{
/* Then get the entry */
HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure it's a valid handle */
if (BaseHeapValidateEntry(HandleEntry))
{
/* Get the lock count first */
uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;
/* Now check if it's discarded */
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
{
/* Set the Win32 Flag */
uFlags |= GMEM_DISCARDED;
}
/* Check if it's movable */
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_MOVABLE)
{
/* Set the Win32 Flag */
uFlags |= GMEM_MOVEABLE;
}
/* Check if it's DDE Shared */
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_DDESHARE)
{
/* Set the Win32 Flag */
uFlags |= GMEM_DDESHARE;
}
}
}
/* Check if by now, we still haven't gotten any useful flags */
if (uFlags == GMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE);
/* All done! Unlock heap and return Win32 Flags */
RtlUnlockHeap(hProcessHeap);
return uFlags;
}
/*
* @implemented
*/
HGLOBAL
NTAPI
GlobalFree(HGLOBAL hMem)
{
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
LPVOID Ptr;
BASE_TRACE_DEALLOC(hMem);
/* Check if this was a simple allocated heap entry */
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{
/* Free it with the RTL Heap Manager */
if (RtlFreeHeap(hProcessHeap, 0, hMem))
{
/* Return NULL since there's no handle */
return NULL;
}
else
{
/* Otherwise fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_HANDLE);
return hMem;
}
}
/* It's a handle probably, so lock the heap */
RtlLockHeap(hProcessHeap);
/* Make sure that this is an entry in our handle database */
if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
{
/* Get the entry */
HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure the handle is valid */
if (!BaseHeapValidateEntry(HandleEntry))
{
/* It's not, fail */
SetLastError(ERROR_INVALID_HANDLE);
Ptr = NULL;
}
else
{
/* It's valid, so get the pointer */
Ptr = HandleEntry->Object;
/* Free this handle */
BaseHeapFreeEntry(HandleEntry);
/* If the pointer is 0, then we don't have a handle either */
if (!Ptr) hMem = NULL;
}
}
else
{
/* Otherwise, reuse the handle as a pointer */
BASE_TRACE_FAILURE();
Ptr = hMem;
}
/* Check if we got here with a valid heap pointer */
if (Ptr)
{
/* Free it */
RtlFreeHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr);
hMem = NULL;
}
/* We're done, so unlock the heap and return the handle */
RtlUnlockHeap(hProcessHeap);
return hMem;
}
/*
* @implemented
*/
HGLOBAL
NTAPI
GlobalHandle(LPCVOID pMem)
{
HANDLE Handle = NULL;
ULONG Flags;
/* Lock the heap */
RtlLockHeap(hProcessHeap);
/* Query RTL Heap */
RtlGetUserInfoHeap(hProcessHeap,
HEAP_NO_SERIALIZE,
(PVOID)pMem,
&Handle,
&Flags);
BASE_TRACE_PTR(Handle, pMem);
/*
* Check if RTL Heap didn't find a handle for us or said that
* this heap isn't movable.
*/
if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{
/* We're actually handle-based, so the pointer is a handle */
Handle = (HANDLE)pMem;
}
/* All done, unlock the heap and return the handle */
RtlUnlockHeap(hProcessHeap);
return Handle;
}
/*
* @implemented
*/
LPVOID
NTAPI
GlobalLock(HGLOBAL hMem)
{
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
LPVOID Ptr;
/* Check if this was a simple allocated heap entry */
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{
/* Then simply return the pointer */
return hMem;
}
/* Otherwise, lock the heap */
RtlLockHeap(hProcessHeap);
/* Get the handle entry */
HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure it's valid */
if (!BaseHeapValidateEntry(HandleEntry))
{
/* It's not, fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_HANDLE);
Ptr = NULL;
}
else
{
/* Otherwise, get the pointer */
Ptr = HandleEntry->Object;
if (Ptr)
{
/* Increase the lock count, unless we've went too far */
if (HandleEntry->LockCount++ == GMEM_LOCKCOUNT)
{
/* In which case we simply unlock once */
HandleEntry->LockCount--;
}
}
else
{
/* The handle is still there but the memory was already freed */
SetLastError(ERROR_DISCARDED);
}
}
/* All done. Unlock the heap and return the pointer */
RtlUnlockHeap(hProcessHeap);
return Ptr;
}
HGLOBAL
NTAPI
GlobalReAlloc(HGLOBAL hMem,
DWORD dwBytes,
UINT uFlags)
{
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
HANDLE Handle;
LPVOID Ptr;
ULONG Flags = 0;
/* Convert ZEROINIT */
if (uFlags & GMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;
/* If this wasn't a movable heap, then we MUST re-alloc in place */
if (!(uFlags & GMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
/* Lock the heap and disable built-in locking in the RTL Heap funcitons */
RtlLockHeap(hProcessHeap);
Flags |= HEAP_NO_SERIALIZE;
/* Check if this is a simple handle-based block */
if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{
/* Get the entry */
HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure the handle is valid */
if (!BaseHeapValidateEntry(HandleEntry))
{
/* Fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_HANDLE);
hMem = NULL;
}
else if (uFlags & GMEM_MODIFY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -