blob: 91b3fd5c770f0e24f6e2ca06403e7ebd555b42de [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
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000019 */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000020/* 0xffff sometimes seems to mean: CURRENT_DS */
Alexandre Julliard121bd981993-07-08 17:37:25 +000021
François Gouget14259412001-11-06 20:57:11 +000022#include "config.h"
Francois Gouget386cf6e2001-10-14 16:25:47 +000023#include "wine/port.h"
24
Alexandre Julliard808cb041995-08-17 17:11:36 +000025#include <sys/types.h>
Alexandre Julliard121bd981993-07-08 17:37:25 +000026#include <stdlib.h>
Marcus Meissner6189c192000-03-04 19:19:15 +000027#include <time.h>
Alexandre Julliard383da682000-02-10 22:15:21 +000028#include <stdio.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000029#ifdef HAVE_UNISTD_H
30# include <unistd.h>
31#endif
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000032#include <string.h>
Bang Jun-Young17eb1692002-07-25 23:57:34 +000033#ifdef HAVE_SYS_PARAM_H
34#include <sys/param.h>
35#endif
Olivier Houchardf41ecf32002-05-07 01:50:02 +000036#ifdef HAVE_SYS_SYSCTL_H
37#include <sys/sysctl.h>
38#endif
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000039
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000040#include "wine/winbase16.h"
Lawson Whitney969515d2000-10-02 22:27:37 +000041#include "wine/exception.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000042#include "global.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000043#include "toolhelp.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000044#include "selectors.h"
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000045#include "miscemu.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000046#include "stackframe.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000047#include "wine/debug.h"
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000048#include "winerror.h"
Dimitrie O. Paun737d4be2002-12-12 23:34:01 +000049#include "excpt.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000050
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000051WINE_DEFAULT_DEBUG_CHANNEL(global);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000052
Alexandre Julliardfa68b751995-04-03 16:55:37 +000053 /* Global arena block */
54typedef struct
55{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000056 DWORD base; /* Base address (0 if discarded) */
57 DWORD size; /* Size in bytes (0 indicates a free block) */
58 HGLOBAL16 handle; /* Handle for this block */
59 HGLOBAL16 hOwner; /* Owner of this block */
60 BYTE lockCount; /* Count of GlobalFix() calls */
61 BYTE pageLockCount; /* Count of GlobalPageLock() calls */
62 BYTE flags; /* Allocation flags */
63 BYTE selCount; /* Number of selectors allocated for this block */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000064} GLOBALARENA;
65
66 /* Flags definitions */
Alexandre Julliard2787be81995-05-22 18:23:01 +000067#define GA_MOVEABLE 0x02 /* same as GMEM_MOVEABLE */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000068#define GA_DGROUP 0x04
69#define GA_DISCARDABLE 0x08
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000070#define GA_IPCSHARE 0x10 /* same as GMEM_DDESHARE */
Andreas Mohrd23f5062000-10-02 22:16:21 +000071#define GA_DOSMEM 0x20
Alexandre Julliardfa68b751995-04-03 16:55:37 +000072
73 /* Arena array */
74static GLOBALARENA *pGlobalArena = NULL;
75static int globalArenaSize = 0;
76
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000077#define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
Alexandre Julliard121bd981993-07-08 17:37:25 +000078
Alexandre Julliarda11d7b11998-03-01 20:05:02 +000079#define VALID_HANDLE(handle) (((handle)>>__AHSHIFT)<globalArenaSize)
Alexandre Julliardfa68b751995-04-03 16:55:37 +000080#define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
Alexandre Julliard75a839a1993-07-15 11:13:45 +000081
Lawson Whitney969515d2000-10-02 22:27:37 +000082/* filter for page-fault exceptions */
83/* It is possible for a bogus global pointer to cause a */
84/* page zero reference, so I include EXCEPTION_PRIV_INSTRUCTION too. */
85
86static WINE_EXCEPTION_FILTER(page_fault)
87{
88 switch (GetExceptionCode()) {
89 case (EXCEPTION_ACCESS_VIOLATION):
90 case (EXCEPTION_PRIV_INSTRUCTION):
91 return EXCEPTION_EXECUTE_HANDLER;
92 default:
93 return EXCEPTION_CONTINUE_SEARCH;
94 }
95}
96
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000097/***********************************************************************
Alexandre Julliardfa68b751995-04-03 16:55:37 +000098 * GLOBAL_GetArena
99 *
100 * Return the arena for a given selector, growing the arena array if needed.
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000101 */
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000102static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000103{
Alexandre Julliard2787be81995-05-22 18:23:01 +0000104 if (((sel >> __AHSHIFT) + selcount) > globalArenaSize)
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000105 {
Alexandre Julliard2787be81995-05-22 18:23:01 +0000106 int newsize = ((sel >> __AHSHIFT) + selcount + 0xff) & ~0xff;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000107 GLOBALARENA *pNewArena = realloc( pGlobalArena,
Alexandre Julliard2787be81995-05-22 18:23:01 +0000108 newsize * sizeof(GLOBALARENA) );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000109 if (!pNewArena) return 0;
110 pGlobalArena = pNewArena;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000111 memset( pGlobalArena + globalArenaSize, 0,
112 (newsize - globalArenaSize) * sizeof(GLOBALARENA) );
113 globalArenaSize = newsize;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000114 }
115 return pGlobalArena + (sel >> __AHSHIFT);
116}
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000117
Juergen Schmiedebc2b771998-11-14 18:59:30 +0000118void debug_handles(void)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000119{
120 int printed=0;
121 int i;
122 for (i = globalArenaSize-1 ; i>=0 ; i--) {
123 if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
124 printed=1;
Alexandre Julliard15657091999-05-23 10:25:25 +0000125 DPRINTF("0x%08x, ",pGlobalArena[i].handle);
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000126 }
127 }
128 if (printed)
Alexandre Julliard15657091999-05-23 10:25:25 +0000129 DPRINTF("\n");
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000130}
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000131
132
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000133/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000134 * GLOBAL_CreateBlock
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000135 *
Alexandre Julliard594997c1995-04-30 10:05:20 +0000136 * Create a global heap block for a fixed range of linear memory.
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000137 */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000138HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
Alexandre Julliard914406f2000-11-14 01:54:49 +0000139 HGLOBAL16 hOwner, unsigned char selflags )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000140{
141 WORD sel, selcount;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000142 GLOBALARENA *pArena;
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000143
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000144 /* Allocate the selector(s) */
145
Alexandre Julliard914406f2000-11-14 01:54:49 +0000146 sel = SELECTOR_AllocBlock( ptr, size, selflags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000147 if (!sel) return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000148 selcount = (size + 0xffff) / 0x10000;
149
150 if (!(pArena = GLOBAL_GetArena( sel, selcount )))
151 {
Alexandre Julliard914406f2000-11-14 01:54:49 +0000152 SELECTOR_FreeBlock( sel );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000153 return 0;
154 }
155
156 /* Fill the arena block */
157
158 pArena->base = (DWORD)ptr;
Alexandre Julliard8c540c62000-11-13 04:16:05 +0000159 pArena->size = GetSelectorLimit16(sel) + 1;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000160 pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000161 pArena->hOwner = hOwner;
162 pArena->lockCount = 0;
163 pArena->pageLockCount = 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000164 pArena->flags = flags & GA_MOVEABLE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000165 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000166 if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000167 if (!(selflags & (WINE_LDT_FLAGS_CODE^WINE_LDT_FLAGS_DATA))) pArena->flags |= GA_DGROUP;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000168 pArena->selCount = selcount;
169 if (selcount > 1) /* clear the next arena blocks */
170 memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000171
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000172 return pArena->handle;
173}
Alexandre Julliard121bd981993-07-08 17:37:25 +0000174
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000175
176/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000177 * GLOBAL_FreeBlock
178 *
179 * Free a block allocated by GLOBAL_CreateBlock, without touching
180 * the associated linear memory range.
181 */
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000182BOOL16 GLOBAL_FreeBlock( HGLOBAL16 handle )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000183{
184 WORD sel;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000185 GLOBALARENA *pArena;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000186
187 if (!handle) return TRUE;
Vincent Béron9a624912002-05-31 23:06:46 +0000188 sel = GlobalHandleToSel16( handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000189 if (!VALID_HANDLE(sel))
190 return FALSE;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000191 pArena = GET_ARENA_PTR(sel);
Alexandre Julliard914406f2000-11-14 01:54:49 +0000192 SELECTOR_FreeBlock( sel );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000193 memset( pArena, 0, sizeof(GLOBALARENA) );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000194 return TRUE;
195}
196
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000197/***********************************************************************
198 * GLOBAL_MoveBlock
199 */
200BOOL16 GLOBAL_MoveBlock( HGLOBAL16 handle, const void *ptr, DWORD size )
201{
202 WORD sel;
203 GLOBALARENA *pArena;
204
205 if (!handle) return TRUE;
Vincent Béron9a624912002-05-31 23:06:46 +0000206 sel = GlobalHandleToSel16( handle );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000207 if (!VALID_HANDLE(sel))
208 return FALSE;
209 pArena = GET_ARENA_PTR(sel);
210 if (pArena->selCount != 1)
211 return FALSE;
212
213 pArena->base = (DWORD)ptr;
214 pArena->size = size;
Alexandre Julliard914406f2000-11-14 01:54:49 +0000215 SELECTOR_ReallocBlock( sel, ptr, size );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000216 return TRUE;
217}
Alexandre Julliard594997c1995-04-30 10:05:20 +0000218
219/***********************************************************************
220 * GLOBAL_Alloc
221 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000222 * Implementation of GlobalAlloc16()
Alexandre Julliard594997c1995-04-30 10:05:20 +0000223 */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000224HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner, unsigned char selflags )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000225{
226 void *ptr;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000227 HGLOBAL16 handle;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000228
Alexandre Julliard15657091999-05-23 10:25:25 +0000229 TRACE("%ld flags=%04x\n", size, flags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000230
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000231 /* If size is 0, create a discarded block */
232
Alexandre Julliard914406f2000-11-14 01:54:49 +0000233 if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, selflags );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000234
235 /* Fixup the size */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000236
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000237 if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000238 size = (size + 0x1f) & ~0x1f;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000239
Marcus Meissnere32a3171999-07-11 14:13:56 +0000240 /* Allocate the linear memory */
Alexandre Julliard079fd722000-01-25 01:41:35 +0000241 ptr = HeapAlloc( GetProcessHeap(), 0, size );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000242 /* FIXME: free discardable blocks and try again? */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000243 if (!ptr) return 0;
244
245 /* Allocate the selector(s) */
246
Alexandre Julliard914406f2000-11-14 01:54:49 +0000247 handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner, selflags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000248 if (!handle)
249 {
Alexandre Julliard079fd722000-01-25 01:41:35 +0000250 HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000251 return 0;
252 }
253
254 if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
255 return handle;
256}
257
Alexandre Julliard594997c1995-04-30 10:05:20 +0000258/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000259 * GlobalAlloc (KERNEL.15)
260 * GlobalAlloc16 (KERNEL32.24)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000261 * RETURNS
262 * Handle: Success
263 * NULL: Failure
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000264 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000265HGLOBAL16 WINAPI GlobalAlloc16(
266 UINT16 flags, /* [in] Object allocation attributes */
267 DWORD size /* [in] Number of bytes to allocate */
268) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000269 HANDLE16 owner = GetCurrentPDB16();
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000270
Alexandre Julliard594997c1995-04-30 10:05:20 +0000271 if (flags & GMEM_DDESHARE)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000272 owner = GetExePtr(owner); /* Make it a module handle */
Alexandre Julliard914406f2000-11-14 01:54:49 +0000273 return GLOBAL_Alloc( flags, size, owner, WINE_LDT_FLAGS_DATA );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000274}
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000275
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000276
277/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000278 * GlobalReAlloc (KERNEL.16)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000279 * RETURNS
280 * Handle: Success
281 * NULL: Failure
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000282 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000283HGLOBAL16 WINAPI GlobalReAlloc16(
284 HGLOBAL16 handle, /* [in] Handle of global memory object */
285 DWORD size, /* [in] New size of block */
286 UINT16 flags /* [in] How to reallocate object */
287) {
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000288 WORD selcount;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000289 DWORD oldsize;
Uwe Bonnes97888152001-12-20 00:00:25 +0000290 void *ptr, *newptr;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000291 GLOBALARENA *pArena, *pNewArena;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000292 WORD sel = GlobalHandleToSel16( handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000293
Alexandre Julliard15657091999-05-23 10:25:25 +0000294 TRACE("%04x %ld flags=%04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000295 handle, size, flags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000296 if (!handle) return 0;
Vincent Béron9a624912002-05-31 23:06:46 +0000297
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000298 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000299 WARN("Invalid handle 0x%04x!\n", handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000300 return 0;
301 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000302 pArena = GET_ARENA_PTR( handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000303
Alexandre Julliard2787be81995-05-22 18:23:01 +0000304 /* Discard the block if requested */
305
Alexandre Julliardded30381995-07-06 17:18:27 +0000306 if ((size == 0) && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY))
Alexandre Julliard2787be81995-05-22 18:23:01 +0000307 {
308 if (!(pArena->flags & GA_MOVEABLE) ||
309 !(pArena->flags & GA_DISCARDABLE) ||
310 (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
Alexandre Julliard079fd722000-01-25 01:41:35 +0000311 HeapFree( GetProcessHeap(), 0, (void *)pArena->base );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000312 pArena->base = 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000313
Vincent Béron9a624912002-05-31 23:06:46 +0000314 /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
Alexandre Julliard77b99181997-09-14 17:17:23 +0000315 * change the selector if we are shrinking the block.
316 * FIXME: shouldn't we keep selectors until the block is deleted?
317 */
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000318 SELECTOR_ReallocBlock( sel, 0, 1 );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000319 return handle;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000320 }
321
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000322 /* Fixup the size */
323
Alexandre Julliard2787be81995-05-22 18:23:01 +0000324 if (size > GLOBAL_MAX_ALLOC_SIZE - 0x20) return 0;
325 if (size == 0) size = 0x20;
326 else size = (size + 0x1f) & ~0x1f;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000327
Alexandre Julliard594997c1995-04-30 10:05:20 +0000328 /* Change the flags */
329
330 if (flags & GMEM_MODIFY)
331 {
332 /* Change the flags, leaving GA_DGROUP alone */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000333 pArena->flags = (pArena->flags & GA_DGROUP) | (flags & GA_MOVEABLE);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000334 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
335 return handle;
336 }
337
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000338 /* Reallocate the linear memory */
339
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000340 ptr = (void *)pArena->base;
341 oldsize = pArena->size;
Uwe Bonnes97888152001-12-20 00:00:25 +0000342 TRACE("oldbase %p oldsize %08lx newsize %08lx\n", ptr,oldsize,size);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +0000343 if (ptr && (size == oldsize)) return handle; /* Nothing to do */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000344
Andreas Mohrd23f5062000-10-02 22:16:21 +0000345 if (pArena->flags & GA_DOSMEM)
Uwe Bonnes97888152001-12-20 00:00:25 +0000346 newptr = DOSMEM_ResizeBlock(ptr, size, NULL);
Bertho Stultiensc1d1cfe1999-04-18 12:14:06 +0000347 else
Uwe Bonnes97888152001-12-20 00:00:25 +0000348 /* if more then one reader (e.g. some pointer has been given out by GetVDMPointer32W16),
349 only try to realloc in place */
350 newptr = HeapReAlloc( GetProcessHeap(),
351 (pArena->pageLockCount > 0)?HEAP_REALLOC_IN_PLACE_ONLY:0, ptr, size );
352 if (!newptr)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000353 {
Uwe Bonnes97888152001-12-20 00:00:25 +0000354 FIXME("Realloc failed lock %d\n",pArena->pageLockCount);
355 if (pArena->pageLockCount <1)
356 {
357 HeapFree( GetProcessHeap(), 0, ptr );
358 SELECTOR_FreeBlock( sel );
359 memset( pArena, 0, sizeof(GLOBALARENA) );
360 }
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000361 return 0;
362 }
Uwe Bonnes97888152001-12-20 00:00:25 +0000363 ptr = newptr;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000364
365 /* Reallocate the selector(s) */
366
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000367 sel = SELECTOR_ReallocBlock( sel, ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000368 if (!sel)
369 {
Alexandre Julliard079fd722000-01-25 01:41:35 +0000370 HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000371 memset( pArena, 0, sizeof(GLOBALARENA) );
372 return 0;
373 }
374 selcount = (size + 0xffff) / 0x10000;
375
376 if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
377 {
Alexandre Julliard079fd722000-01-25 01:41:35 +0000378 HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliard914406f2000-11-14 01:54:49 +0000379 SELECTOR_FreeBlock( sel );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000380 return 0;
381 }
382
Vincent Béron9a624912002-05-31 23:06:46 +0000383 /* Fill the new arena block
Uwe Bonnes97888152001-12-20 00:00:25 +0000384 As we may have used HEAP_REALLOC_IN_PLACE_ONLY, areas may overlap*/
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000385
Uwe Bonnes97888152001-12-20 00:00:25 +0000386 if (pNewArena != pArena) memmove( pNewArena, pArena, sizeof(GLOBALARENA) );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000387 pNewArena->base = (DWORD)ptr;
Alexandre Julliard8c540c62000-11-13 04:16:05 +0000388 pNewArena->size = GetSelectorLimit16(sel) + 1;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000389 pNewArena->selCount = selcount;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000390 pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000391
392 if (selcount > 1) /* clear the next arena blocks */
393 memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
394
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000395 if ((oldsize < size) && (flags & GMEM_ZEROINIT))
396 memset( (char *)ptr + oldsize, 0, size - oldsize );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000397 return pNewArena->handle;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000398}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000399
400
401/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000402 * GlobalFree (KERNEL.17)
403 * GlobalFree16 (KERNEL32.31)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000404 * RETURNS
405 * NULL: Success
406 * Handle: Failure
Alexandre Julliard121bd981993-07-08 17:37:25 +0000407 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000408HGLOBAL16 WINAPI GlobalFree16(
409 HGLOBAL16 handle /* [in] Handle of global memory object */
410) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000411 void *ptr;
Alexandre Julliard121bd981993-07-08 17:37:25 +0000412
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000413 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000414 WARN("Invalid handle 0x%04x passed to GlobalFree16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000415 return 0;
416 }
417 ptr = (void *)GET_ARENA_PTR(handle)->base;
418
Alexandre Julliard15657091999-05-23 10:25:25 +0000419 TRACE("%04x\n", handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000420 if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
Alexandre Julliard079fd722000-01-25 01:41:35 +0000421 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000422 return 0;
423}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000424
425
426/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000427 * GlobalLock (KERNEL.18)
Alexandre Julliard121bd981993-07-08 17:37:25 +0000428 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000429 * This is the GlobalLock16() function used by 16-bit code.
Alexandre Julliard121bd981993-07-08 17:37:25 +0000430 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000431SEGPTR WINAPI WIN16_GlobalLock16( HGLOBAL16 handle )
Alexandre Julliard121bd981993-07-08 17:37:25 +0000432{
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000433 WORD sel = GlobalHandleToSel16( handle );
434 TRACE("(%04x) -> %08lx\n", handle, MAKELONG( 0, sel ) );
435
Alexandre Julliard77b99181997-09-14 17:17:23 +0000436 if (handle)
437 {
438 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000439
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000440 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000441 WARN("Invalid handle 0x%04x passed to WIN16_GlobalLock16!\n",handle);
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000442 sel = 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000443 }
Vincent Béron9a624912002-05-31 23:06:46 +0000444 else if (!GET_ARENA_PTR(handle)->base)
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000445 sel = 0;
446 else
447 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000448 }
Ulrich Weigandb2682d41999-07-27 16:10:24 +0000449
450 CURRENT_STACK16->ecx = sel; /* selector must be returned in CX as well */
Alexandre Julliard982a2232000-12-13 20:20:09 +0000451 return MAKESEGPTR( sel, 0 );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000452}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000453
454
Alexandre Julliard58017232000-12-22 01:09:26 +0000455/**********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000456 * K32WOWGlobalLock16 (KERNEL32.60)
Alexandre Julliard58017232000-12-22 01:09:26 +0000457 */
458SEGPTR WINAPI K32WOWGlobalLock16( HGLOBAL16 hMem )
459{
460 return WIN16_GlobalLock16( hMem );
461}
462
463
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000464/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000465 * GlobalLock16 (KERNEL32.25)
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000466 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000467 * This is the GlobalLock16() function used by 32-bit code.
Vincent Béron9a624912002-05-31 23:06:46 +0000468 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000469 * RETURNS
470 * Pointer to first byte of memory block
471 * NULL: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000472 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000473LPVOID WINAPI GlobalLock16(
474 HGLOBAL16 handle /* [in] Handle of global memory object */
475) {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000476 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000477 if (!VALID_HANDLE(handle))
478 return (LPVOID)0;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000479 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000480 return (LPVOID)GET_ARENA_PTR(handle)->base;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000481}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000482
483
484/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000485 * GlobalUnlock (KERNEL.19)
486 * GlobalUnlock16 (KERNEL32.26)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000487 * NOTES
488 * Should the return values be cast to booleans?
489 *
490 * RETURNS
491 * TRUE: Object is still locked
492 * FALSE: Object is unlocked
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000493 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000494BOOL16 WINAPI GlobalUnlock16(
495 HGLOBAL16 handle /* [in] Handle of global memory object */
496) {
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000497 GLOBALARENA *pArena = GET_ARENA_PTR(handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000498 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000499 WARN("Invalid handle 0x%04x passed to GlobalUnlock16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000500 return 0;
501 }
Alexandre Julliard15657091999-05-23 10:25:25 +0000502 TRACE("%04x\n", handle );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000503 if (pArena->lockCount) pArena->lockCount--;
504 return pArena->lockCount;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000505}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000506
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000507/***********************************************************************
508 * GlobalChangeLockCount (KERNEL.365)
509 *
510 * This is declared as a register function as it has to preserve
511 * *all* registers, even AX/DX !
512 *
513 */
Ulrich Weigandb5151d01999-07-25 11:27:36 +0000514void WINAPI GlobalChangeLockCount16( HGLOBAL16 handle, INT16 delta,
515 CONTEXT86 *context )
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000516{
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000517 if ( delta == 1 )
518 GlobalLock16( handle );
519 else if ( delta == -1 )
520 GlobalUnlock16( handle );
521 else
Alexandre Julliard15657091999-05-23 10:25:25 +0000522 ERR("(%04X, %d): strange delta value\n", handle, delta );
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000523}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000524
525/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000526 * GlobalSize (KERNEL.20)
527 * GlobalSize16 (KERNEL32.32)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000528 * RETURNS
529 * Size in bytes of object
530 * 0: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000531 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000532DWORD WINAPI GlobalSize16(
533 HGLOBAL16 handle /* [in] Handle of global memory object */
534) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000535 TRACE("%04x\n", handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000536 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000537 if (!VALID_HANDLE(handle))
538 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000539 return GET_ARENA_PTR(handle)->size;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000540}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000541
542
543/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000544 * GlobalHandle (KERNEL.21)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000545 * NOTES
546 * Why is GlobalHandleToSel used here with the sel as input?
547 *
548 * RETURNS
549 * Handle: Success
550 * NULL: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000551 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000552DWORD WINAPI GlobalHandle16(
553 WORD sel /* [in] Address of global memory block */
554) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000555 TRACE("%04x\n", sel );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000556 if (!VALID_HANDLE(sel)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000557 WARN("Invalid handle 0x%04x passed to GlobalHandle16!\n",sel);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000558 return 0;
559 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000560 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel16(sel) );
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000561}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000562
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000563/***********************************************************************
564 * GlobalHandleNoRIP (KERNEL.159)
565 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000566DWORD WINAPI GlobalHandleNoRIP16( WORD sel )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000567{
568 int i;
569 for (i = globalArenaSize-1 ; i>=0 ; i--) {
570 if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == sel)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000571 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel16(sel) );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000572 }
573 return 0;
574}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000575
Alexandre Julliard54c27111998-03-29 19:44:57 +0000576
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000577/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000578 * GlobalFlags (KERNEL.22)
Patrik Stridvallb5bb32c2002-09-24 18:29:39 +0000579 *
Alexandre Julliard54c27111998-03-29 19:44:57 +0000580 * NOTES
581 * Should this return GMEM_INVALID_HANDLE instead of 0 on invalid
582 * handle?
583 *
584 * RETURNS
585 * Value specifying flags and lock count
586 * GMEM_INVALID_HANDLE: Invalid handle
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000587 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000588UINT16 WINAPI GlobalFlags16(
589 HGLOBAL16 handle /* [in] Handle of global memory object */
590) {
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000591 GLOBALARENA *pArena;
592
Alexandre Julliard15657091999-05-23 10:25:25 +0000593 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000594 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000595 WARN("Invalid handle 0x%04x passed to GlobalFlags16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000596 return 0;
597 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000598 pArena = GET_ARENA_PTR(handle);
599 return pArena->lockCount |
Alexandre Julliard2787be81995-05-22 18:23:01 +0000600 ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0) |
601 ((pArena->base == 0) ? GMEM_DISCARDED : 0);
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000602}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000603
604
605/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000606 * LockSegment (KERNEL.23)
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000607 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000608HGLOBAL16 WINAPI LockSegment16( HGLOBAL16 handle )
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000609{
Alexandre Julliard15657091999-05-23 10:25:25 +0000610 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000611 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000612 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000613 WARN("Invalid handle 0x%04x passed to LockSegment16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000614 return 0;
615 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000616 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000617 return handle;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000618}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000619
620
621/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000622 * UnlockSegment (KERNEL.24)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000623 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000624void WINAPI UnlockSegment16( HGLOBAL16 handle )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000625{
Alexandre Julliard15657091999-05-23 10:25:25 +0000626 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000627 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000628 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000629 WARN("Invalid handle 0x%04x passed to UnlockSegment16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000630 return;
631 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000632 GET_ARENA_PTR(handle)->lockCount--;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000633 /* FIXME: this ought to return the lock count in CX (go figure...) */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000634}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000635
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000636
637/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000638 * GlobalCompact (KERNEL.25)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000639 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000640DWORD WINAPI GlobalCompact16( DWORD desired )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000641{
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000642 return GLOBAL_MAX_ALLOC_SIZE;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000643}
644
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000645
646/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000647 * GlobalFreeAll (KERNEL.26)
648 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000649void WINAPI GlobalFreeAll16( HGLOBAL16 owner )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000650{
651 DWORD i;
652 GLOBALARENA *pArena;
653
654 pArena = pGlobalArena;
655 for (i = 0; i < globalArenaSize; i++, pArena++)
656 {
657 if ((pArena->size != 0) && (pArena->hOwner == owner))
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000658 GlobalFree16( pArena->handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000659 }
660}
661
662
663/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000664 * GlobalWire (KERNEL.111)
665 * GlobalWire16 (KERNEL32.29)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000666 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000667SEGPTR WINAPI GlobalWire16( HGLOBAL16 handle )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000668{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000669 return WIN16_GlobalLock16( handle );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000670}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000671
672
673/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000674 * GlobalUnWire (KERNEL.112)
675 * GlobalUnWire16 (KERNEL32.30)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000676 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000677BOOL16 WINAPI GlobalUnWire16( HGLOBAL16 handle )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000678{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000679 return !GlobalUnlock16( handle );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000680}
Alexandre Julliardaca05781994-10-17 18:12:41 +0000681
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000682
683/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000684 * SetSwapAreaSize (KERNEL.106)
Alexandre Julliardaca05781994-10-17 18:12:41 +0000685 */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000686LONG WINAPI SetSwapAreaSize16( WORD size )
Alexandre Julliardaca05781994-10-17 18:12:41 +0000687{
Alexandre Julliard15657091999-05-23 10:25:25 +0000688 FIXME("(%d) - stub!\n", size );
Alexandre Julliardaca05781994-10-17 18:12:41 +0000689 return MAKELONG( size, 0xffff );
690}
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000691
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000692
693/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000694 * GlobalLRUOldest (KERNEL.163)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000695 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000696HGLOBAL16 WINAPI GlobalLRUOldest16( HGLOBAL16 handle )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000697{
Alexandre Julliard15657091999-05-23 10:25:25 +0000698 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000699 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000700 return handle;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000701}
702
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000703
704/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000705 * GlobalLRUNewest (KERNEL.164)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000706 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000707HGLOBAL16 WINAPI GlobalLRUNewest16( HGLOBAL16 handle )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000708{
Alexandre Julliard15657091999-05-23 10:25:25 +0000709 TRACE("%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000710 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000711 return handle;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000712}
713
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000714
715/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000716 * GetFreeSpace (KERNEL.169)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000717 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000718DWORD WINAPI GetFreeSpace16( UINT16 wFlags )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000719{
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000720 MEMORYSTATUS ms;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000721 GlobalMemoryStatus( &ms );
722 return ms.dwAvailVirtual;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000723}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000724
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000725/***********************************************************************
726 * GlobalDOSAlloc (KERNEL.184)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000727 * RETURNS
728 * Address (HW=Paragraph segment; LW=Selector)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000729 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000730DWORD WINAPI GlobalDOSAlloc16(
Alexandre Julliard54c27111998-03-29 19:44:57 +0000731 DWORD size /* [in] Number of bytes to be allocated */
732) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000733 UINT16 uParagraph;
Ove Kaaven7b499142000-07-28 22:23:59 +0000734 LPVOID lpBlock = DOSMEM_GetBlock( size, &uParagraph );
Alexandre Julliard54c27111998-03-29 19:44:57 +0000735
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000736 if( lpBlock )
737 {
Alexandre Julliard21979011997-03-05 08:22:35 +0000738 HMODULE16 hModule = GetModuleHandle16("KERNEL");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000739 WORD wSelector;
Andreas Mohrd23f5062000-10-02 22:16:21 +0000740 GLOBALARENA *pArena;
Vincent Béron9a624912002-05-31 23:06:46 +0000741
Alexandre Julliard914406f2000-11-14 01:54:49 +0000742 wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size, hModule, WINE_LDT_FLAGS_DATA );
Andreas Mohrd23f5062000-10-02 22:16:21 +0000743 pArena = GET_ARENA_PTR(wSelector);
744 pArena->flags |= GA_DOSMEM;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000745 return MAKELONG(wSelector,uParagraph);
746 }
747 return 0;
748}
749
Alexandre Julliard54c27111998-03-29 19:44:57 +0000750
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000751/***********************************************************************
752 * GlobalDOSFree (KERNEL.185)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000753 * RETURNS
754 * NULL: Success
755 * sel: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000756 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000757WORD WINAPI GlobalDOSFree16(
Alexandre Julliard54c27111998-03-29 19:44:57 +0000758 WORD sel /* [in] Selector */
759) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000760 DWORD block = GetSelectorBase(sel);
761
Vincent Béron9a624912002-05-31 23:06:46 +0000762 if( block && block < 0x100000 )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000763 {
764 LPVOID lpBlock = DOSMEM_MapDosToLinear( block );
Ove Kaaven7b499142000-07-28 22:23:59 +0000765 if( DOSMEM_FreeBlock( lpBlock ) )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000766 GLOBAL_FreeBlock( sel );
767 sel = 0;
768 }
769 return sel;
770}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000771
Alexandre Julliard54c27111998-03-29 19:44:57 +0000772
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000773/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000774 * GlobalPageLock (KERNEL.191)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000775 * GlobalSmartPageLock(KERNEL.230)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000776 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000777WORD WINAPI GlobalPageLock16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000778{
Alexandre Julliard15657091999-05-23 10:25:25 +0000779 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000780 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000781 WARN("Invalid handle 0x%04x passed to GlobalPageLock!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000782 return 0;
783 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000784 return ++(GET_ARENA_PTR(handle)->pageLockCount);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000785}
786
787
788/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000789 * GlobalPageUnlock (KERNEL.192)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000790 * GlobalSmartPageUnlock(KERNEL.231)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000791 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000792WORD WINAPI GlobalPageUnlock16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000793{
Alexandre Julliard15657091999-05-23 10:25:25 +0000794 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000795 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000796 WARN("Invalid handle 0x%04x passed to GlobalPageUnlock!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000797 return 0;
798 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000799 return --(GET_ARENA_PTR(handle)->pageLockCount);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000800}
801
802
803/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000804 * GlobalFix (KERNEL.197)
805 * GlobalFix16 (KERNEL32.27)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000806 */
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000807WORD WINAPI GlobalFix16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000808{
Alexandre Julliard15657091999-05-23 10:25:25 +0000809 TRACE("%04x\n", handle );
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 GlobalFix16!\n",handle);
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000812 return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000813 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000814 GET_ARENA_PTR(handle)->lockCount++;
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000815
Alexandre Julliarda3960291999-02-26 11:11:13 +0000816 return GlobalHandleToSel16(handle);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000817}
818
819
820/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000821 * GlobalUnfix (KERNEL.198)
822 * GlobalUnfix16 (KERNEL32.28)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000823 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000824void WINAPI GlobalUnfix16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000825{
Alexandre Julliard15657091999-05-23 10:25:25 +0000826 TRACE("%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000827 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000828 WARN("Invalid handle 0x%04x passed to GlobalUnfix16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000829 return;
830 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000831 GET_ARENA_PTR(handle)->lockCount--;
832}
833
834
835/***********************************************************************
836 * FarSetOwner (KERNEL.403)
837 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000838void WINAPI FarSetOwner16( HGLOBAL16 handle, HANDLE16 hOwner )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000839{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000840 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000841 WARN("Invalid handle 0x%04x passed to FarSetOwner!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000842 return;
843 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000844 GET_ARENA_PTR(handle)->hOwner = hOwner;
845}
846
847
848/***********************************************************************
849 * FarGetOwner (KERNEL.404)
850 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000851HANDLE16 WINAPI FarGetOwner16( HGLOBAL16 handle )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000852{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000853 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000854 WARN("Invalid handle 0x%04x passed to FarGetOwner!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000855 return 0;
856 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000857 return GET_ARENA_PTR(handle)->hOwner;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000858}
859
860
861/***********************************************************************
862 * GlobalHandleToSel (TOOLHELP.50)
863 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000864WORD WINAPI GlobalHandleToSel16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000865{
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000866 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000867 if (!VALID_HANDLE(handle)) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000868 WARN("Invalid handle 0x%04x passed to GlobalHandleToSel!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000869 return 0;
870 }
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000871 if (!(handle & 7))
872 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000873 WARN("Program attempted invalid selector conversion\n" );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000874 return handle - 1;
875 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000876 return handle | 7;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000877}
878
879
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000880/***********************************************************************
881 * GlobalFirst (TOOLHELP.51)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000882 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000883BOOL16 WINAPI GlobalFirst16( GLOBALENTRY *pGlobal, WORD wFlags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000884{
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000885 if (wFlags == GLOBAL_LRU) return FALSE;
886 pGlobal->dwNext = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000887 return GlobalNext16( pGlobal, wFlags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000888}
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000889
890
891/***********************************************************************
892 * GlobalNext (TOOLHELP.52)
893 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000894BOOL16 WINAPI GlobalNext16( GLOBALENTRY *pGlobal, WORD wFlags)
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000895{
896 GLOBALARENA *pArena;
897
Alexandre Julliard594997c1995-04-30 10:05:20 +0000898 if (pGlobal->dwNext >= globalArenaSize) return FALSE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000899 pArena = pGlobalArena + pGlobal->dwNext;
900 if (wFlags == GLOBAL_FREE) /* only free blocks */
901 {
902 int i;
903 for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
904 if (pArena->size == 0) break; /* block is free */
905 if (i >= globalArenaSize) return FALSE;
906 pGlobal->dwNext = i;
907 }
908
909 pGlobal->dwAddress = pArena->base;
910 pGlobal->dwBlockSize = pArena->size;
911 pGlobal->hBlock = pArena->handle;
912 pGlobal->wcLock = pArena->lockCount;
913 pGlobal->wcPageLock = pArena->pageLockCount;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000914 pGlobal->wFlags = (GetCurrentPDB16() == pArena->hOwner);
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000915 pGlobal->wHeapPresent = FALSE;
916 pGlobal->hOwner = pArena->hOwner;
917 pGlobal->wType = GT_UNKNOWN;
918 pGlobal->wData = 0;
919 pGlobal->dwNext++;
920 return TRUE;
921}
922
923
924/***********************************************************************
925 * GlobalInfo (TOOLHELP.53)
926 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000927BOOL16 WINAPI GlobalInfo16( GLOBALINFO *pInfo )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000928{
929 int i;
930 GLOBALARENA *pArena;
931
932 pInfo->wcItems = globalArenaSize;
933 pInfo->wcItemsFree = 0;
934 pInfo->wcItemsLRU = 0;
935 for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
936 if (pArena->size == 0) pInfo->wcItemsFree++;
937 return TRUE;
938}
939
940
941/***********************************************************************
942 * GlobalEntryHandle (TOOLHELP.54)
943 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000944BOOL16 WINAPI GlobalEntryHandle16( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000945{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000946 GLOBALARENA *pArena = GET_ARENA_PTR(hItem);
947
948 pGlobal->dwAddress = pArena->base;
949 pGlobal->dwBlockSize = pArena->size;
950 pGlobal->hBlock = pArena->handle;
951 pGlobal->wcLock = pArena->lockCount;
952 pGlobal->wcPageLock = pArena->pageLockCount;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000953 pGlobal->wFlags = (GetCurrentPDB16() == pArena->hOwner);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000954 pGlobal->wHeapPresent = FALSE;
955 pGlobal->hOwner = pArena->hOwner;
956 pGlobal->wType = GT_UNKNOWN;
957 pGlobal->wData = 0;
958 pGlobal->dwNext++;
959 return TRUE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000960}
961
962
963/***********************************************************************
964 * GlobalEntryModule (TOOLHELP.55)
965 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000966BOOL16 WINAPI GlobalEntryModule16( GLOBALENTRY *pGlobal, HMODULE16 hModule,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000967 WORD wSeg )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000968{
Andreas Mohrd23f5062000-10-02 22:16:21 +0000969 FIXME("(%p, 0x%04x, 0x%04x), stub.\n", pGlobal, hModule, wSeg);
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000970 return FALSE;
971}
972
973
974/***********************************************************************
975 * MemManInfo (TOOLHELP.72)
976 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000977BOOL16 WINAPI MemManInfo16( MEMMANINFO *info )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000978{
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000979 MEMORYSTATUS status;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000980
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000981 /*
Vincent Béron9a624912002-05-31 23:06:46 +0000982 * Not unsurprisingly although the documention says you
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000983 * _must_ provide the size in the dwSize field, this function
984 * (under Windows) always fills the structure and returns true.
985 */
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000986 GlobalMemoryStatus( &status );
Alexandre Julliard982a2232000-12-13 20:20:09 +0000987 info->wPageSize = getpagesize();
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000988 info->dwLargestFreeBlock = status.dwAvailVirtual;
989 info->dwMaxPagesAvailable = info->dwLargestFreeBlock / info->wPageSize;
990 info->dwMaxPagesLockable = info->dwMaxPagesAvailable;
991 info->dwTotalLinearSpace = status.dwTotalVirtual / info->wPageSize;
992 info->dwTotalUnlockedPages = info->dwTotalLinearSpace;
993 info->dwFreePages = info->dwMaxPagesAvailable;
994 info->dwTotalPages = info->dwTotalLinearSpace;
995 info->dwFreeLinearSpace = info->dwMaxPagesAvailable;
996 info->dwSwapFilePages = status.dwTotalPageFile / info->wPageSize;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000997 return TRUE;
998}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000999
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001000/***********************************************************************
1001 * GetFreeMemInfo (KERNEL.316)
1002 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001003DWORD WINAPI GetFreeMemInfo16(void)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001004{
1005 MEMMANINFO info;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001006 MemManInfo16( &info );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001007 return MAKELONG( info.dwTotalLinearSpace, info.dwMaxPagesAvailable );
1008}
1009
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001010/*
1011 * Win32 Global heap functions (GlobalXXX).
1012 * These functions included in Win32 for compatibility with 16 bit Windows
Vincent Béron9a624912002-05-31 23:06:46 +00001013 * Especially the moveable blocks and handles are oldish.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001014 * But the ability to directly allocate memory with GPTR and LPTR is widely
1015 * used.
1016 *
1017 * The handle stuff looks horrible, but it's implemented almost like Win95
Vincent Béron9a624912002-05-31 23:06:46 +00001018 * does it.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001019 *
1020 */
1021
1022#define MAGIC_GLOBAL_USED 0x5342
1023#define GLOBAL_LOCK_MAX 0xFF
Alexandre Julliard17216f51997-10-12 16:30:17 +00001024#define HANDLE_TO_INTERN(h) ((PGLOBAL32_INTERN)(((char *)(h))-2))
Alexandre Julliarda3960291999-02-26 11:11:13 +00001025#define INTERN_TO_HANDLE(i) ((HGLOBAL) &((i)->Pointer))
1026#define POINTER_TO_HANDLE(p) (*(((HGLOBAL *)(p))-1))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001027#define ISHANDLE(h) (((DWORD)(h)&2)!=0)
1028#define ISPOINTER(h) (((DWORD)(h)&2)==0)
1029
1030typedef struct __GLOBAL32_INTERN
1031{
1032 WORD Magic;
1033 LPVOID Pointer WINE_PACKED;
1034 BYTE Flags;
1035 BYTE LockCount;
1036} GLOBAL32_INTERN, *PGLOBAL32_INTERN;
1037
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001038
1039/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001040 * GlobalAlloc (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001041 * RETURNS
1042 * Handle: Success
1043 * NULL: Failure
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001044 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001045HGLOBAL WINAPI GlobalAlloc(
1046 UINT flags, /* [in] Object allocation attributes */
Dmitry Timoshkov472d0162002-09-21 01:21:00 +00001047 SIZE_T size /* [in] Number of bytes to allocate */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001048) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001049 PGLOBAL32_INTERN pintern;
1050 DWORD hpflags;
1051 LPVOID palloc;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001052
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001053 if(flags&GMEM_ZEROINIT)
1054 hpflags=HEAP_ZERO_MEMORY;
1055 else
1056 hpflags=0;
Vincent Béron9a624912002-05-31 23:06:46 +00001057
Noel Borthwick83579c81999-07-24 12:18:04 +00001058 TRACE("() flags=%04x\n", flags );
Vincent Béron9a624912002-05-31 23:06:46 +00001059
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001060 if((flags & GMEM_MOVEABLE)==0) /* POINTER */
1061 {
1062 palloc=HeapAlloc(GetProcessHeap(), hpflags, size);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001063 return (HGLOBAL) palloc;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001064 }
1065 else /* HANDLE */
1066 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001067 /* HeapLock(heap); */
1068
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001069 pintern=HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
Alexandre Julliard982a2232000-12-13 20:20:09 +00001070 if (!pintern) return 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001071 if(size)
1072 {
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001073 if (!(palloc=HeapAlloc(GetProcessHeap(), hpflags, size+sizeof(HGLOBAL)))) {
1074 HeapFree(GetProcessHeap(), 0, pintern);
Alexandre Julliard982a2232000-12-13 20:20:09 +00001075 return 0;
Eric Pouech3bcfb902000-06-24 12:51:24 +00001076 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001077 *(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001078 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001079 }
1080 else
1081 pintern->Pointer=NULL;
1082 pintern->Magic=MAGIC_GLOBAL_USED;
1083 pintern->Flags=flags>>8;
1084 pintern->LockCount=0;
Vincent Béron9a624912002-05-31 23:06:46 +00001085
Noel Borthwick83579c81999-07-24 12:18:04 +00001086 /* HeapUnlock(heap); */
Vincent Béron9a624912002-05-31 23:06:46 +00001087
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001088 return INTERN_TO_HANDLE(pintern);
1089 }
1090}
1091
1092
1093/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001094 * GlobalLock (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001095 * RETURNS
1096 * Pointer to first byte of block
1097 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001098 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001099LPVOID WINAPI GlobalLock(
1100 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001101) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001102 PGLOBAL32_INTERN pintern;
1103 LPVOID palloc;
1104
1105 if(ISPOINTER(hmem))
1106 return (LPVOID) hmem;
1107
1108 /* HeapLock(GetProcessHeap()); */
Vincent Béron9a624912002-05-31 23:06:46 +00001109
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001110 pintern=HANDLE_TO_INTERN(hmem);
1111 if(pintern->Magic==MAGIC_GLOBAL_USED)
1112 {
1113 if(pintern->LockCount<GLOBAL_LOCK_MAX)
1114 pintern->LockCount++;
1115 palloc=pintern->Pointer;
1116 }
1117 else
1118 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001119 WARN("invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001120 palloc=(LPVOID) NULL;
Dmitry Timoshkovc34fe082000-11-27 01:33:25 +00001121 SetLastError(ERROR_INVALID_HANDLE);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001122 }
1123 /* HeapUnlock(GetProcessHeap()); */;
1124 return palloc;
1125}
1126
1127
1128/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001129 * GlobalUnlock (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001130 * RETURNS
1131 * TRUE: Object is still locked
1132 * FALSE: Object is unlocked
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001133 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001134BOOL WINAPI GlobalUnlock(
1135 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001136) {
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001137 PGLOBAL32_INTERN pintern;
1138 BOOL locked;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001139
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001140 if (ISPOINTER(hmem)) return FALSE;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001141
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001142 __TRY
1143 {
1144 /* HeapLock(GetProcessHeap()); */
1145 pintern=HANDLE_TO_INTERN(hmem);
1146 if(pintern->Magic==MAGIC_GLOBAL_USED)
1147 {
1148 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
1149 pintern->LockCount--;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001150
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001151 locked = (pintern->LockCount != 0);
1152 if (!locked) SetLastError(NO_ERROR);
1153 }
1154 else
1155 {
1156 WARN("invalid handle\n");
1157 SetLastError(ERROR_INVALID_HANDLE);
1158 locked=FALSE;
1159 }
1160 /* HeapUnlock(GetProcessHeap()); */
1161 }
1162 __EXCEPT(page_fault)
1163 {
1164 ERR("page fault occurred ! Caused by bug ?\n");
1165 SetLastError( ERROR_INVALID_PARAMETER );
1166 return FALSE;
1167 }
1168 __ENDTRY
1169 return locked;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001170}
1171
1172
1173/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001174 * GlobalHandle (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001175 * Returns the handle associated with the specified pointer.
1176 *
Alexandre Julliard54c27111998-03-29 19:44:57 +00001177 * RETURNS
1178 * Handle: Success
1179 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001180 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001181HGLOBAL WINAPI GlobalHandle(
Alexandre Julliard54c27111998-03-29 19:44:57 +00001182 LPCVOID pmem /* [in] Pointer to global memory block */
1183) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001184 HGLOBAL handle;
Guy Albertelli4ef64132000-01-23 02:25:11 +00001185 PGLOBAL32_INTERN maybe_intern;
1186 LPCVOID test;
Guy Albertelli98679972000-01-15 21:59:12 +00001187
1188 if (!pmem)
1189 {
Lawson Whitney969515d2000-10-02 22:27:37 +00001190 SetLastError( ERROR_INVALID_PARAMETER );
1191 return 0;
Guy Albertelli98679972000-01-15 21:59:12 +00001192 }
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001193
Lawson Whitney969515d2000-10-02 22:27:37 +00001194 __TRY
1195 {
1196 handle = 0;
Guy Albertelli4ef64132000-01-23 02:25:11 +00001197
Lawson Whitney969515d2000-10-02 22:27:37 +00001198 /* note that if pmem is a pointer to a a block allocated by */
1199 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
1200 /* will fail. */
1201 if (ISPOINTER(pmem)) {
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001202 if (HeapValidate( GetProcessHeap(), 0, pmem )) {
Lawson Whitney969515d2000-10-02 22:27:37 +00001203 handle = (HGLOBAL)pmem; /* valid fixed block */
1204 break;
1205 }
1206 handle = POINTER_TO_HANDLE(pmem);
1207 } else
1208 handle = (HGLOBAL)pmem;
1209
1210 /* Now test handle either passed in or retrieved from pointer */
Lawson Whitney969515d2000-10-02 22:27:37 +00001211 maybe_intern = HANDLE_TO_INTERN( handle );
1212 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
1213 test = maybe_intern->Pointer;
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001214 if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
1215 HeapValidate( GetProcessHeap(), 0, maybe_intern )) /* intern valid arena? */
Lawson Whitney969515d2000-10-02 22:27:37 +00001216 break; /* valid moveable block */
1217 }
1218 handle = 0;
1219 SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard17216f51997-10-12 16:30:17 +00001220 }
Lawson Whitney969515d2000-10-02 22:27:37 +00001221 __EXCEPT(page_fault)
1222 {
1223 SetLastError( ERROR_INVALID_HANDLE );
1224 return 0;
1225 }
1226 __ENDTRY
Alexandre Julliard17216f51997-10-12 16:30:17 +00001227
Lawson Whitney969515d2000-10-02 22:27:37 +00001228 return handle;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001229}
1230
1231
1232/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001233 * GlobalReAlloc (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001234 * RETURNS
1235 * Handle: Success
1236 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001237 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001238HGLOBAL WINAPI GlobalReAlloc(
1239 HGLOBAL hmem, /* [in] Handle of global memory object */
Dmitry Timoshkov472d0162002-09-21 01:21:00 +00001240 SIZE_T size, /* [in] New size of block */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001241 UINT flags /* [in] How to reallocate object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001242) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001243 LPVOID palloc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001244 HGLOBAL hnew;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001245 PGLOBAL32_INTERN pintern;
Alexandre Julliardd10ca9c1999-09-04 11:26:56 +00001246 DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001247
Alexandre Julliard02e90081998-01-04 17:49:09 +00001248 hnew = 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001249 /* HeapLock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001250 if(flags & GMEM_MODIFY) /* modify flags */
1251 {
1252 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
1253 {
1254 /* make a fixed block moveable
1255 * actually only NT is able to do this. But it's soo simple
1256 */
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001257 if (hmem == 0)
1258 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001259 ERR("GlobalReAlloc32 with null handle!\n");
Alexandre Julliard0ad42fa1999-01-31 15:04:42 +00001260 SetLastError( ERROR_NOACCESS );
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001261 return 0;
1262 }
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001263 size=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001264 hnew=GlobalAlloc( flags, size);
1265 palloc=GlobalLock(hnew);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001266 memcpy(palloc, (LPVOID) hmem, size);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001267 GlobalUnlock(hnew);
1268 GlobalFree(hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001269 }
1270 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
1271 {
1272 /* change the flags to make our block "discardable" */
1273 pintern=HANDLE_TO_INTERN(hmem);
1274 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
1275 hnew=hmem;
1276 }
1277 else
1278 {
1279 SetLastError(ERROR_INVALID_PARAMETER);
Alexandre Julliard02e90081998-01-04 17:49:09 +00001280 hnew = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001281 }
1282 }
1283 else
1284 {
1285 if(ISPOINTER(hmem))
1286 {
1287 /* reallocate fixed memory */
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001288 hnew=(HGLOBAL)HeapReAlloc(GetProcessHeap(), heap_flags, (LPVOID) hmem, size);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001289 }
1290 else
1291 {
1292 /* reallocate a moveable block */
1293 pintern=HANDLE_TO_INTERN(hmem);
Ulrich Weigand2e7008c2000-10-19 20:24:25 +00001294
1295#if 0
1296/* Apparently Windows doesn't care whether the handle is locked at this point */
1297/* See also the same comment in GlobalFree() */
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001298 if(pintern->LockCount>1) {
Alexandre Julliard15657091999-05-23 10:25:25 +00001299 ERR("handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001300 SetLastError(ERROR_INVALID_HANDLE);
Ulrich Weigand2e7008c2000-10-19 20:24:25 +00001301 } else
1302#endif
1303 if(size!=0)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001304 {
1305 hnew=hmem;
1306 if(pintern->Pointer)
1307 {
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001308 if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
Huw D M Daviesc43fdb72000-04-13 15:57:06 +00001309 (char *) pintern->Pointer-sizeof(HGLOBAL),
1310 size+sizeof(HGLOBAL))) == NULL)
1311 return 0; /* Block still valid */
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001312 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001313 }
1314 else
1315 {
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001316 if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+sizeof(HGLOBAL)))
Huw D M Daviesc43fdb72000-04-13 15:57:06 +00001317 == NULL)
1318 return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001319 *(HGLOBAL *)palloc=hmem;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001320 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001321 }
1322 }
1323 else
1324 {
1325 if(pintern->Pointer)
1326 {
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001327 HeapFree(GetProcessHeap(), 0, (char *) pintern->Pointer-sizeof(HGLOBAL));
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001328 pintern->Pointer=NULL;
1329 }
1330 }
1331 }
1332 }
Noel Borthwick83579c81999-07-24 12:18:04 +00001333 /* HeapUnlock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001334 return hnew;
1335}
1336
1337
1338/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001339 * GlobalFree (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001340 * RETURNS
1341 * NULL: Success
1342 * Handle: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001343 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001344HGLOBAL WINAPI GlobalFree(
1345 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001346) {
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001347 PGLOBAL32_INTERN pintern;
1348 HGLOBAL hreturned;
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001349
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001350 __TRY
1351 {
1352 hreturned = 0;
1353 if(ISPOINTER(hmem)) /* POINTER */
1354 {
1355 if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
1356 }
1357 else /* HANDLE */
1358 {
1359 /* HeapLock(heap); */
1360 pintern=HANDLE_TO_INTERN(hmem);
Guy Albertelli4ef64132000-01-23 02:25:11 +00001361
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001362 if(pintern->Magic==MAGIC_GLOBAL_USED)
1363 {
Guy Albertelli4ef64132000-01-23 02:25:11 +00001364
Andreas Mohr55a14ed2001-11-20 20:26:35 +00001365 /* WIN98 does not make this test. That is you can free a */
1366 /* block you have not unlocked. Go figure!! */
1367 /* if(pintern->LockCount!=0) */
1368 /* SetLastError(ERROR_INVALID_HANDLE); */
1369
1370 if(pintern->Pointer)
1371 if(!HeapFree(GetProcessHeap(), 0, (char *)(pintern->Pointer)-sizeof(HGLOBAL)))
1372 hreturned=hmem;
1373 if(!HeapFree(GetProcessHeap(), 0, pintern))
1374 hreturned=hmem;
1375 }
1376 /* HeapUnlock(heap); */
1377 }
1378 }
1379 __EXCEPT(page_fault)
1380 {
1381 ERR("page fault occurred ! Caused by bug ?\n");
1382 SetLastError( ERROR_INVALID_PARAMETER );
1383 return hmem;
1384 }
1385 __ENDTRY
1386 return hreturned;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001387}
1388
1389
1390/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001391 * GlobalSize (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001392 * RETURNS
1393 * Size in bytes of the global memory object
1394 * 0: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001395 */
Dmitry Timoshkov472d0162002-09-21 01:21:00 +00001396SIZE_T WINAPI GlobalSize(
Alexandre Julliarda3960291999-02-26 11:11:13 +00001397 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001398) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001399 DWORD retval;
1400 PGLOBAL32_INTERN pintern;
1401
Vincent Béron9a624912002-05-31 23:06:46 +00001402 if(ISPOINTER(hmem))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001403 {
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001404 retval=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001405 }
1406 else
1407 {
Noel Borthwick83579c81999-07-24 12:18:04 +00001408 /* HeapLock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001409 pintern=HANDLE_TO_INTERN(hmem);
Vincent Béron9a624912002-05-31 23:06:46 +00001410
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001411 if(pintern->Magic==MAGIC_GLOBAL_USED)
1412 {
Guy Albertelli3db8e191999-02-14 17:38:24 +00001413 if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
1414 return 0;
Alexandre Julliard61d32b42001-02-23 01:35:36 +00001415 retval=HeapSize(GetProcessHeap(), 0,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001416 (char *)(pintern->Pointer)-sizeof(HGLOBAL))-4;
Rein Klazeseaec1ee1999-07-11 13:50:24 +00001417 if (retval == 0xffffffff-4) retval = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001418 }
1419 else
1420 {
Alexandre Julliard15657091999-05-23 10:25:25 +00001421 WARN("invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001422 retval=0;
1423 }
Noel Borthwick83579c81999-07-24 12:18:04 +00001424 /* HeapUnlock(heap); */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001425 }
Guy Albertelli3db8e191999-02-14 17:38:24 +00001426 /* HeapSize returns 0xffffffff on failure */
1427 if (retval == 0xffffffff) retval = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001428 return retval;
1429}
1430
1431
1432/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001433 * GlobalWire (KERNEL32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001434 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001435LPVOID WINAPI GlobalWire(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001436{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001437 return GlobalLock( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001438}
1439
1440
1441/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001442 * GlobalUnWire (KERNEL32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001443 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001444BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001445{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001446 return GlobalUnlock( hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001447}
1448
1449
1450/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001451 * GlobalFix (KERNEL32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001452 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001453VOID WINAPI GlobalFix(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001454{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001455 GlobalLock( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001456}
1457
1458
1459/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001460 * GlobalUnfix (KERNEL32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001461 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001462VOID WINAPI GlobalUnfix(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001463{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001464 GlobalUnlock( hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001465}
1466
1467
1468/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001469 * GlobalFlags (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001470 * Returns information about the specified global memory object
1471 *
1472 * NOTES
1473 * Should this return GMEM_INVALID_HANDLE on invalid handle?
1474 *
1475 * RETURNS
1476 * Value specifying allocation flags and lock count
1477 * GMEM_INVALID_HANDLE: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001478 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001479UINT WINAPI GlobalFlags(
1480 HGLOBAL hmem /* [in] Handle to global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001481) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001482 DWORD retval;
1483 PGLOBAL32_INTERN pintern;
Vincent Béron9a624912002-05-31 23:06:46 +00001484
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001485 if(ISPOINTER(hmem))
1486 {
1487 retval=0;
1488 }
1489 else
1490 {
1491 /* HeapLock(GetProcessHeap()); */
1492 pintern=HANDLE_TO_INTERN(hmem);
1493 if(pintern->Magic==MAGIC_GLOBAL_USED)
Vincent Béron9a624912002-05-31 23:06:46 +00001494 {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001495 retval=pintern->LockCount + (pintern->Flags<<8);
1496 if(pintern->Pointer==0)
1497 retval|= GMEM_DISCARDED;
1498 }
1499 else
1500 {
Andrew John Hughesed800c62002-11-21 03:45:01 +00001501 WARN("Invalid handle: %p\n", hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001502 retval=0;
1503 }
1504 /* HeapUnlock(GetProcessHeap()); */
1505 }
1506 return retval;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001507}
1508
1509
1510/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001511 * GlobalCompact (KERNEL32.@)
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001512 */
Dmitry Timoshkov472d0162002-09-21 01:21:00 +00001513SIZE_T WINAPI GlobalCompact( DWORD minfree )
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001514{
1515 return 0; /* GlobalCompact does nothing in Win32 */
1516}
1517
1518
1519/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001520 * GlobalMemoryStatus (KERNEL32.@)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001521 * RETURNS
1522 * None
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001523 */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001524VOID WINAPI GlobalMemoryStatus(
1525 LPMEMORYSTATUS lpmem
1526) {
Marcus Meissner6189c192000-03-04 19:19:15 +00001527 static MEMORYSTATUS cached_memstatus;
1528 static int cache_lastchecked = 0;
Francois Gougetea5924c2000-10-28 00:34:29 +00001529 SYSTEM_INFO si;
Patrik Stridvall7e9913f2000-03-08 18:25:22 +00001530#ifdef linux
Marcus Meissner6189c192000-03-04 19:19:15 +00001531 FILE *f;
Patrik Stridvall7e9913f2000-03-08 18:25:22 +00001532#endif
Olivier Houchardf41ecf32002-05-07 01:50:02 +00001533#ifdef __FreeBSD__
1534 int *tmp;
1535 int size_sys;
1536#endif
Marcus Meissner6189c192000-03-04 19:19:15 +00001537 if (time(NULL)==cache_lastchecked) {
1538 memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
1539 return;
1540 }
1541 cache_lastchecked = time(NULL);
1542
Olivier Houchardf41ecf32002-05-07 01:50:02 +00001543 lpmem->dwMemoryLoad = 0;
1544 lpmem->dwTotalPhys = 16*1024*1024;
1545 lpmem->dwAvailPhys = 16*1024*1024;
1546 lpmem->dwTotalPageFile = 16*1024*1024;
1547 lpmem->dwAvailPageFile = 16*1024*1024;
1548
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001549#ifdef linux
Marcus Meissner6189c192000-03-04 19:19:15 +00001550 f = fopen( "/proc/meminfo", "r" );
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001551 if (f)
1552 {
1553 char buffer[256];
Stephen Crowley59c4a321998-11-24 20:41:02 +00001554 int total, used, free, shared, buffers, cached;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001555
Stephen Crowley59c4a321998-11-24 20:41:02 +00001556 lpmem->dwLength = sizeof(MEMORYSTATUS);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001557 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
1558 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
1559 while (fgets( buffer, sizeof(buffer), f ))
1560 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001561 /* old style /proc/meminfo ... */
Stephen Crowley59c4a321998-11-24 20:41:02 +00001562 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001563 {
1564 lpmem->dwTotalPhys += total;
Stephen Crowley59c4a321998-11-24 20:41:02 +00001565 lpmem->dwAvailPhys += free + buffers + cached;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001566 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001567 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001568 {
1569 lpmem->dwTotalPageFile += total;
1570 lpmem->dwAvailPageFile += free;
1571 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001572
1573 /* new style /proc/meminfo ... */
1574 if (sscanf(buffer, "MemTotal: %d", &total))
1575 lpmem->dwTotalPhys = total*1024;
1576 if (sscanf(buffer, "MemFree: %d", &free))
1577 lpmem->dwAvailPhys = free*1024;
1578 if (sscanf(buffer, "SwapTotal: %d", &total))
1579 lpmem->dwTotalPageFile = total*1024;
1580 if (sscanf(buffer, "SwapFree: %d", &free))
1581 lpmem->dwAvailPageFile = free*1024;
Stephen Crowley59c4a321998-11-24 20:41:02 +00001582 if (sscanf(buffer, "Buffers: %d", &buffers))
1583 lpmem->dwAvailPhys += buffers*1024;
1584 if (sscanf(buffer, "Cached: %d", &cached))
1585 lpmem->dwAvailPhys += cached*1024;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001586 }
1587 fclose( f );
1588
1589 if (lpmem->dwTotalPhys)
1590 {
Francois Gougetea5924c2000-10-28 00:34:29 +00001591 DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
1592 DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
1593 lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
1594 / (TotalPhysical / 100);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001595 }
Marcus Meissnerfddbcf32000-03-07 12:24:58 +00001596 }
Olivier Houchardf41ecf32002-05-07 01:50:02 +00001597#elif defined(__FreeBSD__)
1598 sysctlbyname("hw.physmem", NULL, &size_sys, NULL, 0);
1599 tmp = malloc(size_sys * sizeof(int));
1600 sysctlbyname("hw.physmem", tmp, &size_sys, NULL, 0);
1601 if (tmp && *tmp)
1602 {
1603 lpmem->dwTotalPhys = *tmp;
1604 free(tmp);
1605 sysctlbyname("hw.usermem", NULL, &size_sys, NULL, 0);
1606 tmp = malloc(size_sys * sizeof(int));
1607 sysctlbyname("hw.usermem", tmp, &size_sys, NULL, 0);
1608 if (tmp && *tmp)
1609 {
1610 lpmem->dwAvailPhys = *tmp;
1611 lpmem->dwTotalPageFile = *tmp;
1612 lpmem->dwAvailPageFile = *tmp;
1613 lpmem->dwMemoryLoad = lpmem->dwTotalPhys - lpmem->dwAvailPhys;
1614 } else
1615 {
1616 lpmem->dwAvailPhys = lpmem->dwTotalPhys;
1617 lpmem->dwTotalPageFile = lpmem->dwTotalPhys;
1618 lpmem->dwAvailPageFile = lpmem->dwTotalPhys;
1619 lpmem->dwMemoryLoad = 0;
1620 }
1621 free(tmp);
Vincent Béron9a624912002-05-31 23:06:46 +00001622
Olivier Houchardf41ecf32002-05-07 01:50:02 +00001623 }
1624#endif
Francois Gouget1f0e33c2002-11-13 19:48:07 +00001625 /* Some applications (e.g. QuickTime 6) crash if we tell them there
1626 * is more than 2GB of physical memory.
1627 */
1628 if (lpmem->dwTotalPhys>2U*1024*1024*1024)
1629 {
1630 lpmem->dwTotalPhys=2U*1024*1024*1024;
1631 lpmem->dwAvailPhys=2U*1024*1024*1024;
1632 }
1633
Olivier Houchardf41ecf32002-05-07 01:50:02 +00001634 /* FIXME: should do something for other systems */
Francois Gougetea5924c2000-10-28 00:34:29 +00001635 GetSystemInfo(&si);
Gregg Mattinson7c4cb512002-07-03 21:10:43 +00001636 lpmem->dwTotalVirtual = (char*)si.lpMaximumApplicationAddress-(char*)si.lpMinimumApplicationAddress;
Francois Gougetea5924c2000-10-28 00:34:29 +00001637 /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
1638 lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
Marcus Meissnerfddbcf32000-03-07 12:24:58 +00001639 memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
Mike McCormackc56a79a2001-01-04 19:52:51 +00001640
1641 /* it appears some memory display programs want to divide by these values */
1642 if(lpmem->dwTotalPageFile==0)
1643 lpmem->dwTotalPageFile++;
1644
1645 if(lpmem->dwAvailPageFile==0)
1646 lpmem->dwAvailPageFile++;
Andreas Mohrcacbe212002-04-02 19:40:49 +00001647
1648 TRACE("<-- LPMEMORYSTATUS: dwLength %ld, dwMemoryLoad %ld, dwTotalPhys %ld, dwAvailPhys %ld,"
1649 " dwTotalPageFile %ld, dwAvailPageFile %ld, dwTotalVirtual %ld, dwAvailVirtual %ld\n",
1650 lpmem->dwLength, lpmem->dwMemoryLoad, lpmem->dwTotalPhys, lpmem->dwAvailPhys,
1651 lpmem->dwTotalPageFile, lpmem->dwAvailPageFile, lpmem->dwTotalVirtual,
1652 lpmem->dwAvailVirtual);
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001653}
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001654
Alexandre Julliard4220b291999-07-11 17:20:01 +00001655/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001656 * A20Proc (KERNEL.165)
Patrik Stridvall044855c2001-07-11 18:56:41 +00001657 * A20_Proc (SYSTEM.20)
Alexandre Julliard4220b291999-07-11 17:20:01 +00001658 */
1659void WINAPI A20Proc16( WORD unused )
1660{
1661 /* this is also a NOP in Windows */
1662}
1663
1664/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001665 * LimitEMSPages (KERNEL.156)
Alexandre Julliard4220b291999-07-11 17:20:01 +00001666 */
1667DWORD WINAPI LimitEMSPages16( DWORD unused )
1668{
1669 return 0;
1670}