4 * Copyright 1995 Alexandre Julliard
5 * Copyright 1996 Huw Davies
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * All local heap functions need the current DS as first parameter
25 * when called from the emulation library, so they take one more
26 * parameter than usual.
33 #include "wine/winbase16.h"
37 #include "stackframe.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(local);
46 WORD prev; /* Previous arena | arena type */
47 WORD next; /* Next arena */
48 /* Start of the memory block or free-list info */
49 WORD size; /* Size of the free block */
50 WORD free_prev; /* Previous free block */
51 WORD free_next; /* Next free block */
54 #define ARENA_HEADER_SIZE 4
55 #define ARENA_HEADER( handle) ((handle) - ARENA_HEADER_SIZE)
57 /* Arena types (stored in 'prev' field of the arena) */
58 #define LOCAL_ARENA_FREE 0
59 #define LOCAL_ARENA_FIXED 1
65 WORD check; /* 00 Heap checking flag */
66 WORD freeze; /* 02 Heap frozen flag */
67 WORD items; /* 04 Count of items on the heap */
68 WORD first; /* 06 First item of the heap */
69 WORD pad1; /* 08 Always 0 */
70 WORD last; /* 0a Last item of the heap */
71 WORD pad2; /* 0c Always 0 */
72 BYTE ncompact; /* 0e Compactions counter */
73 BYTE dislevel; /* 0f Discard level */
74 DWORD distotal; /* 10 Total bytes discarded */
75 WORD htable; /* 14 Pointer to handle table */
76 WORD hfree; /* 16 Pointer to free handle table */
77 WORD hdelta; /* 18 Delta to expand the handle table */
78 WORD expand; /* 1a Pointer to expand function (unused) */
79 WORD pstat; /* 1c Pointer to status structure (unused) */
80 FARPROC16 notify WINE_PACKED; /* 1e Pointer to LocalNotify() function */
81 WORD lock; /* 22 Lock count for the heap */
82 WORD extra; /* 24 Extra bytes to allocate when expanding */
83 WORD minsize; /* 26 Minimum size of the heap */
84 WORD magic; /* 28 Magic number */
89 #define LOCAL_HEAP_MAGIC 0x484c /* 'LH' */
91 /* All local heap allocations are aligned on 4-byte boundaries */
92 #define LALIGN(word) (((word) + 3) & ~3)
94 #define ARENA_PTR(ptr,arena) ((LOCALARENA *)((char*)(ptr)+(arena)))
95 #define ARENA_PREV(ptr,arena) (ARENA_PTR((ptr),(arena))->prev & ~3)
96 #define ARENA_NEXT(ptr,arena) (ARENA_PTR((ptr),(arena))->next)
97 #define ARENA_FLAGS(ptr,arena) (ARENA_PTR((ptr),(arena))->prev & 3)
100 /***********************************************************************
101 * LocalInit (KERNEL.4)
103 BOOL16 WINAPI LocalInit16( HANDLE16 selector, WORD start, WORD end )
106 WORD heapInfoArena, freeArena, lastArena;
107 LOCALHEAPINFO *pHeapInfo;
108 LOCALARENA *pArena, *pFirstArena, *pLastArena;
112 /* The initial layout of the heap is: */
113 /* - first arena (FIXED) */
114 /* - heap info structure (FIXED) */
115 /* - large free block (FREE) */
116 /* - last arena (FREE) */
118 TRACE("%04x %04x-%04x\n", selector, start, end);
119 if (!selector) selector = CURRENT_DS;
123 /* start == 0 means: put the local heap at the end of the segment */
125 DWORD size = GlobalSize16( GlobalHandle16( selector ) );
126 start = (WORD)(size > 0xffff ? 0xffff : size) - 1;
127 if ( end > 0xfffe ) end = 0xfffe;
133 if ((pModule = NE_GetPtr( GlobalHandle16( selector ) )))
135 SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule );
138 for ( segNr = 0; segNr < pModule->seg_count; segNr++, pSeg++ )
139 if ( GlobalHandleToSel16(pSeg->hSeg) == selector )
142 if ( segNr < pModule->seg_count )
144 WORD minsize = pSeg->minsize;
145 if ( pModule->ss == segNr+1 )
146 minsize += pModule->stack_size;
148 TRACE(" new start %04x, minstart: %04x\n", start, minsize);
152 ptr = MapSL( MAKESEGPTR( selector, 0 ) );
154 start = LALIGN( max( start, sizeof(INSTANCEDATA) ) );
155 heapInfoArena = LALIGN(start + sizeof(LOCALARENA) );
156 freeArena = LALIGN( heapInfoArena + ARENA_HEADER_SIZE
157 + sizeof(LOCALHEAPINFO) );
158 lastArena = (end - sizeof(LOCALARENA)) & ~3;
160 /* Make sure there's enough space. */
162 if (freeArena + sizeof(LOCALARENA) >= lastArena) goto done;
164 /* Initialise the first arena */
166 pFirstArena = ARENA_PTR( ptr, start );
167 pFirstArena->prev = start | LOCAL_ARENA_FIXED;
168 pFirstArena->next = heapInfoArena;
169 pFirstArena->size = LALIGN(sizeof(LOCALARENA));
170 pFirstArena->free_prev = start; /* this one */
171 pFirstArena->free_next = freeArena;
173 /* Initialise the arena of the heap info structure */
175 pArena = ARENA_PTR( ptr, heapInfoArena );
176 pArena->prev = start | LOCAL_ARENA_FIXED;
177 pArena->next = freeArena;
179 /* Initialise the heap info structure */
181 pHeapInfo = (LOCALHEAPINFO *) (ptr + heapInfoArena + ARENA_HEADER_SIZE );
182 memset( pHeapInfo, 0, sizeof(LOCALHEAPINFO) );
183 pHeapInfo->items = 4;
184 pHeapInfo->first = start;
185 pHeapInfo->last = lastArena;
186 pHeapInfo->htable = 0;
187 pHeapInfo->hdelta = 0x20;
188 pHeapInfo->extra = 0x200;
189 pHeapInfo->minsize = lastArena - freeArena;
190 pHeapInfo->magic = LOCAL_HEAP_MAGIC;
192 /* Initialise the large free block */
194 pArena = ARENA_PTR( ptr, freeArena );
195 pArena->prev = heapInfoArena | LOCAL_ARENA_FREE;
196 pArena->next = lastArena;
197 pArena->size = lastArena - freeArena;
198 pArena->free_prev = start;
199 pArena->free_next = lastArena;
201 /* Initialise the last block */
203 pLastArena = ARENA_PTR( ptr, lastArena );
204 pLastArena->prev = freeArena | LOCAL_ARENA_FREE;
205 pLastArena->next = lastArena; /* this one */
206 pLastArena->size = LALIGN(sizeof(LOCALARENA));
207 pLastArena->free_prev = freeArena;
208 pLastArena->free_next = lastArena; /* this one */
210 /* Store the local heap address in the instance data */
212 ((INSTANCEDATA *)ptr)->heap = heapInfoArena + ARENA_HEADER_SIZE;
216 CURRENT_STACK16->ecx = ret; /* must be returned in cx too */
221 /***********************************************************************
222 * LocalAlloc (KERNEL32.@)
227 HLOCAL WINAPI LocalAlloc(
228 UINT flags, /* [in] Allocation attributes */
229 SIZE_T size /* [in] Number of bytes to allocate */
231 return (HLOCAL)GlobalAlloc( flags, size );
235 /***********************************************************************
236 * LocalCompact (KERNEL32.@)
238 SIZE_T WINAPI LocalCompact( UINT minfree )
240 return 0; /* LocalCompact does nothing in Win32 */
244 /***********************************************************************
245 * LocalFlags (KERNEL32.@)
247 * Value specifying allocation flags and lock count.
248 * LMEM_INVALID_HANDLE: Failure
250 UINT WINAPI LocalFlags(
251 HLOCAL handle /* [in] Handle of memory object */
253 return GlobalFlags( (HGLOBAL)handle );
257 /***********************************************************************
258 * LocalFree (KERNEL32.@)
263 HLOCAL WINAPI LocalFree(
264 HLOCAL handle /* [in] Handle of memory object */
266 return (HLOCAL)GlobalFree( (HGLOBAL)handle );
270 /***********************************************************************
271 * LocalHandle (KERNEL32.@)
276 HLOCAL WINAPI LocalHandle(
277 LPCVOID ptr /* [in] Address of local memory object */
279 return (HLOCAL)GlobalHandle( ptr );
283 /***********************************************************************
284 * LocalLock (KERNEL32.@)
285 * Locks a local memory object and returns pointer to the first byte
286 * of the memory block.
292 LPVOID WINAPI LocalLock(
293 HLOCAL handle /* [in] Address of local memory object */
295 return GlobalLock( (HGLOBAL)handle );
299 /***********************************************************************
300 * LocalReAlloc (KERNEL32.@)
305 HLOCAL WINAPI LocalReAlloc(
306 HLOCAL handle, /* [in] Handle of memory object */
307 SIZE_T size, /* [in] New size of block */
308 UINT flags /* [in] How to reallocate object */
310 return (HLOCAL)GlobalReAlloc( (HGLOBAL)handle, size, flags );
314 /***********************************************************************
315 * LocalShrink (KERNEL32.@)
317 SIZE_T WINAPI LocalShrink( HGLOBAL handle, UINT newsize )
319 return 0; /* LocalShrink does nothing in Win32 */
323 /***********************************************************************
324 * LocalSize (KERNEL32.@)
329 SIZE_T WINAPI LocalSize(
330 HLOCAL handle /* [in] Handle of memory object */
332 return GlobalSize( (HGLOBAL)handle );
336 /***********************************************************************
337 * LocalUnlock (KERNEL32.@)
339 * TRUE: Object is still locked
340 * FALSE: Object is unlocked
342 BOOL WINAPI LocalUnlock(
343 HLOCAL handle /* [in] Handle of memory object */
345 return GlobalUnlock( (HGLOBAL)handle );