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
);