1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/memory/global.c
Alexandre Julliard 594997c900 Release 950430
Sat Apr 29 20:42:01 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [controls/static.c]
	Fixed painting of SS_*FRAME controls.

	* [if1632/callback.c]
	Pass the window instance as DS to the 16-bit window procedure.
	Rewrote Catch() and Throw() to make them work with multiple tasks.

	* [loader/main.c]
	New function MAIN_Init() to perform initializations before the
	first task is started instead of doing them in InitApp().
	Temporary hack to command-line parsing to load one program per
	command-line argument, to make testing task-switching easier.

	* [loader/*.c]
	Reimplemented modules to use a Windows-compatible layout and to
	allow multiple tasks and multiple module instances. Not really
	finished yet.

	* [loader/task.c] [misc/exec.c]
	Reimplemented tasks to use a common address space, and implemented
	preliminary task-switching capabilities.

	* [memory/global.c]
	Fixed bug in GlobalNext().

	* [misc/main.c]
	Updated the list of contributors. Let me know if I forgot someone.

	* [miscemu/int21.c]
	Use one DTA per task instead of a global one.

	* [objects/bitblt.c]
	Fixed bug in BitBlt() that could cause BadMatch errors.

	* [tools/build.c]
	Added new function type 'stub', that makes possible to export an
	unimplemented function by name as well as by ordinal. This will
	avoid loading errors for unimplemented functions.
	Generate an in-memory module layout for built-in DLLs so that the
	same code can be used for built-in and loaded modules.
	Changed relay code to make it unnecessary to save the value of the
	BP register.

	* [windows/message.c]
	Implemented multiple message queues and preliminary task-switching
	capabilities. Inter-task SendMessage() calls are not implemented
	yet and will probably cause crashes if used.

	* [windows/property.c]
	Reimplemented properties and allocate them on the USER heap.

	* [windows/win.c]
	Fixed bug in SetWindowWord().
	Reimplemented EnumWindows() and EnumTaskWindows().

Tue Apr 18 09:48:38 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [misc/main.c]
	GetSystemParametersInfo(): Additional action SPI_GETICONTITLEFONT.
	
	* [loader/resource.c]
	Removed the check for NE_SEGFLAGS_EXECUTEONLY, since it broke
	control.exe.
	Fixed icon loading.
	
	* [objects/font.c] [include/windows.h]
	Fixed a bug in InitFontsList() and worked on the EnumFonts()
	functions to make them comprehensible.

        * [controls/button.c]
	Fixed my previous patch to handle LBUTTONUP messages.

Fri Apr 14 11:41:28 1995  Cameron Heide  (heide@ee.ualberta.ca)

        * [misc/network.c, misc/dos_fs.c]
        Implemented WNetGetConnection.  All that is currently
        supported are drives, for which the remote name is simply
        the redirected UNIX directory name.

        * [miscemu/int2?.c]
        More drive number validity checking.

Wed Apr 12 11:28:37 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
        * [controls/listbox.c]
	Oops, my previous change to ListBoxDirectory broke the Borland
	file open dialog. Fixed.

Mon Apr 10 23:17:12 1995  Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/ole2nls.spec] [misc/ole2nls.c] [misc/Imakefile]
	New file ole2nls.c. Added stubs for GetUserDefaultLCID, 
	GetSystemDefaultLCID, GetUserDefaultLangID, GetSystemDefaultLangID.

Mon Apr 10 10:05:18 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [memory/global.c] [memory/local.c] [include/windows.h]
	GlobalReAlloc(): If GMEM_MODIFY is set, don't resize the block.
	LocalReAlloc(): Same for LMEM_MODIFY.
	
        * [controls/listbox.c]
	Fixed a bug in ListBoxDirectory that prevented commdlg from working.
	Check for errors in some more places.

        * [if1632/gdi.spec] [if1632/user.spec]
	16 bit callback functions should be passed as segptrs.
	
	* [include/dlls.h] [loader/ne_image.c] [loader/selector.c]
	[loader/library.c]
	Prevent a DLL from being initialized twice (Borlands Resource
	Workshop used to do this).
	Provide an additional flag for each w_file that indicates whether
	it's an EXE or a DLL, for combinations like pbrush.exe/.dll.
	
	* [controls/button.c]
	Handle LBUTTONUP messages even if the button no longer has the
	capture (for WinHelp).
	
	* [include/wintypes.h]
	FARPROC is now a segptr for the emulator and a function
	pointer for the library.
	
	* [misc/commdlg.c] [misc/commdlg.h]
	Cleaned the file dialogs up a little. They now work reasonably well,
	although there are still some problems (e.g. files are initially
        invisible).

	* [windows/class.c] [if1632/user.spec] [include/windows.h]
	GetClassInfo() must take a segptr, as it checks whether the
	highword is zero.
	GetClassName() called the wrong atom function. No surprise it didn't
        find anything.

	* [misc/lstr.c]
	AnsiToOem() and OemToAnsi() didn't terminate the strings. Fixed.
        Removed some warnings.

	* [if1632/relay.c] [if1632/ddeml.spec] [include/dlls.h]
	New spec file for the 3.1 DDEML DDL. 

	* [controls/menu.c]
	Small fix to ChangeMenu - mask out the obsolete flags
	(MF_APPEND == MF_OWNERDRAW, this led to problems). It also had
	problems with the MF_BYPOSITION flag.

        * [windows/message.c]
        SendMessage(): call the WH_CALLWNDPROC hook function. This is rather
        ugly, I'm afraid. Windows probably passes a pointer to the 16 bit
        stack for speed reasons.
	
        * [windows/hook.c] [include/windows.h]
        Set/HookWindowsHook() shouldn't just call their *Ex counterparts, as
        they have slightly different semantics.
        MS Hearts now works somewhat, if you disable the new builtin DDEML.
        The graphics are completely messed up, though.
1995-04-30 10:05:20 +00:00

634 lines
17 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_CreateBlock
*
* Create a global heap block for a fixed range of linear memory.
*/
HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
HGLOBAL hOwner, BOOL isCode,
BOOL is32Bit, BOOL isReadOnly )
{
WORD sel, selcount;
GLOBALARENA *pArena;
/* Allocate the selector(s) */
sel = SELECTOR_AllocBlock( ptr, size, isCode ? SEGMENT_CODE : SEGMENT_DATA,
is32Bit, isReadOnly );
if (!sel) return 0;
selcount = (size + 0xffff) / 0x10000;
if (!(pArena = GLOBAL_GetArena( sel, selcount )))
{
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) );
return pArena->handle;
}
/***********************************************************************
* GLOBAL_FreeBlock
*
* Free a block allocated by GLOBAL_CreateBlock, without touching
* the associated linear memory range.
*/
BOOL GLOBAL_FreeBlock( HGLOBAL handle )
{
WORD sel;
if (!handle) return TRUE;
sel = GlobalHandleToSel( handle );
if (FreeSelector( sel )) return FALSE; /* failed */
memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
return TRUE;
}
/***********************************************************************
* GLOBAL_Alloc
*
* Implementation of GlobalAlloc()
*/
HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
BOOL isCode, BOOL is32Bit, BOOL isReadOnly )
{
void *ptr;
HGLOBAL handle;
dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
/* Fixup the size */
if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x0f) return 0;
if (size == 0) size = 0x20;
else size = (size + 0x1f) & ~0x1f;
/* Allocate the linear memory */
ptr = malloc( size );
if (!ptr) return 0;
/* Allocate the selector(s) */
handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
isCode, is32Bit, isReadOnly);
if (!handle)
{
free( ptr );
return 0;
}
if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
return handle;
}
/***********************************************************************
* GlobalAlloc (KERNEL.15)
*/
HGLOBAL GlobalAlloc( WORD flags, DWORD size )
{
HANDLE owner = GetCurrentPDB();
if (flags & GMEM_DDESHARE)
owner = GetExePtr(owner); /* Make it a module handle */
return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
}
/***********************************************************************
* 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) return 0;
pArena = GET_ARENA_PTR( handle );
/* Fixup the size */
if (size >= 0x00ff0000-0x0f) return 0; /* No allocation > 16Mb-64Kb */
if (size == 0) size = 0x10;
else size = (size + 0x0f) & ~0x0f;
/* Change the flags */
if (flags & GMEM_MODIFY)
{
/* Change the flags, leaving GA_DGROUP alone */
pArena->flags = (pArena->flags & GA_DGROUP) |
(flags & ~GA_DGROUP);
if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
return handle;
}
/* Reallocate the linear memory */
sel = GlobalHandleToSel( handle );
ptr = (void *)pArena->base;
oldsize = pArena->size;
dprintf_global(stddeb,"oldsize %08lx\n",oldsize);
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;
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 )
{
void *ptr;
dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
if (!(ptr = GlobalLock( handle ))) return handle; /* failed */
if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
free( ptr );
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) -> %08lx\n",
handle, MAKELONG( 0, GlobalHandleToSel(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;
}
/***********************************************************************
* GlobalFreeAll (KERNEL.26)
*/
void GlobalFreeAll( HANDLE owner )
{
DWORD i;
GLOBALARENA *pArena;
pArena = pGlobalArena;
for (i = 0; i < globalArenaSize; i++, pArena++)
{
if ((pArena->size != 0) && (pArena->hOwner == owner))
GlobalFree( pArena->handle );
}
}
/***********************************************************************
* 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;
if (pGlobal->dwNext >= globalArenaSize) return FALSE;
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;
}