1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/memory/global.c
Alexandre Julliard fa68b75bad Release 950403
Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [Configure] [if1632/Imakefile]
	Removed new build and short names options.

	* [if1632/*.c] [tools/build.c]
	Implemented compiled call-back functions for better performance;
	all the relay code is now done in assembly code generated by the
	build program.
	Relay code is no longer dependent on being loaded below 64K.

	* [loader/resource.c]
	Fixed memory leak in LoadString(). A fix will also be needed for
	other resources.

	* [memory/global.c]
	Implemented global heap arenas, so we can store informations about
	global blocks, like lock counts or owner handle.
	Implemented FarGetOwner() and FarSetOwner().
	Implemented global heap TOOLHELP functions.

	* [memory/selector.c]
	Bug fix: it was not possible to re-use a free selector.

Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)

	*  [controls/listbox.c]
	Major work on listbox code
         - Many bugs fixed (still many bugs)
         - More messages supported
         - Code simplified

Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)

	* [controls/edit.c]
	Lots of bug fixes related to diappearing text, lost carets,
	highlighting, segmentation faults, occurance of random
	characters, insertion of characters over selection, misplaced
	caret location, display corruption, end of line behavior, etc.

	* [controls/widgets.c]
	EDIT class doesn't want to use CS_PARENTDC flag.

Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [loader/selector.c]
	  FixupFunctionPrologs() should also handle multiple data modules.
	  (this bug only became visible because MakeProcInstance() was fixed
	  in 950319)
	
	* [misc/dosfs.c]
	  Simplified DOS_SimplifyPath.
	  Small fix to DOS_opendir to reuse an entry if an open directory
	  is opened again, to prevent "too many open directories" messages.

Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
	CoDisconnectObject: new stub function

	* [include/msdos.h]
	fix DOSVERSION

	* [loader/ne_image.c]
	NE_FixupSegment: Be more generous on additive fixups

	* [if1632/user.spec][misc/network.c]
	Add more WNet* stubs

Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	  DlgDirList(): send segptr instead of linear pointer 
	  in message to static control
	* [controls/menu.c]
	  Tried to implement ownerdrawn menuitems. Doesn't work.
	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
	  Provide a stub for GetRasterizerCaps()
	* [loader/selector.c]
	  Pass end address instead of length to LocalInit() in 
	  CreateSelectors()
	* [memory/local.c]
	  LocalInit(): If there's already a local heap in the segment, do
	  nothing and return TRUE
	* [objects/linedda.c]
	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
	  now.
	* [windows/cursor.c]
	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
	  more work still.

Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
	  [windows/nonclient.c] [misc/message.c]
	  Added a new builtin DLL that provides 16 bit entry points for all
	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
	  again.
	* [misc/shell.c]
	  RegOpenKey()/RegCreateKey() bugs fixed.
        * [loader/ne_image.c]
	  Skipping the initialization of a DLL when CS == 0 was broken.
1995-04-03 16:55:37 +00:00

575 lines
15 KiB
C

/*
* Global heap functions
*
* Copyright 1995 Alexandre Julliard
*/
#include <stdlib.h>
#include <string.h>
#include "windows.h"
#include "toolhelp.h"
#include "selectors.h"
#include "stackframe.h"
#include "stddebug.h"
#include "debug.h"
/* Global arena block */
typedef struct
{
DWORD base; /* Base address */
DWORD size; /* Size in bytes */
HGLOBAL handle; /* Handle for this block */
HGLOBAL hOwner; /* Owner of this block */
BYTE lockCount; /* Count of GlobalFix() calls */
BYTE pageLockCount; /* Count of GlobalPageLock() calls */
BYTE flags; /* Allocation flags */
BYTE selCount; /* Number of selectors allocated for this block */
} GLOBALARENA;
/* Flags definitions */
#define GA_DGROUP 0x04
#define GA_DISCARDABLE 0x08
/* Arena array */
static GLOBALARENA *pGlobalArena = NULL;
static int globalArenaSize = 0;
#define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
#define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
/***********************************************************************
* GLOBAL_GetArena
*
* Return the arena for a given selector, growing the arena array if needed.
*/
static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
{
if (((sel >> __AHSHIFT) + selcount) >= globalArenaSize)
{
GLOBALARENA *pNewArena = realloc( pGlobalArena,
(globalArenaSize + 256) * sizeof(GLOBALARENA) );
if (!pNewArena) return 0;
pGlobalArena = pNewArena;
memset( pGlobalArena + globalArenaSize, 0, 256 * sizeof(GLOBALARENA) );
globalArenaSize += 256;
}
return pGlobalArena + (sel >> __AHSHIFT);
}
/***********************************************************************
* GLOBAL_Alloc
*
* Implementation of GlobalAlloc()
*/
HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
BOOL isCode, BOOL isReadOnly )
{
WORD sel, selcount;
void *ptr;
GLOBALARENA *pArena;
/* Fixup the size */
if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x0f) return 0;
if (size == 0) size = 0x10;
else size = (size + 0x0f) & ~0x0f;
/* Allocate the linear memory */
ptr = malloc( size );
if (!ptr) return 0;
/* Allocate the selector(s) */
sel = SELECTOR_AllocBlock( ptr, size, isCode ? SEGMENT_CODE : SEGMENT_DATA,
0, isReadOnly );
if (!sel)
{
free( ptr );
return 0;
}
selcount = (size + 0xffff) / 0x10000;
if (!(pArena = GLOBAL_GetArena( sel, selcount )))
{
free( ptr );
FreeSelector( sel );
return 0;
}
/* Fill the arena block */
pArena->base = (DWORD)ptr;
pArena->size = GET_SEL_LIMIT(sel) + 1;
pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
pArena->hOwner = hOwner;
pArena->lockCount = 0;
pArena->pageLockCount = 0;
pArena->flags = flags & 0xff;
if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
if (!isCode) pArena->flags |= GA_DGROUP;
pArena->selCount = selcount;
if (selcount > 1) /* clear the next arena blocks */
memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
return pArena->handle;
}
/***********************************************************************
* GlobalAlloc (KERNEL.15)
*/
HGLOBAL GlobalAlloc( WORD flags, DWORD size )
{
dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
return GLOBAL_Alloc( flags, size, GetCurrentPDB(), 0, 0 );
}
/***********************************************************************
* GlobalReAlloc (KERNEL.16)
*/
HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
{
WORD sel, selcount;
DWORD oldsize;
void *ptr;
GLOBALARENA *pArena, *pNewArena;
dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
handle, size, flags );
if (!handle)
{
printf( "GlobalReAlloc: handle is 0.\n" );
return 0;
}
/* Fixup the size */
if (size >= 0x00ff0000-0x0f) return 0; /* No allocation > 16Mb-64Kb */
if (size == 0) size = 0x10;
else size = (size + 0x0f) & ~0x0f;
/* Reallocate the linear memory */
pArena = GET_ARENA_PTR( handle );
sel = GlobalHandleToSel( handle );
ptr = (void *)pArena->base;
oldsize = pArena->size;
if (size == oldsize) return handle; /* Nothing to do */
ptr = realloc( ptr, size );
if (!ptr)
{
FreeSelector( sel );
memset( pArena, 0, sizeof(GLOBALARENA) );
return 0;
}
/* Reallocate the selector(s) */
sel = SELECTOR_ReallocBlock( sel, ptr, size, SEGMENT_DATA, 0, 0 );
if (!sel)
{
free( ptr );
memset( pArena, 0, sizeof(GLOBALARENA) );
return 0;
}
selcount = (size + 0xffff) / 0x10000;
if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
{
free( ptr );
FreeSelector( sel );
return 0;
}
/* Fill the new arena block */
if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
pNewArena->base = (DWORD)ptr;
pNewArena->size = GET_SEL_LIMIT(sel) + 1;
pNewArena->selCount = selcount;
if (flags & GMEM_MODIFY)
{
/* Change the flags, leaving GA_DGROUP alone */
pNewArena->flags = (pNewArena->flags & GA_DGROUP) |
(flags & ~GA_DGROUP);
if (flags & GMEM_DISCARDABLE) pNewArena->flags |= GA_DISCARDABLE;
}
pNewArena->handle = (pNewArena->flags & GMEM_MOVEABLE) ? sel - 1 : sel;
if (selcount > 1) /* clear the next arena blocks */
memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
if ((oldsize < size) && (flags & GMEM_ZEROINIT))
memset( (char *)ptr + oldsize, 0, size - oldsize );
return pNewArena->handle;
}
/***********************************************************************
* GlobalFree (KERNEL.17)
*/
HGLOBAL GlobalFree( HGLOBAL handle )
{
WORD sel;
void *ptr;
dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
if (!handle) return 0;
sel = GlobalHandleToSel( handle );
ptr = (void *)GET_SEL_BASE(sel);
if (FreeSelector( sel )) return handle; /* failed */
free( ptr );
memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
return 0;
}
/***********************************************************************
* WIN16_GlobalLock (KERNEL.18)
*
* This is the GlobalLock() function used by 16-bit code.
*/
SEGPTR WIN16_GlobalLock( HGLOBAL handle )
{
dprintf_global( stddeb, "WIN16_GlobalLock: %04x\n", handle );
if (!handle) return 0;
return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
}
/***********************************************************************
* GlobalLock (KERNEL.18)
*
* This is the GlobalLock() function used by 32-bit code.
*/
LPSTR GlobalLock( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalLock: %04x\n", handle );
if (!handle) return 0;
return (LPSTR)GET_ARENA_PTR(handle)->base;
}
/***********************************************************************
* GlobalUnlock (KERNEL.19)
*/
BOOL GlobalUnlock( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalUnlock: %04x\n", handle );
return 0;
}
/***********************************************************************
* GlobalSize (KERNEL.20)
*/
DWORD GlobalSize( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalSize: %04x\n", handle );
if (!handle) return 0;
return GET_ARENA_PTR(handle)->size;
}
/***********************************************************************
* GlobalHandle (KERNEL.21)
*/
DWORD GlobalHandle( WORD sel )
{
dprintf_global( stddeb, "GlobalHandle: %04x\n", sel );
return MAKELONG( GET_ARENA_PTR(sel)->handle, sel );
}
/***********************************************************************
* GlobalFlags (KERNEL.22)
*/
WORD GlobalFlags( HGLOBAL handle )
{
GLOBALARENA *pArena;
dprintf_global( stddeb, "GlobalFlags: %04x\n", handle );
pArena = GET_ARENA_PTR(handle);
return pArena->lockCount |
((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0);
}
/***********************************************************************
* LockSegment (KERNEL.23)
*/
HGLOBAL LockSegment( HGLOBAL handle )
{
dprintf_global( stddeb, "LockSegment: %04x\n", handle );
if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
GET_ARENA_PTR(handle)->lockCount++;
return handle;
}
/***********************************************************************
* UnlockSegment (KERNEL.24)
*/
void UnlockSegment( HGLOBAL handle )
{
dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
GET_ARENA_PTR(handle)->lockCount--;
/* FIXME: this ought to return the lock count in CX (go figure...) */
}
/***********************************************************************
* GlobalCompact (KERNEL.25)
*/
DWORD GlobalCompact( DWORD desired )
{
return GLOBAL_MAX_ALLOC_SIZE;
}
/***********************************************************************
* GlobalWire (KERNEL.111)
*/
SEGPTR GlobalWire( HGLOBAL handle )
{
return WIN16_GlobalLock( handle );
}
/***********************************************************************
* GlobalUnWire (KERNEL.112)
*/
BOOL GlobalUnWire( HGLOBAL handle )
{
return GlobalUnlock( handle );
}
/***********************************************************************
* GlobalDOSAlloc (KERNEL.184)
*/
DWORD GlobalDOSAlloc( DWORD size )
{
WORD sel = GlobalAlloc( GMEM_FIXED, size );
if (!sel) return 0;
return MAKELONG( sel, sel /* this one ought to be a real-mode segment */ );
}
/***********************************************************************
* GlobalDOSFree (KERNEL.185)
*/
WORD GlobalDOSFree( WORD sel )
{
return GlobalFree( GlobalHandle(sel) ) ? sel : 0;
}
/***********************************************************************
* SetSwapAreaSize (KERNEL.106)
*/
LONG SetSwapAreaSize( WORD size )
{
dprintf_heap(stdnimp, "STUB: SetSwapAreaSize(%d)\n", size );
return MAKELONG( size, 0xffff );
}
/***********************************************************************
* GlobalLRUOldest (KERNEL.163)
*/
HGLOBAL GlobalLRUOldest( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalLRUOldest: %04x\n", handle );
if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
return handle;
}
/***********************************************************************
* GlobalLRUNewest (KERNEL.164)
*/
HGLOBAL GlobalLRUNewest( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalLRUNewest: %04x\n", handle );
if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
return handle;
}
/***********************************************************************
* GetFreeSpace (KERNEL.169)
*/
DWORD GetFreeSpace( UINT wFlags )
{
return GLOBAL_MAX_ALLOC_SIZE;
}
/***********************************************************************
* GlobalPageLock (KERNEL.191)
*/
WORD GlobalPageLock( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
return ++(GET_ARENA_PTR(handle)->pageLockCount);
}
/***********************************************************************
* GlobalPageUnlock (KERNEL.192)
*/
WORD GlobalPageUnlock( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
return --(GET_ARENA_PTR(handle)->pageLockCount);
}
/***********************************************************************
* GlobalFix (KERNEL.197)
*/
void GlobalFix( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalFix: %04x\n", handle );
GET_ARENA_PTR(handle)->lockCount++;
}
/***********************************************************************
* GlobalUnfix (KERNEL.198)
*/
void GlobalUnfix( HGLOBAL handle )
{
dprintf_global( stddeb, "GlobalUnfix: %04x\n", handle );
GET_ARENA_PTR(handle)->lockCount--;
}
/***********************************************************************
* FarSetOwner (KERNEL.403)
*/
void FarSetOwner( HANDLE handle, WORD hOwner )
{
GET_ARENA_PTR(handle)->hOwner = hOwner;
}
/***********************************************************************
* FarGetOwner (KERNEL.404)
*/
WORD FarGetOwner( HANDLE handle )
{
return GET_ARENA_PTR(handle)->hOwner;
}
/***********************************************************************
* GlobalHandleToSel (TOOLHELP.50)
*/
WORD GlobalHandleToSel( HGLOBAL handle )
{
dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
if (!handle) return 0;
if (!(handle & 7))
{
fprintf( stderr, "Program attempted invalid selector conversion\n" );
return handle - 1;
}
return handle | 7;
}
/***********************************************************************
* GlobalFirst (TOOLHELP.51)
*/
BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
{
if (wFlags == GLOBAL_LRU) return FALSE;
pGlobal->dwNext = 0;
return GlobalNext( pGlobal, wFlags );
}
/***********************************************************************
* GlobalNext (TOOLHELP.52)
*/
BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
{
GLOBALARENA *pArena;
pArena = pGlobalArena + pGlobal->dwNext;
if (wFlags == GLOBAL_FREE) /* only free blocks */
{
int i;
for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
if (pArena->size == 0) break; /* block is free */
if (i >= globalArenaSize) return FALSE;
pGlobal->dwNext = i;
}
pGlobal->dwAddress = pArena->base;
pGlobal->dwBlockSize = pArena->size;
pGlobal->hBlock = pArena->handle;
pGlobal->wcLock = pArena->lockCount;
pGlobal->wcPageLock = pArena->pageLockCount;
pGlobal->wFlags = (GetCurrentPDB() == pArena->hOwner);
pGlobal->wHeapPresent = FALSE;
pGlobal->hOwner = pArena->hOwner;
pGlobal->wType = GT_UNKNOWN;
pGlobal->wData = 0;
pGlobal->dwNext++;
return TRUE;
}
/***********************************************************************
* GlobalInfo (TOOLHELP.53)
*/
BOOL GlobalInfo( GLOBALINFO *pInfo )
{
int i;
GLOBALARENA *pArena;
pInfo->wcItems = globalArenaSize;
pInfo->wcItemsFree = 0;
pInfo->wcItemsLRU = 0;
for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
if (pArena->size == 0) pInfo->wcItemsFree++;
return TRUE;
}
/***********************************************************************
* GlobalEntryHandle (TOOLHELP.54)
*/
BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL hItem )
{
return FALSE;
}
/***********************************************************************
* GlobalEntryModule (TOOLHELP.55)
*/
BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg )
{
return FALSE;
}
/***********************************************************************
* MemManInfo (TOOLHELP.72)
*/
BOOL MemManInfo( MEMMANINFO *pInfo )
{
return TRUE;
}