Release 950319
[wine/hacks.git] / memory / global.c
blobf62f2fd0df2606e3d568ba5e3cca8e991365507f
1 /*
2 * Global heap functions
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windows.h"
10 #include "toolhelp.h"
11 #include "selectors.h"
12 #include "stackframe.h"
13 #include "stddebug.h"
14 #include "debug.h"
16 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
18 #define HGLOBAL_TO_SEL(handle) \
19 ((handle == (HGLOBAL)-1) ? CURRENT_DS : GlobalHandleToSel(handle))
21 /***********************************************************************
22 * GlobalAlloc (KERNEL.15)
24 HGLOBAL GlobalAlloc( WORD flags, DWORD size )
26 WORD sel;
27 void *ptr;
29 dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
31 /* Fixup the size */
33 if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x0f) return 0;
34 if (size == 0) size = 0x10;
35 else size = (size + 0x0f) & ~0x0f;
37 /* Allocate the linear memory */
39 ptr = malloc( size );
40 if (!ptr) return 0;
42 /* Allocate the selector(s) */
44 sel = SELECTOR_AllocBlock( ptr, size, SEGMENT_DATA, 0, 0 );
45 if (!sel)
47 free( ptr );
48 return 0;
51 if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
53 /* Return the handle */
54 /* If allocating a GMEM_FIXED block, the handle is the selector. */
55 /* Otherwise, the handle is the selector-1 (don't ask me why :-) */
56 if (flags & GMEM_MOVEABLE) return sel - 1;
57 else return sel;
61 /***********************************************************************
62 * GlobalReAlloc (KERNEL.16)
64 HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
66 WORD sel;
67 DWORD oldsize;
68 void *ptr;
70 dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
71 handle, size, flags );
73 /* Fixup the size */
75 if (size >= 0x00ff0000-0x0f) return 0; /* No allocation > 16Mb-64Kb */
76 if (size == 0) size = 0x10;
77 else size = (size + 0x0f) & ~0x0f;
79 /* Reallocate the linear memory */
81 sel = GlobalHandleToSel( handle );
82 ptr = (void *)GET_SEL_BASE( sel );
83 oldsize = GlobalSize( handle );
84 if (size == oldsize) return handle; /* Nothing to do */
86 ptr = realloc( ptr, size );
87 if (!ptr)
89 FreeSelector( sel );
90 return 0;
93 /* Reallocate the selector(s) */
95 sel = SELECTOR_ReallocBlock( sel, ptr, size, SEGMENT_DATA, 0, 0 );
96 if (!sel)
98 free( ptr );
99 return 0;
102 if ((oldsize < size) && (flags & GMEM_ZEROINIT))
103 memset( (char *)ptr + oldsize, 0, size - oldsize );
105 if (sel == GlobalHandleToSel( handle ))
106 return handle; /* Selector didn't change */
108 if (flags & GMEM_MOVEABLE) return sel - 1;
109 else return sel;
113 /***********************************************************************
114 * GlobalFree (KERNEL.17)
116 HGLOBAL GlobalFree( HGLOBAL handle )
118 WORD sel;
119 void *ptr;
121 dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
122 sel = GlobalHandleToSel( handle );
123 ptr = (void *)GET_SEL_BASE(sel);
124 if (FreeSelector( sel )) return handle; /* failed */
125 free( ptr );
126 return 0;
130 /***********************************************************************
131 * WIN16_GlobalLock (KERNEL.18)
133 * This is the GlobalLock() function used by 16-bit code.
135 SEGPTR WIN16_GlobalLock( HGLOBAL handle )
137 dprintf_global( stddeb, "WIN16_GlobalLock: %04x\n", handle );
138 if (!handle) return 0;
139 return (SEGPTR)MAKELONG( 0, HGLOBAL_TO_SEL(handle) );
143 /***********************************************************************
144 * GlobalLock (KERNEL.18)
146 * This is the GlobalLock() function used by 32-bit code.
148 LPSTR GlobalLock( HGLOBAL handle )
150 dprintf_global( stddeb, "GlobalLock: %04x\n", handle );
151 if (!handle) return 0;
152 return (LPSTR)GET_SEL_BASE( HGLOBAL_TO_SEL(handle) );
156 /***********************************************************************
157 * GlobalUnlock (KERNEL.19)
159 BOOL GlobalUnlock( HGLOBAL handle )
161 dprintf_global( stddeb, "GlobalUnlock: %04x\n", handle );
162 return 0;
166 /***********************************************************************
167 * GlobalSize (KERNEL.20)
169 DWORD GlobalSize( HGLOBAL handle )
171 dprintf_global( stddeb, "GlobalSize: %04x\n", handle );
172 if (!handle) return 0;
173 return GET_SEL_LIMIT( HGLOBAL_TO_SEL(handle) ) + 1;
177 /***********************************************************************
178 * GlobalHandle (KERNEL.21)
180 DWORD GlobalHandle( WORD sel )
182 /* FIXME: what about GMEM_FIXED blocks? */
183 WORD handle = sel & ~1;
184 dprintf_global( stddeb, "GlobalHandle(%04x): returning %08lx\n",
185 sel, MAKELONG( handle, sel ) );
186 return MAKELONG( handle, sel );
190 /***********************************************************************
191 * GlobalFlags (KERNEL.22)
193 WORD GlobalFlags( HGLOBAL handle )
195 dprintf_global( stddeb, "GlobalFlags: %04x\n", handle );
196 return 0; /* lock count is always 0 */
200 /***********************************************************************
201 * LockSegment (KERNEL.23)
203 HGLOBAL LockSegment( HGLOBAL handle )
205 dprintf_global( stddeb, "LockSegment: %04x\n", handle );
206 if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
207 return handle;
211 /***********************************************************************
212 * UnlockSegment (KERNEL.24)
214 void UnlockSegment( HGLOBAL handle )
216 dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
217 /* FIXME: this ought to return the lock count in CX (go figure...) */
221 /***********************************************************************
222 * GlobalCompact (KERNEL.25)
224 DWORD GlobalCompact( DWORD desired )
226 return GLOBAL_MAX_ALLOC_SIZE;
230 /***********************************************************************
231 * GlobalWire (KERNEL.111)
233 LPSTR GlobalWire( HGLOBAL handle )
235 return GlobalLock( handle );
239 /***********************************************************************
240 * GlobalUnWire (KERNEL.112)
242 BOOL GlobalUnWire( HGLOBAL handle )
244 return GlobalUnlock( handle );
248 /***********************************************************************
249 * GlobalDOSAlloc (KERNEL.184)
251 DWORD GlobalDOSAlloc( DWORD size )
253 WORD sel = GlobalAlloc( GMEM_FIXED, size );
254 if (!sel) return 0;
255 return MAKELONG( sel, sel /* this one ought to be a real-mode segment */ );
259 /***********************************************************************
260 * GlobalDOSFree (KERNEL.185)
262 WORD GlobalDOSFree( WORD sel )
264 return GlobalFree( GlobalHandle(sel) ) ? sel : 0;
268 /***********************************************************************
269 * SetSwapAreaSize (KERNEL.106)
271 LONG SetSwapAreaSize( WORD size )
273 dprintf_heap(stdnimp, "STUB: SetSwapAreaSize(%d)\n", size );
274 return MAKELONG( size, 0xffff );
278 /***********************************************************************
279 * GlobalLRUOldest (KERNEL.163)
281 HGLOBAL GlobalLRUOldest( HGLOBAL handle )
283 dprintf_global( stddeb, "GlobalLRUOldest: %04x\n", handle );
284 if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
285 return handle;
289 /***********************************************************************
290 * GlobalLRUNewest (KERNEL.164)
292 HGLOBAL GlobalLRUNewest( HGLOBAL handle )
294 dprintf_global( stddeb, "GlobalLRUNewest: %04x\n", handle );
295 if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
296 return handle;
300 /***********************************************************************
301 * GetFreeSpace (KERNEL.169)
303 DWORD GetFreeSpace( UINT wFlags )
305 return GLOBAL_MAX_ALLOC_SIZE;
309 /***********************************************************************
310 * GlobalPageLock (KERNEL.191)
312 WORD GlobalPageLock( HGLOBAL handle )
314 dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
315 /* Nothing to do, as we can't page-lock a block (and we don't want to) */
316 return 1; /* lock count */
320 /***********************************************************************
321 * GlobalPageUnlock (KERNEL.192)
323 WORD GlobalPageUnlock( HGLOBAL handle )
325 dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
326 return 0; /* lock count */
330 /***********************************************************************
331 * GlobalFix (KERNEL.197)
333 void GlobalFix( HGLOBAL handle )
335 dprintf_global( stddeb, "GlobalFix: %04x\n", handle );
336 /* Nothing to do, as all the blocks are fixed in linear memory anyway */
340 /***********************************************************************
341 * GlobalUnfix (KERNEL.198)
343 void GlobalUnfix( HGLOBAL handle )
345 dprintf_global( stddeb, "GlobalUnfix: %04x\n", handle );
346 /* This one is even more complicated that GlobalFix() :-) */
350 /***********************************************************************
351 * GlobalHandleToSel (TOOLHELP.50)
353 WORD GlobalHandleToSel( HGLOBAL handle )
355 dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
356 if (!(handle & 7))
358 fprintf( stderr, "Program attempted invalid selector conversion\n" );
359 return handle - 1;
361 return handle | 1;
365 /**********************************************************************
366 * MemManInfo (toolhelp.72)
369 BOOL MemManInfo(LPMEMMANINFO lpmmi)
371 return 1;