global.c

来自「一个类似windows」· C语言 代码 · 共 736 行 · 第 1/2 页

C
736
字号
/* $Id: global.c 21253 2006-03-08 21:33:04Z audit $
 *
 * Win32 Global/Local heap functions (GlobalXXX, LocalXXX).
 * These functions included in Win32 for compatibility with 16 bit Windows
 * Especially the moveable blocks and handles are oldish.
 * But the ability to directly allocate memory with GPTR and LPTR is widely
 * used.
 *
 * Updated to support movable memory with algorithms taken from wine.
 */

#include <k32.h>

#define NDEBUG
#include "../include/debug.h"

#ifdef _GNUC_
#define STRUCT_PACK __attribute__((packed))
#else
#define STRUCT_PACK
#endif

#define MAGIC_GLOBAL_USED 0x5342BEEF
#define GLOBAL_LOCK_MAX   0xFF

/*Wine found that some applications complain if memory isn't 8 byte aligned.
* We make use of that experience here.
*/
#define HANDLE_SIZE          8  /*sizeof(HANDLE) *2 */


typedef struct __GLOBAL_LOCAL_HANDLE
{
    DWORD   Magic;
    LPVOID  Pointer; STRUCT_PACK
    BYTE    Flags;
    BYTE    LockCount;
} GLOBAL_HANDLE, LOCAL_HANDLE, *PGLOBAL_HANDLE, *PLOCAL_HANDLE;

#define HANDLE_TO_INTERN(h)  ((PGLOBAL_HANDLE)(((char *)(h))-4))
#define INTERN_TO_HANDLE(i)  ((HGLOBAL) &((i)->Pointer))
#define POINTER_TO_HANDLE(p) (*(PHANDLE)((ULONG_PTR)p - HANDLE_SIZE))
#define ISHANDLE(h)          ((((ULONG)(h)) & 0x4)!=0)
#define ISPOINTER(h)         ((((ULONG)(h)) & 0x4)==0)


static void DbgPrintStruct(PGLOBAL_HANDLE h)
{
    DPRINT("Magic:     0x%X\n", h->Magic);
    DPRINT("Pointer:   0x%X\n", h->Pointer);
    DPRINT("Flags:     0x%X\n", h->Flags);
    DPRINT("LockCount: 0x%X\n", h->LockCount);
}



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

/*
 * @implemented
 */
HGLOBAL STDCALL
GlobalAlloc(UINT uFlags,
            DWORD dwBytes)
{

    PGLOBAL_HANDLE phandle    = 0;
    PVOID          palloc     = 0;
    UINT           heap_flags = 0;

    if (uFlags & GMEM_ZEROINIT)
    {
        heap_flags = HEAP_ZERO_MEMORY;
    }

    DPRINT("GlobalAlloc( 0x%X, 0x%lX )\n", uFlags, dwBytes);

    //Changed hProcessHeap to GetProcessHeap()
    if ((uFlags & GMEM_MOVEABLE)==0) /* POINTER */
    {
        palloc = RtlAllocateHeap(GetProcessHeap(), heap_flags, dwBytes);
        if (! ISPOINTER(palloc))
        {
            DPRINT1("GlobalAlloced pointer which is not 8-byte aligned\n");
            RtlFreeHeap(GetProcessHeap(), 0, palloc);
            return NULL;
        }
        return (HGLOBAL) palloc;
    }
    else  /* HANDLE */
    {
        HeapLock(hProcessHeap);

        phandle = RtlAllocateHeap(GetProcessHeap(), 0,  sizeof(GLOBAL_HANDLE));
        if (phandle)
        {
            phandle->Magic     = MAGIC_GLOBAL_USED;
            phandle->Flags     = uFlags >> 8;
            phandle->LockCount = 0;
            phandle->Pointer   = 0;

            if (dwBytes)
            {
                palloc = RtlAllocateHeap(GetProcessHeap(), heap_flags, dwBytes + HANDLE_SIZE);
                if (palloc)
                {
                    *(PHANDLE)palloc = INTERN_TO_HANDLE(phandle);
                    phandle->Pointer = (PVOID)((ULONG_PTR)palloc + HANDLE_SIZE);
                }
                else /*failed to allocate the memory block*/
                {
                    RtlFreeHeap(GetProcessHeap(), 0, phandle);
                    phandle = 0;
                }
            }
            else
            {
                DPRINT("Allocated a 0 size movable block.\n");
                DbgPrintStruct(phandle);
                DPRINT("Address of the struct: 0x%X\n", phandle);
                DPRINT("Address of pointer:    0x%X\n", &(phandle->Pointer));
            }
        }
        HeapUnlock(hProcessHeap);

        if (phandle)
        {
            if (ISPOINTER(INTERN_TO_HANDLE(phandle)))
            {
                DPRINT1("GlobalAlloced handle which is 8-byte aligned but shouldn't be\n");
                RtlFreeHeap(GetProcessHeap(), 0, palloc);
                RtlFreeHeap(GetProcessHeap(), 0, phandle);
                return NULL;
            }
            return INTERN_TO_HANDLE(phandle);
        }
        else
            return (HGLOBAL)0;
    }
}


/*
 * @implemented
 */
SIZE_T STDCALL
GlobalCompact(DWORD dwMinFree)
{
   return RtlCompactHeap(hProcessHeap, 0);
}


/*
 * @implemented
 */
VOID STDCALL
GlobalFix(HGLOBAL hMem)
{
   if (INVALID_HANDLE_VALUE != hMem)
     GlobalLock(hMem);
}

/*
 * @implemented
 */
UINT STDCALL
GlobalFlags(HGLOBAL hMem)
{
    DWORD		    retval;
    PGLOBAL_HANDLE	phandle;

    DPRINT("GlobalFlags( 0x%lX )\n", (ULONG)hMem);

    if(!ISHANDLE(hMem))
    {
        DPRINT("GlobalFlags: Fixed memory.\n");
        retval = 0;
    }
    else
    {
        HeapLock(GetProcessHeap());

        phandle = HANDLE_TO_INTERN(hMem);

        /*DbgPrintStruct(phandle);*/

        if (MAGIC_GLOBAL_USED == phandle->Magic)
        {
            /*DbgPrint("GlobalFlags: Magic number ok\n");
            **DbgPrint("GlobalFlags: pointer is 0x%X\n", phandle->Pointer);
            */
            retval = phandle->LockCount + (phandle->Flags << 8);
            if (0 == phandle->Pointer)
            {
                retval = retval | GMEM_DISCARDED;
            }
        }
        else
        {
            DPRINT1("GlobalSize: invalid handle\n");
            retval = 0;
        }
        HeapUnlock(GetProcessHeap());
    }
    return retval;
}


/*
 * @implemented
 */
HGLOBAL STDCALL
GlobalFree(HGLOBAL hMem)
{
    PGLOBAL_HANDLE phandle;

    DPRINT("GlobalFree( 0x%lX )\n", (ULONG)hMem);

    if (ISPOINTER(hMem)) /* POINTER */
    {
        RtlFreeHeap(GetProcessHeap(), 0, (PVOID)hMem);
        hMem = 0;
    }
    else /* HANDLE */
    {
        HeapLock(GetProcessHeap());

        phandle = HANDLE_TO_INTERN(hMem);

        if(MAGIC_GLOBAL_USED == phandle->Magic)
        {

            if(phandle->LockCount!=0)
            {
                DPRINT1("Warning! GlobalFree(0x%X) Freeing a handle to a locked object.\n", hMem);
                SetLastError(ERROR_INVALID_HANDLE);
            }

            if(phandle->Pointer)
                RtlFreeHeap(GetProcessHeap(), 0, (PVOID)((ULONG_PTR)phandle->Pointer - HANDLE_SIZE));

            RtlFreeHeap(GetProcessHeap(), 0, phandle);
        }
        HeapUnlock(GetProcessHeap());

        hMem = 0;
    }
    return hMem;
}


/*
 * @implemented
 */
HGLOBAL STDCALL
GlobalHandle(LPCVOID pMem)
{
    HGLOBAL              handle = 0;
    PGLOBAL_HANDLE         test = 0;
    LPCVOID        pointer_test = 0;

    DPRINT("GlobalHandle( 0x%lX )\n", (ULONG)pMem);
    if (0 == pMem) /*Invalid argument */
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        DPRINT1("Error: 0 handle.\n");
        return 0;
    }

    HeapLock(GetProcessHeap());
    /* Now test to see if this pointer is associated with a handle.
    * This is done by calling RtlValidateHeap() and seeing if it fails.
    */
    if (RtlValidateHeap(GetProcessHeap(), 0, (char *)pMem)) /*FIXED*/
    {
        handle = (HGLOBAL)pMem;
        return handle;
    }
    else /*MOVABLE*/
    {
        handle = POINTER_TO_HANDLE(pMem);
    }


    /* Test to see if this memory is valid*/
    test  = HANDLE_TO_INTERN(handle);
    if (!IsBadReadPtr(test, sizeof(GLOBAL_HANDLE)))
    {
        if (MAGIC_GLOBAL_USED == test->Magic)
        {
            pointer_test = test->Pointer;
            if (!RtlValidateHeap(GetProcessHeap(), 0, ((char *)pointer_test) - HANDLE_SIZE) ||
                !RtlValidateHeap(GetProcessHeap(), 0, test))
            {
                SetLastError(ERROR_INVALID_HANDLE);
                handle = 0;
            }
        }
    }
    else
    {
        DPRINT1("GlobalHandle: Bad read pointer.\n");
        SetLastError(ERROR_INVALID_HANDLE);
        handle = 0;
    }

    HeapUnlock(GetProcessHeap());

    return handle;
}


/*
 * @implemented
 */
LPVOID STDCALL
GlobalLock(HGLOBAL hMem)
{
    PGLOBAL_HANDLE phandle;
    LPVOID         palloc;

    DPRINT("GlobalLock( 0x%lX )\n", (ULONG)hMem);

    if (ISPOINTER(hMem))
        return (LPVOID) hMem;

    HeapLock(GetProcessHeap());

    phandle = HANDLE_TO_INTERN(hMem);

    if(MAGIC_GLOBAL_USED == phandle->Magic)
    {
        if(GLOBAL_LOCK_MAX > phandle->LockCount)
        {
            phandle->LockCount++;
        }
        palloc = phandle->Pointer;
    }
    else
    {
        DPRINT("GlobalLock: invalid handle\n");
        palloc = (LPVOID) hMem;
    }

    HeapUnlock(GetProcessHeap());

    return palloc;
}

/*
 * @implemented
 */
BOOL
STDCALL
GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
{
  SYSTEM_BASIC_INFORMATION	SysBasicInfo;
  SYSTEM_PERFORMANCE_INFORMATION	SysPerfInfo;
  ULONG UserMemory;
  NTSTATUS Status;

    DPRINT("GlobalMemoryStatusEx\n");

    if (lpBuffer->dwLength != sizeof(MEMORYSTATUSEX))
      {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
      }

⌨️ 快捷键说明

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