wine/memory/heap.c
Alexandre Julliard 988ca977ab Release 940620
Mon Jun 20 14:26:41 1994  Bob Amstadt  (bob@pooh)

	* [objects/bitmap.c]
	Allow negative bitmap sizes.

Sun Jun 19 12:00:04 1994  David Metcalfe <david@prism.demon.co.uk>

        * [controls/edit.c]
        Improved selection display.  Added processing for WM_SETFONT,
        EM_REPLACESEL, EM_LINELENGTH, EM_UNDO, EM_EMPTYUNDOBUFFER,
        EM_GETHANDLE, EM_SETHANDLE messages.  Text buffer now stored on 
        application's local heap.

        * [windows/graphics.c]
        Corrected bug in Rectangle().  XFillRectangle has the same
        width as Rectangle, but XDrawRectangle is one pixel wider
        for the same co-ordinates.

        * [memory/heap.c] [include/heap.h]
        Added HEAP_LocalSize function.

        * [windows/event.c] [windows/keyboard.c]
        Improvements to KeyStateTable and addition of AsyncKeyStateTable.
        Added supporting code to GetKeyState and GetAsyncKeyState and
        merged mouse button states into GetKeyboardState.

        * [loader/resource.c] [include/accel.h]
        Added recognition of SHIFT, CONTROL and ALT keys to
        TranslateAccelerator.

        * [objects/metafile.c] [objects/font.c] [objects/bitblt.c]
        A bit more metafile support.

Sun Jun 19 17:29:00 MET DST 1994  Erik Bos (erik@hacktic.nl)

        * [loader/resource.c]
        SizeofResource() and AllocResource() added, AccessResource() updated.

        * [if1632/kernel.spec]
        FreeLibrary() used for FreeModule().

        * [windows/graphics.c]
        Rectangle(): swap left & right corners when right < left,
        swap top & bottom when botton < top.

Jun 19, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [controls/combo.c]
	Fix bug in window style of the associated listbox.

	* [controls/menu.c]
	Skip separators in keyboard navigation by using new internal 
		functions SelectPrevItem() & SelectNextItem(),

	* [misc/profile.c]
	Bug fix in GetPrivateProfileInt(), was limited to 4 digit,
		IntBuf must be alloc to (5+1)=6. char instead of 5.

	* [misc/main.c]
	Put code in functions SetEnvironment() & GetEnvironment().

	* [misc/shell.c]
	Start putting some code in ExtractIcon() function.

	* [misc/mmsystem.c]
	Some code for MMTimer functions & timers list.

	* [miscemu/int31.c]
	Few stubs for DPMI interrupt calls. Nothing work yet.

Mon Jun 20 07:37:43 EDT 1994	John Richardson (jrichard@cs.uml.edu)

	* include/win.h (tagWND):
	Added icon fields icon, hIcon and rectClientSave to 
	the tagWND struct.

	* windows/Imakefile
	Added icon.c to the list of files to compile

	* windows/dce.c (GetDCEx):
	Added some checks for iconic mode and pass icon window as drawable,
	not the real window.

	* windows/defwnd.c (DefWindowProc)
	Added PAINTICON default windows procedure.

	* windows/event.c (EVENT_Expose)
	Added check for iconic window expose. If iconic window is exposed
	send a WM_PAINTICON message

	* windows/icon.c 
	New file.  ICON_Iconify, ICON_findIconFromPoint, ICON_Deiconify.

	* windows/mdi.c (DefMDIChildProc)
	Test for IsIconic during a SC_RESTORE, this doesn't work yet.

	* windows/message.c (hardware_event)
	Looks for icon as well as window now.

	* windows/nonclient.c (NC_HandleSysCommand, NC_DoNCPaintIcon)
	Added iconify/deiconify in NC_HandleSysCommand, new function
	NC_DoNCPaintIcon which paints an icon.

	* windows/painting.c (BeginPaint)
	Made a BeginPaint select the STOCK_BLACK_PEN, STOCK_WHITE_BRUSH,
	and STOCK_SYSTEM_FONT objects since this is (hopefully) default
	windows behavior.

	* windows/win.h (CreateWindowEx)
	Set the default background color of a window to be white.
	Create icon window, turn off MINIMIZE if it is on, since
	I don't know what to do with it as of yet... register
	the icon with the hwnd of its window so we can identify where
	icon messages are coming from.

Mon Jun 20 10:15:59 1994  Miguel de Icaza  (miguel@sphinx)

	* windows/event.c: Added a hack to define XPointer when using
	X11R4. 

	* toolkit/hello.c: Test application for WineLib. To compile you'll
	need: gcc -Iinclude -DWINELIB -g hello.c -c, and to link you'll
	need: gcc hello.o libwine.a -lX11 -L/usr/openwin/lib -lm 

	* toolkit/heap.c: Extended the size of the block size per chunk.

	* misc/stress.c (GetFreeFileHandles): Fixed typo.

	* misc/main.c (main): Changes to allow compilation under SunOS. 

	* loader/library.c: Changed some ifdefs to compile WineLib.
1994-06-21 16:15:21 +00:00

651 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "prototypes.h"
#include "segmem.h"
#include "heap.h"
#include "regfunc.h"
/* #define DEBUG_HEAP /* */
LHEAP *LocalHeaps = NULL;
void
HEAP_CheckHeap(MDESC **free_list)
{
MDESC *m;
for (m = *free_list; m != NULL; m = m->next)
if (((int) m & 0xffff0000) != ((int) *free_list & 0xffff0000))
*(char *)0 = 0;
}
/**********************************************************************
* HEAP_Init
*/
void
HEAP_Init(MDESC **free_list, void *start, int length)
{
if (length < 2 * sizeof(MDESC))
return;
*free_list = (MDESC *) start;
(*free_list)->prev = NULL;
(*free_list)->next = NULL;
(*free_list)->length = length - sizeof(MDESC);
}
/**********************************************************************
* HEAP_Alloc
*/
void *
HEAP_Alloc(MDESC **free_list, int flags, int bytes)
{
MDESC *m, *m_new;
#ifdef DEBUG_HEAP
printf("HeapAlloc: free_list %08x, flags %x, bytes %d\n",
free_list, flags, bytes);
HEAP_CheckHeap(free_list);
#endif
/*
* Find free block big enough.
*/
for (m = *free_list; m != NULL; m = m->next)
{
if (m->length >= bytes && m->length < bytes + 4 * sizeof(MDESC))
{
break;
}
else if (m->length > bytes)
{
m_new = m + (bytes / sizeof(MDESC)) + 2;
if (m->prev == NULL)
*free_list = m_new;
else
m->prev->next = m_new;
if (m->next != NULL)
m->next->prev = m_new;
m_new->next = m->next;
m_new->prev = m->prev;
m_new->length = m->length - ((int) m_new - (int) m);
m->length -= (m_new->length + sizeof(MDESC));
m->prev = m;
m->next = m;
m->lock = 0;
m->flags = 0;
if (flags & GLOBAL_FLAGS_ZEROINIT)
memset(m + 1, 0, bytes);
#ifdef DEBUG_HEAP
printf("HeapAlloc: returning %08x\n", (m + 1));
HEAP_CheckHeap(free_list);
#endif
return (void *) (m + 1);
}
}
if (m != NULL)
{
if (m->prev == NULL)
*free_list = m->next;
else
m->prev->next = m->next;
if (m->next != NULL)
m->next->prev = m->prev;
m->prev = m;
m->next = m;
m->lock = 0;
m->flags = 0;
if (flags & GLOBAL_FLAGS_ZEROINIT)
memset(m + 1, 0, bytes);
#ifdef DEBUG_HEAP
printf("HeapAlloc: returning %08x\n", (m + 1));
HEAP_CheckHeap(free_list);
#endif
return (void *) (m + 1);
}
#ifdef DEBUG_HEAP
printf("HeapAlloc: returning %08x\n", 0);
HEAP_CheckHeap(free_list);
#endif
return 0;
}
/**********************************************************************
* HEAP_ReAlloc
*/
void *
HEAP_ReAlloc(MDESC **free_list, void *old_block,
int new_size, unsigned int flags)
{
MDESC *m_free;
MDESC *m;
if (!old_block)
return HEAP_Alloc(free_list, flags, new_size);
/*
* Check validity of block
*/
m = (MDESC *) old_block - 1;
#ifdef DEBUG_HEAP
printf("HEAP_ReAlloc new_size=%d !\n", new_size);
printf("HEAP_ReAlloc old_block=%08X !\n", old_block);
printf("HEAP_ReAlloc m=%08X free_list=%08X !\n", m, free_list);
printf("HEAP_ReAlloc m->prev=%08X !\n", m->prev);
printf("HEAP_ReAlloc m->next=%08X !\n", m->next);
printf("HEAP_ReAlloc *free_list=%08X !\n", *free_list);
HEAP_CheckHeap(free_list);
#endif
if (m->prev != m || m->next != m ||
((int) m & 0xffff0000) != ((int) *free_list & 0xffff0000))
{
#ifdef DEBUG_HEAP
printf("Attempt to resize bad pointer, m = %08x, *free_list = %08x\n",
m, free_list);
HEAP_CheckHeap(free_list);
#endif
return NULL;
}
/*
* Check for grow block
*/
#ifdef DEBUG_HEAP
printf("HEAP_ReAlloc Check for grow block !\n");
#endif
if (new_size > m->length)
{
m_free = m + 1 + m->length / sizeof(MDESC);
if (m_free->next == m_free ||
m_free->prev == m_free ||
m_free->length + sizeof(MDESC) < new_size)
{
void *new_p = HEAP_Alloc(free_list, flags, new_size);
if (new_p ==NULL)
return NULL;
memcpy(new_p, old_block, m->length);
HEAP_Free(free_list, old_block);
#ifdef DEBUG_HEAP
HEAP_CheckHeap(free_list);
#endif
return new_p;
}
if (m_free->prev == NULL)
*free_list = m_free->next;
else
m_free->prev->next = m_free->next;
if (m_free->next != NULL)
m_free->next->prev = m_free->prev;
m->length += sizeof(MDESC) + m_free->length;
#ifdef DEBUG_HEAP
printf("HEAP_ReAlloc before GLOBAL_FLAGS_ZEROINIT !\n");
#endif
if (flags & GLOBAL_FLAGS_ZEROINIT)
memset(m_free, '\0', sizeof(MDESC) + m_free->length);
}
/*
* Check for shrink block.
*/
#ifdef DEBUG_HEAP
printf("HEAP_ReAlloc Check for shrink block !\n");
#endif
if (new_size < m->length - 4 * sizeof(MDESC))
{
m_free = m + new_size / sizeof(MDESC) + 2;
m_free->next = m_free;
m_free->prev = m_free;
m_free->length = m->length - (int) m_free - (int) m;
m->length = (int) m_free - (int) (m + 1);
HEAP_Free(free_list, m_free + 1);
}
#ifdef DEBUG_HEAP
HEAP_CheckHeap(free_list);
#endif
return old_block;
}
/**********************************************************************
* HEAP_Free
*/
int
HEAP_Free(MDESC **free_list, void *block)
{
MDESC *m_free;
MDESC *m;
MDESC *m_prev;
#ifdef DEBUG_HEAP
printf("HeapFree: free_list %08x, block %08x\n",
free_list, block);
HEAP_CheckHeap(free_list);
#endif
/*
* Validate pointer.
*/
m_free = (MDESC *) block - 1;
if (m_free->prev != m_free || m_free->next != m_free)
{
#ifdef DEBUG_HEAP
printf("Attempt to free bad pointer,"
"m_free = %08x, *free_list = %08x\n",
m_free, free_list);
#endif
return -1;
}
if (*free_list == NULL)
{
*free_list = m_free;
(*free_list)->next = NULL;
(*free_list)->prev = NULL;
return 0;
}
else if (((int) m_free & 0xffff0000) != ((int) *free_list & 0xffff0000))
{
#ifdef DEBUG_HEAP
printf("Attempt to free bad pointer,"
"m_free = %08x, *free_list = %08x\n",
m_free, free_list);
#endif
return -1;
}
/*
* Find location in free list.
*/
m_prev = NULL;
for (m = *free_list; m != NULL && m < m_free; m = m->next)
m_prev = m;
if (m_prev != NULL && (int) m_prev + m_prev->length > (int) m_free)
{
#ifdef DEBUG_HEAP
printf("Attempt to free bad pointer,"
"m_free = %08x, m_prev = %08x (length %x)\n",
m_free, m_prev, m_prev->length);
#endif
return -1;
}
if ((m != NULL && (int) m_free + m_free->length > (int) m) ||
(int) m_free + m_free->length > ((int) m_free | 0xffff))
{
#ifdef DEBUG_HEAP
printf("Attempt to free bad pointer,"
"m_free = %08x (length %x), m = %08x\n",
m_free, m_free->length, m);
#endif
return -1;
}
/*
* Put block back in free list.
* Does it merge with the previos block?
*/
if (m_prev != NULL)
{
if ((int) m_prev + m_prev->length == (int) m_free)
{
m_prev->length += sizeof(MDESC) + m_free->length;
m_free = m_prev;
}
else
{
m_prev->next = m_free;
m_free->prev = m_prev;
}
}
else
{
*free_list = m_free;
m_free->prev = NULL;
}
/*
* Does it merge with the next block?
*/
if (m != NULL)
{
if ((int) m_free + m_free->length == (int) m)
{
m_free->length += sizeof(MDESC) + m->length;
m_free->next = m->next;
}
else
{
m->prev = m_free;
m_free->next = m;
}
}
else
{
m_free->next = NULL;
}
#ifdef DEBUG_HEAP
HEAP_CheckHeap(free_list);
#endif
return 0;
}
/**********************************************************************
* HEAP_LocalFindHeap
*/
LHEAP *
HEAP_LocalFindHeap(unsigned short owner)
{
LHEAP *lh;
#ifdef DEBUG_HEAP
printf("HEAP_LocalFindHeap: owner %04x\n", owner);
#endif
for (lh = LocalHeaps; lh != NULL; lh = lh->next)
{
if (lh->selector == owner)
return lh;
}
return NULL;
}
/**********************************************************************
* HEAP_LocalInit
*/
void
HEAP_LocalInit(unsigned short owner, void *start, int length)
{
LHEAP *lh;
#ifdef DEBUG_HEAP
printf("HEAP_LocalInit: owner %04x, start %08x, length %04x\n",
owner, start, length);
#endif
if (length < 2 * sizeof(MDESC))
return;
lh = (LHEAP *) malloc(sizeof(*lh));
if (lh == NULL)
return;
lh->next = LocalHeaps;
lh->selector = owner;
lh->local_table = NULL;
lh->delta = 0x20;
HEAP_Init(&lh->free_list, start, length);
LocalHeaps = lh;
}
/**********************************************************************
* HEAP_LocalSize
*/
unsigned int
HEAP_LocalSize(MDESC **free_list, unsigned int handle)
{
MDESC *m;
m = (MDESC *) (((int) *free_list & 0xffff0000) |
(handle & 0xffff)) - 1;
if (m->next != m || m->prev != m)
return 0;
return m->length;
}
/**********************************************************************
* WIN16_LocalAlloc
*/
void *
WIN16_LocalAlloc(int flags, int bytes)
{
void *m;
#ifdef DEBUG_HEAP
printf("WIN16_LocalAlloc: flags %x, bytes %d\n", flags, bytes);
printf(" called from segment %04x\n", Stack16Frame[11]);
#endif
m = HEAP_Alloc(LOCALHEAP(), flags, bytes);
#ifdef DEBUG_HEAP
printf("WIN16_LocalAlloc: returning %x\n", (int) m);
#endif
return m;
}
/**********************************************************************
* WIN16_LocalCompact
*/
int
WIN16_LocalCompact(int min_free)
{
MDESC *m;
int max_block;
max_block = 0;
for (m = *LOCALHEAP(); m != NULL; m = m->next)
if (m->length > max_block)
max_block = m->length;
return max_block;
}
/**********************************************************************
* WIN16_LocalFlags
*/
unsigned int
WIN16_LocalFlags(unsigned int handle)
{
MDESC *m;
m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
(handle & 0xffff)) - 1;
if (m->next != m || m->prev != m)
return 0;
return m->lock;
}
/**********************************************************************
* WIN16_LocalFree
*/
unsigned int
WIN16_LocalFree(unsigned int handle)
{
unsigned int addr;
addr = ((int) *LOCALHEAP() & 0xffff0000) | (handle & 0xffff);
if (HEAP_Free(LOCALHEAP(), (void *) addr) < 0)
return handle;
else
return 0;
}
/**********************************************************************
* WIN16_LocalInit
*/
unsigned int
WIN16_LocalInit(unsigned int segment, unsigned int start, unsigned int end)
{
unsigned short owner = HEAP_OWNER;
LHEAP *lh = HEAP_LocalFindHeap(owner);
if (segment == 0)
{
/* Get current DS */
segment = Stack16Frame[6];
}
if (lh == NULL)
{
HEAP_LocalInit(owner,
(void *) ((segment << 16) | start), end - start + 1);
}
else
{
HEAP_Init(&lh->free_list,
(void *) ((segment << 16) | start), end - start + 1);
}
printf("WIN16_LocalInit // return segment=%04X !\n", segment);
return segment;
}
/**********************************************************************
* WIN16_LocalLock
*/
void *
WIN16_LocalLock(unsigned int handle)
{
MDESC *m;
m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
(handle & 0xffff)) - 1;
if (m->next != m || m->prev != m)
return 0;
m->lock++;
return (void *) (m + 1);
}
/**********************************************************************
* WIN16_LocalReAlloc
*/
void *
WIN16_LocalReAlloc(unsigned int handle, int bytes, int flags)
{
void *m;
#ifdef DEBUG_HEAP
printf("WIN16_LocalReAlloc(%04X, %d, %04X); !\n", handle, bytes, flags);
printf("WIN16_LocalReAlloc // LOCALHEAP()=%08X !\n", LOCALHEAP());
printf("WIN16_LocalReAlloc // *LOCALHEAP()=%08X !\n", *LOCALHEAP());
#endif
m = HEAP_ReAlloc(LOCALHEAP(), (void *)
(((int) *LOCALHEAP() & 0xffff0000) | (handle & 0xffff)),
bytes, flags);
return m;
}
/**********************************************************************
* WIN16_LocalSize
*/
unsigned int
WIN16_LocalSize(unsigned int handle)
{
MDESC *m;
m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
(handle & 0xffff)) - 1;
if (m->next != m || m->prev != m)
return 0;
return m->length;
}
/**********************************************************************
* WIN16_LocalUnlock
*/
unsigned int
WIN16_LocalUnlock(unsigned int handle)
{
MDESC *m;
m = (MDESC *) (((int) *LOCALHEAP() & 0xffff0000) |
(handle & 0xffff)) - 1;
if (m->next != m || m->prev != m)
return 1;
if (m->lock > 0)
m->lock--;
return 0;
}
/**********************************************************************
* WIN16_LocalHandleDelta
*/
unsigned int
WIN16_LocalHandleDelta(unsigned int new_delta)
{
LHEAP *lh;
lh = HEAP_LocalFindHeap(HEAP_OWNER);
if (lh == NULL)
return 0;
if (new_delta)
lh->delta = new_delta;
return lh->delta;
}
/**********************************************************************
* GetFreeSystemResources (user.284)
*/
#define USERRESOURCES 2
#define GDIRESOURCES 1
#define SYSTEMRESOURCES 0
#include <user.h>
#include <gdi.h>
WORD GetFreeSystemResources(WORD SystemResourceType)
{
unsigned int GdiFree=0,GdiResult=0;
unsigned int UserFree=0,UserResult=0;
unsigned int result=0;
MDESC *m;
printf("GetFreeSystemResources(%u)\n",SystemResourceType);
switch(SystemResourceType) {
case(USERRESOURCES):
for (m = USER_Heap; m != NULL; m = m->next) /* add up free area in heap */
UserFree += m->length;
result=(UserFree*100)/65516; /* 65516 == 64K */
break;
case(GDIRESOURCES):
for (m = GDI_Heap; m != NULL; m = m->next)
GdiFree += m->length;
result=(GdiFree*100)/65516;
break;
case(SYSTEMRESOURCES):
for (m = USER_Heap; m != NULL; m = m->next)
UserFree += m->length;
UserResult=(UserFree*100)/65516;
for (m = GDI_Heap; m != NULL; m = m->next)
GdiFree += m->length;
GdiResult=(GdiFree*100)/65516;
result=(UserResult < GdiResult) ? UserResult:GdiResult;
break;
default:
result=0;
break;
}
return(result);
}