blob: 18b1401d390082dc0062df31711fbab990cc0b14 [file] [log] [blame]
Alexandre Julliard234bc241994-12-10 13:02:28 +00001/*
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00002 * Global heap functions
3 *
4 * Copyright 1995 Alexandre Julliard
5 */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00006/* 0xffff sometimes seems to mean: CURRENT_DS */
Alexandre Julliard121bd981993-07-08 17:37:25 +00007
Alexandre Julliard808cb041995-08-17 17:11:36 +00008#include <sys/types.h>
Alexandre Julliard121bd981993-07-08 17:37:25 +00009#include <stdlib.h>
Marcus Meissner6189c192000-03-04 19:19:15 +000010#include <time.h>
Alexandre Julliard383da682000-02-10 22:15:21 +000011#include <stdio.h>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000012#include <unistd.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000013#include <string.h>
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000014
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000015#include "wine/winbase16.h"
Lawson Whitney969515d2000-10-02 22:27:37 +000016#include "wine/exception.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000017#include "global.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000018#include "heap.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000019#include "toolhelp.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000020#include "selectors.h"
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000021#include "miscemu.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000022#include "stackframe.h"
Alexandre Julliard77b99181997-09-14 17:17:23 +000023#include "module.h"
Alexandre Julliard15657091999-05-23 10:25:25 +000024#include "debugtools.h"
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000025#include "winerror.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000026
Alexandre Julliard383da682000-02-10 22:15:21 +000027DEFAULT_DEBUG_CHANNEL(global);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000028
Alexandre Julliardfa68b751995-04-03 16:55:37 +000029 /* Global arena block */
30typedef struct
31{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000032 DWORD base; /* Base address (0 if discarded) */
33 DWORD size; /* Size in bytes (0 indicates a free block) */
34 HGLOBAL16 handle; /* Handle for this block */
35 HGLOBAL16 hOwner; /* Owner of this block */
36 BYTE lockCount; /* Count of GlobalFix() calls */
37 BYTE pageLockCount; /* Count of GlobalPageLock() calls */
38 BYTE flags; /* Allocation flags */
39 BYTE selCount; /* Number of selectors allocated for this block */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000040} GLOBALARENA;
41
42 /* Flags definitions */
Alexandre Julliard2787be81995-05-22 18:23:01 +000043#define GA_MOVEABLE 0x02 /* same as GMEM_MOVEABLE */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000044#define GA_DGROUP 0x04
45#define GA_DISCARDABLE 0x08
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000046#define GA_IPCSHARE 0x10 /* same as GMEM_DDESHARE */
Andreas Mohrd23f5062000-10-02 22:16:21 +000047#define GA_DOSMEM 0x20
Alexandre Julliardfa68b751995-04-03 16:55:37 +000048
49 /* Arena array */
50static GLOBALARENA *pGlobalArena = NULL;
51static int globalArenaSize = 0;
52
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000053#define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
Alexandre Julliard121bd981993-07-08 17:37:25 +000054
Alexandre Julliarda11d7b11998-03-01 20:05:02 +000055#define VALID_HANDLE(handle) (((handle)>>__AHSHIFT)<globalArenaSize)
Alexandre Julliardfa68b751995-04-03 16:55:37 +000056#define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
Alexandre Julliard75a839a1993-07-15 11:13:45 +000057
Lawson Whitney969515d2000-10-02 22:27:37 +000058/* filter for page-fault exceptions */
59/* It is possible for a bogus global pointer to cause a */
60/* page zero reference, so I include EXCEPTION_PRIV_INSTRUCTION too. */
61
62static WINE_EXCEPTION_FILTER(page_fault)
63{
64 switch (GetExceptionCode()) {
65 case (EXCEPTION_ACCESS_VIOLATION):
66 case (EXCEPTION_PRIV_INSTRUCTION):
67 return EXCEPTION_EXECUTE_HANDLER;
68 default:
69 return EXCEPTION_CONTINUE_SEARCH;
70 }
71}
72
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000073/***********************************************************************
Alexandre Julliardfa68b751995-04-03 16:55:37 +000074 * GLOBAL_GetArena
75 *
76 * Return the arena for a given selector, growing the arena array if needed.
Alexandre Julliarddba420a1994-02-02 06:48:31 +000077 */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000078static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
Alexandre Julliarddba420a1994-02-02 06:48:31 +000079{
Alexandre Julliard2787be81995-05-22 18:23:01 +000080 if (((sel >> __AHSHIFT) + selcount) > globalArenaSize)
Alexandre Julliardfa68b751995-04-03 16:55:37 +000081 {
Alexandre Julliard2787be81995-05-22 18:23:01 +000082 int newsize = ((sel >> __AHSHIFT) + selcount + 0xff) & ~0xff;
Alexandre Julliardfa68b751995-04-03 16:55:37 +000083 GLOBALARENA *pNewArena = realloc( pGlobalArena,
Alexandre Julliard2787be81995-05-22 18:23:01 +000084 newsize * sizeof(GLOBALARENA) );
Alexandre Julliardfa68b751995-04-03 16:55:37 +000085 if (!pNewArena) return 0;
86 pGlobalArena = pNewArena;
Alexandre Julliard2787be81995-05-22 18:23:01 +000087 memset( pGlobalArena + globalArenaSize, 0,
88 (newsize - globalArenaSize) * sizeof(GLOBALARENA) );
89 globalArenaSize = newsize;
Alexandre Julliardfa68b751995-04-03 16:55:37 +000090 }
91 return pGlobalArena + (sel >> __AHSHIFT);
92}
Alexandre Julliarddba420a1994-02-02 06:48:31 +000093
Juergen Schmiedebc2b771998-11-14 18:59:30 +000094void debug_handles(void)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000095{
96 int printed=0;
97 int i;
98 for (i = globalArenaSize-1 ; i>=0 ; i--) {
99 if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
100 printed=1;
Alexandre Julliard15657091999-05-23 10:25:25 +0000101 DPRINTF("0x%08x, ",pGlobalArena[i].handle);
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000102 }
103 }
104 if (printed)
Alexandre Julliard15657091999-05-23 10:25:25 +0000105 DPRINTF("\n");
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000106}
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000107
108
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000109/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000110 * GLOBAL_CreateBlock
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000111 *
Alexandre Julliard594997c1995-04-30 10:05:20 +0000112 * Create a global heap block for a fixed range of linear memory.
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000113 */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000114HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000115 HGLOBAL16 hOwner, BOOL16 isCode,
Alexandre Julliard4fef2f12000-08-09 22:27:11 +0000116 BOOL16 is32Bit, BOOL16 isReadOnly )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000117{
118 WORD sel, selcount;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000119 GLOBALARENA *pArena;
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000120
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000121 /* Allocate the selector(s) */
122
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000123 sel = SELECTOR_AllocBlock( ptr, size,
124 isCode ? SEGMENT_CODE : SEGMENT_DATA,
125 is32Bit, isReadOnly );
126
Alexandre Julliard594997c1995-04-30 10:05:20 +0000127 if (!sel) return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000128 selcount = (size + 0xffff) / 0x10000;
129
130 if (!(pArena = GLOBAL_GetArena( sel, selcount )))
131 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000132 SELECTOR_FreeBlock( sel, selcount );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000133 return 0;
134 }
135
136 /* Fill the arena block */
137
138 pArena->base = (DWORD)ptr;
139 pArena->size = GET_SEL_LIMIT(sel) + 1;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000140 pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000141 pArena->hOwner = hOwner;
142 pArena->lockCount = 0;
143 pArena->pageLockCount = 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000144 pArena->flags = flags & GA_MOVEABLE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000145 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000146 if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000147 if (!isCode) pArena->flags |= GA_DGROUP;
148 pArena->selCount = selcount;
149 if (selcount > 1) /* clear the next arena blocks */
150 memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000151
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000152 return pArena->handle;
153}
Alexandre Julliard121bd981993-07-08 17:37:25 +0000154
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000155
156/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000157 * GLOBAL_FreeBlock
158 *
159 * Free a block allocated by GLOBAL_CreateBlock, without touching
160 * the associated linear memory range.
161 */
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000162BOOL16 GLOBAL_FreeBlock( HGLOBAL16 handle )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000163{
164 WORD sel;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000165 GLOBALARENA *pArena;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000166
167 if (!handle) return TRUE;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000168 sel = GlobalHandleToSel16( handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000169 if (!VALID_HANDLE(sel))
170 return FALSE;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000171 pArena = GET_ARENA_PTR(sel);
172 SELECTOR_FreeBlock( sel, (pArena->size + 0xffff) / 0x10000 );
173 memset( pArena, 0, sizeof(GLOBALARENA) );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000174 return TRUE;
175}
176
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000177/***********************************************************************
178 * GLOBAL_MoveBlock
179 */
180BOOL16 GLOBAL_MoveBlock( HGLOBAL16 handle, const void *ptr, DWORD size )
181{
182 WORD sel;
183 GLOBALARENA *pArena;
184
185 if (!handle) return TRUE;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000186 sel = GlobalHandleToSel16( handle );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000187 if (!VALID_HANDLE(sel))
188 return FALSE;
189 pArena = GET_ARENA_PTR(sel);
190 if (pArena->selCount != 1)
191 return FALSE;
192
193 pArena->base = (DWORD)ptr;
194 pArena->size = size;
195
196 SELECTOR_MoveBlock( sel, ptr );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000197 SetSelectorLimit16( sel, size-1 );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000198
199 return TRUE;
200}
Alexandre Julliard594997c1995-04-30 10:05:20 +0000201
202/***********************************************************************
203 * GLOBAL_Alloc
204 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000205 * Implementation of GlobalAlloc16()
Alexandre Julliard594997c1995-04-30 10:05:20 +0000206 */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000207HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000208 BOOL16 isCode, BOOL16 is32Bit, BOOL16 isReadOnly )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000209{
210 void *ptr;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000211 HGLOBAL16 handle;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000212
Alexandre Julliard15657091999-05-23 10:25:25 +0000213 TRACE("%ld flags=%04x\n", size, flags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000214
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000215 /* If size is 0, create a discarded block */
216
217 if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
Alexandre Julliard4fef2f12000-08-09 22:27:11 +0000218 is32Bit, isReadOnly );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000219
220 /* Fixup the size */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000221
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000222 if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000223 size = (size + 0x1f) & ~0x1f;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000224
Marcus Meissnere32a3171999-07-11 14:13:56 +0000225 /* Allocate the linear memory */
Alexandre Julliard079fd722000-01-25 01:41:35 +0000226 ptr = HeapAlloc( GetProcessHeap(), 0, size );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000227 /* FIXME: free discardable blocks and try again? */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000228 if (!ptr) return 0;
229
230 /* Allocate the selector(s) */
231
232 handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
Alexandre Julliard4fef2f12000-08-09 22:27:11 +0000233 isCode, is32Bit, isReadOnly );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000234 if (!handle)
235 {
Alexandre Julliard079fd722000-01-25 01:41:35 +0000236 HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000237 return 0;
238 }
239
240 if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
241 return handle;
242}
243
Alexandre Julliard594997c1995-04-30 10:05:20 +0000244/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000245 * GlobalAlloc16 (KERNEL.15)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000246 * RETURNS
247 * Handle: Success
248 * NULL: Failure
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000249 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000250HGLOBAL16 WINAPI GlobalAlloc16(
251 UINT16 flags, /* [in] Object allocation attributes */
252 DWORD size /* [in] Number of bytes to allocate */
253) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000254 HANDLE16 owner = GetCurrentPDB16();
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000255
Alexandre Julliard594997c1995-04-30 10:05:20 +0000256 if (flags & GMEM_DDESHARE)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000257 owner = GetExePtr(owner); /* Make it a module handle */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000258 return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000259}
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000260
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000261
262/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000263 * GlobalReAlloc16 (KERNEL.16)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000264 * RETURNS
265 * Handle: Success
266 * NULL: Failure
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000267 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000268HGLOBAL16 WINAPI GlobalReAlloc16(
269 HGLOBAL16 handle, /* [in] Handle of global memory object */
270 DWORD size, /* [in] New size of block */
271 UINT16 flags /* [in] How to reallocate object */
272) {
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000273 WORD selcount;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000274 DWORD oldsize;
275 void *ptr;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000276 GLOBALARENA *pArena, *pNewArena;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000277 WORD sel = GlobalHandleToSel16( handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000278
Alexandre Julliard15657091999-05-23 10:25:25 +0000279 TRACE("%04x %ld flags=%04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000280 handle, size, flags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000281 if (!handle) return 0;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000282
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000283 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000284 WARN("Invalid handle 0x%04x!\n", handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000285 return 0;
286 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000287 pArena = GET_ARENA_PTR( handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000288
Alexandre Julliard2787be81995-05-22 18:23:01 +0000289 /* Discard the block if requested */
290
Alexandre Julliardded30381995-07-06 17:18:27 +0000291 if ((size == 0) && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY))
Alexandre Julliard2787be81995-05-22 18:23:01 +0000292 {
293 if (!(pArena->flags & GA_MOVEABLE) ||
294 !(pArena->flags & GA_DISCARDABLE) ||
295 (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
Alexandre Julliard079fd722000-01-25 01:41:35 +0000296 HeapFree( GetProcessHeap(), 0, (void *)pArena->base );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000297 pArena->base = 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000298
299 /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
300 * change the selector if we are shrinking the block.
301 * FIXME: shouldn't we keep selectors until the block is deleted?
302 */
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000303 SELECTOR_ReallocBlock( sel, 0, 1 );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000304 return handle;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000305 }
306
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000307 /* Fixup the size */
308
Alexandre Julliard2787be81995-05-22 18:23:01 +0000309 if (size > GLOBAL_MAX_ALLOC_SIZE - 0x20) return 0;
310 if (size == 0) size = 0x20;
311 else size = (size + 0x1f) & ~0x1f;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000312
Alexandre Julliard594997c1995-04-30 10:05:20 +0000313 /* Change the flags */
314
315 if (flags & GMEM_MODIFY)
316 {
317 /* Change the flags, leaving GA_DGROUP alone */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000318 pArena->flags = (pArena->flags & GA_DGROUP) | (flags & GA_MOVEABLE);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000319 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
320 return handle;
321 }
322
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000323 /* Reallocate the linear memory */
324
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000325 ptr = (void *)pArena->base;
326 oldsize = pArena->size;
Alexandre Julliard15657091999-05-23 10:25:25 +0000327 TRACE("oldsize %08lx\n",oldsize);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +0000328 if (ptr && (size == oldsize)) return handle; /* Nothing to do */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000329
Andreas Mohrd23f5062000-10-02 22:16:21 +0000330 if (pArena->flags & GA_DOSMEM)
Ove Kaaven7b499142000-07-28 22:23:59 +0000331 ptr = DOSMEM_ResizeBlock(ptr, size, NULL);
Bertho Stultiensc1d1cfe1999-04-18 12:14:06 +0000332 else
Alexandre Julliard079fd722000-01-25 01:41:35 +0000333 ptr = HeapReAlloc( GetProcessHeap(), 0, ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000334 if (!ptr)
335 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000336 SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000337 memset( pArena, 0, sizeof(GLOBALARENA) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000338 return 0;
339 }
340
341 /* Reallocate the selector(s) */
342
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000343 sel = SELECTOR_ReallocBlock( sel, ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000344 if (!sel)
345 {
Alexandre Julliard079fd722000-01-25 01:41:35 +0000346 HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000347 memset( pArena, 0, sizeof(GLOBALARENA) );
348 return 0;
349 }
350 selcount = (size + 0xffff) / 0x10000;
351
352 if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
353 {
Alexandre Julliard079fd722000-01-25 01:41:35 +0000354 HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000355 SELECTOR_FreeBlock( sel, selcount );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000356 return 0;
357 }
358
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000359 /* Fill the new arena block */
360
361 if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
362 pNewArena->base = (DWORD)ptr;
363 pNewArena->size = GET_SEL_LIMIT(sel) + 1;
364 pNewArena->selCount = selcount;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000365 pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000366
367 if (selcount > 1) /* clear the next arena blocks */
368 memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
369
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000370 if ((oldsize < size) && (flags & GMEM_ZEROINIT))
371 memset( (char *)ptr + oldsize, 0, size - oldsize );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000372 return pNewArena->handle;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000373}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000374
375
376/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000377 * GlobalFree16 (KERNEL.17)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000378 * RETURNS
379 * NULL: Success
380 * Handle: Failure
Alexandre Julliard121bd981993-07-08 17:37:25 +0000381 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000382HGLOBAL16 WINAPI GlobalFree16(
383 HGLOBAL16 handle /* [in] Handle of global memory object */
384) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000385 void *ptr;
Alexandre Julliard121bd981993-07-08 17:37:25 +0000386
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000387 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000388 WARN("Invalid handle 0x%04x passed to GlobalFree16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000389 return 0;
390 }
391 ptr = (void *)GET_ARENA_PTR(handle)->base;
392
Alexandre Julliard15657091999-05-23 10:25:25 +0000393 TRACE("%04x\n", handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000394 if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
Alexandre Julliard079fd722000-01-25 01:41:35 +0000395 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000396 return 0;
397}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000398
399
400/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000401 * WIN16_GlobalLock16 (KERNEL.18)
Alexandre Julliard121bd981993-07-08 17:37:25 +0000402 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000403 * This is the GlobalLock16() function used by 16-bit code.
Alexandre Julliard121bd981993-07-08 17:37:25 +0000404 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000405SEGPTR WINAPI WIN16_GlobalLock16( HGLOBAL16 handle )
Alexandre Julliard121bd981993-07-08 17:37:25 +0000406{
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000407 WORD sel = GlobalHandleToSel16( handle );
408 TRACE("(%04x) -> %08lx\n", handle, MAKELONG( 0, sel ) );
409
Alexandre Julliard77b99181997-09-14 17:17:23 +0000410 if (handle)
411 {
412 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000413
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000414 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000415 WARN("Invalid handle 0x%04x passed to WIN16_GlobalLock16!\n",handle);
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000416 sel = 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000417 }
Ulrich Weigand81a80571999-07-28 16:36:29 +0000418 else if (!GET_ARENA_PTR(handle)->base)
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000419 sel = 0;
420 else
421 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000422 }
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000423
424 CURRENT_STACK16->ecx = sel; /* selector must be returned in CX as well */
425 return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000426}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000427
428
429/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000430 * GlobalLock16 (KERNEL.18)
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000431 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000432 * This is the GlobalLock16() function used by 32-bit code.
Alexandre Julliard54c27111998-03-29 19:44:57 +0000433 *
434 * RETURNS
435 * Pointer to first byte of memory block
436 * NULL: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000437 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000438LPVOID WINAPI GlobalLock16(
439 HGLOBAL16 handle /* [in] Handle of global memory object */
440) {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000441 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000442 if (!VALID_HANDLE(handle))
443 return (LPVOID)0;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000444 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000445 return (LPVOID)GET_ARENA_PTR(handle)->base;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000446}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000447
448
449/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000450 * GlobalUnlock16 (KERNEL.19)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000451 * NOTES
452 * Should the return values be cast to booleans?
453 *
454 * RETURNS
455 * TRUE: Object is still locked
456 * FALSE: Object is unlocked
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000457 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000458BOOL16 WINAPI GlobalUnlock16(
459 HGLOBAL16 handle /* [in] Handle of global memory object */
460) {
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000461 GLOBALARENA *pArena = GET_ARENA_PTR(handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000462 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000463 WARN("Invalid handle 0x%04x passed to GlobalUnlock16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000464 return 0;
465 }
Alexandre Julliard15657091999-05-23 10:25:25 +0000466 TRACE("%04x\n", handle );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000467 if (pArena->lockCount) pArena->lockCount--;
468 return pArena->lockCount;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000469}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000470
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000471/***********************************************************************
472 * GlobalChangeLockCount (KERNEL.365)
473 *
474 * This is declared as a register function as it has to preserve
475 * *all* registers, even AX/DX !
476 *
477 */
Ulrich Weigandb5151d01999-07-25 11:27:36 +0000478void WINAPI GlobalChangeLockCount16( HGLOBAL16 handle, INT16 delta,
479 CONTEXT86 *context )
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000480{
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000481 if ( delta == 1 )
482 GlobalLock16( handle );
483 else if ( delta == -1 )
484 GlobalUnlock16( handle );
485 else
Alexandre Julliard15657091999-05-23 10:25:25 +0000486 ERR("(%04X, %d): strange delta value\n", handle, delta );
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000487}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000488
489/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000490 * GlobalSize16 (KERNEL.20)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000491 * RETURNS
492 * Size in bytes of object
493 * 0: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000494 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000495DWORD WINAPI GlobalSize16(
496 HGLOBAL16 handle /* [in] Handle of global memory object */
497) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000498 TRACE("%04x\n", handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000499 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000500 if (!VALID_HANDLE(handle))
501 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000502 return GET_ARENA_PTR(handle)->size;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000503}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000504
505
506/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000507 * GlobalHandle16 (KERNEL.21)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000508 * NOTES
509 * Why is GlobalHandleToSel used here with the sel as input?
510 *
511 * RETURNS
512 * Handle: Success
513 * NULL: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000514 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000515DWORD WINAPI GlobalHandle16(
516 WORD sel /* [in] Address of global memory block */
517) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000518 TRACE("%04x\n", sel );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000519 if (!VALID_HANDLE(sel)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000520 WARN("Invalid handle 0x%04x passed to GlobalHandle16!\n",sel);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000521 return 0;
522 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000523 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel16(sel) );
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000524}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000525
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000526/***********************************************************************
527 * GlobalHandleNoRIP (KERNEL.159)
528 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000529DWORD WINAPI GlobalHandleNoRIP16( WORD sel )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000530{
531 int i;
532 for (i = globalArenaSize-1 ; i>=0 ; i--) {
533 if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == sel)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000534 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel16(sel) );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000535 }
536 return 0;
537}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000538
Alexandre Julliard54c27111998-03-29 19:44:57 +0000539
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000540/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000541 * GlobalFlags16 (KERNEL.22)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000542 * NOTES
543 * Should this return GMEM_INVALID_HANDLE instead of 0 on invalid
544 * handle?
545 *
546 * RETURNS
547 * Value specifying flags and lock count
548 * GMEM_INVALID_HANDLE: Invalid handle
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000549 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000550UINT16 WINAPI GlobalFlags16(
551 HGLOBAL16 handle /* [in] Handle of global memory object */
552) {
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000553 GLOBALARENA *pArena;
554
Alexandre Julliard15657091999-05-23 10:25:25 +0000555 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000556 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000557 WARN("Invalid handle 0x%04x passed to GlobalFlags16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000558 return 0;
559 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000560 pArena = GET_ARENA_PTR(handle);
561 return pArena->lockCount |
Alexandre Julliard2787be81995-05-22 18:23:01 +0000562 ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0) |
563 ((pArena->base == 0) ? GMEM_DISCARDED : 0);
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000564}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000565
566
567/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000568 * LockSegment16 (KERNEL.23)
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000569 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000570HGLOBAL16 WINAPI LockSegment16( HGLOBAL16 handle )
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000571{
Alexandre Julliard15657091999-05-23 10:25:25 +0000572 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000573 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000574 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000575 WARN("Invalid handle 0x%04x passed to LockSegment16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000576 return 0;
577 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000578 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000579 return handle;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000580}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000581
582
583/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000584 * UnlockSegment16 (KERNEL.24)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000585 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000586void WINAPI UnlockSegment16( HGLOBAL16 handle )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000587{
Alexandre Julliard15657091999-05-23 10:25:25 +0000588 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000589 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000590 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000591 WARN("Invalid handle 0x%04x passed to UnlockSegment16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000592 return;
593 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000594 GET_ARENA_PTR(handle)->lockCount--;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000595 /* FIXME: this ought to return the lock count in CX (go figure...) */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000596}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000597
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000598
599/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000600 * GlobalCompact16 (KERNEL.25)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000601 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000602DWORD WINAPI GlobalCompact16( DWORD desired )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000603{
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000604 return GLOBAL_MAX_ALLOC_SIZE;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000605}
606
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000607
608/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000609 * GlobalFreeAll (KERNEL.26)
610 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000611void WINAPI GlobalFreeAll16( HGLOBAL16 owner )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000612{
613 DWORD i;
614 GLOBALARENA *pArena;
615
616 pArena = pGlobalArena;
617 for (i = 0; i < globalArenaSize; i++, pArena++)
618 {
619 if ((pArena->size != 0) && (pArena->hOwner == owner))
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000620 GlobalFree16( pArena->handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000621 }
622}
623
624
625/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000626 * GlobalWire16 (KERNEL.111)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000627 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000628SEGPTR WINAPI GlobalWire16( HGLOBAL16 handle )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000629{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000630 return WIN16_GlobalLock16( handle );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000631}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000632
633
634/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000635 * GlobalUnWire16 (KERNEL.112)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000636 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000637BOOL16 WINAPI GlobalUnWire16( HGLOBAL16 handle )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000638{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000639 return !GlobalUnlock16( handle );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000640}
Alexandre Julliardaca05781994-10-17 18:12:41 +0000641
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000642
643/***********************************************************************
Alexandre Julliarde658d821997-11-30 17:45:40 +0000644 * SetSwapAreaSize16 (KERNEL.106)
Alexandre Julliardaca05781994-10-17 18:12:41 +0000645 */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000646LONG WINAPI SetSwapAreaSize16( WORD size )
Alexandre Julliardaca05781994-10-17 18:12:41 +0000647{
Alexandre Julliard15657091999-05-23 10:25:25 +0000648 FIXME("(%d) - stub!\n", size );
Alexandre Julliardaca05781994-10-17 18:12:41 +0000649 return MAKELONG( size, 0xffff );
650}
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000651
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000652
653/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000654 * GlobalLRUOldest (KERNEL.163)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000655 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000656HGLOBAL16 WINAPI GlobalLRUOldest16( HGLOBAL16 handle )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000657{
Alexandre Julliard15657091999-05-23 10:25:25 +0000658 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000659 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000660 return handle;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000661}
662
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000663
664/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000665 * GlobalLRUNewest (KERNEL.164)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000666 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000667HGLOBAL16 WINAPI GlobalLRUNewest16( HGLOBAL16 handle )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000668{
Alexandre Julliard15657091999-05-23 10:25:25 +0000669 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000670 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000671 return handle;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000672}
673
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000674
675/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000676 * GetFreeSpace16 (KERNEL.169)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000677 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000678DWORD WINAPI GetFreeSpace16( UINT16 wFlags )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000679{
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000680 MEMORYSTATUS ms;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000681 GlobalMemoryStatus( &ms );
682 return ms.dwAvailVirtual;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000683}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000684
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000685/***********************************************************************
686 * GlobalDOSAlloc (KERNEL.184)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000687 * RETURNS
688 * Address (HW=Paragraph segment; LW=Selector)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000689 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000690DWORD WINAPI GlobalDOSAlloc16(
Alexandre Julliard54c27111998-03-29 19:44:57 +0000691 DWORD size /* [in] Number of bytes to be allocated */
692) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000693 UINT16 uParagraph;
Ove Kaaven7b499142000-07-28 22:23:59 +0000694 LPVOID lpBlock = DOSMEM_GetBlock( size, &uParagraph );
Alexandre Julliard54c27111998-03-29 19:44:57 +0000695
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000696 if( lpBlock )
697 {
Alexandre Julliard21979011997-03-05 08:22:35 +0000698 HMODULE16 hModule = GetModuleHandle16("KERNEL");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000699 WORD wSelector;
Andreas Mohrd23f5062000-10-02 22:16:21 +0000700 GLOBALARENA *pArena;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000701
702 wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size,
Alexandre Julliard4fef2f12000-08-09 22:27:11 +0000703 hModule, 0, 0, 0 );
Andreas Mohrd23f5062000-10-02 22:16:21 +0000704 pArena = GET_ARENA_PTR(wSelector);
705 pArena->flags |= GA_DOSMEM;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000706 return MAKELONG(wSelector,uParagraph);
707 }
708 return 0;
709}
710
Alexandre Julliard54c27111998-03-29 19:44:57 +0000711
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000712/***********************************************************************
713 * GlobalDOSFree (KERNEL.185)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000714 * RETURNS
715 * NULL: Success
716 * sel: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000717 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000718WORD WINAPI GlobalDOSFree16(
Alexandre Julliard54c27111998-03-29 19:44:57 +0000719 WORD sel /* [in] Selector */
720) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000721 DWORD block = GetSelectorBase(sel);
722
723 if( block && block < 0x100000 )
724 {
725 LPVOID lpBlock = DOSMEM_MapDosToLinear( block );
Ove Kaaven7b499142000-07-28 22:23:59 +0000726 if( DOSMEM_FreeBlock( lpBlock ) )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000727 GLOBAL_FreeBlock( sel );
728 sel = 0;
729 }
730 return sel;
731}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000732
Alexandre Julliard54c27111998-03-29 19:44:57 +0000733
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000734/***********************************************************************
735 * GlobalPageLock (KERNEL.191)
736 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000737WORD WINAPI GlobalPageLock16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000738{
Alexandre Julliard15657091999-05-23 10:25:25 +0000739 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000740 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000741 WARN("Invalid handle 0x%04x passed to GlobalPageLock!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000742 return 0;
743 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000744 return ++(GET_ARENA_PTR(handle)->pageLockCount);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000745}
746
747
748/***********************************************************************
749 * GlobalPageUnlock (KERNEL.192)
750 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000751WORD WINAPI GlobalPageUnlock16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000752{
Alexandre Julliard15657091999-05-23 10:25:25 +0000753 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000754 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000755 WARN("Invalid handle 0x%04x passed to GlobalPageUnlock!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000756 return 0;
757 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000758 return --(GET_ARENA_PTR(handle)->pageLockCount);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000759}
760
761
762/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000763 * GlobalFix16 (KERNEL.197)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000764 */
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000765WORD WINAPI GlobalFix16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000766{
Alexandre Julliard15657091999-05-23 10:25:25 +0000767 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000768 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000769 WARN("Invalid handle 0x%04x passed to GlobalFix16!\n",handle);
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000770 return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000771 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000772 GET_ARENA_PTR(handle)->lockCount++;
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000773
Alexandre Julliarda3960291999-02-26 11:11:13 +0000774 return GlobalHandleToSel16(handle);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000775}
776
777
778/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000779 * GlobalUnfix16 (KERNEL.198)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000780 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000781void WINAPI GlobalUnfix16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000782{
Alexandre Julliard15657091999-05-23 10:25:25 +0000783 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000784 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000785 WARN("Invalid handle 0x%04x passed to GlobalUnfix16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000786 return;
787 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000788 GET_ARENA_PTR(handle)->lockCount--;
789}
790
791
792/***********************************************************************
793 * FarSetOwner (KERNEL.403)
794 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000795void WINAPI FarSetOwner16( HGLOBAL16 handle, HANDLE16 hOwner )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000796{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000797 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000798 WARN("Invalid handle 0x%04x passed to FarSetOwner!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000799 return;
800 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000801 GET_ARENA_PTR(handle)->hOwner = hOwner;
802}
803
804
805/***********************************************************************
806 * FarGetOwner (KERNEL.404)
807 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000808HANDLE16 WINAPI FarGetOwner16( HGLOBAL16 handle )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000809{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000810 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000811 WARN("Invalid handle 0x%04x passed to FarGetOwner!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000812 return 0;
813 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000814 return GET_ARENA_PTR(handle)->hOwner;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000815}
816
817
818/***********************************************************************
819 * GlobalHandleToSel (TOOLHELP.50)
820 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000821WORD WINAPI GlobalHandleToSel16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000822{
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000823 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000824 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000825 WARN("Invalid handle 0x%04x passed to GlobalHandleToSel!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000826 return 0;
827 }
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000828 if (!(handle & 7))
829 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000830 WARN("Program attempted invalid selector conversion\n" );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000831 return handle - 1;
832 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000833 return handle | 7;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000834}
835
836
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000837/***********************************************************************
838 * GlobalFirst (TOOLHELP.51)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000839 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000840BOOL16 WINAPI GlobalFirst16( GLOBALENTRY *pGlobal, WORD wFlags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000841{
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000842 if (wFlags == GLOBAL_LRU) return FALSE;
843 pGlobal->dwNext = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000844 return GlobalNext16( pGlobal, wFlags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000845}
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000846
847
848/***********************************************************************
849 * GlobalNext (TOOLHELP.52)
850 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000851BOOL16 WINAPI GlobalNext16( GLOBALENTRY *pGlobal, WORD wFlags)
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000852{
853 GLOBALARENA *pArena;
854
Alexandre Julliard594997c1995-04-30 10:05:20 +0000855 if (pGlobal->dwNext >= globalArenaSize) return FALSE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000856 pArena = pGlobalArena + pGlobal->dwNext;
857 if (wFlags == GLOBAL_FREE) /* only free blocks */
858 {
859 int i;
860 for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
861 if (pArena->size == 0) break; /* block is free */
862 if (i >= globalArenaSize) return FALSE;
863 pGlobal->dwNext = i;
864 }
865
866 pGlobal->dwAddress = pArena->base;
867 pGlobal->dwBlockSize = pArena->size;
868 pGlobal->hBlock = pArena->handle;
869 pGlobal->wcLock = pArena->lockCount;
870 pGlobal->wcPageLock = pArena->pageLockCount;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000871 pGlobal->wFlags = (GetCurrentPDB16() == pArena->hOwner);
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000872 pGlobal->wHeapPresent = FALSE;
873 pGlobal->hOwner = pArena->hOwner;
874 pGlobal->wType = GT_UNKNOWN;
875 pGlobal->wData = 0;
876 pGlobal->dwNext++;
877 return TRUE;
878}
879
880
881/***********************************************************************
882 * GlobalInfo (TOOLHELP.53)
883 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000884BOOL16 WINAPI GlobalInfo16( GLOBALINFO *pInfo )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000885{
886 int i;
887 GLOBALARENA *pArena;
888
889 pInfo->wcItems = globalArenaSize;
890 pInfo->wcItemsFree = 0;
891 pInfo->wcItemsLRU = 0;
892 for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
893 if (pArena->size == 0) pInfo->wcItemsFree++;
894 return TRUE;
895}
896
897
898/***********************************************************************
899 * GlobalEntryHandle (TOOLHELP.54)
900 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000901BOOL16 WINAPI GlobalEntryHandle16( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000902{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000903 GLOBALARENA *pArena = GET_ARENA_PTR(hItem);
904
905 pGlobal->dwAddress = pArena->base;
906 pGlobal->dwBlockSize = pArena->size;
907 pGlobal->hBlock = pArena->handle;
908 pGlobal->wcLock = pArena->lockCount;
909 pGlobal->wcPageLock = pArena->pageLockCount;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000910 pGlobal->wFlags = (GetCurrentPDB16() == pArena->hOwner);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000911 pGlobal->wHeapPresent = FALSE;
912 pGlobal->hOwner = pArena->hOwner;
913 pGlobal->wType = GT_UNKNOWN;
914 pGlobal->wData = 0;
915 pGlobal->dwNext++;
916 return TRUE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000917}
918
919
920/***********************************************************************
921 * GlobalEntryModule (TOOLHELP.55)
922 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000923BOOL16 WINAPI GlobalEntryModule16( GLOBALENTRY *pGlobal, HMODULE16 hModule,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000924 WORD wSeg )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000925{
Andreas Mohrd23f5062000-10-02 22:16:21 +0000926 FIXME("(%p, 0x%04x, 0x%04x), stub.\n", pGlobal, hModule, wSeg);
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000927 return FALSE;
928}
929
930
931/***********************************************************************
932 * MemManInfo (TOOLHELP.72)
933 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000934BOOL16 WINAPI MemManInfo16( MEMMANINFO *info )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000935{
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000936 MEMORYSTATUS status;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000937
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000938 /*
939 * Not unsurprisingly although the documention says you
940 * _must_ provide the size in the dwSize field, this function
941 * (under Windows) always fills the structure and returns true.
942 */
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000943 GlobalMemoryStatus( &status );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000944 info->wPageSize = VIRTUAL_GetPageSize();
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000945 info->dwLargestFreeBlock = status.dwAvailVirtual;
946 info->dwMaxPagesAvailable = info->dwLargestFreeBlock / info->wPageSize;
947 info->dwMaxPagesLockable = info->dwMaxPagesAvailable;
948 info->dwTotalLinearSpace = status.dwTotalVirtual / info->wPageSize;
949 info->dwTotalUnlockedPages = info->dwTotalLinearSpace;
950 info->dwFreePages = info->dwMaxPagesAvailable;
951 info->dwTotalPages = info->dwTotalLinearSpace;
952 info->dwFreeLinearSpace = info->dwMaxPagesAvailable;
953 info->dwSwapFilePages = status.dwTotalPageFile / info->wPageSize;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000954 return TRUE;
955}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000956
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000957/***********************************************************************
958 * GetFreeMemInfo (KERNEL.316)
959 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000960DWORD WINAPI GetFreeMemInfo16(void)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000961{
962 MEMMANINFO info;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000963 MemManInfo16( &info );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000964 return MAKELONG( info.dwTotalLinearSpace, info.dwMaxPagesAvailable );
965}
966
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000967/*
968 * Win32 Global heap functions (GlobalXXX).
969 * These functions included in Win32 for compatibility with 16 bit Windows
970 * Especially the moveable blocks and handles are oldish.
971 * But the ability to directly allocate memory with GPTR and LPTR is widely
972 * used.
973 *
974 * The handle stuff looks horrible, but it's implemented almost like Win95
975 * does it.
976 *
977 */
978
979#define MAGIC_GLOBAL_USED 0x5342
980#define GLOBAL_LOCK_MAX 0xFF
Alexandre Julliard17216f51997-10-12 16:30:17 +0000981#define HANDLE_TO_INTERN(h) ((PGLOBAL32_INTERN)(((char *)(h))-2))
Alexandre Julliarda3960291999-02-26 11:11:13 +0000982#define INTERN_TO_HANDLE(i) ((HGLOBAL) &((i)->Pointer))
983#define POINTER_TO_HANDLE(p) (*(((HGLOBAL *)(p))-1))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000984#define ISHANDLE(h) (((DWORD)(h)&2)!=0)
985#define ISPOINTER(h) (((DWORD)(h)&2)==0)
986
987typedef struct __GLOBAL32_INTERN
988{
989 WORD Magic;
990 LPVOID Pointer WINE_PACKED;
991 BYTE Flags;
992 BYTE LockCount;
993} GLOBAL32_INTERN, *PGLOBAL32_INTERN;
994
Noel Borthwick83579c81999-07-24 12:18:04 +0000995/***********************************************************************
996 * GLOBAL_GetHeap
997 *
998 * Returns the appropriate heap to be used. If the object was created
999 * With GMEM_DDESHARE we allocated it on the system heap.
1000 */
1001static HANDLE GLOBAL_GetHeap( HGLOBAL hmem )
1002{
1003 HANDLE heap;
1004
1005 TRACE("() hmem=%x\n", hmem);
1006
1007 /* Get the appropriate heap to be used for this object */
1008 if (ISPOINTER(hmem))
1009 heap = GetProcessHeap();
1010 else
1011 {
1012 PGLOBAL32_INTERN pintern;
1013 pintern=HANDLE_TO_INTERN(hmem);
1014
1015 /* If it was DDESHARE it was created on the shared system heap */
1016 pintern=HANDLE_TO_INTERN(hmem);
1017 heap = ( pintern->Flags & (GMEM_DDESHARE >> 8) )
1018 ? SystemHeap : GetProcessHeap();
1019 }
1020
1021 return heap;
1022}
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001023
1024/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001025 * GlobalAlloc (KERNEL32.315)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001026 * RETURNS
1027 * Handle: Success
1028 * NULL: Failure
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001029 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001030HGLOBAL WINAPI GlobalAlloc(
1031 UINT flags, /* [in] Object allocation attributes */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001032 DWORD size /* [in] Number of bytes to allocate */
1033) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001034 PGLOBAL32_INTERN pintern;
1035 DWORD hpflags;
1036 LPVOID palloc;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001037
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001038 if(flags&GMEM_ZEROINIT)
1039 hpflags=HEAP_ZERO_MEMORY;
1040 else
1041 hpflags=0;
1042
Noel Borthwick83579c81999-07-24 12:18:04 +00001043 TRACE("() flags=%04x\n", flags );
1044
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001045 if((flags & GMEM_MOVEABLE)==0) /* POINTER */
1046 {
1047 palloc=HeapAlloc(GetProcessHeap(), hpflags, size);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001048 return (HGLOBAL) palloc;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001049 }
1050 else /* HANDLE */
1051 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001052 HANDLE heap;
1053
1054 /* If DDESHARE is set, create on the shared system heap */
1055 heap = (flags & GMEM_DDESHARE) ? SystemHeap : GetProcessHeap();
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001056
Noel Borthwick83579c81999-07-24 12:18:04 +00001057 /* HeapLock(heap); */
1058
1059 pintern=HeapAlloc(heap, 0, sizeof(GLOBAL32_INTERN));
Eric Pouech3bcfb902000-06-24 12:51:24 +00001060 if (!pintern) return NULL;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001061 if(size)
1062 {
Eric Pouech3bcfb902000-06-24 12:51:24 +00001063 if (!(palloc=HeapAlloc(heap, hpflags, size+sizeof(HGLOBAL)))) {
1064 HeapFree(heap, 0, pintern);
1065 return NULL;
1066 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001067 *(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001068 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001069 }
1070 else
1071 pintern->Pointer=NULL;
1072 pintern->Magic=MAGIC_GLOBAL_USED;
1073 pintern->Flags=flags>>8;
1074 pintern->LockCount=0;
1075
Noel Borthwick83579c81999-07-24 12:18:04 +00001076 /* HeapUnlock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001077
1078 return INTERN_TO_HANDLE(pintern);
1079 }
1080}
1081
1082
1083/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001084 * GlobalLock (KERNEL32.326)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001085 * RETURNS
1086 * Pointer to first byte of block
1087 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001088 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001089LPVOID WINAPI GlobalLock(
1090 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001091) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001092 PGLOBAL32_INTERN pintern;
1093 LPVOID palloc;
1094
1095 if(ISPOINTER(hmem))
1096 return (LPVOID) hmem;
1097
1098 /* HeapLock(GetProcessHeap()); */
1099
1100 pintern=HANDLE_TO_INTERN(hmem);
1101 if(pintern->Magic==MAGIC_GLOBAL_USED)
1102 {
1103 if(pintern->LockCount<GLOBAL_LOCK_MAX)
1104 pintern->LockCount++;
1105 palloc=pintern->Pointer;
1106 }
1107 else
1108 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001109 WARN("invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001110 palloc=(LPVOID) NULL;
1111 }
1112 /* HeapUnlock(GetProcessHeap()); */;
1113 return palloc;
1114}
1115
1116
1117/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001118 * GlobalUnlock (KERNEL32.332)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001119 * RETURNS
1120 * TRUE: Object is still locked
1121 * FALSE: Object is unlocked
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001122 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001123BOOL WINAPI GlobalUnlock(
1124 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001125) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001126 PGLOBAL32_INTERN pintern;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001127 BOOL locked;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001128
1129 if(ISPOINTER(hmem))
1130 return FALSE;
1131
1132 /* HeapLock(GetProcessHeap()); */
1133 pintern=HANDLE_TO_INTERN(hmem);
1134
1135 if(pintern->Magic==MAGIC_GLOBAL_USED)
1136 {
1137 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
1138 pintern->LockCount--;
1139
1140 locked=(pintern->LockCount==0) ? FALSE : TRUE;
1141 }
1142 else
1143 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001144 WARN("invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001145 locked=FALSE;
1146 }
1147 /* HeapUnlock(GetProcessHeap()); */
1148 return locked;
1149}
1150
1151
1152/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001153 * GlobalHandle (KERNEL32.325)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001154 * Returns the handle associated with the specified pointer.
1155 *
Alexandre Julliard54c27111998-03-29 19:44:57 +00001156 * RETURNS
1157 * Handle: Success
1158 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001159 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001160HGLOBAL WINAPI GlobalHandle(
Alexandre Julliard54c27111998-03-29 19:44:57 +00001161 LPCVOID pmem /* [in] Pointer to global memory block */
1162) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001163 HGLOBAL handle;
Guy Albertelli98679972000-01-15 21:59:12 +00001164 HANDLE heap;
Guy Albertelli4ef64132000-01-23 02:25:11 +00001165 PGLOBAL32_INTERN maybe_intern;
1166 LPCVOID test;
Guy Albertelli98679972000-01-15 21:59:12 +00001167
1168 if (!pmem)
1169 {
Lawson Whitney969515d2000-10-02 22:27:37 +00001170 SetLastError( ERROR_INVALID_PARAMETER );
1171 return 0;
Guy Albertelli98679972000-01-15 21:59:12 +00001172 }
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001173
Lawson Whitney969515d2000-10-02 22:27:37 +00001174 __TRY
1175 {
1176 handle = 0;
Guy Albertelli4ef64132000-01-23 02:25:11 +00001177
Lawson Whitney969515d2000-10-02 22:27:37 +00001178 /* note that if pmem is a pointer to a a block allocated by */
1179 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
1180 /* will fail. */
1181 if (ISPOINTER(pmem)) {
1182 heap = GLOBAL_GetHeap( (HGLOBAL)pmem );
1183 if (HeapValidate( heap, 0, pmem )) {
1184 handle = (HGLOBAL)pmem; /* valid fixed block */
1185 break;
1186 }
1187 handle = POINTER_TO_HANDLE(pmem);
1188 } else
1189 handle = (HGLOBAL)pmem;
1190
1191 /* Now test handle either passed in or retrieved from pointer */
1192 heap = GLOBAL_GetHeap( handle );
1193 maybe_intern = HANDLE_TO_INTERN( handle );
1194 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
1195 test = maybe_intern->Pointer;
1196 if (HeapValidate( heap, 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
1197 HeapValidate( heap, 0, maybe_intern )) /* intern valid arena? */
1198 break; /* valid moveable block */
1199 }
1200 handle = 0;
1201 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard17216f51997-10-12 16:30:17 +00001202 }
Lawson Whitney969515d2000-10-02 22:27:37 +00001203 __EXCEPT(page_fault)
1204 {
1205 SetLastError( ERROR_INVALID_HANDLE );
1206 return 0;
1207 }
1208 __ENDTRY
Alexandre Julliard17216f51997-10-12 16:30:17 +00001209
Lawson Whitney969515d2000-10-02 22:27:37 +00001210 return handle;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001211}
1212
1213
1214/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001215 * GlobalReAlloc (KERNEL32.328)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001216 * RETURNS
1217 * Handle: Success
1218 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001219 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001220HGLOBAL WINAPI GlobalReAlloc(
1221 HGLOBAL hmem, /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001222 DWORD size, /* [in] New size of block */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001223 UINT flags /* [in] How to reallocate object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001224) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001225 LPVOID palloc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001226 HGLOBAL hnew;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001227 PGLOBAL32_INTERN pintern;
Noel Borthwick83579c81999-07-24 12:18:04 +00001228 HANDLE heap = GLOBAL_GetHeap( hmem );
Alexandre Julliardd10ca9c1999-09-04 11:26:56 +00001229 DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001230
Alexandre Julliard02e90081998-01-04 17:49:09 +00001231 hnew = 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001232 /* HeapLock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001233 if(flags & GMEM_MODIFY) /* modify flags */
1234 {
1235 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
1236 {
1237 /* make a fixed block moveable
1238 * actually only NT is able to do this. But it's soo simple
1239 */
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001240 if (hmem == 0)
1241 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001242 ERR("GlobalReAlloc32 with null handle!\n");
Alexandre Julliard0ad42fa1999-01-31 15:04:42 +00001243 SetLastError( ERROR_NOACCESS );
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001244 return 0;
1245 }
Noel Borthwick83579c81999-07-24 12:18:04 +00001246 size=HeapSize(heap, 0, (LPVOID) hmem);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001247 hnew=GlobalAlloc( flags, size);
1248 palloc=GlobalLock(hnew);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001249 memcpy(palloc, (LPVOID) hmem, size);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001250 GlobalUnlock(hnew);
1251 GlobalFree(hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001252 }
1253 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
1254 {
1255 /* change the flags to make our block "discardable" */
1256 pintern=HANDLE_TO_INTERN(hmem);
1257 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
1258 hnew=hmem;
1259 }
1260 else
1261 {
1262 SetLastError(ERROR_INVALID_PARAMETER);
Alexandre Julliard02e90081998-01-04 17:49:09 +00001263 hnew = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001264 }
1265 }
1266 else
1267 {
1268 if(ISPOINTER(hmem))
1269 {
1270 /* reallocate fixed memory */
Alexandre Julliardd10ca9c1999-09-04 11:26:56 +00001271 hnew=(HGLOBAL)HeapReAlloc(heap, heap_flags, (LPVOID) hmem, size);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001272 }
1273 else
1274 {
1275 /* reallocate a moveable block */
1276 pintern=HANDLE_TO_INTERN(hmem);
Ulrich Weigand2e7008c2000-10-19 20:24:25 +00001277
1278#if 0
1279/* Apparently Windows doesn't care whether the handle is locked at this point */
1280/* See also the same comment in GlobalFree() */
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001281 if(pintern->LockCount>1) {
Alexandre Julliard15657091999-05-23 10:25:25 +00001282 ERR("handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001283 SetLastError(ERROR_INVALID_HANDLE);
Ulrich Weigand2e7008c2000-10-19 20:24:25 +00001284 } else
1285#endif
1286 if(size!=0)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001287 {
1288 hnew=hmem;
1289 if(pintern->Pointer)
1290 {
Huw D M Daviesc43fdb72000-04-13 15:57:06 +00001291 if((palloc = HeapReAlloc(heap, heap_flags,
1292 (char *) pintern->Pointer-sizeof(HGLOBAL),
1293 size+sizeof(HGLOBAL))) == NULL)
1294 return 0; /* Block still valid */
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001295 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001296 }
1297 else
1298 {
Huw D M Daviesc43fdb72000-04-13 15:57:06 +00001299 if((palloc=HeapAlloc(heap, heap_flags, size+sizeof(HGLOBAL)))
1300 == NULL)
1301 return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001302 *(HGLOBAL *)palloc=hmem;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001303 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001304 }
1305 }
1306 else
1307 {
1308 if(pintern->Pointer)
1309 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001310 HeapFree(heap, 0, (char *) pintern->Pointer-sizeof(HGLOBAL));
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001311 pintern->Pointer=NULL;
1312 }
1313 }
1314 }
1315 }
Noel Borthwick83579c81999-07-24 12:18:04 +00001316 /* HeapUnlock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001317 return hnew;
1318}
1319
1320
1321/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001322 * GlobalFree (KERNEL32.322)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001323 * RETURNS
1324 * NULL: Success
1325 * Handle: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001326 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001327HGLOBAL WINAPI GlobalFree(
1328 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001329) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001330 PGLOBAL32_INTERN pintern;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001331 HGLOBAL hreturned = 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001332 HANDLE heap = GLOBAL_GetHeap( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001333
1334 if(ISPOINTER(hmem)) /* POINTER */
1335 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001336 if(!HeapFree(heap, 0, (LPVOID) hmem)) hmem = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001337 }
1338 else /* HANDLE */
1339 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001340 /* HeapLock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001341 pintern=HANDLE_TO_INTERN(hmem);
1342
1343 if(pintern->Magic==MAGIC_GLOBAL_USED)
1344 {
Guy Albertelli4ef64132000-01-23 02:25:11 +00001345
1346/* WIN98 does not make this test. That is you can free a */
1347/* block you have not unlocked. Go figure!! */
1348 /* if(pintern->LockCount!=0) */
1349 /* SetLastError(ERROR_INVALID_HANDLE); */
1350
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001351 if(pintern->Pointer)
Noel Borthwick83579c81999-07-24 12:18:04 +00001352 if(!HeapFree(heap, 0,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001353 (char *)(pintern->Pointer)-sizeof(HGLOBAL)))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001354 hreturned=hmem;
Noel Borthwick83579c81999-07-24 12:18:04 +00001355 if(!HeapFree(heap, 0, pintern))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001356 hreturned=hmem;
1357 }
Noel Borthwick83579c81999-07-24 12:18:04 +00001358 /* HeapUnlock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001359 }
1360 return hreturned;
1361}
1362
1363
1364/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001365 * GlobalSize (KERNEL32.329)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001366 * RETURNS
1367 * Size in bytes of the global memory object
1368 * 0: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001369 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001370DWORD WINAPI GlobalSize(
1371 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001372) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001373 DWORD retval;
1374 PGLOBAL32_INTERN pintern;
Noel Borthwick83579c81999-07-24 12:18:04 +00001375 HANDLE heap = GLOBAL_GetHeap( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001376
1377 if(ISPOINTER(hmem))
1378 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001379 retval=HeapSize(heap, 0, (LPVOID) hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001380 }
1381 else
1382 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001383 /* HeapLock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001384 pintern=HANDLE_TO_INTERN(hmem);
1385
1386 if(pintern->Magic==MAGIC_GLOBAL_USED)
1387 {
Guy Albertelli3db8e191999-02-14 17:38:24 +00001388 if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
1389 return 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001390 retval=HeapSize(heap, 0,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001391 (char *)(pintern->Pointer)-sizeof(HGLOBAL))-4;
Rein Klazeseaec1ee1999-07-11 13:50:24 +00001392 if (retval == 0xffffffff-4) retval = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001393 }
1394 else
1395 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001396 WARN("invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001397 retval=0;
1398 }
Noel Borthwick83579c81999-07-24 12:18:04 +00001399 /* HeapUnlock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001400 }
Guy Albertelli3db8e191999-02-14 17:38:24 +00001401 /* HeapSize returns 0xffffffff on failure */
1402 if (retval == 0xffffffff) retval = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001403 return retval;
1404}
1405
1406
1407/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001408 * GlobalWire (KERNEL32.333)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001409 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001410LPVOID WINAPI GlobalWire(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001411{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001412 return GlobalLock( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001413}
1414
1415
1416/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001417 * GlobalUnWire (KERNEL32.330)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001418 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001419BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001420{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001421 return GlobalUnlock( hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001422}
1423
1424
1425/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001426 * GlobalFix (KERNEL32.320)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001427 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001428VOID WINAPI GlobalFix(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001429{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001430 GlobalLock( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001431}
1432
1433
1434/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001435 * GlobalUnfix (KERNEL32.331)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001436 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001437VOID WINAPI GlobalUnfix(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001438{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001439 GlobalUnlock( hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001440}
1441
1442
1443/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001444 * GlobalFlags (KERNEL32.321)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001445 * Returns information about the specified global memory object
1446 *
1447 * NOTES
1448 * Should this return GMEM_INVALID_HANDLE on invalid handle?
1449 *
1450 * RETURNS
1451 * Value specifying allocation flags and lock count
1452 * GMEM_INVALID_HANDLE: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001453 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001454UINT WINAPI GlobalFlags(
1455 HGLOBAL hmem /* [in] Handle to global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001456) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001457 DWORD retval;
1458 PGLOBAL32_INTERN pintern;
1459
1460 if(ISPOINTER(hmem))
1461 {
1462 retval=0;
1463 }
1464 else
1465 {
1466 /* HeapLock(GetProcessHeap()); */
1467 pintern=HANDLE_TO_INTERN(hmem);
1468 if(pintern->Magic==MAGIC_GLOBAL_USED)
1469 {
1470 retval=pintern->LockCount + (pintern->Flags<<8);
1471 if(pintern->Pointer==0)
1472 retval|= GMEM_DISCARDED;
1473 }
1474 else
1475 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001476 WARN("Invalid handle: %04x", hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001477 retval=0;
1478 }
1479 /* HeapUnlock(GetProcessHeap()); */
1480 }
1481 return retval;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001482}
1483
1484
1485/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001486 * GlobalCompact (KERNEL32.316)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001487 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001488DWORD WINAPI GlobalCompact( DWORD minfree )
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001489{
1490 return 0; /* GlobalCompact does nothing in Win32 */
1491}
1492
1493
1494/***********************************************************************
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001495 * GlobalMemoryStatus (KERNEL32.327)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001496 * RETURNS
1497 * None
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001498 */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001499VOID WINAPI GlobalMemoryStatus(
1500 LPMEMORYSTATUS lpmem
1501) {
Marcus Meissner6189c192000-03-04 19:19:15 +00001502 static MEMORYSTATUS cached_memstatus;
1503 static int cache_lastchecked = 0;
Francois Gougetea5924c2000-10-28 00:34:29 +00001504 SYSTEM_INFO si;
Patrik Stridvall7e9913f2000-03-08 18:25:22 +00001505#ifdef linux
Marcus Meissner6189c192000-03-04 19:19:15 +00001506 FILE *f;
Patrik Stridvall7e9913f2000-03-08 18:25:22 +00001507#endif
Marcus Meissner6189c192000-03-04 19:19:15 +00001508
1509 if (time(NULL)==cache_lastchecked) {
1510 memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
1511 return;
1512 }
1513 cache_lastchecked = time(NULL);
1514
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001515#ifdef linux
Marcus Meissner6189c192000-03-04 19:19:15 +00001516 f = fopen( "/proc/meminfo", "r" );
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001517 if (f)
1518 {
1519 char buffer[256];
Stephen Crowley59c4a321998-11-24 20:41:02 +00001520 int total, used, free, shared, buffers, cached;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001521
Stephen Crowley59c4a321998-11-24 20:41:02 +00001522 lpmem->dwLength = sizeof(MEMORYSTATUS);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001523 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
1524 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
1525 while (fgets( buffer, sizeof(buffer), f ))
1526 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001527 /* old style /proc/meminfo ... */
Stephen Crowley59c4a321998-11-24 20:41:02 +00001528 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001529 {
1530 lpmem->dwTotalPhys += total;
Stephen Crowley59c4a321998-11-24 20:41:02 +00001531 lpmem->dwAvailPhys += free + buffers + cached;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001532 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001533 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001534 {
1535 lpmem->dwTotalPageFile += total;
1536 lpmem->dwAvailPageFile += free;
1537 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001538
1539 /* new style /proc/meminfo ... */
1540 if (sscanf(buffer, "MemTotal: %d", &total))
1541 lpmem->dwTotalPhys = total*1024;
1542 if (sscanf(buffer, "MemFree: %d", &free))
1543 lpmem->dwAvailPhys = free*1024;
1544 if (sscanf(buffer, "SwapTotal: %d", &total))
1545 lpmem->dwTotalPageFile = total*1024;
1546 if (sscanf(buffer, "SwapFree: %d", &free))
1547 lpmem->dwAvailPageFile = free*1024;
Stephen Crowley59c4a321998-11-24 20:41:02 +00001548 if (sscanf(buffer, "Buffers: %d", &buffers))
1549 lpmem->dwAvailPhys += buffers*1024;
1550 if (sscanf(buffer, "Cached: %d", &cached))
1551 lpmem->dwAvailPhys += cached*1024;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001552 }
1553 fclose( f );
1554
1555 if (lpmem->dwTotalPhys)
1556 {
Francois Gougetea5924c2000-10-28 00:34:29 +00001557 DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
1558 DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
1559 lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
1560 / (TotalPhysical / 100);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001561 }
Marcus Meissnerfddbcf32000-03-07 12:24:58 +00001562 } else
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001563#endif
Marcus Meissnerfddbcf32000-03-07 12:24:58 +00001564 {
1565 /* FIXME: should do something for other systems */
1566 lpmem->dwMemoryLoad = 0;
1567 lpmem->dwTotalPhys = 16*1024*1024;
1568 lpmem->dwAvailPhys = 16*1024*1024;
1569 lpmem->dwTotalPageFile = 16*1024*1024;
1570 lpmem->dwAvailPageFile = 16*1024*1024;
Marcus Meissnerfddbcf32000-03-07 12:24:58 +00001571 }
Francois Gougetea5924c2000-10-28 00:34:29 +00001572 GetSystemInfo(&si);
1573 lpmem->dwTotalVirtual = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
1574 /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
1575 lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
Marcus Meissnerfddbcf32000-03-07 12:24:58 +00001576 memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001577}
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001578
Alexandre Julliard4220b291999-07-11 17:20:01 +00001579/***********************************************************************
1580 * A20Proc16 (KERNEL.165)
1581 */
1582void WINAPI A20Proc16( WORD unused )
1583{
1584 /* this is also a NOP in Windows */
1585}
1586
1587/***********************************************************************
1588 * LimitEMSPages16 (KERNEL.156)
1589 */
1590DWORD WINAPI LimitEMSPages16( DWORD unused )
1591{
1592 return 0;
1593}