* Global heap functions
*
* Copyright 1995 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* 0xffff sometimes seems to mean: CURRENT_DS */
+#include "config.h"
+#include "wine/port.h"
+
#include <sys/types.h>
#include <stdlib.h>
-#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#include <string.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
#include "wine/winbase16.h"
+#include "wine/exception.h"
#include "global.h"
-#include "heap.h"
#include "toolhelp.h"
#include "selectors.h"
#include "miscemu.h"
-#include "dde_mem.h"
#include "stackframe.h"
#include "module.h"
-#include "debugtools.h"
+#include "wine/debug.h"
#include "winerror.h"
+#include "msvcrt/excpt.h"
-DEFAULT_DEBUG_CHANNEL(global)
+WINE_DEFAULT_DEBUG_CHANNEL(global);
/* Global arena block */
typedef struct
BYTE pageLockCount; /* Count of GlobalPageLock() calls */
BYTE flags; /* Allocation flags */
BYTE selCount; /* Number of selectors allocated for this block */
-#ifdef CONFIG_IPC
- int shmid;
-#endif
} GLOBALARENA;
/* Flags definitions */
#define GA_DGROUP 0x04
#define GA_DISCARDABLE 0x08
#define GA_IPCSHARE 0x10 /* same as GMEM_DDESHARE */
+#define GA_DOSMEM 0x20
/* Arena array */
static GLOBALARENA *pGlobalArena = NULL;
#define VALID_HANDLE(handle) (((handle)>>__AHSHIFT)<globalArenaSize)
#define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
+/* filter for page-fault exceptions */
+/* It is possible for a bogus global pointer to cause a */
+/* page zero reference, so I include EXCEPTION_PRIV_INSTRUCTION too. */
+
+static WINE_EXCEPTION_FILTER(page_fault)
+{
+ switch (GetExceptionCode()) {
+ case (EXCEPTION_ACCESS_VIOLATION):
+ case (EXCEPTION_PRIV_INSTRUCTION):
+ return EXCEPTION_EXECUTE_HANDLER;
+ default:
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+}
+
/***********************************************************************
* GLOBAL_GetArena
*
return pGlobalArena + (sel >> __AHSHIFT);
}
-
void debug_handles(void)
{
int printed=0;
* Create a global heap block for a fixed range of linear memory.
*/
HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
- HGLOBAL16 hOwner, BOOL16 isCode,
- BOOL16 is32Bit, BOOL16 isReadOnly,
- SHMDATA *shmdata )
+ HGLOBAL16 hOwner, unsigned char selflags )
{
WORD sel, selcount;
GLOBALARENA *pArena;
/* Allocate the selector(s) */
- sel = SELECTOR_AllocBlock( ptr, size,
- isCode ? SEGMENT_CODE : SEGMENT_DATA,
- is32Bit, isReadOnly );
-
+ sel = SELECTOR_AllocBlock( ptr, size, selflags );
if (!sel) return 0;
selcount = (size + 0xffff) / 0x10000;
if (!(pArena = GLOBAL_GetArena( sel, selcount )))
{
- SELECTOR_FreeBlock( sel, selcount );
+ SELECTOR_FreeBlock( sel );
return 0;
}
/* Fill the arena block */
pArena->base = (DWORD)ptr;
- pArena->size = GET_SEL_LIMIT(sel) + 1;
-
-#ifdef CONFIG_IPC
- if (flags & GMEM_DDESHARE)
- {
- pArena->handle = shmdata->handle;
- pArena->shmid = shmdata->shmid;
- shmdata->sel = sel;
- }
- else
- {
- pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
- pArena->shmid = 0;
- }
-#else
+ pArena->size = GetSelectorLimit16(sel) + 1;
pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
-#endif
pArena->hOwner = hOwner;
pArena->lockCount = 0;
pArena->pageLockCount = 0;
pArena->flags = flags & GA_MOVEABLE;
if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
- if (!isCode) pArena->flags |= GA_DGROUP;
+ if (!(selflags & (WINE_LDT_FLAGS_CODE^WINE_LDT_FLAGS_DATA))) pArena->flags |= GA_DGROUP;
pArena->selCount = selcount;
if (selcount > 1) /* clear the next arena blocks */
memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
GLOBALARENA *pArena;
if (!handle) return TRUE;
- sel = GlobalHandleToSel16( handle );
+ sel = GlobalHandleToSel16( handle );
if (!VALID_HANDLE(sel))
return FALSE;
pArena = GET_ARENA_PTR(sel);
- SELECTOR_FreeBlock( sel, (pArena->size + 0xffff) / 0x10000 );
+ SELECTOR_FreeBlock( sel );
memset( pArena, 0, sizeof(GLOBALARENA) );
return TRUE;
}
GLOBALARENA *pArena;
if (!handle) return TRUE;
- sel = GlobalHandleToSel16( handle );
+ sel = GlobalHandleToSel16( handle );
if (!VALID_HANDLE(sel))
return FALSE;
pArena = GET_ARENA_PTR(sel);
pArena->base = (DWORD)ptr;
pArena->size = size;
-
- SELECTOR_MoveBlock( sel, ptr );
- SetSelectorLimit16( sel, size-1 );
-
+ SELECTOR_ReallocBlock( sel, ptr, size );
return TRUE;
}
*
* Implementation of GlobalAlloc16()
*/
-HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
- BOOL16 isCode, BOOL16 is32Bit, BOOL16 isReadOnly )
+HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner, unsigned char selflags )
{
void *ptr;
HGLOBAL16 handle;
- SHMDATA shmdata;
TRACE("%ld flags=%04x\n", size, flags );
/* If size is 0, create a discarded block */
- if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
- is32Bit, isReadOnly, NULL );
+ if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, selflags );
/* Fixup the size */
if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
size = (size + 0x1f) & ~0x1f;
- /* Allocate the linear memory */
-
-#ifdef CONFIG_IPC
- if (flags & GMEM_DDESHARE)
- ptr = DDE_malloc(flags, size, &shmdata);
- else
-#endif /* CONFIG_IPC */
- {
- ptr = HeapAlloc( SystemHeap, 0, size );
- }
+ /* Allocate the linear memory */
+ ptr = HeapAlloc( GetProcessHeap(), 0, size );
/* FIXME: free discardable blocks and try again? */
if (!ptr) return 0;
/* Allocate the selector(s) */
- handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
- isCode, is32Bit, isReadOnly, &shmdata);
+ handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner, selflags );
if (!handle)
{
- HeapFree( SystemHeap, 0, ptr );
+ HeapFree( GetProcessHeap(), 0, ptr );
return 0;
}
return handle;
}
-
-#ifdef CONFIG_IPC
-/***********************************************************************
- * GLOBAL_FindArena
- *
- * Find the arena for a given handle
- * (when handle is not serial - e.g. DDE)
- */
-static GLOBALARENA *GLOBAL_FindArena( HGLOBAL16 handle)
-{
- int i;
- for (i = globalArenaSize-1 ; i>=0 ; i--) {
- if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
- return ( &pGlobalArena[i] );
- }
- return NULL;
-}
-
-
-/***********************************************************************
- * DDE_GlobalHandleToSel
- */
-
-WORD DDE_GlobalHandleToSel( HGLOBAL16 handle )
-{
- GLOBALARENA *pArena;
- SEGPTR segptr;
-
- pArena= GLOBAL_FindArena(handle);
- if (pArena) {
- int ArenaIdx = pArena - pGlobalArena;
-
- /* See if synchronized to the shared memory */
- return DDE_SyncHandle(handle, ( ArenaIdx << __AHSHIFT) | 7);
- }
-
- /* attach the block */
- DDE_AttachHandle(handle, &segptr);
-
- return SELECTOROF( segptr );
-}
-#endif /* CONFIG_IPC */
-
-
/***********************************************************************
- * GlobalAlloc16 (KERNEL.15)
+ * GlobalAlloc (KERNEL.15)
+ * GlobalAlloc16 (KERNEL32.24)
* RETURNS
* Handle: Success
* NULL: Failure
if (flags & GMEM_DDESHARE)
owner = GetExePtr(owner); /* Make it a module handle */
- return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
+ return GLOBAL_Alloc( flags, size, owner, WINE_LDT_FLAGS_DATA );
}
/***********************************************************************
- * GlobalReAlloc16 (KERNEL.16)
+ * GlobalReAlloc (KERNEL.16)
* RETURNS
* Handle: Success
* NULL: Failure
) {
WORD selcount;
DWORD oldsize;
- void *ptr;
+ void *ptr, *newptr;
GLOBALARENA *pArena, *pNewArena;
WORD sel = GlobalHandleToSel16( handle );
TRACE("%04x %ld flags=%04x\n",
handle, size, flags );
if (!handle) return 0;
-
-#ifdef CONFIG_IPC
- if (flags & GMEM_DDESHARE || is_dde_handle(handle))
- {
- FIXME("shared memory reallocating unimplemented\n");
- return 0;
- }
-#endif /* CONFIG_IPC */
if (!VALID_HANDLE(handle)) {
WARN("Invalid handle 0x%04x!\n", handle);
if (!(pArena->flags & GA_MOVEABLE) ||
!(pArena->flags & GA_DISCARDABLE) ||
(pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
- HeapFree( SystemHeap, 0, (void *)pArena->base );
+ HeapFree( GetProcessHeap(), 0, (void *)pArena->base );
pArena->base = 0;
- /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
+ /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
* change the selector if we are shrinking the block.
* FIXME: shouldn't we keep selectors until the block is deleted?
*/
ptr = (void *)pArena->base;
oldsize = pArena->size;
- TRACE("oldsize %08lx\n",oldsize);
+ TRACE("oldbase %p oldsize %08lx newsize %08lx\n", ptr,oldsize,size);
if (ptr && (size == oldsize)) return handle; /* Nothing to do */
- if (((char *)ptr >= DOSMEM_MemoryBase(0)) &&
- ((char *)ptr <= DOSMEM_MemoryBase(0) + 0x100000))
- ptr = DOSMEM_ResizeBlock(0, ptr, size, NULL);
+ if (pArena->flags & GA_DOSMEM)
+ newptr = DOSMEM_ResizeBlock(ptr, size, NULL);
else
- ptr = HeapReAlloc( SystemHeap, 0, ptr, size );
- if (!ptr)
+ /* if more then one reader (e.g. some pointer has been given out by GetVDMPointer32W16),
+ only try to realloc in place */
+ newptr = HeapReAlloc( GetProcessHeap(),
+ (pArena->pageLockCount > 0)?HEAP_REALLOC_IN_PLACE_ONLY:0, ptr, size );
+ if (!newptr)
{
- SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
- memset( pArena, 0, sizeof(GLOBALARENA) );
+ FIXME("Realloc failed lock %d\n",pArena->pageLockCount);
+ if (pArena->pageLockCount <1)
+ {
+ HeapFree( GetProcessHeap(), 0, ptr );
+ SELECTOR_FreeBlock( sel );
+ memset( pArena, 0, sizeof(GLOBALARENA) );
+ }
return 0;
}
+ ptr = newptr;
/* Reallocate the selector(s) */
sel = SELECTOR_ReallocBlock( sel, ptr, size );
if (!sel)
{
- HeapFree( SystemHeap, 0, ptr );
+ HeapFree( GetProcessHeap(), 0, ptr );
memset( pArena, 0, sizeof(GLOBALARENA) );
return 0;
}
if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
{
- HeapFree( SystemHeap, 0, ptr );
- SELECTOR_FreeBlock( sel, selcount );
+ HeapFree( GetProcessHeap(), 0, ptr );
+ SELECTOR_FreeBlock( sel );
return 0;
}
- /* Fill the new arena block */
+ /* Fill the new arena block
+ As we may have used HEAP_REALLOC_IN_PLACE_ONLY, areas may overlap*/
- if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
+ if (pNewArena != pArena) memmove( pNewArena, pArena, sizeof(GLOBALARENA) );
pNewArena->base = (DWORD)ptr;
- pNewArena->size = GET_SEL_LIMIT(sel) + 1;
+ pNewArena->size = GetSelectorLimit16(sel) + 1;
pNewArena->selCount = selcount;
pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
/***********************************************************************
- * GlobalFree16 (KERNEL.17)
+ * GlobalFree (KERNEL.17)
+ * GlobalFree16 (KERNEL32.31)
* RETURNS
* NULL: Success
* Handle: Failure
TRACE("%04x\n", handle );
if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
-#ifdef CONFIG_IPC
- if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
-#endif /* CONFIG_IPC */
- if (ptr) HeapFree( SystemHeap, 0, ptr );
+ if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
return 0;
}
/***********************************************************************
- * WIN16_GlobalLock16 (KERNEL.18)
+ * GlobalLock (KERNEL.18)
*
* This is the GlobalLock16() function used by 16-bit code.
*/
SEGPTR WINAPI WIN16_GlobalLock16( HGLOBAL16 handle )
{
- TRACE("(%04x) -> %08lx\n",
- handle, MAKELONG( 0, GlobalHandleToSel16(handle)) );
+ WORD sel = GlobalHandleToSel16( handle );
+ TRACE("(%04x) -> %08lx\n", handle, MAKELONG( 0, sel ) );
+
if (handle)
{
if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
-#ifdef CONFIG_IPC
- if (is_dde_handle(handle))
- return PTR_SEG_OFF_TO_SEGPTR( DDE_GlobalHandleToSel(handle), 0 );
-#endif /* CONFIG_IPC */
-
if (!VALID_HANDLE(handle)) {
WARN("Invalid handle 0x%04x passed to WIN16_GlobalLock16!\n",handle);
- return (SEGPTR)0;
+ sel = 0;
}
- if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
- GET_ARENA_PTR(handle)->lockCount++;
- return PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel16(handle), 0 );
- /* FIXME: put segment value in CX as well */
+ else if (!GET_ARENA_PTR(handle)->base)
+ sel = 0;
+ else
+ GET_ARENA_PTR(handle)->lockCount++;
}
- return (SEGPTR)0;
+
+ CURRENT_STACK16->ecx = sel; /* selector must be returned in CX as well */
+ return MAKESEGPTR( sel, 0 );
+}
+
+
+/**********************************************************************
+ * K32WOWGlobalLock16 (KERNEL32.60)
+ */
+SEGPTR WINAPI K32WOWGlobalLock16( HGLOBAL16 hMem )
+{
+ return WIN16_GlobalLock16( hMem );
}
/***********************************************************************
- * GlobalLock16 (KERNEL.18)
+ * GlobalLock16 (KERNEL32.25)
*
* This is the GlobalLock16() function used by 32-bit code.
- *
+ *
* RETURNS
* Pointer to first byte of memory block
* NULL: Failure
if (!VALID_HANDLE(handle))
return (LPVOID)0;
GET_ARENA_PTR(handle)->lockCount++;
-#ifdef CONFIG_IPC
- if (is_dde_handle(handle)) return DDE_AttachHandle(handle, NULL);
-#endif
return (LPVOID)GET_ARENA_PTR(handle)->base;
}
/***********************************************************************
- * GlobalUnlock16 (KERNEL.19)
+ * GlobalUnlock (KERNEL.19)
+ * GlobalUnlock16 (KERNEL32.26)
* NOTES
* Should the return values be cast to booleans?
*
* *all* registers, even AX/DX !
*
*/
-void WINAPI GlobalChangeLockCount16( CONTEXT86 *context )
+void WINAPI GlobalChangeLockCount16( HGLOBAL16 handle, INT16 delta,
+ CONTEXT86 *context )
{
- LPWORD args = PTR_SEG_OFF_TO_LIN( SS_reg( context ), SP_reg( context ) );
- HGLOBAL16 handle = (HGLOBAL16)args[3];
- INT16 delta = (INT16) args[2];
-
if ( delta == 1 )
GlobalLock16( handle );
else if ( delta == -1 )
}
/***********************************************************************
- * GlobalSize16 (KERNEL.20)
+ * GlobalSize (KERNEL.20)
+ * GlobalSize16 (KERNEL32.32)
* RETURNS
* Size in bytes of object
* 0: Failure
/***********************************************************************
- * GlobalHandle16 (KERNEL.21)
+ * GlobalHandle (KERNEL.21)
* NOTES
* Why is GlobalHandleToSel used here with the sel as input?
*
/***********************************************************************
- * GlobalFlags16 (KERNEL.22)
+ * GlobalFlags (KERNEL.22)
+ *
* NOTES
* Should this return GMEM_INVALID_HANDLE instead of 0 on invalid
* handle?
/***********************************************************************
- * LockSegment16 (KERNEL.23)
+ * LockSegment (KERNEL.23)
*/
HGLOBAL16 WINAPI LockSegment16( HGLOBAL16 handle )
{
/***********************************************************************
- * UnlockSegment16 (KERNEL.24)
+ * UnlockSegment (KERNEL.24)
*/
void WINAPI UnlockSegment16( HGLOBAL16 handle )
{
/***********************************************************************
- * GlobalCompact16 (KERNEL.25)
+ * GlobalCompact (KERNEL.25)
*/
DWORD WINAPI GlobalCompact16( DWORD desired )
{
/***********************************************************************
- * GlobalWire16 (KERNEL.111)
+ * GlobalWire (KERNEL.111)
+ * GlobalWire16 (KERNEL32.29)
*/
SEGPTR WINAPI GlobalWire16( HGLOBAL16 handle )
{
/***********************************************************************
- * GlobalUnWire16 (KERNEL.112)
+ * GlobalUnWire (KERNEL.112)
+ * GlobalUnWire16 (KERNEL32.30)
*/
BOOL16 WINAPI GlobalUnWire16( HGLOBAL16 handle )
{
/***********************************************************************
- * SetSwapAreaSize16 (KERNEL.106)
+ * SetSwapAreaSize (KERNEL.106)
*/
LONG WINAPI SetSwapAreaSize16( WORD size )
{
/***********************************************************************
- * GetFreeSpace16 (KERNEL.169)
+ * GetFreeSpace (KERNEL.169)
*/
DWORD WINAPI GetFreeSpace16( UINT16 wFlags )
{
DWORD size /* [in] Number of bytes to be allocated */
) {
UINT16 uParagraph;
- LPVOID lpBlock = DOSMEM_GetBlock( 0, size, &uParagraph );
+ LPVOID lpBlock = DOSMEM_GetBlock( size, &uParagraph );
if( lpBlock )
{
HMODULE16 hModule = GetModuleHandle16("KERNEL");
WORD wSelector;
-
- wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size,
- hModule, 0, 0, 0, NULL );
+ GLOBALARENA *pArena;
+
+ wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size, hModule, WINE_LDT_FLAGS_DATA );
+ pArena = GET_ARENA_PTR(wSelector);
+ pArena->flags |= GA_DOSMEM;
return MAKELONG(wSelector,uParagraph);
}
return 0;
) {
DWORD block = GetSelectorBase(sel);
- if( block && block < 0x100000 )
+ if( block && block < 0x100000 )
{
LPVOID lpBlock = DOSMEM_MapDosToLinear( block );
- if( DOSMEM_FreeBlock( 0, lpBlock ) )
+ if( DOSMEM_FreeBlock( lpBlock ) )
GLOBAL_FreeBlock( sel );
sel = 0;
}
/***********************************************************************
* GlobalPageLock (KERNEL.191)
+ * GlobalSmartPageLock(KERNEL.230)
*/
WORD WINAPI GlobalPageLock16( HGLOBAL16 handle )
{
/***********************************************************************
* GlobalPageUnlock (KERNEL.192)
+ * GlobalSmartPageUnlock(KERNEL.231)
*/
WORD WINAPI GlobalPageUnlock16( HGLOBAL16 handle )
{
/***********************************************************************
- * GlobalFix16 (KERNEL.197)
+ * GlobalFix (KERNEL.197)
+ * GlobalFix16 (KERNEL32.27)
*/
WORD WINAPI GlobalFix16( HGLOBAL16 handle )
{
/***********************************************************************
- * GlobalUnfix16 (KERNEL.198)
+ * GlobalUnfix (KERNEL.198)
+ * GlobalUnfix16 (KERNEL32.28)
*/
void WINAPI GlobalUnfix16( HGLOBAL16 handle )
{
WORD WINAPI GlobalHandleToSel16( HGLOBAL16 handle )
{
if (!handle) return 0;
-#ifdef CONFIG_IPC
- if (is_dde_handle(handle)) return DDE_GlobalHandleToSel(handle);
-#endif
if (!VALID_HANDLE(handle)) {
WARN("Invalid handle 0x%04x passed to GlobalHandleToSel!\n",handle);
return 0;
BOOL16 WINAPI GlobalEntryModule16( GLOBALENTRY *pGlobal, HMODULE16 hModule,
WORD wSeg )
{
+ FIXME("(%p, 0x%04x, 0x%04x), stub.\n", pGlobal, hModule, wSeg);
return FALSE;
}
MEMORYSTATUS status;
/*
- * Not unsurprisingly although the documention says you
+ * Not unsurprisingly although the documention says you
* _must_ provide the size in the dwSize field, this function
* (under Windows) always fills the structure and returns true.
*/
GlobalMemoryStatus( &status );
- info->wPageSize = VIRTUAL_GetPageSize();
+ info->wPageSize = getpagesize();
info->dwLargestFreeBlock = status.dwAvailVirtual;
info->dwMaxPagesAvailable = info->dwLargestFreeBlock / info->wPageSize;
info->dwMaxPagesLockable = info->dwMaxPagesAvailable;
/*
* Win32 Global heap functions (GlobalXXX).
* These functions included in Win32 for compatibility with 16 bit Windows
- * Especially the moveable blocks and handles are oldish.
+ * Especially the moveable blocks and handles are oldish.
* But the ability to directly allocate memory with GPTR and LPTR is widely
* used.
*
* The handle stuff looks horrible, but it's implemented almost like Win95
- * does it.
+ * does it.
*
*/
/***********************************************************************
- * GlobalAlloc32 (KERNEL32.315)
+ * GlobalAlloc (KERNEL32.@)
* RETURNS
* Handle: Success
* NULL: Failure
*/
HGLOBAL WINAPI GlobalAlloc(
UINT flags, /* [in] Object allocation attributes */
- DWORD size /* [in] Number of bytes to allocate */
+ SIZE_T size /* [in] Number of bytes to allocate */
) {
PGLOBAL32_INTERN pintern;
DWORD hpflags;
hpflags=HEAP_ZERO_MEMORY;
else
hpflags=0;
-
+
+ TRACE("() flags=%04x\n", flags );
+
if((flags & GMEM_MOVEABLE)==0) /* POINTER */
{
palloc=HeapAlloc(GetProcessHeap(), hpflags, size);
}
else /* HANDLE */
{
- /* HeapLock(GetProcessHeap()); */
+ /* HeapLock(heap); */
pintern=HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
+ if (!pintern) return 0;
if(size)
{
- palloc=HeapAlloc(GetProcessHeap(), hpflags, size+sizeof(HGLOBAL));
+ if (!(palloc=HeapAlloc(GetProcessHeap(), hpflags, size+sizeof(HGLOBAL)))) {
+ HeapFree(GetProcessHeap(), 0, pintern);
+ return 0;
+ }
*(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
}
pintern->Magic=MAGIC_GLOBAL_USED;
pintern->Flags=flags>>8;
pintern->LockCount=0;
-
- /* HeapUnlock(GetProcessHeap()); */
-
+
+ /* HeapUnlock(heap); */
+
return INTERN_TO_HANDLE(pintern);
}
}
/***********************************************************************
- * GlobalLock32 (KERNEL32.326)
+ * GlobalLock (KERNEL32.@)
* RETURNS
* Pointer to first byte of block
* NULL: Failure
return (LPVOID) hmem;
/* HeapLock(GetProcessHeap()); */
-
+
pintern=HANDLE_TO_INTERN(hmem);
if(pintern->Magic==MAGIC_GLOBAL_USED)
{
{
WARN("invalid handle\n");
palloc=(LPVOID) NULL;
+ SetLastError(ERROR_INVALID_HANDLE);
}
/* HeapUnlock(GetProcessHeap()); */;
return palloc;
/***********************************************************************
- * GlobalUnlock32 (KERNEL32.332)
+ * GlobalUnlock (KERNEL32.@)
* RETURNS
* TRUE: Object is still locked
* FALSE: Object is unlocked
BOOL WINAPI GlobalUnlock(
HGLOBAL hmem /* [in] Handle of global memory object */
) {
- PGLOBAL32_INTERN pintern;
- BOOL locked;
+ PGLOBAL32_INTERN pintern;
+ BOOL locked;
- if(ISPOINTER(hmem))
- return FALSE;
+ if (ISPOINTER(hmem)) return FALSE;
- /* HeapLock(GetProcessHeap()); */
- pintern=HANDLE_TO_INTERN(hmem);
-
- if(pintern->Magic==MAGIC_GLOBAL_USED)
- {
- if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
- pintern->LockCount--;
+ __TRY
+ {
+ /* HeapLock(GetProcessHeap()); */
+ pintern=HANDLE_TO_INTERN(hmem);
+ if(pintern->Magic==MAGIC_GLOBAL_USED)
+ {
+ if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
+ pintern->LockCount--;
- locked=(pintern->LockCount==0) ? FALSE : TRUE;
- }
- else
- {
- WARN("invalid handle\n");
- locked=FALSE;
- }
- /* HeapUnlock(GetProcessHeap()); */
- return locked;
+ locked = (pintern->LockCount != 0);
+ if (!locked) SetLastError(NO_ERROR);
+ }
+ else
+ {
+ WARN("invalid handle\n");
+ SetLastError(ERROR_INVALID_HANDLE);
+ locked=FALSE;
+ }
+ /* HeapUnlock(GetProcessHeap()); */
+ }
+ __EXCEPT(page_fault)
+ {
+ ERR("page fault occurred ! Caused by bug ?\n");
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ __ENDTRY
+ return locked;
}
/***********************************************************************
- * GlobalHandle32 (KERNEL32.325)
+ * GlobalHandle (KERNEL32.@)
* Returns the handle associated with the specified pointer.
*
- * NOTES
- * Since there in only one goto, can it be removed and the return
- * be put 'inline'?
- *
* RETURNS
* Handle: Success
* NULL: Failure
LPCVOID pmem /* [in] Pointer to global memory block */
) {
HGLOBAL handle;
+ PGLOBAL32_INTERN maybe_intern;
+ LPCVOID test;
- if (!HEAP_IsInsideHeap( GetProcessHeap(), 0, pmem )) goto error;
- handle = POINTER_TO_HANDLE(pmem);
- if (HEAP_IsInsideHeap( GetProcessHeap(), 0, (LPCVOID)handle ))
+ if (!pmem)
{
- if (HANDLE_TO_INTERN(handle)->Magic == MAGIC_GLOBAL_USED)
- return handle; /* valid moveable block */
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
}
- /* maybe FIXED block */
- if (HeapValidate( GetProcessHeap(), 0, pmem ))
- return (HGLOBAL)pmem; /* valid fixed block */
-error:
- SetLastError( ERROR_INVALID_HANDLE );
- return 0;
+ __TRY
+ {
+ handle = 0;
+
+ /* note that if pmem is a pointer to a a block allocated by */
+ /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
+ /* will fail. */
+ if (ISPOINTER(pmem)) {
+ if (HeapValidate( GetProcessHeap(), 0, pmem )) {
+ handle = (HGLOBAL)pmem; /* valid fixed block */
+ break;
+ }
+ handle = POINTER_TO_HANDLE(pmem);
+ } else
+ handle = (HGLOBAL)pmem;
+
+ /* Now test handle either passed in or retrieved from pointer */
+ maybe_intern = HANDLE_TO_INTERN( handle );
+ if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
+ test = maybe_intern->Pointer;
+ if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
+ HeapValidate( GetProcessHeap(), 0, maybe_intern )) /* intern valid arena? */
+ break; /* valid moveable block */
+ }
+ handle = 0;
+ SetLastError( ERROR_INVALID_HANDLE );
+ }
+ __EXCEPT(page_fault)
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return 0;
+ }
+ __ENDTRY
+
+ return handle;
}
/***********************************************************************
- * GlobalReAlloc32 (KERNEL32.328)
+ * GlobalReAlloc (KERNEL32.@)
* RETURNS
* Handle: Success
* NULL: Failure
*/
HGLOBAL WINAPI GlobalReAlloc(
HGLOBAL hmem, /* [in] Handle of global memory object */
- DWORD size, /* [in] New size of block */
+ 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;
- /* HeapLock(GetProcessHeap()); */
+ /* HeapLock(heap); */
if(flags & GMEM_MODIFY) /* modify flags */
{
if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
if(ISPOINTER(hmem))
{
/* reallocate fixed memory */
- hnew=(HGLOBAL)HeapReAlloc(GetProcessHeap(), 0, (LPVOID) hmem, size);
+ hnew=(HGLOBAL)HeapReAlloc(GetProcessHeap(), heap_flags, (LPVOID) 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 if(size!=0)
+ } else
+#endif
+ if(size!=0)
{
hnew=hmem;
if(pintern->Pointer)
{
- palloc=HeapReAlloc(GetProcessHeap(), 0,
- (char *) pintern->Pointer-sizeof(HGLOBAL),
- size+sizeof(HGLOBAL) );
+ if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
+ (char *) pintern->Pointer-sizeof(HGLOBAL),
+ size+sizeof(HGLOBAL))) == NULL)
+ return 0; /* Block still valid */
pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
}
else
{
- palloc=HeapAlloc(GetProcessHeap(), 0, size+sizeof(HGLOBAL));
+ if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+sizeof(HGLOBAL)))
+ == NULL)
+ return 0;
*(HGLOBAL *)palloc=hmem;
pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
}
}
}
}
- /* HeapUnlock(GetProcessHeap()); */
+ /* HeapUnlock(heap); */
return hnew;
}
/***********************************************************************
- * GlobalFree32 (KERNEL32.322)
+ * GlobalFree (KERNEL32.@)
* RETURNS
* NULL: Success
* Handle: Failure
HGLOBAL WINAPI GlobalFree(
HGLOBAL hmem /* [in] Handle of global memory object */
) {
- PGLOBAL32_INTERN pintern;
- HGLOBAL hreturned = 0;
-
- if(ISPOINTER(hmem)) /* POINTER */
- {
- if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
- }
- else /* HANDLE */
- {
- /* HeapLock(GetProcessHeap()); */
- pintern=HANDLE_TO_INTERN(hmem);
-
- if(pintern->Magic==MAGIC_GLOBAL_USED)
- {
- if(pintern->LockCount!=0)
- SetLastError(ERROR_INVALID_HANDLE);
- if(pintern->Pointer)
- if(!HeapFree(GetProcessHeap(), 0,
- (char *)(pintern->Pointer)-sizeof(HGLOBAL)))
- hreturned=hmem;
- if(!HeapFree(GetProcessHeap(), 0, pintern))
- hreturned=hmem;
- }
- /* HeapUnlock(GetProcessHeap()); */
- }
- return hreturned;
+ PGLOBAL32_INTERN pintern;
+ HGLOBAL hreturned;
+
+ __TRY
+ {
+ hreturned = 0;
+ if(ISPOINTER(hmem)) /* POINTER */
+ {
+ if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
+ }
+ else /* HANDLE */
+ {
+ /* HeapLock(heap); */
+ pintern=HANDLE_TO_INTERN(hmem);
+
+ if(pintern->Magic==MAGIC_GLOBAL_USED)
+ {
+
+ /* 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(), 0, (char *)(pintern->Pointer)-sizeof(HGLOBAL)))
+ hreturned=hmem;
+ if(!HeapFree(GetProcessHeap(), 0, pintern))
+ hreturned=hmem;
+ }
+ /* HeapUnlock(heap); */
+ }
+ }
+ __EXCEPT(page_fault)
+ {
+ ERR("page fault occurred ! Caused by bug ?\n");
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return hmem;
+ }
+ __ENDTRY
+ return hreturned;
}
/***********************************************************************
- * GlobalSize32 (KERNEL32.329)
+ * GlobalSize (KERNEL32.@)
* RETURNS
* Size in bytes of the global memory object
* 0: Failure
*/
-DWORD WINAPI GlobalSize(
+SIZE_T WINAPI GlobalSize(
HGLOBAL hmem /* [in] Handle of global memory object */
) {
DWORD retval;
PGLOBAL32_INTERN pintern;
- if(ISPOINTER(hmem))
+ if(ISPOINTER(hmem))
{
retval=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
}
else
{
- /* HeapLock(GetProcessHeap()); */
+ /* HeapLock(heap); */
pintern=HANDLE_TO_INTERN(hmem);
-
+
if(pintern->Magic==MAGIC_GLOBAL_USED)
{
if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
return 0;
- retval=HeapSize(GetProcessHeap(), 0,
+ retval=HeapSize(GetProcessHeap(), 0,
(char *)(pintern->Pointer)-sizeof(HGLOBAL))-4;
+ if (retval == 0xffffffff-4) retval = 0;
}
else
{
WARN("invalid handle\n");
retval=0;
}
- /* HeapUnlock(GetProcessHeap()); */
+ /* HeapUnlock(heap); */
}
/* HeapSize returns 0xffffffff on failure */
if (retval == 0xffffffff) retval = 0;
/***********************************************************************
- * GlobalWire32 (KERNEL32.333)
+ * GlobalWire (KERNEL32.@)
*/
LPVOID WINAPI GlobalWire(HGLOBAL hmem)
{
/***********************************************************************
- * GlobalUnWire32 (KERNEL32.330)
+ * GlobalUnWire (KERNEL32.@)
*/
BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
{
/***********************************************************************
- * GlobalFix32 (KERNEL32.320)
+ * GlobalFix (KERNEL32.@)
*/
VOID WINAPI GlobalFix(HGLOBAL hmem)
{
/***********************************************************************
- * GlobalUnfix32 (KERNEL32.331)
+ * GlobalUnfix (KERNEL32.@)
*/
VOID WINAPI GlobalUnfix(HGLOBAL hmem)
{
/***********************************************************************
- * GlobalFlags32 (KERNEL32.321)
+ * GlobalFlags (KERNEL32.@)
* Returns information about the specified global memory object
*
* NOTES
) {
DWORD retval;
PGLOBAL32_INTERN pintern;
-
+
if(ISPOINTER(hmem))
{
retval=0;
/* HeapLock(GetProcessHeap()); */
pintern=HANDLE_TO_INTERN(hmem);
if(pintern->Magic==MAGIC_GLOBAL_USED)
- {
+ {
retval=pintern->LockCount + (pintern->Flags<<8);
if(pintern->Pointer==0)
retval|= GMEM_DISCARDED;
}
else
{
- WARN("Invalid handle: %04x", hmem);
+ WARN("Invalid handle: %p\n", hmem);
retval=0;
}
/* HeapUnlock(GetProcessHeap()); */
/***********************************************************************
- * GlobalCompact32 (KERNEL32.316)
+ * GlobalCompact (KERNEL32.@)
*/
-DWORD WINAPI GlobalCompact( DWORD minfree )
+SIZE_T WINAPI GlobalCompact( DWORD minfree )
{
return 0; /* GlobalCompact does nothing in Win32 */
}
/***********************************************************************
- * GlobalMemoryStatus (KERNEL32.327)
+ * GlobalMemoryStatus (KERNEL32.@)
* RETURNS
* None
*/
VOID WINAPI GlobalMemoryStatus(
LPMEMORYSTATUS lpmem
) {
+ static MEMORYSTATUS cached_memstatus;
+ static int cache_lastchecked = 0;
+ SYSTEM_INFO si;
#ifdef linux
- FILE *f = fopen( "/proc/meminfo", "r" );
+ FILE *f;
+#endif
+#ifdef __FreeBSD__
+ int *tmp;
+ int size_sys;
+#endif
+ if (time(NULL)==cache_lastchecked) {
+ memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
+ return;
+ }
+ cache_lastchecked = time(NULL);
+
+ lpmem->dwMemoryLoad = 0;
+ lpmem->dwTotalPhys = 16*1024*1024;
+ lpmem->dwAvailPhys = 16*1024*1024;
+ lpmem->dwTotalPageFile = 16*1024*1024;
+ lpmem->dwAvailPageFile = 16*1024*1024;
+
+#ifdef linux
+ f = fopen( "/proc/meminfo", "r" );
if (f)
{
char buffer[256];
if (lpmem->dwTotalPhys)
{
- lpmem->dwTotalVirtual = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
- lpmem->dwAvailVirtual = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
- lpmem->dwMemoryLoad = (lpmem->dwTotalVirtual-lpmem->dwAvailVirtual)
- / (lpmem->dwTotalVirtual / 100);
- return;
+ DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
+ DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
+ lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
+ / (TotalPhysical / 100);
}
}
+#elif defined(__FreeBSD__)
+ sysctlbyname("hw.physmem", NULL, &size_sys, NULL, 0);
+ tmp = malloc(size_sys * sizeof(int));
+ sysctlbyname("hw.physmem", tmp, &size_sys, NULL, 0);
+ if (tmp && *tmp)
+ {
+ lpmem->dwTotalPhys = *tmp;
+ free(tmp);
+ sysctlbyname("hw.usermem", NULL, &size_sys, NULL, 0);
+ tmp = malloc(size_sys * sizeof(int));
+ sysctlbyname("hw.usermem", tmp, &size_sys, NULL, 0);
+ if (tmp && *tmp)
+ {
+ lpmem->dwAvailPhys = *tmp;
+ lpmem->dwTotalPageFile = *tmp;
+ lpmem->dwAvailPageFile = *tmp;
+ lpmem->dwMemoryLoad = lpmem->dwTotalPhys - lpmem->dwAvailPhys;
+ } else
+ {
+ lpmem->dwAvailPhys = lpmem->dwTotalPhys;
+ lpmem->dwTotalPageFile = lpmem->dwTotalPhys;
+ lpmem->dwAvailPageFile = lpmem->dwTotalPhys;
+ lpmem->dwMemoryLoad = 0;
+ }
+ free(tmp);
+
+ }
#endif
+ /* Some applications (e.g. QuickTime 6) crash if we tell them there
+ * is more than 2GB of physical memory.
+ */
+ if (lpmem->dwTotalPhys>2U*1024*1024*1024)
+ {
+ lpmem->dwTotalPhys=2U*1024*1024*1024;
+ lpmem->dwAvailPhys=2U*1024*1024*1024;
+ }
+
/* FIXME: should do something for other systems */
- lpmem->dwMemoryLoad = 0;
- lpmem->dwTotalPhys = 16*1024*1024;
- lpmem->dwAvailPhys = 16*1024*1024;
- lpmem->dwTotalPageFile = 16*1024*1024;
- lpmem->dwAvailPageFile = 16*1024*1024;
- lpmem->dwTotalVirtual = 32*1024*1024;
- lpmem->dwAvailVirtual = 32*1024*1024;
+ GetSystemInfo(&si);
+ lpmem->dwTotalVirtual = (char*)si.lpMaximumApplicationAddress-(char*)si.lpMinimumApplicationAddress;
+ /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
+ lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
+ memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
+
+ /* it appears some memory display programs want to divide by these values */
+ if(lpmem->dwTotalPageFile==0)
+ lpmem->dwTotalPageFile++;
+
+ if(lpmem->dwAvailPageFile==0)
+ lpmem->dwAvailPageFile++;
+
+ TRACE("<-- LPMEMORYSTATUS: dwLength %ld, dwMemoryLoad %ld, dwTotalPhys %ld, dwAvailPhys %ld,"
+ " dwTotalPageFile %ld, dwAvailPageFile %ld, dwTotalVirtual %ld, dwAvailVirtual %ld\n",
+ lpmem->dwLength, lpmem->dwMemoryLoad, lpmem->dwTotalPhys, lpmem->dwAvailPhys,
+ lpmem->dwTotalPageFile, lpmem->dwAvailPageFile, lpmem->dwTotalVirtual,
+ lpmem->dwAvailVirtual);
}
-
-/**********************************************************************
- * WOWGlobalAllocLock (KERNEL32.62)
- *
- * Combined GlobalAlloc and GlobalLock.
+/***********************************************************************
+ * A20Proc (KERNEL.165)
+ * A20_Proc (SYSTEM.20)
*/
-SEGPTR WINAPI WOWGlobalAllocLock16(DWORD flags,DWORD cb,HGLOBAL16 *hmem)
+void WINAPI A20Proc16( WORD unused )
{
- HGLOBAL16 xhmem;
- xhmem = GlobalAlloc16(flags,cb);
- if (hmem) *hmem = xhmem;
- return WIN16_GlobalLock16(xhmem);
+ /* this is also a NOP in Windows */
}
-
-/**********************************************************************
- * WOWGlobalUnlockFree (KERNEL32.64)
- *
- * Combined GlobalUnlock and GlobalFree.
+/***********************************************************************
+ * LimitEMSPages (KERNEL.156)
*/
-WORD WINAPI WOWGlobalUnlockFree16(DWORD vpmem) {
- if (!GlobalUnlock16(HIWORD(vpmem)))
- return 0;
- return GlobalFree16(HIWORD(vpmem));
+DWORD WINAPI LimitEMSPages16( DWORD unused )
+{
+ return 0;
}