⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 global.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * PROJECT:         ReactOS Win32 Base API
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            dll/win32/kernel32/mem/global.c
 * PURPOSE:         Global Memory APIs (sits on top of Heap*)
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 */

/* INCLUDES ******************************************************************/

#include <k32.h>

#define NDEBUG
#include "debug.h"

/* TYPES *********************************************************************/

extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
RTL_HANDLE_TABLE BaseHeapHandleTable;

/* FUNCTIONS ***************************************************************/

/*
 * @implemented
 */
HGLOBAL
NTAPI
GlobalAlloc(UINT uFlags,
            DWORD dwBytes)
{
    ULONG Flags = 0;
    PVOID Ptr = NULL;
    HANDLE hMemory;
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    BASE_TRACE_ALLOC(dwBytes, uFlags);
    ASSERT(hProcessHeap);

    /* Make sure the flags are valid */
    if (uFlags & ~GMEM_VALID_FLAGS)
    {
        /* They aren't, fail */
        BASE_TRACE_FAILURE();
        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /* Convert ZEROINIT */
    if (uFlags & GMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;

    /* Check if we're not movable, which means pointer-based heap */
    if (!(uFlags & GMEM_MOVEABLE))
    {
        /* Check if this is DDESHARE (deprecated) */
        if (uFlags & GMEM_DDESHARE) Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;

        /* Allocate heap for it */
        Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
        BASE_TRACE_ALLOC2(Ptr);
        return Ptr;
    }

    /* This is heap based, so lock it in first */
    RtlLockHeap(hProcessHeap);

    /*
     * Disable locking, enable custom flags, and write the
     * movable flag (deprecated)
     */
    Flags |= HEAP_NO_SERIALIZE |
             HEAP_SETTABLE_USER_VALUE |
             BASE_HEAP_FLAG_MOVABLE;

    /* Allocate the handle */
    HandleEntry = BaseHeapAllocEntry();
    if (!HandleEntry)
    {
        /* Fail */
        hMemory = NULL;
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        BASE_TRACE_FAILURE();
        goto Quickie;
    }

    /* Get the object and make sure we have size */
    hMemory = &HandleEntry->Object;
    if (dwBytes)
    {
        /* Allocate the actual memory for it */
        Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
        BASE_TRACE_PTR(HandleEntry, Ptr);
        if (!Ptr)
        {
            /* We failed, manually set the allocate flag and free the handle */
            HandleEntry->Flags = RTL_HANDLE_VALID;
            BaseHeapFreeEntry(HandleEntry);

            /* For the cleanup case */
            HandleEntry = NULL;
        }
        else
        {
            /* All worked well, save our heap entry */
            RtlSetUserValueHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, hMemory);
        }
    }

Quickie:
    /* Cleanup! First unlock the heap */
    RtlUnlockHeap(hProcessHeap);

    /* Check if a handle was allocated */
    if (HandleEntry)
    {
        /* Set the pointer and allocated flag */
        HandleEntry->Object = Ptr;
        HandleEntry->Flags = RTL_HANDLE_VALID;
        if (!Ptr)
        {
            /* We don't have a valid pointer, but so reuse this handle */
            HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;
        }

        /* Check if the handle is discardable */
        if (uFlags & GMEM_DISCARDABLE)
        {
            /* Save it in the handle entry */
            HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
        }

        /* Check if the handle is moveable */
        if (uFlags & GMEM_MOVEABLE)
        {
            /* Save it in the handle entry */
            HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE;
        }

        /* Check if the handle is DDE Shared */
        if (uFlags & GMEM_DDESHARE)
        {
            /* Save it in the handle entry */
            HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
        }

        /* Set the pointer */
        Ptr = hMemory;
    }

    /* Return the pointer */
    return Ptr;
}

/*
 * @implemented
 */
SIZE_T
NTAPI
GlobalCompact(DWORD dwMinFree)
{
    /* Call the RTL Heap Manager */
    return RtlCompactHeap(hProcessHeap, 0);
}

/*
 * @implemented
 */
VOID
NTAPI
GlobalFix(HGLOBAL hMem)
{
    /* Lock the memory if it the handle is valid */
    if (INVALID_HANDLE_VALUE != hMem) GlobalLock(hMem);
}

/*
 * @implemented
 */
UINT
NTAPI
GlobalFlags(HGLOBAL hMem)
{
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    HANDLE Handle = NULL;
    ULONG Flags = 0;
    UINT uFlags = GMEM_INVALID_HANDLE;

    /* Start by locking the heap */
    RtlLockHeap(hProcessHeap);

    /* Check if this is a simple RTL Heap Managed block */
    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
    {
        /* Then we'll query RTL Heap */
        RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
        BASE_TRACE_PTR(Handle, hMem);

        /*
         * Check if RTL Heap didn't find a handle associated with us or
         * said that this heap isn't movable, which means something we're
         * really not a handle-based heap.
         */
        if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
        {
            /* Then set the flags to 0 */
            uFlags = 0;
        }
        else
        {
            /* Otherwise we're handle-based, so get the internal handle */
            hMem = Handle;
        }
    }

    /* Check if the handle is actually an entry in our table */
    if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
    {
        /* Then get the entry */
        HandleEntry = BaseHeapGetEntry(hMem);
        BASE_TRACE_HANDLE(HandleEntry, hMem);

        /* Make sure it's a valid handle */
        if (BaseHeapValidateEntry(HandleEntry))
        {
            /* Get the lock count first */
            uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;

            /* Now check if it's discarded */
            if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
            {
                /* Set the Win32 Flag */
                uFlags |= GMEM_DISCARDED;
            }

            /* Check if it's movable */
            if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_MOVABLE)
            {
                /* Set the Win32 Flag */
                uFlags |= GMEM_MOVEABLE;
            }

            /* Check if it's DDE Shared */
            if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_DDESHARE)
            {
                /* Set the Win32 Flag */
                uFlags |= GMEM_DDESHARE;
            }
        }
    }

    /* Check if by now, we still haven't gotten any useful flags */
    if (uFlags == GMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE);

    /* All done! Unlock heap and return Win32 Flags */
    RtlUnlockHeap(hProcessHeap);
    return uFlags;
}

/*
 * @implemented
 */
HGLOBAL
NTAPI
GlobalFree(HGLOBAL hMem)
{
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    LPVOID Ptr;
    BASE_TRACE_DEALLOC(hMem);

    /* Check if this was a simple allocated heap entry */
    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
    {
        /* Free it with the RTL Heap Manager */
        if (RtlFreeHeap(hProcessHeap, 0, hMem))
        {
            /* Return NULL since there's no handle */
            return NULL;
        }
        else
        {
            /* Otherwise fail */
            BASE_TRACE_FAILURE();
            SetLastError(ERROR_INVALID_HANDLE);
            return hMem;
        }
    }

    /* It's a handle probably, so lock the heap */
    RtlLockHeap(hProcessHeap);

    /* Make sure that this is an entry in our handle database */
    if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
    {
        /* Get the entry */
        HandleEntry = BaseHeapGetEntry(hMem);
        BASE_TRACE_HANDLE(HandleEntry, hMem);

        /* Make sure the handle is valid */
        if (!BaseHeapValidateEntry(HandleEntry))
        {
            /* It's not, fail */
            SetLastError(ERROR_INVALID_HANDLE);
            Ptr = NULL;
        }
        else
        {
            /* It's valid, so get the pointer */
            Ptr = HandleEntry->Object;

            /* Free this handle */
            BaseHeapFreeEntry(HandleEntry);

            /* If the pointer is 0, then we don't have a handle either */
            if (!Ptr) hMem = NULL;
        }
    }
    else
    {
        /* Otherwise, reuse the handle as a pointer */
        BASE_TRACE_FAILURE();
        Ptr = hMem;
    }

    /* Check if we got here with a valid heap pointer */
    if (Ptr)
    {
        /* Free it */
        RtlFreeHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr);
        hMem = NULL;
    }

    /* We're done, so unlock the heap and return the handle */
    RtlUnlockHeap(hProcessHeap);
    return hMem;
}

/*
 * @implemented
 */
HGLOBAL
NTAPI
GlobalHandle(LPCVOID pMem)
{
    HANDLE Handle = NULL;
    ULONG Flags;

    /* Lock the heap */
    RtlLockHeap(hProcessHeap);

    /* Query RTL Heap */
    RtlGetUserInfoHeap(hProcessHeap,
                       HEAP_NO_SERIALIZE,
                       (PVOID)pMem,
                       &Handle,
                       &Flags);
    BASE_TRACE_PTR(Handle, pMem);

    /*
     * Check if RTL Heap didn't find a handle for us or said that
     * this heap isn't movable.
     */
    if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
    {
        /* We're actually handle-based, so the pointer is a handle */
        Handle = (HANDLE)pMem;
    }

    /* All done, unlock the heap and return the handle */
    RtlUnlockHeap(hProcessHeap);
    return Handle;
}

/*
 * @implemented
 */
LPVOID
NTAPI
GlobalLock(HGLOBAL hMem)
{
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    LPVOID Ptr;

    /* Check if this was a simple allocated heap entry */
    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
    {
        /* Then simply return the pointer */
        return hMem;
    }

    /* Otherwise, lock the heap */
    RtlLockHeap(hProcessHeap);

    /* Get the handle entry */
    HandleEntry = BaseHeapGetEntry(hMem);
    BASE_TRACE_HANDLE(HandleEntry, hMem);

    /* Make sure it's valid */
    if (!BaseHeapValidateEntry(HandleEntry))
    {
        /* It's not, fail */
        BASE_TRACE_FAILURE();
        SetLastError(ERROR_INVALID_HANDLE);
        Ptr = NULL;
    }
    else
    {
        /* Otherwise, get the pointer */
        Ptr = HandleEntry->Object;
        if (Ptr)
        {
            /* Increase the lock count, unless we've went too far */
            if (HandleEntry->LockCount++ == GMEM_LOCKCOUNT)
            {
                /* In which case we simply unlock once */
                HandleEntry->LockCount--;
            }
        }
        else
        {
            /* The handle is still there but the memory was already freed */
            SetLastError(ERROR_DISCARDED);
        }
    }

    /* All done. Unlock the heap and return the pointer */
    RtlUnlockHeap(hProcessHeap);
    return Ptr;
}

HGLOBAL
NTAPI
GlobalReAlloc(HGLOBAL hMem,
              DWORD dwBytes,
              UINT uFlags)
{
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    HANDLE Handle;
    LPVOID Ptr;
    ULONG Flags = 0;

    /* Convert ZEROINIT */
    if (uFlags & GMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;

    /* If this wasn't a movable heap, then we MUST re-alloc in place */
    if (!(uFlags & GMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY;

    /* Lock the heap and disable built-in locking in the RTL Heap funcitons */
    RtlLockHeap(hProcessHeap);
    Flags |= HEAP_NO_SERIALIZE;

    /* Check if this is a simple handle-based block */
    if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
    {
        /* Get the entry */
        HandleEntry = BaseHeapGetEntry(hMem);
        BASE_TRACE_HANDLE(HandleEntry, hMem);

        /* Make sure the handle is valid */
        if (!BaseHeapValidateEntry(HandleEntry))
        {
            /* Fail */
            BASE_TRACE_FAILURE();
            SetLastError(ERROR_INVALID_HANDLE);
            hMem = NULL;
        }
        else if (uFlags & GMEM_MODIFY)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -