kernel32: Move global/local memory functions to kernelbase.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
67a9700267
commit
d38a5ba4e6
|
@ -236,78 +236,6 @@ typedef struct __GLOBAL32_INTERN
|
|||
|
||||
#include "poppack.h"
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalAlloc (KERNEL32.@)
|
||||
*
|
||||
* Allocate a global memory object.
|
||||
*
|
||||
* RETURNS
|
||||
* Handle: Success
|
||||
* NULL: Failure
|
||||
*/
|
||||
HGLOBAL WINAPI GlobalAlloc(
|
||||
UINT flags, /* [in] Object allocation attributes */
|
||||
SIZE_T size /* [in] Number of bytes to allocate */
|
||||
) {
|
||||
PGLOBAL32_INTERN pintern;
|
||||
DWORD hpflags;
|
||||
LPVOID palloc;
|
||||
|
||||
if(flags&GMEM_ZEROINIT)
|
||||
hpflags=HEAP_ZERO_MEMORY;
|
||||
else
|
||||
hpflags=0;
|
||||
|
||||
if((flags & GMEM_MOVEABLE)==0) /* POINTER */
|
||||
{
|
||||
palloc = HeapAlloc( GetProcessHeap(), hpflags, max( 1, size ));
|
||||
TRACE( "(flags=%04x) returning %p\n", flags, palloc );
|
||||
return palloc;
|
||||
}
|
||||
else /* HANDLE */
|
||||
{
|
||||
if (size > INT_MAX-HGLOBAL_STORAGE)
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pintern = HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
|
||||
if (pintern)
|
||||
{
|
||||
/* Mask out obsolete flags */
|
||||
flags &= ~(GMEM_LOWER | GMEM_NOCOMPACT | GMEM_NOT_BANKED | GMEM_NOTIFY);
|
||||
|
||||
pintern->Magic = MAGIC_GLOBAL_USED;
|
||||
pintern->Flags = flags >> 8;
|
||||
pintern->LockCount = 0;
|
||||
|
||||
if (size)
|
||||
{
|
||||
palloc = HeapAlloc(GetProcessHeap(), hpflags, size+HGLOBAL_STORAGE);
|
||||
if (!palloc)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, pintern);
|
||||
pintern = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(HGLOBAL *)palloc = INTERN_TO_HANDLE(pintern);
|
||||
pintern->Pointer = (char *)palloc + HGLOBAL_STORAGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
pintern->Pointer = NULL;
|
||||
}
|
||||
|
||||
if (!pintern) return 0;
|
||||
TRACE( "(flags=%04x) returning handle %p pointer %p\n",
|
||||
flags, INTERN_TO_HANDLE(pintern), pintern->Pointer );
|
||||
return INTERN_TO_HANDLE(pintern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalLock (KERNEL32.@)
|
||||
*
|
||||
|
@ -326,40 +254,7 @@ HGLOBAL WINAPI GlobalAlloc(
|
|||
*/
|
||||
LPVOID WINAPI GlobalLock(HGLOBAL hmem)
|
||||
{
|
||||
PGLOBAL32_INTERN pintern;
|
||||
LPVOID palloc;
|
||||
|
||||
if (ISPOINTER(hmem))
|
||||
return IsBadReadPtr(hmem, 1) ? NULL : hmem;
|
||||
|
||||
RtlLockHeap(GetProcessHeap());
|
||||
__TRY
|
||||
{
|
||||
pintern = HANDLE_TO_INTERN(hmem);
|
||||
if (pintern->Magic == MAGIC_GLOBAL_USED)
|
||||
{
|
||||
palloc = pintern->Pointer;
|
||||
if (!pintern->Pointer)
|
||||
SetLastError(ERROR_DISCARDED);
|
||||
else if (pintern->LockCount < GMEM_LOCKCOUNT)
|
||||
pintern->LockCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic);
|
||||
palloc = NULL;
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem);
|
||||
palloc = NULL;
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
}
|
||||
__ENDTRY
|
||||
RtlUnlockHeap(GetProcessHeap());
|
||||
return palloc;
|
||||
return LocalLock( hmem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -381,46 +276,8 @@ LPVOID WINAPI GlobalLock(HGLOBAL hmem)
|
|||
*/
|
||||
BOOL WINAPI GlobalUnlock(HGLOBAL hmem)
|
||||
{
|
||||
PGLOBAL32_INTERN pintern;
|
||||
BOOL locked;
|
||||
|
||||
if (ISPOINTER(hmem)) return TRUE;
|
||||
|
||||
RtlLockHeap(GetProcessHeap());
|
||||
__TRY
|
||||
{
|
||||
pintern=HANDLE_TO_INTERN(hmem);
|
||||
if(pintern->Magic==MAGIC_GLOBAL_USED)
|
||||
{
|
||||
if(pintern->LockCount)
|
||||
{
|
||||
pintern->LockCount--;
|
||||
locked = (pintern->LockCount != 0);
|
||||
if (!locked) SetLastError(NO_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("%p not locked\n", hmem);
|
||||
SetLastError(ERROR_NOT_LOCKED);
|
||||
locked = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
locked=FALSE;
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem);
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
locked=FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
RtlUnlockHeap(GetProcessHeap());
|
||||
return locked;
|
||||
if (ISPOINTER( hmem )) return TRUE;
|
||||
return LocalUnlock( hmem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -495,200 +352,9 @@ HGLOBAL WINAPI GlobalHandle(
|
|||
* Handle: Success
|
||||
* NULL: Failure
|
||||
*/
|
||||
HGLOBAL WINAPI GlobalReAlloc(
|
||||
HGLOBAL hmem, /* [in] Handle of global memory object */
|
||||
SIZE_T size, /* [in] New size of block */
|
||||
UINT flags /* [in] How to reallocate object */
|
||||
) {
|
||||
LPVOID palloc;
|
||||
HGLOBAL hnew;
|
||||
PGLOBAL32_INTERN pintern;
|
||||
DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
|
||||
|
||||
hnew = 0;
|
||||
RtlLockHeap(GetProcessHeap());
|
||||
if(flags & GMEM_MODIFY) /* modify flags */
|
||||
{
|
||||
if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
|
||||
{
|
||||
/* make a fixed block moveable
|
||||
* actually only NT is able to do this. But it's soo simple
|
||||
*/
|
||||
if (hmem == 0)
|
||||
{
|
||||
WARN("GlobalReAlloc with null handle!\n");
|
||||
SetLastError( ERROR_NOACCESS );
|
||||
hnew = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = HeapSize(GetProcessHeap(), 0, hmem);
|
||||
hnew = GlobalAlloc(flags, size);
|
||||
palloc = GlobalLock(hnew);
|
||||
memcpy(palloc, hmem, size);
|
||||
GlobalUnlock(hnew);
|
||||
GlobalFree(hmem);
|
||||
}
|
||||
}
|
||||
else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
|
||||
{
|
||||
/* change the flags to make our block "discardable" */
|
||||
pintern=HANDLE_TO_INTERN(hmem);
|
||||
pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
|
||||
hnew=hmem;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
hnew = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ISPOINTER(hmem))
|
||||
{
|
||||
/* reallocate fixed memory */
|
||||
if (!(flags & GMEM_MOVEABLE))
|
||||
heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
|
||||
hnew=HeapReAlloc(GetProcessHeap(), heap_flags, hmem, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reallocate a moveable block */
|
||||
pintern=HANDLE_TO_INTERN(hmem);
|
||||
|
||||
#if 0
|
||||
/* Apparently Windows doesn't care whether the handle is locked at this point */
|
||||
/* See also the same comment in GlobalFree() */
|
||||
if(pintern->LockCount>1) {
|
||||
ERR("handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
} else
|
||||
#endif
|
||||
if(size!=0)
|
||||
{
|
||||
hnew=hmem;
|
||||
if(pintern->Pointer)
|
||||
{
|
||||
if(size > INT_MAX-HGLOBAL_STORAGE)
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
hnew = 0;
|
||||
}
|
||||
else if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
|
||||
(char *) pintern->Pointer-HGLOBAL_STORAGE,
|
||||
size+HGLOBAL_STORAGE)) == NULL)
|
||||
hnew = 0; /* Block still valid */
|
||||
else
|
||||
pintern->Pointer = (char *)palloc+HGLOBAL_STORAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(size > INT_MAX-HGLOBAL_STORAGE)
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
hnew = 0;
|
||||
}
|
||||
else if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+HGLOBAL_STORAGE))
|
||||
== NULL)
|
||||
hnew = 0;
|
||||
else
|
||||
{
|
||||
*(HGLOBAL *)palloc = hmem;
|
||||
pintern->Pointer = (char *)palloc + HGLOBAL_STORAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pintern->LockCount == 0)
|
||||
{
|
||||
if(pintern->Pointer)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, (char *) pintern->Pointer-HGLOBAL_STORAGE);
|
||||
pintern->Pointer = NULL;
|
||||
}
|
||||
hnew = hmem;
|
||||
}
|
||||
else
|
||||
WARN("not freeing memory associated with locked handle\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
RtlUnlockHeap(GetProcessHeap());
|
||||
return hnew;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalFree (KERNEL32.@)
|
||||
*
|
||||
* Free a global memory object.
|
||||
*
|
||||
* PARAMS
|
||||
* hmem [I] Handle of the global memory object
|
||||
*
|
||||
* RETURNS
|
||||
* Success: NULL
|
||||
* Failure: The provided handle
|
||||
*
|
||||
* NOTES
|
||||
* When the handle is invalid, last error is set to ERROR_INVALID_HANDLE
|
||||
*
|
||||
*/
|
||||
HGLOBAL WINAPI GlobalFree(HGLOBAL hmem)
|
||||
HGLOBAL WINAPI GlobalReAlloc( HGLOBAL hmem, SIZE_T size, UINT flags )
|
||||
{
|
||||
PGLOBAL32_INTERN pintern;
|
||||
HGLOBAL hreturned;
|
||||
|
||||
RtlLockHeap(GetProcessHeap());
|
||||
__TRY
|
||||
{
|
||||
hreturned = 0;
|
||||
if(ISPOINTER(hmem)) /* POINTER */
|
||||
{
|
||||
if(!HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, hmem))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
hreturned = hmem;
|
||||
}
|
||||
}
|
||||
else /* HANDLE */
|
||||
{
|
||||
pintern=HANDLE_TO_INTERN(hmem);
|
||||
|
||||
if(pintern->Magic==MAGIC_GLOBAL_USED)
|
||||
{
|
||||
pintern->Magic = 0xdead;
|
||||
|
||||
/* WIN98 does not make this test. That is you can free a */
|
||||
/* block you have not unlocked. Go figure!! */
|
||||
/* if(pintern->LockCount!=0) */
|
||||
/* SetLastError(ERROR_INVALID_HANDLE); */
|
||||
|
||||
if(pintern->Pointer)
|
||||
if(!HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, (char *)(pintern->Pointer)-HGLOBAL_STORAGE))
|
||||
hreturned=hmem;
|
||||
if(!HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pintern))
|
||||
hreturned=hmem;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
hreturned = hmem;
|
||||
}
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
ERR("invalid handle %p\n", hmem);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
hreturned = hmem;
|
||||
}
|
||||
__ENDTRY
|
||||
RtlUnlockHeap(GetProcessHeap());
|
||||
return hreturned;
|
||||
return LocalReAlloc( hmem, size, flags );
|
||||
}
|
||||
|
||||
|
||||
|
@ -846,33 +512,6 @@ SIZE_T WINAPI GlobalCompact( DWORD minfree )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalAlloc (KERNEL32.@)
|
||||
*
|
||||
* Allocate a local memory object.
|
||||
*
|
||||
* RETURNS
|
||||
* Handle: Success
|
||||
* NULL: Failure
|
||||
*
|
||||
* NOTES
|
||||
* Windows memory management does not provide a separate local heap
|
||||
* and global heap.
|
||||
*/
|
||||
HLOCAL WINAPI LocalAlloc( UINT flags, SIZE_T size )
|
||||
{
|
||||
/* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
|
||||
if (!(flags & LMEM_MOVEABLE))
|
||||
{
|
||||
DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
|
||||
void *ret = HeapAlloc( GetProcessHeap(), heap_flags, size );
|
||||
TRACE( "(flags=%04x) returning %p\n", flags, ret );
|
||||
return ret;
|
||||
}
|
||||
return GlobalAlloc( flags, size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalCompact (KERNEL32.@)
|
||||
*/
|
||||
|
@ -902,26 +541,6 @@ UINT WINAPI LocalFlags(
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalFree (KERNEL32.@)
|
||||
*
|
||||
* Free a local memory object.
|
||||
*
|
||||
* RETURNS
|
||||
* NULL: Success
|
||||
* Handle: Failure
|
||||
*
|
||||
* NOTES
|
||||
* Windows memory management does not provide a separate local heap
|
||||
* and global heap.
|
||||
*/
|
||||
HLOCAL WINAPI LocalFree(
|
||||
HLOCAL handle /* [in] Handle of memory object */
|
||||
) {
|
||||
return GlobalFree( handle );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalHandle (KERNEL32.@)
|
||||
*
|
||||
|
@ -942,48 +561,6 @@ HLOCAL WINAPI LocalHandle(
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalLock (KERNEL32.@)
|
||||
* Locks a local memory object and returns pointer to the first byte
|
||||
* of the memory block.
|
||||
*
|
||||
* RETURNS
|
||||
* Pointer: Success
|
||||
* NULL: Failure
|
||||
*
|
||||
* NOTES
|
||||
* Windows memory management does not provide a separate local heap
|
||||
* and global heap.
|
||||
*/
|
||||
LPVOID WINAPI LocalLock(
|
||||
HLOCAL handle /* [in] Address of local memory object */
|
||||
) {
|
||||
return GlobalLock( handle );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalReAlloc (KERNEL32.@)
|
||||
*
|
||||
* Change the size or attributes of a local memory object.
|
||||
*
|
||||
* RETURNS
|
||||
* Handle: Success
|
||||
* NULL: Failure
|
||||
*
|
||||
* NOTES
|
||||
* Windows memory management does not provide a separate local heap
|
||||
* and global heap.
|
||||
*/
|
||||
HLOCAL WINAPI LocalReAlloc(
|
||||
HLOCAL handle, /* [in] Handle of memory object */
|
||||
SIZE_T size, /* [in] New size of block */
|
||||
UINT flags /* [in] How to reallocate object */
|
||||
) {
|
||||
return GlobalReAlloc( handle, size, flags );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalShrink (KERNEL32.@)
|
||||
*/
|
||||
|
@ -1013,32 +590,6 @@ SIZE_T WINAPI LocalSize(
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalUnlock (KERNEL32.@)
|
||||
*
|
||||
* Unlock a local memory object.
|
||||
*
|
||||
* RETURNS
|
||||
* TRUE: Object is still locked
|
||||
* FALSE: Object is unlocked
|
||||
*
|
||||
* NOTES
|
||||
* Windows memory management does not provide a separate local heap
|
||||
* and global heap.
|
||||
*/
|
||||
BOOL WINAPI LocalUnlock(
|
||||
HLOCAL handle /* [in] Handle of memory object */
|
||||
)
|
||||
{
|
||||
if (ISPOINTER( handle ))
|
||||
{
|
||||
SetLastError( ERROR_NOT_LOCKED );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return GlobalUnlock( handle );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalMemoryStatusEx (KERNEL32.@)
|
||||
|
|
|
@ -893,14 +893,14 @@
|
|||
# @ stub GetXStateFeaturesMask
|
||||
@ stdcall GlobalAddAtomA(str)
|
||||
@ stdcall GlobalAddAtomW(wstr)
|
||||
@ stdcall GlobalAlloc(long long)
|
||||
@ stdcall -import GlobalAlloc(long long)
|
||||
@ stdcall GlobalCompact(long)
|
||||
@ stdcall GlobalDeleteAtom(long)
|
||||
@ stdcall GlobalFindAtomA(str)
|
||||
@ stdcall GlobalFindAtomW(wstr)
|
||||
@ stdcall GlobalFix(long)
|
||||
@ stdcall GlobalFlags(long)
|
||||
@ stdcall GlobalFree(long)
|
||||
@ stdcall -import GlobalFree(long)
|
||||
@ stdcall GlobalGetAtomNameA(long ptr long)
|
||||
@ stdcall GlobalGetAtomNameW(long ptr long)
|
||||
@ stdcall GlobalHandle(ptr)
|
||||
|
@ -1050,17 +1050,17 @@
|
|||
@ stdcall -import LoadResource(long long)
|
||||
# @ stub LoadStringBaseExW
|
||||
# @ stub LoadStringBaseW
|
||||
@ stdcall LocalAlloc(long long)
|
||||
@ stdcall -import LocalAlloc(long long)
|
||||
@ stdcall LocalCompact(long)
|
||||
@ stdcall LocalFileTimeToFileTime(ptr ptr)
|
||||
@ stdcall LocalFlags(long)
|
||||
@ stdcall LocalFree(long)
|
||||
@ stdcall -import LocalFree(long)
|
||||
@ stdcall LocalHandle(ptr)
|
||||
@ stdcall LocalLock(long)
|
||||
@ stdcall LocalReAlloc(long long long)
|
||||
@ stdcall -import LocalLock(long)
|
||||
@ stdcall -import LocalReAlloc(long long long)
|
||||
@ stdcall LocalShrink(long long)
|
||||
@ stdcall LocalSize(long)
|
||||
@ stdcall LocalUnlock(long)
|
||||
@ stdcall -import LocalUnlock(long)
|
||||
@ stdcall LocaleNameToLCID(wstr long)
|
||||
# @ stub LocateXStateFeature
|
||||
@ stdcall -import LockFile(long long long long long)
|
||||
|
|
|
@ -766,8 +766,8 @@
|
|||
# @ stub GetWsChanges
|
||||
# @ stub GetWsChangesEx
|
||||
# @ stub GetXStateFeaturesMask
|
||||
@ stdcall GlobalAlloc(long long) kernel32.GlobalAlloc
|
||||
@ stdcall GlobalFree(long) kernel32.GlobalFree
|
||||
@ stdcall GlobalAlloc(long long)
|
||||
@ stdcall GlobalFree(long)
|
||||
@ stdcall GlobalMemoryStatusEx(ptr) kernel32.GlobalMemoryStatusEx
|
||||
# @ stub GuardCheckLongJumpTarget
|
||||
# @ stub HasPolicyForegroundProcessingCompletedInternal
|
||||
|
@ -933,12 +933,12 @@
|
|||
@ stub LoadStringBaseExW
|
||||
@ stub LoadStringByReference
|
||||
@ stdcall LoadStringW(long long ptr long)
|
||||
@ stdcall LocalAlloc(long long) kernel32.LocalAlloc
|
||||
@ stdcall LocalAlloc(long long)
|
||||
@ stdcall LocalFileTimeToFileTime(ptr ptr) kernel32.LocalFileTimeToFileTime
|
||||
@ stdcall LocalFree(long) kernel32.LocalFree
|
||||
@ stdcall LocalLock(long) kernel32.LocalLock
|
||||
@ stdcall LocalReAlloc(long long long) kernel32.LocalReAlloc
|
||||
@ stdcall LocalUnlock(long) kernel32.LocalUnlock
|
||||
@ stdcall LocalFree(long)
|
||||
@ stdcall LocalLock(long)
|
||||
@ stdcall LocalReAlloc(long long long)
|
||||
@ stdcall LocalUnlock(long)
|
||||
@ stdcall LocaleNameToLCID(wstr long) kernel32.LocaleNameToLCID
|
||||
# @ stub LocateXStateFeature
|
||||
@ stdcall LockFile(long long long long long)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
|
@ -36,7 +37,7 @@
|
|||
#include "wine/exception.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(virtual);
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(heap);
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -384,6 +385,354 @@ BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Global/local heap functions
|
||||
***********************************************************************/
|
||||
|
||||
#include "pshpack1.h"
|
||||
|
||||
struct local_header
|
||||
{
|
||||
WORD magic;
|
||||
void *ptr;
|
||||
BYTE flags;
|
||||
BYTE lock;
|
||||
};
|
||||
|
||||
#include "poppack.h"
|
||||
|
||||
#define MAGIC_LOCAL_USED 0x5342
|
||||
/* align the storage needed for the HLOCAL on an 8-byte boundary thus
|
||||
* LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
|
||||
* size = 8*k, where k=1,2,3,... allocs exactly the given size.
|
||||
* The Minolta DiMAGE Image Viewer heavily relies on this, corrupting
|
||||
* the output jpeg's > 1 MB if not */
|
||||
#define HLOCAL_STORAGE (sizeof(HLOCAL) * 2)
|
||||
|
||||
static inline struct local_header *get_header( HLOCAL hmem )
|
||||
{
|
||||
return (struct local_header *)((char *)hmem - 2);
|
||||
}
|
||||
|
||||
static inline HLOCAL get_handle( struct local_header *header )
|
||||
{
|
||||
return &header->ptr;
|
||||
}
|
||||
|
||||
static inline BOOL is_pointer( HLOCAL hmem )
|
||||
{
|
||||
return !((ULONG_PTR)hmem & 2);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalAlloc (kernelbase.@)
|
||||
*/
|
||||
HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size )
|
||||
{
|
||||
/* mask out obsolete flags */
|
||||
flags &= ~(GMEM_NOCOMPACT | GMEM_NOT_BANKED | GMEM_NOTIFY);
|
||||
|
||||
/* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
|
||||
if (!(flags & GMEM_MOVEABLE) && !size) size = 1;
|
||||
|
||||
return LocalAlloc( flags, size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GlobalFree (kernelbase.@)
|
||||
*/
|
||||
HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL hmem )
|
||||
{
|
||||
return LocalFree( hmem );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalAlloc (kernelbase.@)
|
||||
*/
|
||||
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
|
||||
{
|
||||
struct local_header *header;
|
||||
DWORD heap_flags = 0;
|
||||
void *ptr;
|
||||
|
||||
if (flags & LMEM_ZEROINIT) heap_flags = HEAP_ZERO_MEMORY;
|
||||
|
||||
if (!(flags & LMEM_MOVEABLE)) /* pointer */
|
||||
{
|
||||
ptr = HeapAlloc( GetProcessHeap(), heap_flags, size );
|
||||
TRACE( "(flags=%04x) returning %p\n", flags, ptr );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (size > INT_MAX - HLOCAL_STORAGE)
|
||||
{
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return 0;
|
||||
}
|
||||
if (!(header = HeapAlloc( GetProcessHeap(), 0, sizeof(*header) ))) return 0;
|
||||
|
||||
header->magic = MAGIC_LOCAL_USED;
|
||||
header->flags = flags >> 8;
|
||||
header->lock = 0;
|
||||
|
||||
if (size)
|
||||
{
|
||||
if (!(ptr = HeapAlloc(GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, header );
|
||||
return 0;
|
||||
}
|
||||
*(HLOCAL *)ptr = get_handle( header );
|
||||
header->ptr = (char *)ptr + HLOCAL_STORAGE;
|
||||
}
|
||||
else header->ptr = NULL;
|
||||
|
||||
TRACE( "(flags=%04x) returning handle %p pointer %p\n",
|
||||
flags, get_handle( header ), header->ptr );
|
||||
return get_handle( header );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalFree (kernelbase.@)
|
||||
*/
|
||||
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL hmem )
|
||||
{
|
||||
struct local_header *header;
|
||||
HLOCAL ret;
|
||||
|
||||
RtlLockHeap( GetProcessHeap() );
|
||||
__TRY
|
||||
{
|
||||
ret = 0;
|
||||
if (is_pointer(hmem)) /* POINTER */
|
||||
{
|
||||
if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, hmem ))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
ret = hmem;
|
||||
}
|
||||
}
|
||||
else /* HANDLE */
|
||||
{
|
||||
header = get_header( hmem );
|
||||
if (header->magic == MAGIC_LOCAL_USED)
|
||||
{
|
||||
header->magic = 0xdead;
|
||||
if (header->ptr)
|
||||
{
|
||||
if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE,
|
||||
(char *)header->ptr - HLOCAL_STORAGE ))
|
||||
ret = hmem;
|
||||
}
|
||||
if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, header )) ret = hmem;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN( "invalid handle %p (magic: 0x%04x)\n", hmem, header->magic );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
ret = hmem;
|
||||
}
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
WARN( "invalid handle %p\n", hmem );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
ret = hmem;
|
||||
}
|
||||
__ENDTRY
|
||||
RtlUnlockHeap( GetProcessHeap() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalLock (kernelbase.@)
|
||||
*/
|
||||
LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL hmem )
|
||||
{
|
||||
void *ret = NULL;
|
||||
|
||||
if (is_pointer( hmem )) return IsBadReadPtr( hmem, 1 ) ? NULL : hmem;
|
||||
|
||||
RtlLockHeap( GetProcessHeap() );
|
||||
__TRY
|
||||
{
|
||||
struct local_header *header = get_header( hmem );
|
||||
if (header->magic == MAGIC_LOCAL_USED)
|
||||
{
|
||||
ret = header->ptr;
|
||||
if (!header->ptr) SetLastError( ERROR_DISCARDED );
|
||||
else if (header->lock < LMEM_LOCKCOUNT) header->lock++;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN( "invalid handle %p (magic: 0x%04x)\n", hmem, header->magic );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem);
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
}
|
||||
__ENDTRY
|
||||
RtlUnlockHeap( GetProcessHeap() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalReAlloc (kernelbase.@)
|
||||
*/
|
||||
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL hmem, SIZE_T size, UINT flags )
|
||||
{
|
||||
struct local_header *header;
|
||||
void *ptr;
|
||||
HLOCAL ret = 0;
|
||||
DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
|
||||
|
||||
RtlLockHeap( GetProcessHeap() );
|
||||
if (flags & LMEM_MODIFY) /* modify flags */
|
||||
{
|
||||
if (is_pointer( hmem ) && (flags & LMEM_MOVEABLE))
|
||||
{
|
||||
/* make a fixed block moveable
|
||||
* actually only NT is able to do this. But it's soo simple
|
||||
*/
|
||||
if (hmem == 0)
|
||||
{
|
||||
WARN( "null handle\n");
|
||||
SetLastError( ERROR_NOACCESS );
|
||||
}
|
||||
else
|
||||
{
|
||||
size = RtlSizeHeap( GetProcessHeap(), 0, hmem );
|
||||
ret = LocalAlloc( flags, size );
|
||||
ptr = LocalLock( ret );
|
||||
memcpy( ptr, hmem, size );
|
||||
LocalUnlock( ret );
|
||||
LocalFree( hmem );
|
||||
}
|
||||
}
|
||||
else if (!is_pointer( hmem ) && (flags & LMEM_DISCARDABLE))
|
||||
{
|
||||
/* change the flags to make our block "discardable" */
|
||||
header = get_header( hmem );
|
||||
header->flags |= LMEM_DISCARDABLE >> 8;
|
||||
ret = hmem;
|
||||
}
|
||||
else SetLastError( ERROR_INVALID_PARAMETER );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_pointer( hmem ))
|
||||
{
|
||||
/* reallocate fixed memory */
|
||||
if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
|
||||
ret = HeapReAlloc( GetProcessHeap(), heap_flags, hmem, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reallocate a moveable block */
|
||||
header = get_header( hmem );
|
||||
if (size != 0)
|
||||
{
|
||||
if (size <= INT_MAX - HLOCAL_STORAGE)
|
||||
{
|
||||
if (header->ptr)
|
||||
{
|
||||
if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags,
|
||||
(char *)header->ptr - HLOCAL_STORAGE,
|
||||
size + HLOCAL_STORAGE )))
|
||||
{
|
||||
header->ptr = (char *)ptr + HLOCAL_STORAGE;
|
||||
ret = hmem;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
|
||||
{
|
||||
*(HLOCAL *)ptr = hmem;
|
||||
header->ptr = (char *)ptr + HLOCAL_STORAGE;
|
||||
ret = hmem;
|
||||
}
|
||||
}
|
||||
}
|
||||
else SetLastError( ERROR_OUTOFMEMORY );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (header->lock == 0)
|
||||
{
|
||||
if (header->ptr)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, (char *)header->ptr - HLOCAL_STORAGE );
|
||||
header->ptr = NULL;
|
||||
}
|
||||
ret = hmem;
|
||||
}
|
||||
else WARN( "not freeing memory associated with locked handle\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
RtlUnlockHeap( GetProcessHeap() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocalUnlock (kernelbase.@)
|
||||
*/
|
||||
BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL hmem )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (is_pointer( hmem ))
|
||||
{
|
||||
SetLastError( ERROR_NOT_LOCKED );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RtlLockHeap( GetProcessHeap() );
|
||||
__TRY
|
||||
{
|
||||
struct local_header *header = get_header( hmem );
|
||||
if (header->magic == MAGIC_LOCAL_USED)
|
||||
{
|
||||
if (header->lock)
|
||||
{
|
||||
header->lock--;
|
||||
ret = (header->lock != 0);
|
||||
if (!ret) SetLastError( NO_ERROR );
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN( "%p not locked\n", hmem );
|
||||
SetLastError( ERROR_NOT_LOCKED );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, header->magic );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem);
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
}
|
||||
__ENDTRY
|
||||
RtlUnlockHeap( GetProcessHeap() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Memory resource functions
|
||||
***********************************************************************/
|
||||
|
|
Loading…
Reference in New Issue