Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / dll / win32 / kernel32 / client / heapmem.c
diff --git a/reactos/dll/win32/kernel32/client/heapmem.c b/reactos/dll/win32/kernel32/client/heapmem.c
deleted file mode 100644 (file)
index 0ef199e..0000000
+++ /dev/null
@@ -1,1847 +0,0 @@
-/*
- * PROJECT:         ReactOS Win32 Base API
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            dll/win32/kernel32/client/heapmem.c
- * PURPOSE:         Heap Memory APIs (wrappers for RtlHeap*)
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES *******************************************************************/
-
-#include <k32.h>
-
-#define NDEBUG
-#include <debug.h>
-
-/* GLOBALS ********************************************************************/
-
-RTL_HANDLE_TABLE BaseHeapHandleTable;
-HANDLE BaseHeap;
-ULONG_PTR SystemRangeStart;
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-VOID
-NTAPI
-BaseDllInitializeMemoryManager(VOID)
-{
-    BaseHeap = RtlGetProcessHeap();
-    RtlInitializeHandleTable(0xFFFF,
-                             sizeof(BASE_HEAP_HANDLE_ENTRY),
-                             &BaseHeapHandleTable);
-    NtQuerySystemInformation(SystemRangeStartInformation,
-                             &SystemRangeStart,
-                             sizeof(SystemRangeStart),
-                             NULL);
-}
-
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-/*
- * @implemented
- */
-HANDLE
-WINAPI
-HeapCreate(DWORD flOptions,
-           SIZE_T dwInitialSize,
-           SIZE_T dwMaximumSize)
-{
-    HANDLE hRet;
-    ULONG Flags;
-
-    /* Remove non-Win32 flags and tag this allocation */
-    Flags = (flOptions & (HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE)) |
-            HEAP_CLASS_1;
-
-    /* Check if heap is growable and ensure max size is correct */
-    if (dwMaximumSize == 0)
-        Flags |= HEAP_GROWABLE;
-    else if (dwMaximumSize < BaseStaticServerData->SysInfo.PageSize &&
-            dwInitialSize > dwMaximumSize)
-    {
-        /* Max size is non-zero but less than page size which can't be correct.
-           Fix it up by bumping it to the initial size whatever it is. */
-        dwMaximumSize = dwInitialSize;
-    }
-
-    /* Call RTL Heap */
-    hRet = RtlCreateHeap(Flags,
-                         NULL,
-                         dwMaximumSize,
-                         dwInitialSize,
-                         NULL,
-                         NULL);
-
-    /* Set the last error if we failed, and return the pointer */
-    if (!hRet) SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-    return hRet;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapDestroy(HANDLE hHeap)
-{
-    /* Return TRUE if the heap was destroyed */
-   if (!RtlDestroyHeap(hHeap)) return TRUE;
-
-    /* Otherwise, we got the handle back, so fail */
-    SetLastError(ERROR_INVALID_HANDLE);
-    return FALSE;
-}
-
-/*
- * @implemented
- */
-HANDLE
-WINAPI
-GetProcessHeap(VOID)
-{
-    /* Call the RTL API */
-    return RtlGetProcessHeap();
-}
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-GetProcessHeaps(DWORD NumberOfHeaps,
-                PHANDLE ProcessHeaps)
-{
-    /* Call the RTL API */
-    return RtlGetProcessHeaps(NumberOfHeaps, ProcessHeaps);
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapLock(HANDLE hHeap)
-{
-    /* Call the RTL API */
-    return RtlLockHeap(hHeap);
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapUnlock(HANDLE hHeap)
-{
-    /* Call the RTL API */
-    return RtlUnlockHeap(hHeap);
-}
-
-/*
- * @implemented
- */
-SIZE_T
-WINAPI
-HeapCompact(HANDLE hHeap, DWORD dwFlags)
-{
-    /* Call the RTL API */
-    return RtlCompactHeap(hHeap, dwFlags);
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapValidate(HANDLE hHeap,
-             DWORD dwFlags,
-             LPCVOID lpMem)
-{
-    /* Call the RTL API */
-    return RtlValidateHeap(hHeap, dwFlags, (PVOID)lpMem);
-}
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-HeapCreateTagsW(HANDLE hHeap,
-                DWORD dwFlags,
-                PWSTR lpTagName,
-                PWSTR lpTagSubName)
-{
-    /* Call the RTL API */
-    return RtlCreateTagHeap(hHeap,
-                            dwFlags,
-                            lpTagName,
-                            lpTagSubName);
-}
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-HeapExtend(HANDLE hHeap,
-           DWORD dwFlags,
-           PVOID BaseAddress,
-           DWORD dwBytes)
-{
-    NTSTATUS Status;
-
-    /* Call the RTL API. Gone in Vista, so commented out. */
-    Status = STATUS_NOT_IMPLEMENTED; //RtlExtendHeap(hHeap, dwFlags, BaseAddress, dwBytes);
-    if (!NT_SUCCESS(Status))
-    {
-        /* We failed */
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
-    /* Return success */
-    return TRUE;
-}
-
-/*
- * @implemented
- */
-PWSTR
-WINAPI
-HeapQueryTagW(HANDLE hHeap,
-              DWORD dwFlags,
-              WORD wTagIndex,
-              BOOL bResetCounters,
-              PVOID lpTagInfo)
-{
-    /* Call the RTL API */
-    return RtlQueryTagHeap(hHeap,
-                           dwFlags,
-                           wTagIndex,
-                           (BOOLEAN)bResetCounters,
-                           lpTagInfo);
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapSummary(HANDLE hHeap,
-            DWORD dwFlags,
-            PVOID Summary)
-{
-    NTSTATUS Status;
-    RTL_HEAP_USAGE Usage;
-
-    /* Fill in the length information */
-    Usage.Length = sizeof(Usage);
-
-    /* Call RTL. Gone in Vista, so commented out */
-    Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage);
-    if (!NT_SUCCESS(Status))
-    {
-        /* We failed */
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
-    /* FIXME: Summary == Usage?! */
-    RtlCopyMemory(Summary, &Usage, sizeof(Usage));
-    return TRUE;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapUsage(HANDLE hHeap,
-          DWORD dwFlags,
-          DWORD Unknown,
-          DWORD Unknown2,
-          IN PVOID Usage)
-{
-    NTSTATUS Status;
-
-    /* Call RTL. Gone in Vista, so commented out */
-    Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage);
-    if (!NT_SUCCESS(Status))
-    {
-        /* We failed */
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-    else if (Status == STATUS_MORE_ENTRIES)
-    {
-        /* There are still more entries to parse */
-        return TRUE;
-    }
-
-    /* Otherwise, we're completely done, so we return FALSE, but NO_ERROR */
-    SetLastError(NO_ERROR);
-    return FALSE;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapWalk(HANDLE        hHeap,
-         LPPROCESS_HEAP_ENTRY lpEntry)
-{
-    NTSTATUS Status;
-
-    DPRINT1("Warning, HeapWalk is calling RtlWalkHeap with Win32 parameters\n");
-
-    Status = RtlWalkHeap(hHeap, lpEntry);
-
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapQueryInformation(HANDLE HeapHandle,
-                     HEAP_INFORMATION_CLASS HeapInformationClass,
-                     PVOID HeapInformation OPTIONAL,
-                     SIZE_T HeapInformationLength OPTIONAL,
-                     PSIZE_T ReturnLength OPTIONAL)
-{
-    NTSTATUS Status;
-
-    Status = RtlQueryHeapInformation(HeapHandle,
-                                     HeapInformationClass,
-                                     HeapInformation,
-                                     HeapInformationLength,
-                                     ReturnLength);
-
-    if (!NT_SUCCESS(Status))
-    {
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-HeapSetInformation(HANDLE HeapHandle,
-                   HEAP_INFORMATION_CLASS HeapInformationClass,
-                   PVOID HeapInformation OPTIONAL,
-                   SIZE_T HeapInformationLength OPTIONAL)
-{
-    NTSTATUS Status;
-
-    Status = RtlSetHeapInformation(HeapHandle,
-                                   HeapInformationClass,
-                                   HeapInformation,
-                                   HeapInformationLength);
-
-    if (!NT_SUCCESS(Status))
-    {
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-/*
- * @implemented
- */
-HGLOBAL
-NTAPI
-GlobalAlloc(UINT uFlags,
-            SIZE_T dwBytes)
-{
-    ULONG Flags = 0;
-    PVOID Ptr = NULL;
-    HANDLE hMemory;
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    BASE_TRACE_ALLOC(dwBytes, uFlags);
-    ASSERT(BaseHeap);
-
-    /* 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(BaseHeap, Flags, dwBytes ? dwBytes : 1);
-        if (!Ptr) SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        BASE_TRACE_ALLOC2(Ptr);
-        return Ptr;
-    }
-
-    /* This is heap based, so lock it in first */
-    RtlLockHeap(BaseHeap);
-
-    /*
-     * 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();
-    }
-    else
-    {
-        /* Get the object and make sure we have size */
-        hMemory = &HandleEntry->Object;
-        if (dwBytes)
-        {
-            /* Allocate the actual memory for it */
-            Ptr = RtlAllocateHeap(BaseHeap, 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(BaseHeap, HEAP_NO_SERIALIZE, Ptr, hMemory);
-            }
-        }
-    }
-
-    /* Cleanup! First unlock the heap */
-    RtlUnlockHeap(BaseHeap);
-
-    /* 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(BaseHeap, 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(BaseHeap);
-    _SEH2_TRY
-    {
-        /* 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(BaseHeap, 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 discardable */
-                if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
-                {
-                    /* Set the Win32 Flag */
-                    uFlags |= GMEM_DISCARDABLE;
-                }
-
-                /* Check if it's DDE Shared */
-                if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_DDESHARE)
-                {
-                    /* Set the Win32 Flag */
-                    uFlags |= GMEM_DDESHARE;
-                }
-
-                /* Now check if it's discarded */
-                if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE)
-                {
-                   /* Set the Win32 Flag */
-                   uFlags |= GMEM_DISCARDED;
-               }
-            }
-        }
-
-        /* Check if by now, we still haven't gotten any useful flags */
-        if (uFlags == GMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        /* Set the exception code */
-        BaseSetLastNTError(_SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    /* All done! Unlock heap and return Win32 Flags */
-    RtlUnlockHeap(BaseHeap);
-    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(BaseHeap, 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(BaseHeap);
-    _SEH2_TRY
-    {
-        /* 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 with the RTL Heap Manager */
-            if (RtlFreeHeap(BaseHeap, HEAP_NO_SERIALIZE, Ptr))
-            {
-                /* Everything worked */
-                hMem = NULL;
-            }
-            else
-            {
-                /* This wasn't a real heap handle */
-                SetLastError(ERROR_INVALID_HANDLE);
-            }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        /* Set the exception code */
-        BaseSetLastNTError(_SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    /* We're done, so unlock the heap and return the handle */
-    RtlUnlockHeap(BaseHeap);
-    return hMem;
-}
-
-/*
- * @implemented
- */
-HGLOBAL
-NTAPI
-GlobalHandle(LPCVOID pMem)
-{
-    HANDLE Handle = NULL;
-    ULONG Flags;
-
-    /* Lock the heap */
-    RtlLockHeap(BaseHeap);
-    _SEH2_TRY
-    {
-        /* Query RTL Heap */
-        if (!RtlGetUserInfoHeap(BaseHeap,
-                                HEAP_NO_SERIALIZE,
-                                (PVOID)pMem,
-                                &Handle,
-                                &Flags))
-        {
-            /* RTL Heap Manager does not know about this heap */
-            SetLastError(ERROR_INVALID_HANDLE);
-        }
-        else
-        {
-            /*
-             * Check if RTL Heap didn't find a handle for us or said that
-             * this heap isn't movable.
-             */
-            BASE_TRACE_PTR(Handle, pMem);
-            if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
-            {
-                /* We're actually handle-based, so the pointer is a handle */
-                Handle = (HANDLE)pMem;
-            }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        /* Set the exception code */
-        BaseSetLastNTError(_SEH2_GetExceptionCode());
-    }
-    _SEH2_END;
-
-    /* All done, unlock the heap and return the handle */
-    RtlUnlockHeap(BaseHeap);
-    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))
-    {
-        /* Make sure it's not a kernel or invalid address */
-        if ((hMem >= (HGLOBAL)SystemRangeStart) || (IsBadReadPtr(hMem, 1)))
-        {
-            /* Signal an error */
-            SetLastError(ERROR_INVALID_HANDLE);
-            return NULL;
-        }
-
-        /* It's all good */
-        return hMem;
-    }
-
-    /* Otherwise, lock the heap */
-    RtlLockHeap(BaseHeap);
-    _SEH2_TRY
-    {
-        /* 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);
-            }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastError(ERROR_INVALID_HANDLE);
-        Ptr = NULL;
-    }
-    _SEH2_END;
-
-    /* All done. Unlock the heap and return the pointer */
-    RtlUnlockHeap(BaseHeap);
-    return Ptr;
-}
-
-HGLOBAL
-NTAPI
-GlobalReAlloc(HGLOBAL hMem,
-              SIZE_T dwBytes,
-              UINT uFlags)
-{
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    HANDLE Handle;
-    LPVOID Ptr;
-    ULONG Flags = 0;
-
-    /* Throw out invalid flags */
-    if (uFlags & ~(GMEM_VALID_FLAGS | GMEM_MODIFY))
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return NULL;
-    }
-
-    /* Throw out invalid combo */
-    if ((uFlags & GMEM_DISCARDABLE) && !(uFlags & GMEM_MODIFY))
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return NULL;
-    }
-
-    /* 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 functions */
-    RtlLockHeap(BaseHeap);
-    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)
-        {
-            /* User is changing flags... check if the memory was discardable */
-            if (uFlags & GMEM_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 & GMEM_MOVEABLE) && !(HandleEntry->LockCount))
-                    {
-                        /* Free the current heap */
-                        if (RtlFreeHeap(BaseHeap, 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(BaseHeap, Flags, dwBytes);
-                    BASE_TRACE_ALLOC2(Ptr);
-                    if (Ptr)
-                    {
-                        /* Allocation succeeded, so save our entry */
-                        RtlSetUserValueHeap(BaseHeap,
-                                            HEAP_NO_SERIALIZE,
-                                            Ptr,
-                                            hMem);
-                    }
-                }
-                else
-                {
-                    /*
-                     * If it's not movable or currently locked, we MUST allocate
-                     * in-place!
-                     */
-                    if (!(uFlags & GMEM_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;
-                    }
-
-                    /* Do the re-allocation. No need to save the entry again */
-                    Ptr = RtlReAllocateHeap(BaseHeap, 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 & GMEM_MODIFY)
-    {
-        /* This is not a handle-based heap and the caller wants it to be one */
-        if (uFlags & GMEM_MOVEABLE)
-        {
-            /* Get information on its current state */
-            Handle = hMem;
-            if (RtlGetUserInfoHeap(BaseHeap,
-                                   HEAP_NO_SERIALIZE,
-                                   hMem,
-                                   &Handle,
-                                   NULL))
-            {
-                /*
-                 * Check if the handle matches the pointer or the moveable flag
-                 * isn't there, which is what we expect since it currently isn't.
-                 */
-                if ((Handle == hMem) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
-                {
-                    /* Allocate a handle for it */
-                    HandleEntry = BaseHeapAllocEntry();
-                    if (!HandleEntry)
-                    {
-                        /* No entry could be allocated */
-                        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                        RtlUnlockHeap(BaseHeap);
-                        return NULL;
-                    }
-
-                    /* Calculate the size of the current heap */
-                    dwBytes = RtlSizeHeap(BaseHeap, HEAP_NO_SERIALIZE, hMem);
-
-                    /* Set the movable flag */
-                    Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
-
-                    /* Now allocate the actual heap for it */
-                    HandleEntry->Object = RtlAllocateHeap(BaseHeap,
-                                                          Flags,
-                                                          dwBytes);
-                    BASE_TRACE_PTR(HandleEntry->Object, HandleEntry);
-                    if (!HandleEntry->Object)
-                    {
-                        /*
-                         * We failed, manually set the allocate flag and
-                         * free the handle
-                         */
-                        HandleEntry->Flags = RTL_HANDLE_VALID;
-                        BaseHeapFreeEntry(HandleEntry);
-
-                        /* For the cleanup case */
-                        BASE_TRACE_FAILURE();
-                        HandleEntry = NULL;
-                        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                    }
-                    else
-                    {
-                        /* Otherwise, copy the new heap and free the old one */
-                        RtlMoveMemory(HandleEntry->Object, hMem, dwBytes);
-                        RtlFreeHeap(BaseHeap, HEAP_NO_SERIALIZE, hMem);
-
-                        /* Select the heap pointer */
-                        hMem = (HANDLE)&HandleEntry->Object;
-
-                        /* Initialize the count and default flags */
-                        HandleEntry->LockCount = 0;
-                        HandleEntry->Flags = RTL_HANDLE_VALID |
-                                             BASE_HEAP_ENTRY_FLAG_MOVABLE;
-
-                        /* Check if it's also discardable */
-                        if (uFlags & GMEM_DISCARDABLE)
-                        {
-                            /* Set the internal flag */
-                            HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
-                        }
-
-                        /* Check if it's also DDE Shared */
-                        if (uFlags & GMEM_DDESHARE)
-                        {
-                            /* Set the internal flag */
-                            HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
-                        }
-
-                        /* Allocation succeeded, so save our entry */
-                        RtlSetUserValueHeap(BaseHeap,
-                                            HEAP_NO_SERIALIZE,
-                                            HandleEntry->Object,
-                                            hMem);
-                    }
-                }
-            }
-        }
-    }
-    else
-    {
-        /* Otherwise, this is a simple RTL Managed Heap, so just call it */
-        hMem = RtlReAllocateHeap(BaseHeap,
-                                 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(BaseHeap);
-    return hMem;
-}
-
-/*
- * @implemented
- */
-SIZE_T
-NTAPI
-GlobalSize(HGLOBAL hMem)
-{
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    PVOID Handle = NULL;
-    ULONG Flags = 0;
-    SIZE_T dwSize = MAXULONG_PTR;
-
-    /* Lock the heap */
-    RtlLockHeap(BaseHeap);
-    _SEH2_TRY
-    {
-        /* 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 */
-            if (RtlGetUserInfoHeap(BaseHeap, Flags, hMem, &Handle, &Flags))
-            {
-                BASE_TRACE_PTR(Handle, hMem);
-                /*
-                 * Check if RTL Heap didn't give us a handle or said that this
-                 * heap isn't movable.
-                 */
-                if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
-                {
-                    /* We're not a handle heap, so use the generic call */
-                    dwSize = RtlSizeHeap(BaseHeap, HEAP_NO_SERIALIZE, hMem);
-                }
-                else
-                {
-                    /* We're a handle heap so get the internal handle */
-                    hMem = Handle;
-                }
-            }
-        }
-
-        /* 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))
-            {
-                /* Fail */
-                BASE_TRACE_FAILURE();
-                SetLastError(ERROR_INVALID_HANDLE);
-            }
-            else if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE)
-            {
-                /* We've reused this block, but we've saved the size for you */
-                dwSize = HandleEntry->OldSize;
-            }
-            else
-            {
-                /* Otherwise, query RTL about it */
-                dwSize = RtlSizeHeap(BaseHeap,
-                                     HEAP_NO_SERIALIZE,
-                                     HandleEntry->Object);
-            }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        /* Set failure for later */
-        dwSize = MAXULONG_PTR;
-    }
-    _SEH2_END;
-
-    /* Check if by now, we still haven't gotten any useful size */
-    if (dwSize == MAXULONG_PTR)
-    {
-        /* Fail */
-        BASE_TRACE_FAILURE();
-        SetLastError(ERROR_INVALID_HANDLE);
-        dwSize = 0;
-    }
-
-    /* All done! Unlock heap and return the size */
-    RtlUnlockHeap(BaseHeap);
-    return dwSize;
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-GlobalUnfix(HGLOBAL hMem)
-{
-    /* If the handle is valid, unlock it */
-    if (hMem != INVALID_HANDLE_VALUE) GlobalUnlock(hMem);
-}
-
-/*
- * @implemented
- */
-BOOL
-NTAPI
-GlobalUnlock(HGLOBAL hMem)
-{
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    BOOL RetVal = TRUE;
-
-    /* Check if this was a simple allocated heap entry */
-    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) return RetVal;
-
-    /* Otherwise, lock the heap */
-    RtlLockHeap(BaseHeap);
-
-    /* Get the handle entry */
-    HandleEntry = BaseHeapGetEntry(hMem);
-    BASE_TRACE_HANDLE(HandleEntry, hMem);
-
-    _SEH2_TRY
-    {
-        /* Make sure it's valid */
-        if (!BaseHeapValidateEntry(HandleEntry))
-        {
-            /* It's not, fail */
-            BASE_TRACE_FAILURE();
-            SetLastError(ERROR_INVALID_HANDLE);
-            RetVal = FALSE;
-        }
-        else
-        {
-            /* Otherwise, decrement lock count, unless we're already at 0*/
-            if (!HandleEntry->LockCount--)
-            {
-                /* In which case we simply lock it back and fail */
-                HandleEntry->LockCount++;
-                SetLastError(ERROR_NOT_LOCKED);
-                RetVal = FALSE;
-            }
-            else if (!HandleEntry->LockCount)
-            {
-                /* Nothing to unlock */
-                SetLastError(NO_ERROR);
-                RetVal = FALSE;
-            }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        RetVal = FALSE;
-    }
-    _SEH2_END;
-
-    /* All done. Unlock the heap and return the pointer */
-    RtlUnlockHeap(BaseHeap);
-    return RetVal;
-}
-
-/*
- * @implemented
- */
-BOOL
-NTAPI
-GlobalUnWire(HGLOBAL hMem)
-{
-    /* This is simply an unlock */
-    return GlobalUnlock(hMem);
-}
-
-/*
- * @implemented
- */
-LPVOID
-NTAPI
-GlobalWire(HGLOBAL hMem)
-{
-    /* This is just a lock */
-    return GlobalLock(hMem);
-}
-
-/*
- * @implemented
- */
-BOOL
-NTAPI
-GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
-{
-    SYSTEM_PERFORMANCE_INFORMATION PerformanceInfo;
-    VM_COUNTERS VmCounters;
-    QUOTA_LIMITS QuotaLimits;
-    ULONGLONG PageFile, PhysicalMemory;
-
-    if (lpBuffer->dwLength != sizeof(*lpBuffer))
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    /* Query performance information */
-    NtQuerySystemInformation(SystemPerformanceInformation,
-                             &PerformanceInfo,
-                             sizeof(PerformanceInfo),
-                             NULL);
-
-    /* Calculate memory load */
-    lpBuffer->dwMemoryLoad = ((DWORD)(BaseStaticServerData->SysInfo.NumberOfPhysicalPages -
-                                      PerformanceInfo.AvailablePages) * 100) /
-                                      BaseStaticServerData->SysInfo.NumberOfPhysicalPages;
-
-    /* Save physical memory */
-    PhysicalMemory = BaseStaticServerData->SysInfo.NumberOfPhysicalPages *
-                     BaseStaticServerData->SysInfo.PageSize;
-    lpBuffer->ullTotalPhys = PhysicalMemory;
-
-    /* Now save available physical memory */
-    PhysicalMemory = PerformanceInfo.AvailablePages *
-                     BaseStaticServerData->SysInfo.PageSize;
-    lpBuffer->ullAvailPhys = PhysicalMemory;
-
-    /* Query VM and Quota Limits */
-    NtQueryInformationProcess(NtCurrentProcess(),
-                              ProcessQuotaLimits,
-                              &QuotaLimits,
-                              sizeof(QUOTA_LIMITS),
-                              NULL);
-    NtQueryInformationProcess(NtCurrentProcess(),
-                              ProcessVmCounters,
-                              &VmCounters,
-                              sizeof(VM_COUNTERS),
-                              NULL);
-
-    /* Save the commit limit */
-    lpBuffer->ullTotalPageFile = min(QuotaLimits.PagefileLimit,
-                                     PerformanceInfo.CommitLimit);
-    lpBuffer->ullTotalPageFile *= BaseStaticServerData->SysInfo.PageSize;
-
-    /* Calculate how many pages are left */
-    PageFile = PerformanceInfo.CommitLimit - PerformanceInfo.CommittedPages;
-
-    /* Save the total */
-    lpBuffer->ullAvailPageFile = min(PageFile,
-                                     QuotaLimits.PagefileLimit -
-                                     VmCounters.PagefileUsage);
-    lpBuffer->ullAvailPageFile *= BaseStaticServerData->SysInfo.PageSize;
-
-    /* Now calculate the total virtual space */
-    lpBuffer->ullTotalVirtual = (BaseStaticServerData->SysInfo.MaximumUserModeAddress -
-                                 BaseStaticServerData->SysInfo.MinimumUserModeAddress) + 1;
-
-    /* And finally the available virtual space */
-    lpBuffer->ullAvailVirtual = lpBuffer->ullTotalVirtual - VmCounters.VirtualSize;
-    lpBuffer->ullAvailExtendedVirtual = 0;
-
-    return TRUE;
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer)
-{
-    MEMORYSTATUSEX lpBufferEx;
-
-    /* Call the extended function */
-    lpBufferEx.dwLength = sizeof(MEMORYSTATUSEX);
-    if (GlobalMemoryStatusEx(&lpBufferEx))
-    {
-        /* Reset the right size and fill out the information */
-        lpBuffer->dwLength = sizeof(MEMORYSTATUS);
-        lpBuffer->dwMemoryLoad = lpBufferEx.dwMemoryLoad;
-        lpBuffer->dwTotalPhys = (SIZE_T)min(lpBufferEx.ullTotalPhys, MAXULONG_PTR);
-        lpBuffer->dwAvailPhys = (SIZE_T)min(lpBufferEx.ullAvailPhys, MAXULONG_PTR);
-        lpBuffer->dwTotalPageFile = (SIZE_T)min(lpBufferEx.ullTotalPageFile, MAXULONG_PTR);
-        lpBuffer->dwAvailPageFile = (SIZE_T)min(lpBufferEx.ullAvailPageFile, MAXULONG_PTR);
-        lpBuffer->dwTotalVirtual = (SIZE_T)min(lpBufferEx.ullTotalVirtual, MAXULONG_PTR);
-        lpBuffer->dwAvailVirtual = (SIZE_T)min(lpBufferEx.ullAvailVirtual, MAXULONG_PTR);
-    }
-}
-
-/*
- * @implemented
- */
-HLOCAL
-NTAPI
-LocalAlloc(UINT uFlags,
-           SIZE_T dwBytes)
-{
-    ULONG Flags = 0;
-    PVOID Ptr = NULL;
-    HANDLE hMemory;
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    BASE_TRACE_ALLOC(dwBytes, uFlags);
-    ASSERT(BaseHeap);
-
-    /* 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(BaseHeap, Flags, dwBytes);
-        BASE_TRACE_ALLOC2(Ptr);
-        return Ptr;
-    }
-
-    /* This is heap based, so lock it in first */
-    RtlLockHeap(BaseHeap);
-
-    /*
-     * 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(BaseHeap, 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(BaseHeap, HEAP_NO_SERIALIZE, Ptr, hMemory);
-        }
-    }
-
-Quickie:
-    /* Cleanup! First unlock the heap */
-    RtlUnlockHeap(BaseHeap);
-
-    /* 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
- */
-SIZE_T
-NTAPI
-LocalCompact(UINT dwMinFree)
-{
-    /* Call the RTL Heap Manager */
-    return RtlCompactHeap(BaseHeap, 0);
-}
-
-/*
- * @implemented
- */
-UINT
-NTAPI
-LocalFlags(HLOCAL hMem)
-{
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    HANDLE Handle = NULL;
-    ULONG Flags = 0;
-    UINT uFlags = LMEM_INVALID_HANDLE;
-
-    /* Start by locking the heap */
-    RtlLockHeap(BaseHeap);
-
-    /* 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(BaseHeap, 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 discardable */
-            if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
-            {
-                /* Set the Win32 Flag */
-                uFlags |= LMEM_DISCARDABLE;
-            }
-
-            /* Now check if it's discarded */
-            if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE)
-               /* Set the Win32 Flag */
-               uFlags |= LMEM_DISCARDED;
-        }
-    }
-
-    /* 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(BaseHeap);
-    return uFlags;
-}
-
-/*
- * @implemented
- */
-HLOCAL
-NTAPI
-LocalFree(HLOCAL hMem)
-{
-    /* This is identical to a Global Free */
-    return GlobalFree(hMem);
-}
-
-/*
- * @implemented
- */
-HLOCAL
-NTAPI
-LocalHandle(LPCVOID pMem)
-{
-    /* This is identical to a Global Handle */
-    return GlobalHandle(pMem);
-}
-
-/*
- * @implemented
- */
-LPVOID
-NTAPI
-LocalLock(HLOCAL hMem)
-{
-    /* This is the same as a GlobalLock, assuming these never change */
-    C_ASSERT(LMEM_LOCKCOUNT == GMEM_LOCKCOUNT);
-    return GlobalLock(hMem);
-}
-
-HLOCAL
-NTAPI
-LocalReAlloc(HLOCAL hMem,
-             SIZE_T dwBytes,
-             UINT 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 functions */
-    RtlLockHeap(BaseHeap);
-    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(BaseHeap, 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(BaseHeap, Flags, dwBytes);
-                    BASE_TRACE_ALLOC2(Ptr);
-                    if (Ptr)
-                    {
-                        /* Allocation succeeded, so save our entry */
-                        RtlSetUserValueHeap(BaseHeap,
-                                            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(BaseHeap, 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(BaseHeap,
-                                 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(BaseHeap);
-    return hMem;
-}
-
-/*
- * @implemented
- */
-SIZE_T
-WINAPI
-LocalShrink(HLOCAL hMem,
-            UINT cbNewSize)
-{
-    /* Call RTL */
-    return RtlCompactHeap(BaseHeap, 0);
-}
-
-/*
- * @implemented
- */
-SIZE_T
-NTAPI
-LocalSize(HLOCAL hMem)
-{
-    /* This is the same as a Global Size */
-    return GlobalSize(hMem);
-}
-
-/*
- * @implemented
- */
-BOOL
-NTAPI
-LocalUnlock(HLOCAL hMem)
-{
-    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
-    BOOL RetVal = TRUE;
-
-    /* Check if this was a simple allocated heap entry */
-    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
-    {
-       /* Fail, because LocalUnlock is not supported on LMEM_FIXED allocations */
-       SetLastError(ERROR_NOT_LOCKED);
-       return FALSE;
-    }
-
-    /* Otherwise, lock the heap */
-    RtlLockHeap(BaseHeap);
-
-    /* Get the handle entry */
-    HandleEntry = BaseHeapGetEntry(hMem);
-    BASE_TRACE_HANDLE(HandleEntry, hMem);
-    _SEH2_TRY
-    {
-        /* Make sure it's valid */
-        if (!BaseHeapValidateEntry(HandleEntry))
-        {
-            /* It's not, fail */
-            BASE_TRACE_FAILURE();
-            SetLastError(ERROR_INVALID_HANDLE);
-            RetVal = FALSE;
-        }
-        else
-        {
-            /* Otherwise, decrement lock count, unless we're already at 0*/
-            if (!HandleEntry->LockCount--)
-            {
-                /* In which case we simply lock it back and fail */
-                HandleEntry->LockCount++;
-                SetLastError(ERROR_NOT_LOCKED);
-                RetVal = FALSE;
-            }
-            else if (!HandleEntry->LockCount)
-            {
-                /* Nothing to unlock */
-                SetLastError(NO_ERROR);
-                RetVal = FALSE;
-            }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        RetVal = FALSE;
-    }
-    _SEH2_END;
-
-    /* All done. Unlock the heap and return the pointer */
-    RtlUnlockHeap(BaseHeap);
-    return RetVal;
-}
-
-/* EOF */