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 + -
显示快捷键?