mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 00:27:13 +00:00
- Fixup Local* Heap implementation so that calls which have different semantics don't call the Global APIs (ie: LocalAlloc/LocalReAlloc and LocalFlags). The rest can be shared beteween them. Also fix some prototypes.
- Rename all the defintions to BASE_HEAP instead of GLOBAL_HEAP, since they apply just as well to the Local Heap. svn path=/trunk/; revision=22582
This commit is contained in:
parent
aa75a24d24
commit
8ec0cfcce6
5 changed files with 459 additions and 145 deletions
|
@ -36,7 +36,7 @@
|
||||||
//
|
//
|
||||||
// The Handle Table
|
// The Handle Table
|
||||||
//
|
//
|
||||||
extern RTL_HANDLE_TABLE BaseGlobalHandleTable;
|
extern RTL_HANDLE_TABLE BaseHeapHandleTable;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tracing Support
|
// Tracing Support
|
||||||
|
@ -62,13 +62,15 @@ extern RTL_HANDLE_TABLE BaseGlobalHandleTable;
|
||||||
#define BASE_TRACE_DEALLOC(x) \
|
#define BASE_TRACE_DEALLOC(x) \
|
||||||
BH_PRINT("[BASE_HEAP] %s : Freeing %p\n", \
|
BH_PRINT("[BASE_HEAP] %s : Freeing %p\n", \
|
||||||
__FUNCTION__, x)
|
__FUNCTION__, x)
|
||||||
|
#define BASE_TRACE_FAILURE() \
|
||||||
|
BH_PRINT("[BASE_HEAP] %s : Failing %d\n", \
|
||||||
|
__FUNCTION__, __LINE__)
|
||||||
//
|
//
|
||||||
// The handle structure for global heap handles.
|
// The handle structure for global heap handles.
|
||||||
// Notice that it nicely overlays with RTL_HANDLE_ENTRY.
|
// Notice that it nicely overlays with RTL_HANDLE_ENTRY.
|
||||||
// KEEP IT THAT WAY! ;-)
|
// KEEP IT THAT WAY! ;-)
|
||||||
//
|
//
|
||||||
typedef struct _GLOBAL_HEAP_HANDLE_ENTRY
|
typedef struct _BASE_HEAP_HANDLE_ENTRY
|
||||||
{
|
{
|
||||||
USHORT Flags;
|
USHORT Flags;
|
||||||
USHORT LockCount;
|
USHORT LockCount;
|
||||||
|
@ -77,45 +79,45 @@ typedef struct _GLOBAL_HEAP_HANDLE_ENTRY
|
||||||
PVOID Object;
|
PVOID Object;
|
||||||
ULONG OldSize;
|
ULONG OldSize;
|
||||||
};
|
};
|
||||||
} GLOBAL_HEAP_HANDLE_ENTRY, *PGLOBAL_HEAP_HANDLE_ENTRY;
|
} BASE_HEAP_HANDLE_ENTRY, *PBASE_HEAP_HANDLE_ENTRY;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle entry flags
|
// Handle entry flags
|
||||||
// Note that 0x0001 is the shared/generic RTL_HANDLE_VALID
|
// Note that 0x0001 is the shared/generic RTL_HANDLE_VALID
|
||||||
//
|
//
|
||||||
#define GLOBAL_HEAP_ENTRY_FLAG_MOVABLE 0x0002
|
#define BASE_HEAP_ENTRY_FLAG_MOVABLE 0x0002
|
||||||
#define GLOBAL_HEAP_ENTRY_FLAG_REUSABLE 0x0004
|
#define BASE_HEAP_ENTRY_FLAG_REUSABLE 0x0004
|
||||||
#define GLOBAL_HEAP_ENTRY_FLAG_REUSE 0x0008
|
#define BASE_HEAP_ENTRY_FLAG_REUSE 0x0008
|
||||||
#define GLOBAL_HEAP_ENTRY_FLAG_DDESHARE 0x0010
|
#define BASE_HEAP_ENTRY_FLAG_DDESHARE 0x0010
|
||||||
|
|
||||||
//
|
//
|
||||||
// Easy way to check if the global handle is actually an entry in our table
|
// Easy way to check if the global handle is actually an entry in our table
|
||||||
//
|
//
|
||||||
#define GLOBAL_HEAP_IS_HANDLE_ENTRY \
|
#define BASE_HEAP_IS_HANDLE_ENTRY \
|
||||||
(ULONG_PTR)FIELD_OFFSET(GLOBAL_HEAP_HANDLE_ENTRY, Object)
|
(ULONG_PTR)FIELD_OFFSET(BASE_HEAP_HANDLE_ENTRY, Object)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tags for the entire heap allocation for this global memory.
|
// Tags for the entire heap allocation for this global memory.
|
||||||
// They are set part of the User Flags of the RTL Heap.
|
// They are set part of the User Flags of the RTL Heap.
|
||||||
//
|
//
|
||||||
#define GLOBAL_HEAP_FLAG_MOVABLE HEAP_SETTABLE_USER_FLAG1
|
#define BASE_HEAP_FLAG_MOVABLE HEAP_SETTABLE_USER_FLAG1
|
||||||
#define GLOBAL_HEAP_FLAG_DDESHARE HEAP_SETTABLE_USER_FLAG2
|
#define BASE_HEAP_FLAG_DDESHARE HEAP_SETTABLE_USER_FLAG2
|
||||||
|
|
||||||
//
|
//
|
||||||
// Internal Handle Functions
|
// Internal Handle Functions
|
||||||
//
|
//
|
||||||
#define GlobalAllocEntry() \
|
#define BaseHeapAllocEntry() \
|
||||||
(PGLOBAL_HEAP_HANDLE_ENTRY)RtlAllocateHandle(&BaseGlobalHandleTable, NULL)
|
(PBASE_HEAP_HANDLE_ENTRY)RtlAllocateHandle(&BaseHeapHandleTable, NULL)
|
||||||
|
|
||||||
#define GlobalGetEntry(h) \
|
#define BaseHeapGetEntry(h) \
|
||||||
(PGLOBAL_HEAP_HANDLE_ENTRY) \
|
(PBASE_HEAP_HANDLE_ENTRY) \
|
||||||
CONTAINING_RECORD(h, \
|
CONTAINING_RECORD(h, \
|
||||||
GLOBAL_HEAP_HANDLE_ENTRY, \
|
BASE_HEAP_HANDLE_ENTRY, \
|
||||||
Object);
|
Object);
|
||||||
|
|
||||||
#define GlobalValidateEntry(he) \
|
#define BaseHeapValidateEntry(he) \
|
||||||
RtlIsValidHandle(&BaseGlobalHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he)
|
RtlIsValidHandle(&BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he)
|
||||||
|
|
||||||
#define GlobalFreeEntry(he) \
|
#define BaseHeapFreeEntry(he) \
|
||||||
RtlFreeHandle(&BaseGlobalHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he);
|
RtlFreeHandle(&BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he);
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,10 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#define BASE_TRACE_FAILURE() \
|
|
||||||
DbgPrint("[BASE_HEAP] %s : Failing %d\n", \
|
|
||||||
__FUNCTION__, __LINE__)
|
|
||||||
|
|
||||||
/* TYPES *********************************************************************/
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
|
extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
|
||||||
RTL_HANDLE_TABLE BaseGlobalHandleTable;
|
RTL_HANDLE_TABLE BaseHeapHandleTable;
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
@ -35,7 +31,7 @@ GlobalAlloc(UINT uFlags,
|
||||||
ULONG Flags = 0;
|
ULONG Flags = 0;
|
||||||
PVOID Ptr = NULL;
|
PVOID Ptr = NULL;
|
||||||
HANDLE hMemory;
|
HANDLE hMemory;
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
BASE_TRACE_ALLOC(dwBytes, uFlags);
|
BASE_TRACE_ALLOC(dwBytes, uFlags);
|
||||||
ASSERT(hProcessHeap);
|
ASSERT(hProcessHeap);
|
||||||
|
|
||||||
|
@ -55,7 +51,7 @@ GlobalAlloc(UINT uFlags,
|
||||||
if (!(uFlags & GMEM_MOVEABLE))
|
if (!(uFlags & GMEM_MOVEABLE))
|
||||||
{
|
{
|
||||||
/* Check if this is DDESHARE (deprecated) */
|
/* Check if this is DDESHARE (deprecated) */
|
||||||
if (uFlags & GMEM_DDESHARE) Flags |= GLOBAL_HEAP_ENTRY_FLAG_DDESHARE;
|
if (uFlags & GMEM_DDESHARE) Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
|
||||||
|
|
||||||
/* Allocate heap for it */
|
/* Allocate heap for it */
|
||||||
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
|
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
|
||||||
|
@ -72,10 +68,10 @@ GlobalAlloc(UINT uFlags,
|
||||||
*/
|
*/
|
||||||
Flags |= HEAP_NO_SERIALIZE |
|
Flags |= HEAP_NO_SERIALIZE |
|
||||||
HEAP_SETTABLE_USER_VALUE |
|
HEAP_SETTABLE_USER_VALUE |
|
||||||
GLOBAL_HEAP_FLAG_MOVABLE;
|
BASE_HEAP_FLAG_MOVABLE;
|
||||||
|
|
||||||
/* Allocate the handle */
|
/* Allocate the handle */
|
||||||
HandleEntry = GlobalAllocEntry();
|
HandleEntry = BaseHeapAllocEntry();
|
||||||
if (!HandleEntry)
|
if (!HandleEntry)
|
||||||
{
|
{
|
||||||
/* Fail */
|
/* Fail */
|
||||||
|
@ -96,7 +92,7 @@ GlobalAlloc(UINT uFlags,
|
||||||
{
|
{
|
||||||
/* We failed, manually set the allocate flag and free the handle */
|
/* We failed, manually set the allocate flag and free the handle */
|
||||||
HandleEntry->Flags = RTL_HANDLE_VALID;
|
HandleEntry->Flags = RTL_HANDLE_VALID;
|
||||||
GlobalFreeEntry(HandleEntry);
|
BaseHeapFreeEntry(HandleEntry);
|
||||||
|
|
||||||
/* For the cleanup case */
|
/* For the cleanup case */
|
||||||
HandleEntry = NULL;
|
HandleEntry = NULL;
|
||||||
|
@ -121,28 +117,28 @@ Quickie:
|
||||||
if (!Ptr)
|
if (!Ptr)
|
||||||
{
|
{
|
||||||
/* We don't have a valid pointer, but so reuse this handle */
|
/* We don't have a valid pointer, but so reuse this handle */
|
||||||
HandleEntry->Flags = GLOBAL_HEAP_ENTRY_FLAG_REUSE;
|
HandleEntry->Flags = BASE_HEAP_ENTRY_FLAG_REUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the handle is discardable */
|
/* Check if the handle is discardable */
|
||||||
if (uFlags & GMEM_DISCARDABLE)
|
if (uFlags & GMEM_DISCARDABLE)
|
||||||
{
|
{
|
||||||
/* Save it in the handle entry */
|
/* Save it in the handle entry */
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the handle is moveable */
|
/* Check if the handle is moveable */
|
||||||
if (uFlags & GMEM_MOVEABLE)
|
if (uFlags & GMEM_MOVEABLE)
|
||||||
{
|
{
|
||||||
/* Save it in the handle entry */
|
/* Save it in the handle entry */
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_MOVABLE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the handle is DDE Shared */
|
/* Check if the handle is DDE Shared */
|
||||||
if (uFlags & GMEM_DDESHARE)
|
if (uFlags & GMEM_DDESHARE)
|
||||||
{
|
{
|
||||||
/* Save it in the handle entry */
|
/* Save it in the handle entry */
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_DDESHARE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the pointer */
|
/* Set the pointer */
|
||||||
|
@ -182,7 +178,7 @@ UINT
|
||||||
NTAPI
|
NTAPI
|
||||||
GlobalFlags(HGLOBAL hMem)
|
GlobalFlags(HGLOBAL hMem)
|
||||||
{
|
{
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
HANDLE Handle = NULL;
|
HANDLE Handle = NULL;
|
||||||
ULONG Flags = 0;
|
ULONG Flags = 0;
|
||||||
UINT uFlags = GMEM_INVALID_HANDLE;
|
UINT uFlags = GMEM_INVALID_HANDLE;
|
||||||
|
@ -191,7 +187,7 @@ GlobalFlags(HGLOBAL hMem)
|
||||||
RtlLockHeap(hProcessHeap);
|
RtlLockHeap(hProcessHeap);
|
||||||
|
|
||||||
/* Check if this is a simple RTL Heap Managed block */
|
/* Check if this is a simple RTL Heap Managed block */
|
||||||
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY))
|
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
|
||||||
{
|
{
|
||||||
/* Then we'll query RTL Heap */
|
/* Then we'll query RTL Heap */
|
||||||
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
|
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
|
||||||
|
@ -202,7 +198,7 @@ GlobalFlags(HGLOBAL hMem)
|
||||||
* said that this heap isn't movable, which means something we're
|
* said that this heap isn't movable, which means something we're
|
||||||
* really not a handle-based heap.
|
* really not a handle-based heap.
|
||||||
*/
|
*/
|
||||||
if (!(Handle) || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE))
|
if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
|
||||||
{
|
{
|
||||||
/* Then set the flags to 0 */
|
/* Then set the flags to 0 */
|
||||||
uFlags = 0;
|
uFlags = 0;
|
||||||
|
@ -215,34 +211,34 @@ GlobalFlags(HGLOBAL hMem)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the handle is actually an entry in our table */
|
/* Check if the handle is actually an entry in our table */
|
||||||
if ((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)
|
if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
|
||||||
{
|
{
|
||||||
/* Then get the entry */
|
/* Then get the entry */
|
||||||
HandleEntry = GlobalGetEntry(hMem);
|
HandleEntry = BaseHeapGetEntry(hMem);
|
||||||
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
||||||
|
|
||||||
/* Make sure it's a valid handle */
|
/* Make sure it's a valid handle */
|
||||||
if (GlobalValidateEntry(HandleEntry))
|
if (BaseHeapValidateEntry(HandleEntry))
|
||||||
{
|
{
|
||||||
/* Get the lock count first */
|
/* Get the lock count first */
|
||||||
uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;
|
uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;
|
||||||
|
|
||||||
/* Now check if it's discarded */
|
/* Now check if it's discarded */
|
||||||
if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_REUSABLE)
|
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
|
||||||
{
|
{
|
||||||
/* Set the Win32 Flag */
|
/* Set the Win32 Flag */
|
||||||
uFlags |= GMEM_DISCARDED;
|
uFlags |= GMEM_DISCARDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if it's movable */
|
/* Check if it's movable */
|
||||||
if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_MOVABLE)
|
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_MOVABLE)
|
||||||
{
|
{
|
||||||
/* Set the Win32 Flag */
|
/* Set the Win32 Flag */
|
||||||
uFlags |= GMEM_MOVEABLE;
|
uFlags |= GMEM_MOVEABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if it's DDE Shared */
|
/* Check if it's DDE Shared */
|
||||||
if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_DDESHARE)
|
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_DDESHARE)
|
||||||
{
|
{
|
||||||
/* Set the Win32 Flag */
|
/* Set the Win32 Flag */
|
||||||
uFlags |= GMEM_DDESHARE;
|
uFlags |= GMEM_DDESHARE;
|
||||||
|
@ -265,12 +261,12 @@ HGLOBAL
|
||||||
NTAPI
|
NTAPI
|
||||||
GlobalFree(HGLOBAL hMem)
|
GlobalFree(HGLOBAL hMem)
|
||||||
{
|
{
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
LPVOID Ptr;
|
LPVOID Ptr;
|
||||||
BASE_TRACE_DEALLOC(hMem);
|
BASE_TRACE_DEALLOC(hMem);
|
||||||
|
|
||||||
/* Check if this was a simple allocated heap entry */
|
/* Check if this was a simple allocated heap entry */
|
||||||
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY))
|
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
|
||||||
{
|
{
|
||||||
/* Free it with the RTL Heap Manager */
|
/* Free it with the RTL Heap Manager */
|
||||||
if (RtlFreeHeap(hProcessHeap, 0, hMem))
|
if (RtlFreeHeap(hProcessHeap, 0, hMem))
|
||||||
|
@ -291,14 +287,14 @@ GlobalFree(HGLOBAL hMem)
|
||||||
RtlLockHeap(hProcessHeap);
|
RtlLockHeap(hProcessHeap);
|
||||||
|
|
||||||
/* Make sure that this is an entry in our handle database */
|
/* Make sure that this is an entry in our handle database */
|
||||||
if ((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)
|
if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
|
||||||
{
|
{
|
||||||
/* Get the entry */
|
/* Get the entry */
|
||||||
HandleEntry = GlobalGetEntry(hMem);
|
HandleEntry = BaseHeapGetEntry(hMem);
|
||||||
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
||||||
|
|
||||||
/* Make sure the handle is valid */
|
/* Make sure the handle is valid */
|
||||||
if (!GlobalValidateEntry(HandleEntry))
|
if (!BaseHeapValidateEntry(HandleEntry))
|
||||||
{
|
{
|
||||||
/* It's not, fail */
|
/* It's not, fail */
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
@ -310,7 +306,7 @@ GlobalFree(HGLOBAL hMem)
|
||||||
Ptr = HandleEntry->Object;
|
Ptr = HandleEntry->Object;
|
||||||
|
|
||||||
/* Free this handle */
|
/* Free this handle */
|
||||||
GlobalFreeEntry(HandleEntry);
|
BaseHeapFreeEntry(HandleEntry);
|
||||||
|
|
||||||
/* If the pointer is 0, then we don't have a handle either */
|
/* If the pointer is 0, then we don't have a handle either */
|
||||||
if (!Ptr) hMem = NULL;
|
if (!Ptr) hMem = NULL;
|
||||||
|
@ -361,7 +357,7 @@ GlobalHandle(LPCVOID pMem)
|
||||||
* Check if RTL Heap didn't find a handle for us or said that
|
* Check if RTL Heap didn't find a handle for us or said that
|
||||||
* this heap isn't movable.
|
* this heap isn't movable.
|
||||||
*/
|
*/
|
||||||
if (!(Handle) || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE))
|
if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
|
||||||
{
|
{
|
||||||
/* We're actually handle-based, so the pointer is a handle */
|
/* We're actually handle-based, so the pointer is a handle */
|
||||||
Handle = (HANDLE)pMem;
|
Handle = (HANDLE)pMem;
|
||||||
|
@ -379,11 +375,11 @@ LPVOID
|
||||||
NTAPI
|
NTAPI
|
||||||
GlobalLock(HGLOBAL hMem)
|
GlobalLock(HGLOBAL hMem)
|
||||||
{
|
{
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
LPVOID Ptr;
|
LPVOID Ptr;
|
||||||
|
|
||||||
/* Check if this was a simple allocated heap entry */
|
/* Check if this was a simple allocated heap entry */
|
||||||
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY))
|
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
|
||||||
{
|
{
|
||||||
/* Then simply return the pointer */
|
/* Then simply return the pointer */
|
||||||
return hMem;
|
return hMem;
|
||||||
|
@ -393,11 +389,11 @@ GlobalLock(HGLOBAL hMem)
|
||||||
RtlLockHeap(hProcessHeap);
|
RtlLockHeap(hProcessHeap);
|
||||||
|
|
||||||
/* Get the handle entry */
|
/* Get the handle entry */
|
||||||
HandleEntry = GlobalGetEntry(hMem);
|
HandleEntry = BaseHeapGetEntry(hMem);
|
||||||
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
||||||
|
|
||||||
/* Make sure it's valid */
|
/* Make sure it's valid */
|
||||||
if (!GlobalValidateEntry(HandleEntry))
|
if (!BaseHeapValidateEntry(HandleEntry))
|
||||||
{
|
{
|
||||||
/* It's not, fail */
|
/* It's not, fail */
|
||||||
BASE_TRACE_FAILURE();
|
BASE_TRACE_FAILURE();
|
||||||
|
@ -435,7 +431,7 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
DWORD dwBytes,
|
DWORD dwBytes,
|
||||||
UINT uFlags)
|
UINT uFlags)
|
||||||
{
|
{
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
LPVOID Ptr;
|
LPVOID Ptr;
|
||||||
ULONG Flags = 0;
|
ULONG Flags = 0;
|
||||||
|
@ -449,17 +445,16 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
/* Lock the heap and disable built-in locking in the RTL Heap funcitons */
|
/* Lock the heap and disable built-in locking in the RTL Heap funcitons */
|
||||||
RtlLockHeap(hProcessHeap);
|
RtlLockHeap(hProcessHeap);
|
||||||
Flags |= HEAP_NO_SERIALIZE;
|
Flags |= HEAP_NO_SERIALIZE;
|
||||||
DPRINT1("hmem: %p Flags: %lx\n", hMem, uFlags);
|
|
||||||
|
|
||||||
/* Check if this is a simple handle-based block */
|
/* Check if this is a simple handle-based block */
|
||||||
if (((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY))
|
if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
|
||||||
{
|
{
|
||||||
/* Get the entry */
|
/* Get the entry */
|
||||||
HandleEntry = GlobalGetEntry(hMem);
|
HandleEntry = BaseHeapGetEntry(hMem);
|
||||||
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
||||||
|
|
||||||
/* Make sure the handle is valid */
|
/* Make sure the handle is valid */
|
||||||
if (!GlobalValidateEntry(HandleEntry))
|
if (!BaseHeapValidateEntry(HandleEntry))
|
||||||
{
|
{
|
||||||
/* Fail */
|
/* Fail */
|
||||||
BASE_TRACE_FAILURE();
|
BASE_TRACE_FAILURE();
|
||||||
|
@ -472,12 +467,12 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
if (uFlags & GMEM_DISCARDABLE)
|
if (uFlags & GMEM_DISCARDABLE)
|
||||||
{
|
{
|
||||||
/* Then set the flag */
|
/* Then set the flag */
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Otherwise, remove the flag */
|
/* Otherwise, remove the flag */
|
||||||
HandleEntry->Flags &= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE;
|
HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -498,7 +493,7 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
|
|
||||||
/* Free the handle */
|
/* Free the handle */
|
||||||
HandleEntry->Object = NULL;
|
HandleEntry->Object = NULL;
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;
|
||||||
|
|
||||||
/* Get the object pointer */
|
/* Get the object pointer */
|
||||||
hMem = &HandleEntry->Object;
|
hMem = &HandleEntry->Object;
|
||||||
|
@ -513,7 +508,7 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Otherwise, we're allocating, so set the new flags needed */
|
/* Otherwise, we're allocating, so set the new flags needed */
|
||||||
Flags |= HEAP_SETTABLE_USER_VALUE | GLOBAL_HEAP_FLAG_MOVABLE;
|
Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
|
||||||
if (!Ptr)
|
if (!Ptr)
|
||||||
{
|
{
|
||||||
/* We don't have a base, so allocate one */
|
/* We don't have a base, so allocate one */
|
||||||
|
@ -554,7 +549,7 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
{
|
{
|
||||||
/* Write it in the handle entry and mark it in use */
|
/* Write it in the handle entry and mark it in use */
|
||||||
HandleEntry->Object = Ptr;
|
HandleEntry->Object = Ptr;
|
||||||
HandleEntry->Flags &= ~GLOBAL_HEAP_ENTRY_FLAG_REUSE;
|
HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -584,16 +579,16 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
* Check if the handle matches the pointer or if the moveable flag
|
* Check if the handle matches the pointer or if the moveable flag
|
||||||
* isn't there, which is what we expect since it currenly isn't.
|
* isn't there, which is what we expect since it currenly isn't.
|
||||||
*/
|
*/
|
||||||
if (Handle == hMem || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE))
|
if (Handle == hMem || !(Flags & BASE_HEAP_FLAG_MOVABLE))
|
||||||
{
|
{
|
||||||
/* Allocate a handle for it */
|
/* Allocate a handle for it */
|
||||||
HandleEntry = GlobalAllocEntry();
|
HandleEntry = BaseHeapAllocEntry();
|
||||||
|
|
||||||
/* Calculate the size of the current heap */
|
/* Calculate the size of the current heap */
|
||||||
dwBytes = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
|
dwBytes = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
|
||||||
|
|
||||||
/* Set the movable flag */
|
/* Set the movable flag */
|
||||||
Flags |= HEAP_SETTABLE_USER_VALUE | GLOBAL_HEAP_FLAG_MOVABLE;
|
Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
|
||||||
|
|
||||||
/* Now allocate the actual heap for it */
|
/* Now allocate the actual heap for it */
|
||||||
HandleEntry->Object = RtlAllocateHeap(hProcessHeap,
|
HandleEntry->Object = RtlAllocateHeap(hProcessHeap,
|
||||||
|
@ -607,7 +602,7 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
* free the handle
|
* free the handle
|
||||||
*/
|
*/
|
||||||
HandleEntry->Flags = RTL_HANDLE_VALID;
|
HandleEntry->Flags = RTL_HANDLE_VALID;
|
||||||
GlobalFreeEntry(HandleEntry);
|
BaseHeapFreeEntry(HandleEntry);
|
||||||
|
|
||||||
/* For the cleanup case */
|
/* For the cleanup case */
|
||||||
BASE_TRACE_FAILURE();
|
BASE_TRACE_FAILURE();
|
||||||
|
@ -626,20 +621,20 @@ GlobalReAlloc(HGLOBAL hMem,
|
||||||
/* Initialize the count and default flags */
|
/* Initialize the count and default flags */
|
||||||
HandleEntry->LockCount = 0;
|
HandleEntry->LockCount = 0;
|
||||||
HandleEntry->Flags = RTL_HANDLE_VALID |
|
HandleEntry->Flags = RTL_HANDLE_VALID |
|
||||||
GLOBAL_HEAP_ENTRY_FLAG_MOVABLE;
|
BASE_HEAP_ENTRY_FLAG_MOVABLE;
|
||||||
|
|
||||||
/* Check if it's also discardable */
|
/* Check if it's also discardable */
|
||||||
if (uFlags & GMEM_DISCARDABLE)
|
if (uFlags & GMEM_DISCARDABLE)
|
||||||
{
|
{
|
||||||
/* Set the internal flag */
|
/* Set the internal flag */
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if it's also DDE Shared */
|
/* Check if it's also DDE Shared */
|
||||||
if (uFlags & GMEM_DDESHARE)
|
if (uFlags & GMEM_DDESHARE)
|
||||||
{
|
{
|
||||||
/* Set the internal flag */
|
/* Set the internal flag */
|
||||||
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_DDESHARE;
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocation succeeded, so save our entry */
|
/* Allocation succeeded, so save our entry */
|
||||||
|
@ -678,7 +673,7 @@ DWORD
|
||||||
NTAPI
|
NTAPI
|
||||||
GlobalSize(HGLOBAL hMem)
|
GlobalSize(HGLOBAL hMem)
|
||||||
{
|
{
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
PVOID Handle = NULL;
|
PVOID Handle = NULL;
|
||||||
ULONG Flags = 0;
|
ULONG Flags = 0;
|
||||||
SIZE_T dwSize = MAXULONG_PTR;
|
SIZE_T dwSize = MAXULONG_PTR;
|
||||||
|
@ -687,7 +682,7 @@ GlobalSize(HGLOBAL hMem)
|
||||||
RtlLockHeap(hProcessHeap);
|
RtlLockHeap(hProcessHeap);
|
||||||
|
|
||||||
/* Check if this is a simple RTL Heap Managed block */
|
/* Check if this is a simple RTL Heap Managed block */
|
||||||
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY))
|
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
|
||||||
{
|
{
|
||||||
/* Then we'll query RTL Heap */
|
/* Then we'll query RTL Heap */
|
||||||
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
|
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
|
||||||
|
@ -697,7 +692,7 @@ GlobalSize(HGLOBAL hMem)
|
||||||
* Check if RTL Heap didn't give us a handle or said that this heap
|
* Check if RTL Heap didn't give us a handle or said that this heap
|
||||||
* isn't movable.
|
* isn't movable.
|
||||||
*/
|
*/
|
||||||
if (!(Handle) || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE))
|
if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
|
||||||
{
|
{
|
||||||
/* This implies we're not a handle heap, so use the generic call */
|
/* This implies we're not a handle heap, so use the generic call */
|
||||||
dwSize = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
|
dwSize = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
|
||||||
|
@ -710,20 +705,20 @@ GlobalSize(HGLOBAL hMem)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure that this is an entry in our handle database */
|
/* Make sure that this is an entry in our handle database */
|
||||||
if ((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)
|
if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
|
||||||
{
|
{
|
||||||
/* Get the entry */
|
/* Get the entry */
|
||||||
HandleEntry = GlobalGetEntry(hMem);
|
HandleEntry = BaseHeapGetEntry(hMem);
|
||||||
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
||||||
|
|
||||||
/* Make sure the handle is valid */
|
/* Make sure the handle is valid */
|
||||||
if (!GlobalValidateEntry(HandleEntry))
|
if (!BaseHeapValidateEntry(HandleEntry))
|
||||||
{
|
{
|
||||||
/* Fail */
|
/* Fail */
|
||||||
BASE_TRACE_FAILURE();
|
BASE_TRACE_FAILURE();
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
}
|
}
|
||||||
else if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_REUSE)
|
else if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE)
|
||||||
{
|
{
|
||||||
/* We've reused this block, but we've saved the size for you */
|
/* We've reused this block, but we've saved the size for you */
|
||||||
dwSize = HandleEntry->OldSize;
|
dwSize = HandleEntry->OldSize;
|
||||||
|
@ -769,21 +764,21 @@ BOOL
|
||||||
NTAPI
|
NTAPI
|
||||||
GlobalUnlock(HGLOBAL hMem)
|
GlobalUnlock(HGLOBAL hMem)
|
||||||
{
|
{
|
||||||
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry;
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
BOOL RetVal = TRUE;
|
BOOL RetVal = TRUE;
|
||||||
|
|
||||||
/* Check if this was a simple allocated heap entry */
|
/* Check if this was a simple allocated heap entry */
|
||||||
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) return RetVal;
|
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) return RetVal;
|
||||||
|
|
||||||
/* Otherwise, lock the heap */
|
/* Otherwise, lock the heap */
|
||||||
RtlLockHeap(hProcessHeap);
|
RtlLockHeap(hProcessHeap);
|
||||||
|
|
||||||
/* Get the handle entry */
|
/* Get the handle entry */
|
||||||
HandleEntry = GlobalGetEntry(hMem);
|
HandleEntry = BaseHeapGetEntry(hMem);
|
||||||
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
BASE_TRACE_HANDLE(HandleEntry, hMem);
|
||||||
|
|
||||||
/* Make sure it's valid */
|
/* Make sure it's valid */
|
||||||
if (!GlobalValidateEntry(HandleEntry))
|
if (!BaseHeapValidateEntry(HandleEntry))
|
||||||
{
|
{
|
||||||
/* It's not, fail */
|
/* It's not, fail */
|
||||||
BASE_TRACE_FAILURE();
|
BASE_TRACE_FAILURE();
|
||||||
|
|
|
@ -1,134 +1,450 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
* PROJECT: ReactOS Win32 Base API
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* Copyright (C) 1996, Onno Hovers, All rights reserved
|
* FILE: dll/win32/kernel32/mem/local.c
|
||||||
* PROJECT: ReactOS system libraries
|
* PURPOSE: Local Memory APIs (sits on top of Heap*)
|
||||||
* FILE: lib/kernel32/mem/local.c
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* PURPOSE: Manages the local heap
|
|
||||||
* PROGRAMER: Onno Hovers (original wfc version)
|
|
||||||
* David Welch (adapted for ReactOS)
|
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 9/4/98: Adapted from the wfc project
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
/* NOTES
|
|
||||||
*
|
|
||||||
* The local heap is the same as the global heap for win32 and both are only
|
|
||||||
* required for legacy apps
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
|
||||||
|
|
||||||
#include <k32.h>
|
#include <k32.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "../include/debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
|
extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
HLOCAL STDCALL
|
HLOCAL
|
||||||
|
NTAPI
|
||||||
LocalAlloc(UINT uFlags,
|
LocalAlloc(UINT uFlags,
|
||||||
SIZE_T uBytes)
|
SIZE_T dwBytes)
|
||||||
{
|
{
|
||||||
return (HLOCAL)GlobalAlloc(uFlags, uBytes);
|
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 & ~LMEM_VALID_FLAGS)
|
||||||
|
{
|
||||||
|
/* They aren't, fail */
|
||||||
|
BASE_TRACE_FAILURE();
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert ZEROINIT */
|
||||||
|
if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;
|
||||||
|
|
||||||
|
/* Check if we're not movable, which means pointer-based heap */
|
||||||
|
if (!(uFlags & LMEM_MOVEABLE))
|
||||||
|
{
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the pointer */
|
||||||
|
Ptr = hMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the pointer */
|
||||||
|
return Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
SIZE_T STDCALL
|
SIZE_T
|
||||||
LocalCompact(UINT uMinFree)
|
NTAPI
|
||||||
|
LocalCompact(UINT dwMinFree)
|
||||||
{
|
{
|
||||||
|
/* Call the RTL Heap Manager */
|
||||||
return RtlCompactHeap(hProcessHeap, 0);
|
return RtlCompactHeap(hProcessHeap, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
UINT STDCALL
|
UINT
|
||||||
|
NTAPI
|
||||||
LocalFlags(HLOCAL hMem)
|
LocalFlags(HLOCAL hMem)
|
||||||
{
|
{
|
||||||
return GlobalFlags((HGLOBAL)hMem);
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
}
|
HANDLE Handle = NULL;
|
||||||
|
ULONG Flags = 0;
|
||||||
|
UINT uFlags = LMEM_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 & LMEM_LOCKCOUNT;
|
||||||
|
|
||||||
|
/* Now check if it's discarded */
|
||||||
|
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
|
||||||
|
{
|
||||||
|
/* Set the Win32 Flag */
|
||||||
|
uFlags |= LMEM_DISCARDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if it's movable */
|
||||||
|
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_MOVABLE)
|
||||||
|
{
|
||||||
|
/* Set the Win32 Flag */
|
||||||
|
uFlags |= LMEM_DISCARDABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if by now, we still haven't gotten any useful flags */
|
||||||
|
if (uFlags == LMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
|
||||||
|
/* All done! Unlock heap and return Win32 Flags */
|
||||||
|
RtlUnlockHeap(hProcessHeap);
|
||||||
|
return uFlags;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
HLOCAL STDCALL
|
HLOCAL
|
||||||
|
NTAPI
|
||||||
LocalFree(HLOCAL hMem)
|
LocalFree(HLOCAL hMem)
|
||||||
{
|
{
|
||||||
return (HLOCAL)GlobalFree((HGLOBAL)hMem);
|
/* This is identical to a Global Free */
|
||||||
|
return GlobalFree(hMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
HLOCAL STDCALL
|
HLOCAL
|
||||||
|
NTAPI
|
||||||
LocalHandle(LPCVOID pMem)
|
LocalHandle(LPCVOID pMem)
|
||||||
{
|
{
|
||||||
return (HLOCAL)GlobalHandle(pMem);
|
/* This is identical to a Global Handle */
|
||||||
|
return GlobalHandle(pMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
LPVOID STDCALL
|
LPVOID
|
||||||
|
NTAPI
|
||||||
LocalLock(HLOCAL hMem)
|
LocalLock(HLOCAL hMem)
|
||||||
{
|
{
|
||||||
return GlobalLock((HGLOBAL)hMem);
|
/* This is the same as a GlobalLock, assuming these never change */
|
||||||
|
ASSERT(LMEM_LOCKCOUNT == GMEM_LOCKCOUNT);
|
||||||
|
return GlobalLock(hMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HLOCAL
|
||||||
/*
|
NTAPI
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HLOCAL STDCALL
|
|
||||||
LocalReAlloc(HLOCAL hMem,
|
LocalReAlloc(HLOCAL hMem,
|
||||||
SIZE_T uBytes,
|
SIZE_T dwBytes,
|
||||||
UINT uFlags)
|
UINT uFlags)
|
||||||
{
|
{
|
||||||
return (HLOCAL)GlobalReAlloc((HGLOBAL)hMem, uBytes, uFlags);
|
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
|
||||||
}
|
LPVOID Ptr;
|
||||||
|
ULONG Flags = 0;
|
||||||
|
|
||||||
|
/* Convert ZEROINIT */
|
||||||
|
if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;
|
||||||
|
|
||||||
|
/* If this wasn't a movable heap, then we MUST re-alloc in place */
|
||||||
|
if (!(uFlags & LMEM_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 & LMEM_MODIFY)
|
||||||
|
{
|
||||||
|
/* User is changing flags... check if the memory was discardable */
|
||||||
|
if (uFlags & LMEM_DISCARDABLE)
|
||||||
|
{
|
||||||
|
/* Then set the flag */
|
||||||
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, remove the flag */
|
||||||
|
HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, get the object and check if we have no size */
|
||||||
|
Ptr = HandleEntry->Object;
|
||||||
|
if (!dwBytes)
|
||||||
|
{
|
||||||
|
/* Clear the handle and check for a pointer */
|
||||||
|
hMem = NULL;
|
||||||
|
if (Ptr)
|
||||||
|
{
|
||||||
|
/* Make sure the handle isn't locked */
|
||||||
|
if ((uFlags & LMEM_MOVEABLE) & !(HandleEntry->LockCount))
|
||||||
|
{
|
||||||
|
/* Free the current heap */
|
||||||
|
RtlFreeHeap(hProcessHeap, Flags, Ptr);
|
||||||
|
|
||||||
|
/* Free the handle */
|
||||||
|
HandleEntry->Object = NULL;
|
||||||
|
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;
|
||||||
|
|
||||||
|
/* Get the object pointer */
|
||||||
|
hMem = &HandleEntry->Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise just return the object pointer */
|
||||||
|
hMem = &HandleEntry->Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise, we're allocating, so set the new flags needed */
|
||||||
|
Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
|
||||||
|
if (!Ptr)
|
||||||
|
{
|
||||||
|
/* We don't have a base, so allocate one */
|
||||||
|
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
|
||||||
|
BASE_TRACE_ALLOC2(Ptr);
|
||||||
|
if (Ptr)
|
||||||
|
{
|
||||||
|
/* Allocation succeeded, so save our entry */
|
||||||
|
RtlSetUserValueHeap(hProcessHeap,
|
||||||
|
HEAP_NO_SERIALIZE,
|
||||||
|
Ptr,
|
||||||
|
hMem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If it's not movable or currently locked, we MUST allocate
|
||||||
|
* in-place!
|
||||||
|
*/
|
||||||
|
if (!(uFlags & LMEM_MOVEABLE) && (HandleEntry->LockCount))
|
||||||
|
{
|
||||||
|
/* Set the flag */
|
||||||
|
Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise clear the flag if we set it previously */
|
||||||
|
Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And do the re-allocation */
|
||||||
|
Ptr = RtlReAllocateHeap(hProcessHeap, Flags, Ptr, dwBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we have a pointer by now */
|
||||||
|
if (Ptr)
|
||||||
|
{
|
||||||
|
/* Write it in the handle entry and mark it in use */
|
||||||
|
HandleEntry->Object = Ptr;
|
||||||
|
HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise we failed */
|
||||||
|
hMem = NULL;
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!(uFlags & LMEM_MODIFY))
|
||||||
|
{
|
||||||
|
/* Otherwise, this is a simple RTL Managed Heap, so just call it */
|
||||||
|
hMem = RtlReAllocateHeap(hProcessHeap,
|
||||||
|
Flags | HEAP_NO_SERIALIZE,
|
||||||
|
hMem,
|
||||||
|
dwBytes);
|
||||||
|
if (!hMem)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
BASE_TRACE_FAILURE();
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All done, unlock the heap and return the pointer */
|
||||||
|
RtlUnlockHeap(hProcessHeap);
|
||||||
|
return hMem;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
SIZE_T STDCALL
|
SIZE_T
|
||||||
LocalShrink(HLOCAL hMem, UINT cbNewSize)
|
STDCALL
|
||||||
|
LocalShrink(HLOCAL hMem,
|
||||||
|
UINT cbNewSize)
|
||||||
{
|
{
|
||||||
|
/* Call RTL */
|
||||||
return RtlCompactHeap(hProcessHeap, 0);
|
return RtlCompactHeap(hProcessHeap, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
UINT STDCALL
|
SIZE_T
|
||||||
|
NTAPI
|
||||||
LocalSize(HLOCAL hMem)
|
LocalSize(HLOCAL hMem)
|
||||||
{
|
{
|
||||||
return GlobalSize((HGLOBAL)hMem);
|
/* This is the same as a Global Size */
|
||||||
|
return GlobalSize(hMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL STDCALL
|
BOOL
|
||||||
|
NTAPI
|
||||||
LocalUnlock(HLOCAL hMem)
|
LocalUnlock(HLOCAL hMem)
|
||||||
{
|
{
|
||||||
return GlobalUnlock((HGLOBAL)hMem);
|
/* This is the same as a Global Unlock */
|
||||||
|
return GlobalUnlock(hMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -340,8 +340,8 @@ DllMain(HANDLE hDll,
|
||||||
|
|
||||||
hProcessHeap = RtlGetProcessHeap();
|
hProcessHeap = RtlGetProcessHeap();
|
||||||
RtlInitializeHandleTable(0xFFFF,
|
RtlInitializeHandleTable(0xFFFF,
|
||||||
sizeof(GLOBAL_HEAP_HANDLE_ENTRY),
|
sizeof(BASE_HEAP_HANDLE_ENTRY),
|
||||||
&BaseGlobalHandleTable);
|
&BaseHeapHandleTable);
|
||||||
hCurrentModule = hDll;
|
hCurrentModule = hDll;
|
||||||
DPRINT("Heap: %p\n", hProcessHeap);
|
DPRINT("Heap: %p\n", hProcessHeap);
|
||||||
|
|
||||||
|
|
|
@ -327,6 +327,7 @@ extern "C" {
|
||||||
#define LMEM_MODIFY 128
|
#define LMEM_MODIFY 128
|
||||||
#define LMEM_INVALID_HANDLE 32768
|
#define LMEM_INVALID_HANDLE 32768
|
||||||
#define LMEM_LOCKCOUNT 255
|
#define LMEM_LOCKCOUNT 255
|
||||||
|
#define LMEM_VALID_FLAGS 0x0F72
|
||||||
#define LPTR 64
|
#define LPTR 64
|
||||||
#define LHND 66
|
#define LHND 66
|
||||||
#define NONZEROLHND 2
|
#define NONZEROLHND 2
|
||||||
|
@ -1698,7 +1699,7 @@ HLOCAL WINAPI LocalHandle(LPCVOID);
|
||||||
PVOID WINAPI LocalLock(HLOCAL);
|
PVOID WINAPI LocalLock(HLOCAL);
|
||||||
HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT);
|
HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT);
|
||||||
SIZE_T WINAPI LocalShrink(HLOCAL,UINT); /* Obsolete: Has no effect. */
|
SIZE_T WINAPI LocalShrink(HLOCAL,UINT); /* Obsolete: Has no effect. */
|
||||||
UINT WINAPI LocalSize(HLOCAL);
|
SIZE_T WINAPI LocalSize(HLOCAL);
|
||||||
BOOL WINAPI LocalUnlock(HLOCAL);
|
BOOL WINAPI LocalUnlock(HLOCAL);
|
||||||
BOOL WINAPI LockFile(HANDLE,DWORD,DWORD,DWORD,DWORD);
|
BOOL WINAPI LockFile(HANDLE,DWORD,DWORD,DWORD,DWORD);
|
||||||
BOOL WINAPI LockFileEx(HANDLE,DWORD,DWORD,DWORD,DWORD,LPOVERLAPPED);
|
BOOL WINAPI LockFileEx(HANDLE,DWORD,DWORD,DWORD,DWORD,LPOVERLAPPED);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue