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"
|
#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.@)
|
* GlobalLock (KERNEL32.@)
|
||||||
*
|
*
|
||||||
|
@ -326,40 +254,7 @@ HGLOBAL WINAPI GlobalAlloc(
|
||||||
*/
|
*/
|
||||||
LPVOID WINAPI GlobalLock(HGLOBAL hmem)
|
LPVOID WINAPI GlobalLock(HGLOBAL hmem)
|
||||||
{
|
{
|
||||||
PGLOBAL32_INTERN pintern;
|
return LocalLock( hmem );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -381,46 +276,8 @@ LPVOID WINAPI GlobalLock(HGLOBAL hmem)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI GlobalUnlock(HGLOBAL hmem)
|
BOOL WINAPI GlobalUnlock(HGLOBAL hmem)
|
||||||
{
|
{
|
||||||
PGLOBAL32_INTERN pintern;
|
if (ISPOINTER( hmem )) return TRUE;
|
||||||
BOOL locked;
|
return LocalUnlock( hmem );
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -495,200 +352,9 @@ HGLOBAL WINAPI GlobalHandle(
|
||||||
* Handle: Success
|
* Handle: Success
|
||||||
* NULL: Failure
|
* NULL: Failure
|
||||||
*/
|
*/
|
||||||
HGLOBAL WINAPI GlobalReAlloc(
|
HGLOBAL WINAPI GlobalReAlloc( HGLOBAL hmem, SIZE_T size, UINT flags )
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
PGLOBAL32_INTERN pintern;
|
return LocalReAlloc( hmem, size, flags );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.@)
|
* 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.@)
|
* 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.@)
|
* 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.@)
|
* GlobalMemoryStatusEx (KERNEL32.@)
|
||||||
|
|
|
@ -893,14 +893,14 @@
|
||||||
# @ stub GetXStateFeaturesMask
|
# @ stub GetXStateFeaturesMask
|
||||||
@ stdcall GlobalAddAtomA(str)
|
@ stdcall GlobalAddAtomA(str)
|
||||||
@ stdcall GlobalAddAtomW(wstr)
|
@ stdcall GlobalAddAtomW(wstr)
|
||||||
@ stdcall GlobalAlloc(long long)
|
@ stdcall -import GlobalAlloc(long long)
|
||||||
@ stdcall GlobalCompact(long)
|
@ stdcall GlobalCompact(long)
|
||||||
@ stdcall GlobalDeleteAtom(long)
|
@ stdcall GlobalDeleteAtom(long)
|
||||||
@ stdcall GlobalFindAtomA(str)
|
@ stdcall GlobalFindAtomA(str)
|
||||||
@ stdcall GlobalFindAtomW(wstr)
|
@ stdcall GlobalFindAtomW(wstr)
|
||||||
@ stdcall GlobalFix(long)
|
@ stdcall GlobalFix(long)
|
||||||
@ stdcall GlobalFlags(long)
|
@ stdcall GlobalFlags(long)
|
||||||
@ stdcall GlobalFree(long)
|
@ stdcall -import GlobalFree(long)
|
||||||
@ stdcall GlobalGetAtomNameA(long ptr long)
|
@ stdcall GlobalGetAtomNameA(long ptr long)
|
||||||
@ stdcall GlobalGetAtomNameW(long ptr long)
|
@ stdcall GlobalGetAtomNameW(long ptr long)
|
||||||
@ stdcall GlobalHandle(ptr)
|
@ stdcall GlobalHandle(ptr)
|
||||||
|
@ -1050,17 +1050,17 @@
|
||||||
@ stdcall -import LoadResource(long long)
|
@ stdcall -import LoadResource(long long)
|
||||||
# @ stub LoadStringBaseExW
|
# @ stub LoadStringBaseExW
|
||||||
# @ stub LoadStringBaseW
|
# @ stub LoadStringBaseW
|
||||||
@ stdcall LocalAlloc(long long)
|
@ stdcall -import LocalAlloc(long long)
|
||||||
@ stdcall LocalCompact(long)
|
@ stdcall LocalCompact(long)
|
||||||
@ stdcall LocalFileTimeToFileTime(ptr ptr)
|
@ stdcall LocalFileTimeToFileTime(ptr ptr)
|
||||||
@ stdcall LocalFlags(long)
|
@ stdcall LocalFlags(long)
|
||||||
@ stdcall LocalFree(long)
|
@ stdcall -import LocalFree(long)
|
||||||
@ stdcall LocalHandle(ptr)
|
@ stdcall LocalHandle(ptr)
|
||||||
@ stdcall LocalLock(long)
|
@ stdcall -import LocalLock(long)
|
||||||
@ stdcall LocalReAlloc(long long long)
|
@ stdcall -import LocalReAlloc(long long long)
|
||||||
@ stdcall LocalShrink(long long)
|
@ stdcall LocalShrink(long long)
|
||||||
@ stdcall LocalSize(long)
|
@ stdcall LocalSize(long)
|
||||||
@ stdcall LocalUnlock(long)
|
@ stdcall -import LocalUnlock(long)
|
||||||
@ stdcall LocaleNameToLCID(wstr long)
|
@ stdcall LocaleNameToLCID(wstr long)
|
||||||
# @ stub LocateXStateFeature
|
# @ stub LocateXStateFeature
|
||||||
@ stdcall -import LockFile(long long long long long)
|
@ stdcall -import LockFile(long long long long long)
|
||||||
|
|
|
@ -766,8 +766,8 @@
|
||||||
# @ stub GetWsChanges
|
# @ stub GetWsChanges
|
||||||
# @ stub GetWsChangesEx
|
# @ stub GetWsChangesEx
|
||||||
# @ stub GetXStateFeaturesMask
|
# @ stub GetXStateFeaturesMask
|
||||||
@ stdcall GlobalAlloc(long long) kernel32.GlobalAlloc
|
@ stdcall GlobalAlloc(long long)
|
||||||
@ stdcall GlobalFree(long) kernel32.GlobalFree
|
@ stdcall GlobalFree(long)
|
||||||
@ stdcall GlobalMemoryStatusEx(ptr) kernel32.GlobalMemoryStatusEx
|
@ stdcall GlobalMemoryStatusEx(ptr) kernel32.GlobalMemoryStatusEx
|
||||||
# @ stub GuardCheckLongJumpTarget
|
# @ stub GuardCheckLongJumpTarget
|
||||||
# @ stub HasPolicyForegroundProcessingCompletedInternal
|
# @ stub HasPolicyForegroundProcessingCompletedInternal
|
||||||
|
@ -933,12 +933,12 @@
|
||||||
@ stub LoadStringBaseExW
|
@ stub LoadStringBaseExW
|
||||||
@ stub LoadStringByReference
|
@ stub LoadStringByReference
|
||||||
@ stdcall LoadStringW(long long ptr long)
|
@ stdcall LoadStringW(long long ptr long)
|
||||||
@ stdcall LocalAlloc(long long) kernel32.LocalAlloc
|
@ stdcall LocalAlloc(long long)
|
||||||
@ stdcall LocalFileTimeToFileTime(ptr ptr) kernel32.LocalFileTimeToFileTime
|
@ stdcall LocalFileTimeToFileTime(ptr ptr) kernel32.LocalFileTimeToFileTime
|
||||||
@ stdcall LocalFree(long) kernel32.LocalFree
|
@ stdcall LocalFree(long)
|
||||||
@ stdcall LocalLock(long) kernel32.LocalLock
|
@ stdcall LocalLock(long)
|
||||||
@ stdcall LocalReAlloc(long long long) kernel32.LocalReAlloc
|
@ stdcall LocalReAlloc(long long long)
|
||||||
@ stdcall LocalUnlock(long) kernel32.LocalUnlock
|
@ stdcall LocalUnlock(long)
|
||||||
@ stdcall LocaleNameToLCID(wstr long) kernel32.LocaleNameToLCID
|
@ stdcall LocaleNameToLCID(wstr long) kernel32.LocaleNameToLCID
|
||||||
# @ stub LocateXStateFeature
|
# @ stub LocateXStateFeature
|
||||||
@ stdcall LockFile(long long long long long)
|
@ stdcall LockFile(long long long long long)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "ntstatus.h"
|
#include "ntstatus.h"
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
#include "wine/exception.h"
|
#include "wine/exception.h"
|
||||||
#include "wine/debug.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
|
* Memory resource functions
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
Loading…
Reference in New Issue