blob: e5b9a1b32b8a64e3166f4246d48f9ad41155adf0 [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>
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000010#include <unistd.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000011#include <string.h>
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000012
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000013#include "wine/winbase16.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000014#include "global.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000015#include "heap.h"
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +000016#include "toolhelp.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000017#include "selectors.h"
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000018#include "miscemu.h"
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000019#include "dde_mem.h"
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000020#include "stackframe.h"
Alexandre Julliard77b99181997-09-14 17:17:23 +000021#include "module.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000022#include "debug.h"
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000023#include "winerror.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000024
Alexandre Julliardfa68b751995-04-03 16:55:37 +000025 /* Global arena block */
26typedef struct
27{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000028 DWORD base; /* Base address (0 if discarded) */
29 DWORD size; /* Size in bytes (0 indicates a free block) */
30 HGLOBAL16 handle; /* Handle for this block */
31 HGLOBAL16 hOwner; /* Owner of this block */
32 BYTE lockCount; /* Count of GlobalFix() calls */
33 BYTE pageLockCount; /* Count of GlobalPageLock() calls */
34 BYTE flags; /* Allocation flags */
35 BYTE selCount; /* Number of selectors allocated for this block */
Alexandre Julliard7e56f681996-01-31 19:02:28 +000036#ifdef CONFIG_IPC
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000037 int shmid;
Alexandre Julliard7e56f681996-01-31 19:02:28 +000038#endif
Alexandre Julliardfa68b751995-04-03 16:55:37 +000039} GLOBALARENA;
40
41 /* Flags definitions */
Alexandre Julliard2787be81995-05-22 18:23:01 +000042#define GA_MOVEABLE 0x02 /* same as GMEM_MOVEABLE */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000043#define GA_DGROUP 0x04
44#define GA_DISCARDABLE 0x08
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000045#define GA_IPCSHARE 0x10 /* same as GMEM_DDESHARE */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000046
47 /* Arena array */
48static GLOBALARENA *pGlobalArena = NULL;
49static int globalArenaSize = 0;
50
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000051#define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
Alexandre Julliard121bd981993-07-08 17:37:25 +000052
Alexandre Julliarda11d7b11998-03-01 20:05:02 +000053#define VALID_HANDLE(handle) (((handle)>>__AHSHIFT)<globalArenaSize)
Alexandre Julliardfa68b751995-04-03 16:55:37 +000054#define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
Alexandre Julliard75a839a1993-07-15 11:13:45 +000055
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000056/***********************************************************************
Alexandre Julliardfa68b751995-04-03 16:55:37 +000057 * GLOBAL_GetArena
58 *
59 * Return the arena for a given selector, growing the arena array if needed.
Alexandre Julliarddba420a1994-02-02 06:48:31 +000060 */
Alexandre Julliardfa68b751995-04-03 16:55:37 +000061static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
Alexandre Julliarddba420a1994-02-02 06:48:31 +000062{
Alexandre Julliard2787be81995-05-22 18:23:01 +000063 if (((sel >> __AHSHIFT) + selcount) > globalArenaSize)
Alexandre Julliardfa68b751995-04-03 16:55:37 +000064 {
Alexandre Julliard2787be81995-05-22 18:23:01 +000065 int newsize = ((sel >> __AHSHIFT) + selcount + 0xff) & ~0xff;
Alexandre Julliardfa68b751995-04-03 16:55:37 +000066 GLOBALARENA *pNewArena = realloc( pGlobalArena,
Alexandre Julliard2787be81995-05-22 18:23:01 +000067 newsize * sizeof(GLOBALARENA) );
Alexandre Julliardfa68b751995-04-03 16:55:37 +000068 if (!pNewArena) return 0;
69 pGlobalArena = pNewArena;
Alexandre Julliard2787be81995-05-22 18:23:01 +000070 memset( pGlobalArena + globalArenaSize, 0,
71 (newsize - globalArenaSize) * sizeof(GLOBALARENA) );
72 globalArenaSize = newsize;
Alexandre Julliardfa68b751995-04-03 16:55:37 +000073 }
74 return pGlobalArena + (sel >> __AHSHIFT);
75}
Alexandre Julliarddba420a1994-02-02 06:48:31 +000076
Alexandre Julliardfa68b751995-04-03 16:55:37 +000077
Juergen Schmiedebc2b771998-11-14 18:59:30 +000078void debug_handles(void)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000079{
80 int printed=0;
81 int i;
82 for (i = globalArenaSize-1 ; i>=0 ; i--) {
83 if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
84 printed=1;
Alexandre Julliard54c27111998-03-29 19:44:57 +000085 DUMP("0x%08x, ",pGlobalArena[i].handle);
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000086 }
87 }
88 if (printed)
Alexandre Julliard54c27111998-03-29 19:44:57 +000089 DUMP("\n");
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000090}
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000091
92
Alexandre Julliardfa68b751995-04-03 16:55:37 +000093/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +000094 * GLOBAL_CreateBlock
Alexandre Julliardfa68b751995-04-03 16:55:37 +000095 *
Alexandre Julliard594997c1995-04-30 10:05:20 +000096 * Create a global heap block for a fixed range of linear memory.
Alexandre Julliardfa68b751995-04-03 16:55:37 +000097 */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000098HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
Alexandre Julliardd90840e1996-06-11 16:02:08 +000099 HGLOBAL16 hOwner, BOOL16 isCode,
100 BOOL16 is32Bit, BOOL16 isReadOnly,
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000101 SHMDATA *shmdata )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000102{
103 WORD sel, selcount;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000104 GLOBALARENA *pArena;
Alexandre Julliarddba420a1994-02-02 06:48:31 +0000105
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000106 /* Allocate the selector(s) */
107
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000108 sel = SELECTOR_AllocBlock( ptr, size,
109 isCode ? SEGMENT_CODE : SEGMENT_DATA,
110 is32Bit, isReadOnly );
111
Alexandre Julliard594997c1995-04-30 10:05:20 +0000112 if (!sel) return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000113 selcount = (size + 0xffff) / 0x10000;
114
115 if (!(pArena = GLOBAL_GetArena( sel, selcount )))
116 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000117 SELECTOR_FreeBlock( sel, selcount );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000118 return 0;
119 }
120
121 /* Fill the arena block */
122
123 pArena->base = (DWORD)ptr;
124 pArena->size = GET_SEL_LIMIT(sel) + 1;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000125
126#ifdef CONFIG_IPC
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000127 if (flags & GMEM_DDESHARE)
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000128 {
129 pArena->handle = shmdata->handle;
130 pArena->shmid = shmdata->shmid;
131 shmdata->sel = sel;
132 }
133 else
134 {
135 pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
136 pArena->shmid = 0;
137 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000138#else
139 pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
140#endif
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 Julliarde2991ea1995-07-29 13:09:43 +0000212 SHMDATA shmdata;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000213
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000214 TRACE(global, "%ld flags=%04x\n", size, flags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000215
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000216 /* If size is 0, create a discarded block */
217
218 if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
219 is32Bit, isReadOnly, NULL );
220
221 /* Fixup the size */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000222
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000223 if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000224 size = (size + 0x1f) & ~0x1f;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000225
226 /* Allocate the linear memory */
227
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000228#ifdef CONFIG_IPC
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000229 if (flags & GMEM_DDESHARE)
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000230 ptr = DDE_malloc(flags, size, &shmdata);
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000231 else
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000232#endif /* CONFIG_IPC */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000233 {
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000234 ptr = HeapAlloc( SystemHeap, 0, size );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000235 }
Alexandre Julliard77b99181997-09-14 17:17:23 +0000236 /* FIXME: free discardable blocks and try again? */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000237 if (!ptr) return 0;
238
239 /* Allocate the selector(s) */
240
241 handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000242 isCode, is32Bit, isReadOnly, &shmdata);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000243 if (!handle)
244 {
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000245 HeapFree( SystemHeap, 0, ptr );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000246 return 0;
247 }
248
249 if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
250 return handle;
251}
252
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000253
254#ifdef CONFIG_IPC
255/***********************************************************************
256 * GLOBAL_FindArena
257 *
258 * Find the arena for a given handle
259 * (when handle is not serial - e.g. DDE)
260 */
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000261static GLOBALARENA *GLOBAL_FindArena( HGLOBAL16 handle)
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000262{
263 int i;
264 for (i = globalArenaSize-1 ; i>=0 ; i--) {
265 if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
266 return ( &pGlobalArena[i] );
267 }
268 return NULL;
269}
270
271
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000272/***********************************************************************
273 * DDE_GlobalHandleToSel
274 */
275
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000276WORD DDE_GlobalHandleToSel( HGLOBAL16 handle )
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000277{
278 GLOBALARENA *pArena;
279 SEGPTR segptr;
280
281 pArena= GLOBAL_FindArena(handle);
282 if (pArena) {
283 int ArenaIdx = pArena - pGlobalArena;
284
285 /* See if synchronized to the shared memory */
286 return DDE_SyncHandle(handle, ( ArenaIdx << __AHSHIFT) | 7);
287 }
288
289 /* attach the block */
290 DDE_AttachHandle(handle, &segptr);
291
292 return SELECTOROF( segptr );
293}
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000294#endif /* CONFIG_IPC */
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000295
Alexandre Julliard594997c1995-04-30 10:05:20 +0000296
297/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000298 * GlobalAlloc16 (KERNEL.15)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000299 * RETURNS
300 * Handle: Success
301 * NULL: Failure
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000302 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000303HGLOBAL16 WINAPI GlobalAlloc16(
304 UINT16 flags, /* [in] Object allocation attributes */
305 DWORD size /* [in] Number of bytes to allocate */
306) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000307 HANDLE16 owner = GetCurrentPDB16();
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000308
Alexandre Julliard594997c1995-04-30 10:05:20 +0000309 if (flags & GMEM_DDESHARE)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000310 owner = GetExePtr(owner); /* Make it a module handle */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000311 return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000312}
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000313
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000314
315/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000316 * GlobalReAlloc16 (KERNEL.16)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000317 * RETURNS
318 * Handle: Success
319 * NULL: Failure
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000320 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000321HGLOBAL16 WINAPI GlobalReAlloc16(
322 HGLOBAL16 handle, /* [in] Handle of global memory object */
323 DWORD size, /* [in] New size of block */
324 UINT16 flags /* [in] How to reallocate object */
325) {
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000326 WORD selcount;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000327 DWORD oldsize;
328 void *ptr;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000329 GLOBALARENA *pArena, *pNewArena;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000330 WORD sel = GlobalHandleToSel16( handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000331
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000332 TRACE(global, "%04x %ld flags=%04x\n",
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000333 handle, size, flags );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000334 if (!handle) return 0;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000335
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000336#ifdef CONFIG_IPC
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000337 if (flags & GMEM_DDESHARE || is_dde_handle(handle))
338 {
Alexandre Julliard54c27111998-03-29 19:44:57 +0000339 FIXME(global, "shared memory reallocating unimplemented\n");
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000340 return 0;
341 }
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000342#endif /* CONFIG_IPC */
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000343
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000344 if (!VALID_HANDLE(handle)) {
Alexandre Julliard54c27111998-03-29 19:44:57 +0000345 WARN(global, "Invalid handle 0x%04x!\n", handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000346 return 0;
347 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000348 pArena = GET_ARENA_PTR( handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000349
Alexandre Julliard2787be81995-05-22 18:23:01 +0000350 /* Discard the block if requested */
351
Alexandre Julliardded30381995-07-06 17:18:27 +0000352 if ((size == 0) && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY))
Alexandre Julliard2787be81995-05-22 18:23:01 +0000353 {
354 if (!(pArena->flags & GA_MOVEABLE) ||
355 !(pArena->flags & GA_DISCARDABLE) ||
356 (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000357 HeapFree( SystemHeap, 0, (void *)pArena->base );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000358 pArena->base = 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000359
360 /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
361 * change the selector if we are shrinking the block.
362 * FIXME: shouldn't we keep selectors until the block is deleted?
363 */
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000364 SELECTOR_ReallocBlock( sel, 0, 1 );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000365 return handle;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000366 }
367
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000368 /* Fixup the size */
369
Alexandre Julliard2787be81995-05-22 18:23:01 +0000370 if (size > GLOBAL_MAX_ALLOC_SIZE - 0x20) return 0;
371 if (size == 0) size = 0x20;
372 else size = (size + 0x1f) & ~0x1f;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000373
Alexandre Julliard594997c1995-04-30 10:05:20 +0000374 /* Change the flags */
375
376 if (flags & GMEM_MODIFY)
377 {
378 /* Change the flags, leaving GA_DGROUP alone */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000379 pArena->flags = (pArena->flags & GA_DGROUP) | (flags & GA_MOVEABLE);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000380 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
381 return handle;
382 }
383
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000384 /* Reallocate the linear memory */
385
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000386 ptr = (void *)pArena->base;
387 oldsize = pArena->size;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000388 TRACE(global,"oldsize %08lx\n",oldsize);
Alexandre Julliard7d654eb1996-02-25 11:36:22 +0000389 if (ptr && (size == oldsize)) return handle; /* Nothing to do */
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000390
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000391 ptr = HeapReAlloc( SystemHeap, 0, ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000392 if (!ptr)
393 {
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000394 SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000395 memset( pArena, 0, sizeof(GLOBALARENA) );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000396 return 0;
397 }
398
399 /* Reallocate the selector(s) */
400
Alexandre Julliard284c9b91999-04-11 15:07:13 +0000401 sel = SELECTOR_ReallocBlock( sel, ptr, size );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000402 if (!sel)
403 {
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000404 HeapFree( SystemHeap, 0, ptr );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000405 memset( pArena, 0, sizeof(GLOBALARENA) );
406 return 0;
407 }
408 selcount = (size + 0xffff) / 0x10000;
409
410 if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
411 {
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000412 HeapFree( SystemHeap, 0, ptr );
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000413 SELECTOR_FreeBlock( sel, selcount );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000414 return 0;
415 }
416
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000417 /* Fill the new arena block */
418
419 if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
420 pNewArena->base = (DWORD)ptr;
421 pNewArena->size = GET_SEL_LIMIT(sel) + 1;
422 pNewArena->selCount = selcount;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000423 pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000424
425 if (selcount > 1) /* clear the next arena blocks */
426 memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
427
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000428 if ((oldsize < size) && (flags & GMEM_ZEROINIT))
429 memset( (char *)ptr + oldsize, 0, size - oldsize );
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000430 return pNewArena->handle;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000431}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000432
433
434/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000435 * GlobalFree16 (KERNEL.17)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000436 * RETURNS
437 * NULL: Success
438 * Handle: Failure
Alexandre Julliard121bd981993-07-08 17:37:25 +0000439 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000440HGLOBAL16 WINAPI GlobalFree16(
441 HGLOBAL16 handle /* [in] Handle of global memory object */
442) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000443 void *ptr;
Alexandre Julliard121bd981993-07-08 17:37:25 +0000444
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000445 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000446 WARN(global,"Invalid handle 0x%04x passed to GlobalFree16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000447 return 0;
448 }
449 ptr = (void *)GET_ARENA_PTR(handle)->base;
450
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000451 TRACE(global, "%04x\n", handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000452 if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000453#ifdef CONFIG_IPC
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000454 if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000455#endif /* CONFIG_IPC */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000456 if (ptr) HeapFree( SystemHeap, 0, ptr );
Alexandre Julliard121bd981993-07-08 17:37:25 +0000457 return 0;
458}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000459
460
461/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000462 * WIN16_GlobalLock16 (KERNEL.18)
Alexandre Julliard121bd981993-07-08 17:37:25 +0000463 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000464 * This is the GlobalLock16() function used by 16-bit code.
Alexandre Julliard121bd981993-07-08 17:37:25 +0000465 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000466SEGPTR WINAPI WIN16_GlobalLock16( HGLOBAL16 handle )
Alexandre Julliard121bd981993-07-08 17:37:25 +0000467{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000468 TRACE(global, "(%04x) -> %08lx\n",
Alexandre Julliarda3960291999-02-26 11:11:13 +0000469 handle, MAKELONG( 0, GlobalHandleToSel16(handle)) );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000470 if (handle)
471 {
472 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000473
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000474#ifdef CONFIG_IPC
Alexandre Julliard77b99181997-09-14 17:17:23 +0000475 if (is_dde_handle(handle))
476 return PTR_SEG_OFF_TO_SEGPTR( DDE_GlobalHandleToSel(handle), 0 );
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000477#endif /* CONFIG_IPC */
478
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000479 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000480 WARN(global,"Invalid handle 0x%04x passed to WIN16_GlobalLock16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000481 return (SEGPTR)0;
482 }
Alexandre Julliard77b99181997-09-14 17:17:23 +0000483 if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000484 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000485 return PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel16(handle), 0 );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000486 /* FIXME: put segment value in CX as well */
487 }
488 return (SEGPTR)0;
Alexandre Julliard121bd981993-07-08 17:37:25 +0000489}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000490
491
492/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000493 * GlobalLock16 (KERNEL.18)
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000494 *
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000495 * This is the GlobalLock16() function used by 32-bit code.
Alexandre Julliard54c27111998-03-29 19:44:57 +0000496 *
497 * RETURNS
498 * Pointer to first byte of memory block
499 * NULL: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000500 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000501LPVOID WINAPI GlobalLock16(
502 HGLOBAL16 handle /* [in] Handle of global memory object */
503) {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000504 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000505 if (!VALID_HANDLE(handle))
506 return (LPVOID)0;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000507 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000508#ifdef CONFIG_IPC
509 if (is_dde_handle(handle)) return DDE_AttachHandle(handle, NULL);
510#endif
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000511 return (LPVOID)GET_ARENA_PTR(handle)->base;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000512}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000513
514
515/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000516 * GlobalUnlock16 (KERNEL.19)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000517 * NOTES
518 * Should the return values be cast to booleans?
519 *
520 * RETURNS
521 * TRUE: Object is still locked
522 * FALSE: Object is unlocked
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000523 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000524BOOL16 WINAPI GlobalUnlock16(
525 HGLOBAL16 handle /* [in] Handle of global memory object */
526) {
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000527 GLOBALARENA *pArena = GET_ARENA_PTR(handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000528 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000529 WARN(global,"Invalid handle 0x%04x passed to GlobalUnlock16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000530 return 0;
531 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000532 TRACE(global, "%04x\n", handle );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000533 if (pArena->lockCount) pArena->lockCount--;
534 return pArena->lockCount;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000535}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000536
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000537/***********************************************************************
538 * GlobalChangeLockCount (KERNEL.365)
539 *
540 * This is declared as a register function as it has to preserve
541 * *all* registers, even AX/DX !
542 *
543 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000544void WINAPI GlobalChangeLockCount16( CONTEXT *context )
Ulrich Weigand23e9b041998-12-01 15:19:54 +0000545{
546 LPWORD args = PTR_SEG_OFF_TO_LIN( SS_reg( context ), SP_reg( context ) );
547 HGLOBAL16 handle = (HGLOBAL16)args[3];
548 INT16 delta = (INT16) args[2];
549
550 if ( delta == 1 )
551 GlobalLock16( handle );
552 else if ( delta == -1 )
553 GlobalUnlock16( handle );
554 else
555 ERR( global, "(%04X, %d): strange delta value\n", handle, delta );
556}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000557
558/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000559 * GlobalSize16 (KERNEL.20)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000560 * RETURNS
561 * Size in bytes of object
562 * 0: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000563 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000564DWORD WINAPI GlobalSize16(
565 HGLOBAL16 handle /* [in] Handle of global memory object */
566) {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000567 TRACE(global, "%04x\n", handle );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000568 if (!handle) return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000569 if (!VALID_HANDLE(handle))
570 return 0;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000571 return GET_ARENA_PTR(handle)->size;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000572}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000573
574
575/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000576 * GlobalHandle16 (KERNEL.21)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000577 * NOTES
578 * Why is GlobalHandleToSel used here with the sel as input?
579 *
580 * RETURNS
581 * Handle: Success
582 * NULL: Failure
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000583 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000584DWORD WINAPI GlobalHandle16(
585 WORD sel /* [in] Address of global memory block */
586) {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000587 TRACE(global, "%04x\n", sel );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000588 if (!VALID_HANDLE(sel)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000589 WARN(global,"Invalid handle 0x%04x passed to GlobalHandle16!\n",sel);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000590 return 0;
591 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000592 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel16(sel) );
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000593}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000594
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000595/***********************************************************************
596 * GlobalHandleNoRIP (KERNEL.159)
597 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000598DWORD WINAPI GlobalHandleNoRIP16( WORD sel )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000599{
600 int i;
601 for (i = globalArenaSize-1 ; i>=0 ; i--) {
602 if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == sel)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000603 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel16(sel) );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000604 }
605 return 0;
606}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000607
Alexandre Julliard54c27111998-03-29 19:44:57 +0000608
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000609/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000610 * GlobalFlags16 (KERNEL.22)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000611 * NOTES
612 * Should this return GMEM_INVALID_HANDLE instead of 0 on invalid
613 * handle?
614 *
615 * RETURNS
616 * Value specifying flags and lock count
617 * GMEM_INVALID_HANDLE: Invalid handle
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000618 */
Alexandre Julliard54c27111998-03-29 19:44:57 +0000619UINT16 WINAPI GlobalFlags16(
620 HGLOBAL16 handle /* [in] Handle of global memory object */
621) {
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000622 GLOBALARENA *pArena;
623
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000624 TRACE(global, "%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000625 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000626 WARN(global,"Invalid handle 0x%04x passed to GlobalFlags16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000627 return 0;
628 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000629 pArena = GET_ARENA_PTR(handle);
630 return pArena->lockCount |
Alexandre Julliard2787be81995-05-22 18:23:01 +0000631 ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0) |
632 ((pArena->base == 0) ? GMEM_DISCARDED : 0);
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000633}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000634
635
636/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000637 * LockSegment16 (KERNEL.23)
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000638 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000639HGLOBAL16 WINAPI LockSegment16( HGLOBAL16 handle )
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000640{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000641 TRACE(global, "%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000642 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000643 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000644 WARN(global,"Invalid handle 0x%04x passed to LockSegment16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000645 return 0;
646 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000647 GET_ARENA_PTR(handle)->lockCount++;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000648 return handle;
Alexandre Julliard75a839a1993-07-15 11:13:45 +0000649}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000650
651
652/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000653 * UnlockSegment16 (KERNEL.24)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000654 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000655void WINAPI UnlockSegment16( HGLOBAL16 handle )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000656{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000657 TRACE(global, "%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000658 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000659 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000660 WARN(global,"Invalid handle 0x%04x passed to UnlockSegment16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000661 return;
662 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000663 GET_ARENA_PTR(handle)->lockCount--;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000664 /* FIXME: this ought to return the lock count in CX (go figure...) */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000665}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000666
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000667
668/***********************************************************************
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000669 * GlobalCompact16 (KERNEL.25)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000670 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000671DWORD WINAPI GlobalCompact16( DWORD desired )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000672{
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000673 return GLOBAL_MAX_ALLOC_SIZE;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000674}
675
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000676
677/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000678 * GlobalFreeAll (KERNEL.26)
679 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000680void WINAPI GlobalFreeAll16( HGLOBAL16 owner )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000681{
682 DWORD i;
683 GLOBALARENA *pArena;
684
685 pArena = pGlobalArena;
686 for (i = 0; i < globalArenaSize; i++, pArena++)
687 {
688 if ((pArena->size != 0) && (pArena->hOwner == owner))
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000689 GlobalFree16( pArena->handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000690 }
691}
692
693
694/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000695 * GlobalWire16 (KERNEL.111)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000696 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000697SEGPTR WINAPI GlobalWire16( HGLOBAL16 handle )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000698{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000699 return WIN16_GlobalLock16( handle );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000700}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000701
702
703/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000704 * GlobalUnWire16 (KERNEL.112)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000705 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000706BOOL16 WINAPI GlobalUnWire16( HGLOBAL16 handle )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000707{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000708 return !GlobalUnlock16( handle );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000709}
Alexandre Julliardaca05781994-10-17 18:12:41 +0000710
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000711
712/***********************************************************************
Alexandre Julliarde658d821997-11-30 17:45:40 +0000713 * SetSwapAreaSize16 (KERNEL.106)
Alexandre Julliardaca05781994-10-17 18:12:41 +0000714 */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000715LONG WINAPI SetSwapAreaSize16( WORD size )
Alexandre Julliardaca05781994-10-17 18:12:41 +0000716{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000717 FIXME(global, "(%d) - stub!\n", size );
Alexandre Julliardaca05781994-10-17 18:12:41 +0000718 return MAKELONG( size, 0xffff );
719}
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000720
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000721
722/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000723 * GlobalLRUOldest (KERNEL.163)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000724 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000725HGLOBAL16 WINAPI GlobalLRUOldest16( HGLOBAL16 handle )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000726{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000727 TRACE(global, "%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000728 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000729 return handle;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000730}
731
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000732
733/***********************************************************************
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000734 * GlobalLRUNewest (KERNEL.164)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000735 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000736HGLOBAL16 WINAPI GlobalLRUNewest16( HGLOBAL16 handle )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000737{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000738 TRACE(global, "%04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000739 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000740 return handle;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000741}
742
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000743
744/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000745 * GetFreeSpace16 (KERNEL.169)
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000746 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000747DWORD WINAPI GetFreeSpace16( UINT16 wFlags )
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000748{
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000749 MEMORYSTATUS ms;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000750 GlobalMemoryStatus( &ms );
751 return ms.dwAvailVirtual;
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000752}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000753
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000754/***********************************************************************
755 * GlobalDOSAlloc (KERNEL.184)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000756 * RETURNS
757 * Address (HW=Paragraph segment; LW=Selector)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000758 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000759DWORD WINAPI GlobalDOSAlloc16(
Alexandre Julliard54c27111998-03-29 19:44:57 +0000760 DWORD size /* [in] Number of bytes to be allocated */
761) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000762 UINT16 uParagraph;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000763 LPVOID lpBlock = DOSMEM_GetBlock( 0, size, &uParagraph );
Alexandre Julliard54c27111998-03-29 19:44:57 +0000764
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000765 if( lpBlock )
766 {
Alexandre Julliard21979011997-03-05 08:22:35 +0000767 HMODULE16 hModule = GetModuleHandle16("KERNEL");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000768 WORD wSelector;
769
770 wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size,
771 hModule, 0, 0, 0, NULL );
772 return MAKELONG(wSelector,uParagraph);
773 }
774 return 0;
775}
776
Alexandre Julliard54c27111998-03-29 19:44:57 +0000777
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000778/***********************************************************************
779 * GlobalDOSFree (KERNEL.185)
Alexandre Julliard54c27111998-03-29 19:44:57 +0000780 * RETURNS
781 * NULL: Success
782 * sel: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000783 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000784WORD WINAPI GlobalDOSFree16(
Alexandre Julliard54c27111998-03-29 19:44:57 +0000785 WORD sel /* [in] Selector */
786) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000787 DWORD block = GetSelectorBase(sel);
788
789 if( block && block < 0x100000 )
790 {
791 LPVOID lpBlock = DOSMEM_MapDosToLinear( block );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000792 if( DOSMEM_FreeBlock( 0, lpBlock ) )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000793 GLOBAL_FreeBlock( sel );
794 sel = 0;
795 }
796 return sel;
797}
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000798
Alexandre Julliard54c27111998-03-29 19:44:57 +0000799
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000800/***********************************************************************
801 * GlobalPageLock (KERNEL.191)
802 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000803WORD WINAPI GlobalPageLock16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000804{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000805 TRACE(global, "%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000806 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000807 WARN(global,"Invalid handle 0x%04x passed to GlobalPageLock!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000808 return 0;
809 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000810 return ++(GET_ARENA_PTR(handle)->pageLockCount);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000811}
812
813
814/***********************************************************************
815 * GlobalPageUnlock (KERNEL.192)
816 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000817WORD WINAPI GlobalPageUnlock16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000818{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000819 TRACE(global, "%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000820 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000821 WARN(global,"Invalid handle 0x%04x passed to GlobalPageUnlock!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000822 return 0;
823 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000824 return --(GET_ARENA_PTR(handle)->pageLockCount);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000825}
826
827
828/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000829 * GlobalFix16 (KERNEL.197)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000830 */
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000831WORD WINAPI GlobalFix16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000832{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000833 TRACE(global, "%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000834 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000835 WARN(global,"Invalid handle 0x%04x passed to GlobalFix16!\n",handle);
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000836 return 0;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000837 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000838 GET_ARENA_PTR(handle)->lockCount++;
Ulrich Weigand85a7ff41998-10-11 19:10:10 +0000839
Alexandre Julliarda3960291999-02-26 11:11:13 +0000840 return GlobalHandleToSel16(handle);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000841}
842
843
844/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000845 * GlobalUnfix16 (KERNEL.198)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000846 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000847void WINAPI GlobalUnfix16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000848{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000849 TRACE(global, "%04x\n", handle );
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000850 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000851 WARN(global,"Invalid handle 0x%04x passed to GlobalUnfix16!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000852 return;
853 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000854 GET_ARENA_PTR(handle)->lockCount--;
855}
856
857
858/***********************************************************************
859 * FarSetOwner (KERNEL.403)
860 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000861void WINAPI FarSetOwner16( HGLOBAL16 handle, HANDLE16 hOwner )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000862{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000863 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000864 WARN(global,"Invalid handle 0x%04x passed to FarSetOwner!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000865 return;
866 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000867 GET_ARENA_PTR(handle)->hOwner = hOwner;
868}
869
870
871/***********************************************************************
872 * FarGetOwner (KERNEL.404)
873 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000874HANDLE16 WINAPI FarGetOwner16( HGLOBAL16 handle )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000875{
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000876 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000877 WARN(global,"Invalid handle 0x%04x passed to FarGetOwner!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000878 return 0;
879 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000880 return GET_ARENA_PTR(handle)->hOwner;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000881}
882
883
884/***********************************************************************
885 * GlobalHandleToSel (TOOLHELP.50)
886 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000887WORD WINAPI GlobalHandleToSel16( HGLOBAL16 handle )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000888{
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000889 if (!handle) return 0;
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000890#ifdef CONFIG_IPC
891 if (is_dde_handle(handle)) return DDE_GlobalHandleToSel(handle);
892#endif
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000893 if (!VALID_HANDLE(handle)) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000894 WARN(global,"Invalid handle 0x%04x passed to GlobalHandleToSel!\n",handle);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000895 return 0;
896 }
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000897 if (!(handle & 7))
898 {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000899 WARN(global, "Program attempted invalid selector conversion\n" );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000900 return handle - 1;
901 }
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000902 return handle | 7;
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000903}
904
905
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000906/***********************************************************************
907 * GlobalFirst (TOOLHELP.51)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000908 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000909BOOL16 WINAPI GlobalFirst16( GLOBALENTRY *pGlobal, WORD wFlags )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000910{
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000911 if (wFlags == GLOBAL_LRU) return FALSE;
912 pGlobal->dwNext = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000913 return GlobalNext16( pGlobal, wFlags );
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000914}
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000915
916
917/***********************************************************************
918 * GlobalNext (TOOLHELP.52)
919 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000920BOOL16 WINAPI GlobalNext16( GLOBALENTRY *pGlobal, WORD wFlags)
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000921{
922 GLOBALARENA *pArena;
923
Alexandre Julliard594997c1995-04-30 10:05:20 +0000924 if (pGlobal->dwNext >= globalArenaSize) return FALSE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000925 pArena = pGlobalArena + pGlobal->dwNext;
926 if (wFlags == GLOBAL_FREE) /* only free blocks */
927 {
928 int i;
929 for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
930 if (pArena->size == 0) break; /* block is free */
931 if (i >= globalArenaSize) return FALSE;
932 pGlobal->dwNext = i;
933 }
934
935 pGlobal->dwAddress = pArena->base;
936 pGlobal->dwBlockSize = pArena->size;
937 pGlobal->hBlock = pArena->handle;
938 pGlobal->wcLock = pArena->lockCount;
939 pGlobal->wcPageLock = pArena->pageLockCount;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000940 pGlobal->wFlags = (GetCurrentPDB16() == pArena->hOwner);
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000941 pGlobal->wHeapPresent = FALSE;
942 pGlobal->hOwner = pArena->hOwner;
943 pGlobal->wType = GT_UNKNOWN;
944 pGlobal->wData = 0;
945 pGlobal->dwNext++;
946 return TRUE;
947}
948
949
950/***********************************************************************
951 * GlobalInfo (TOOLHELP.53)
952 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000953BOOL16 WINAPI GlobalInfo16( GLOBALINFO *pInfo )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000954{
955 int i;
956 GLOBALARENA *pArena;
957
958 pInfo->wcItems = globalArenaSize;
959 pInfo->wcItemsFree = 0;
960 pInfo->wcItemsLRU = 0;
961 for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
962 if (pArena->size == 0) pInfo->wcItemsFree++;
963 return TRUE;
964}
965
966
967/***********************************************************************
968 * GlobalEntryHandle (TOOLHELP.54)
969 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000970BOOL16 WINAPI GlobalEntryHandle16( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000971{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000972 GLOBALARENA *pArena = GET_ARENA_PTR(hItem);
973
974 pGlobal->dwAddress = pArena->base;
975 pGlobal->dwBlockSize = pArena->size;
976 pGlobal->hBlock = pArena->handle;
977 pGlobal->wcLock = pArena->lockCount;
978 pGlobal->wcPageLock = pArena->pageLockCount;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000979 pGlobal->wFlags = (GetCurrentPDB16() == pArena->hOwner);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000980 pGlobal->wHeapPresent = FALSE;
981 pGlobal->hOwner = pArena->hOwner;
982 pGlobal->wType = GT_UNKNOWN;
983 pGlobal->wData = 0;
984 pGlobal->dwNext++;
985 return TRUE;
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000986}
987
988
989/***********************************************************************
990 * GlobalEntryModule (TOOLHELP.55)
991 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000992BOOL16 WINAPI GlobalEntryModule16( GLOBALENTRY *pGlobal, HMODULE16 hModule,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000993 WORD wSeg )
Alexandre Julliardfa68b751995-04-03 16:55:37 +0000994{
995 return FALSE;
996}
997
998
999/***********************************************************************
1000 * MemManInfo (TOOLHELP.72)
1001 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001002BOOL16 WINAPI MemManInfo16( MEMMANINFO *info )
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001003{
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001004 MEMORYSTATUS status;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001005
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001006 /*
1007 * Not unsurprisingly although the documention says you
1008 * _must_ provide the size in the dwSize field, this function
1009 * (under Windows) always fills the structure and returns true.
1010 */
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001011 GlobalMemoryStatus( &status );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001012 info->wPageSize = VIRTUAL_GetPageSize();
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001013 info->dwLargestFreeBlock = status.dwAvailVirtual;
1014 info->dwMaxPagesAvailable = info->dwLargestFreeBlock / info->wPageSize;
1015 info->dwMaxPagesLockable = info->dwMaxPagesAvailable;
1016 info->dwTotalLinearSpace = status.dwTotalVirtual / info->wPageSize;
1017 info->dwTotalUnlockedPages = info->dwTotalLinearSpace;
1018 info->dwFreePages = info->dwMaxPagesAvailable;
1019 info->dwTotalPages = info->dwTotalLinearSpace;
1020 info->dwFreeLinearSpace = info->dwMaxPagesAvailable;
1021 info->dwSwapFilePages = status.dwTotalPageFile / info->wPageSize;
Alexandre Julliardfa68b751995-04-03 16:55:37 +00001022 return TRUE;
1023}
Alexandre Julliard2787be81995-05-22 18:23:01 +00001024
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001025/***********************************************************************
1026 * GetFreeMemInfo (KERNEL.316)
1027 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001028DWORD WINAPI GetFreeMemInfo16(void)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001029{
1030 MEMMANINFO info;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001031 MemManInfo16( &info );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001032 return MAKELONG( info.dwTotalLinearSpace, info.dwMaxPagesAvailable );
1033}
1034
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001035/*
1036 * Win32 Global heap functions (GlobalXXX).
1037 * These functions included in Win32 for compatibility with 16 bit Windows
1038 * Especially the moveable blocks and handles are oldish.
1039 * But the ability to directly allocate memory with GPTR and LPTR is widely
1040 * used.
1041 *
1042 * The handle stuff looks horrible, but it's implemented almost like Win95
1043 * does it.
1044 *
1045 */
1046
1047#define MAGIC_GLOBAL_USED 0x5342
1048#define GLOBAL_LOCK_MAX 0xFF
Alexandre Julliard17216f51997-10-12 16:30:17 +00001049#define HANDLE_TO_INTERN(h) ((PGLOBAL32_INTERN)(((char *)(h))-2))
Alexandre Julliarda3960291999-02-26 11:11:13 +00001050#define INTERN_TO_HANDLE(i) ((HGLOBAL) &((i)->Pointer))
1051#define POINTER_TO_HANDLE(p) (*(((HGLOBAL *)(p))-1))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001052#define ISHANDLE(h) (((DWORD)(h)&2)!=0)
1053#define ISPOINTER(h) (((DWORD)(h)&2)==0)
1054
1055typedef struct __GLOBAL32_INTERN
1056{
1057 WORD Magic;
1058 LPVOID Pointer WINE_PACKED;
1059 BYTE Flags;
1060 BYTE LockCount;
1061} GLOBAL32_INTERN, *PGLOBAL32_INTERN;
1062
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001063
1064/***********************************************************************
1065 * GlobalAlloc32 (KERNEL32.315)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001066 * RETURNS
1067 * Handle: Success
1068 * NULL: Failure
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001069 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001070HGLOBAL WINAPI GlobalAlloc(
1071 UINT flags, /* [in] Object allocation attributes */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001072 DWORD size /* [in] Number of bytes to allocate */
1073) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001074 PGLOBAL32_INTERN pintern;
1075 DWORD hpflags;
1076 LPVOID palloc;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001077
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001078 if(flags&GMEM_ZEROINIT)
1079 hpflags=HEAP_ZERO_MEMORY;
1080 else
1081 hpflags=0;
1082
1083 if((flags & GMEM_MOVEABLE)==0) /* POINTER */
1084 {
1085 palloc=HeapAlloc(GetProcessHeap(), hpflags, size);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001086 return (HGLOBAL) palloc;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001087 }
1088 else /* HANDLE */
1089 {
1090 /* HeapLock(GetProcessHeap()); */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001091
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001092 pintern=HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
1093 if(size)
1094 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001095 palloc=HeapAlloc(GetProcessHeap(), hpflags, size+sizeof(HGLOBAL));
1096 *(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
1097 pintern->Pointer=palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001098 }
1099 else
1100 pintern->Pointer=NULL;
1101 pintern->Magic=MAGIC_GLOBAL_USED;
1102 pintern->Flags=flags>>8;
1103 pintern->LockCount=0;
1104
1105 /* HeapUnlock(GetProcessHeap()); */
1106
1107 return INTERN_TO_HANDLE(pintern);
1108 }
1109}
1110
1111
1112/***********************************************************************
1113 * GlobalLock32 (KERNEL32.326)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001114 * RETURNS
1115 * Pointer to first byte of block
1116 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001117 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001118LPVOID WINAPI GlobalLock(
1119 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001120) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001121 PGLOBAL32_INTERN pintern;
1122 LPVOID palloc;
1123
1124 if(ISPOINTER(hmem))
1125 return (LPVOID) hmem;
1126
1127 /* HeapLock(GetProcessHeap()); */
1128
1129 pintern=HANDLE_TO_INTERN(hmem);
1130 if(pintern->Magic==MAGIC_GLOBAL_USED)
1131 {
1132 if(pintern->LockCount<GLOBAL_LOCK_MAX)
1133 pintern->LockCount++;
1134 palloc=pintern->Pointer;
1135 }
1136 else
1137 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001138 WARN(global, "invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001139 palloc=(LPVOID) NULL;
1140 }
1141 /* HeapUnlock(GetProcessHeap()); */;
1142 return palloc;
1143}
1144
1145
1146/***********************************************************************
1147 * GlobalUnlock32 (KERNEL32.332)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001148 * RETURNS
1149 * TRUE: Object is still locked
1150 * FALSE: Object is unlocked
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001151 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001152BOOL WINAPI GlobalUnlock(
1153 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001154) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001155 PGLOBAL32_INTERN pintern;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001156 BOOL locked;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001157
1158 if(ISPOINTER(hmem))
1159 return FALSE;
1160
1161 /* HeapLock(GetProcessHeap()); */
1162 pintern=HANDLE_TO_INTERN(hmem);
1163
1164 if(pintern->Magic==MAGIC_GLOBAL_USED)
1165 {
1166 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
1167 pintern->LockCount--;
1168
1169 locked=(pintern->LockCount==0) ? FALSE : TRUE;
1170 }
1171 else
1172 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001173 WARN(global, "invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001174 locked=FALSE;
1175 }
1176 /* HeapUnlock(GetProcessHeap()); */
1177 return locked;
1178}
1179
1180
1181/***********************************************************************
1182 * GlobalHandle32 (KERNEL32.325)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001183 * Returns the handle associated with the specified pointer.
1184 *
1185 * NOTES
1186 * Since there in only one goto, can it be removed and the return
1187 * be put 'inline'?
1188 *
1189 * RETURNS
1190 * Handle: Success
1191 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001192 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001193HGLOBAL WINAPI GlobalHandle(
Alexandre Julliard54c27111998-03-29 19:44:57 +00001194 LPCVOID pmem /* [in] Pointer to global memory block */
1195) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001196 HGLOBAL handle;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001197
1198 if (!HEAP_IsInsideHeap( GetProcessHeap(), 0, pmem )) goto error;
1199 handle = POINTER_TO_HANDLE(pmem);
Alexandre Julliard17216f51997-10-12 16:30:17 +00001200 if (HEAP_IsInsideHeap( GetProcessHeap(), 0, (LPCVOID)handle ))
1201 {
1202 if (HANDLE_TO_INTERN(handle)->Magic == MAGIC_GLOBAL_USED)
1203 return handle; /* valid moveable block */
1204 }
1205 /* maybe FIXED block */
1206 if (HeapValidate( GetProcessHeap(), 0, pmem ))
Alexandre Julliarda3960291999-02-26 11:11:13 +00001207 return (HGLOBAL)pmem; /* valid fixed block */
Alexandre Julliard17216f51997-10-12 16:30:17 +00001208
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001209error:
Alexandre Julliard17216f51997-10-12 16:30:17 +00001210 SetLastError( ERROR_INVALID_HANDLE );
1211 return 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001212}
1213
1214
1215/***********************************************************************
1216 * GlobalReAlloc32 (KERNEL32.328)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001217 * RETURNS
1218 * Handle: Success
1219 * NULL: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001220 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001221HGLOBAL WINAPI GlobalReAlloc(
1222 HGLOBAL hmem, /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001223 DWORD size, /* [in] New size of block */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001224 UINT flags /* [in] How to reallocate object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001225) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001226 LPVOID palloc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001227 HGLOBAL hnew;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001228 PGLOBAL32_INTERN pintern;
1229
Alexandre Julliard02e90081998-01-04 17:49:09 +00001230 hnew = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001231 /* HeapLock(GetProcessHeap()); */
1232 if(flags & GMEM_MODIFY) /* modify flags */
1233 {
1234 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
1235 {
1236 /* make a fixed block moveable
1237 * actually only NT is able to do this. But it's soo simple
1238 */
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001239 if (hmem == 0)
1240 {
1241 ERR(global, "GlobalReAlloc32 with null handle!\n");
Alexandre Julliard0ad42fa1999-01-31 15:04:42 +00001242 SetLastError( ERROR_NOACCESS );
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001243 return 0;
1244 }
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001245 size=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001246 hnew=GlobalAlloc( flags, size);
1247 palloc=GlobalLock(hnew);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001248 memcpy(palloc, (LPVOID) hmem, size);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001249 GlobalUnlock(hnew);
1250 GlobalFree(hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001251 }
1252 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
1253 {
1254 /* change the flags to make our block "discardable" */
1255 pintern=HANDLE_TO_INTERN(hmem);
1256 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
1257 hnew=hmem;
1258 }
1259 else
1260 {
1261 SetLastError(ERROR_INVALID_PARAMETER);
Alexandre Julliard02e90081998-01-04 17:49:09 +00001262 hnew = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001263 }
1264 }
1265 else
1266 {
1267 if(ISPOINTER(hmem))
1268 {
1269 /* reallocate fixed memory */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001270 hnew=(HGLOBAL)HeapReAlloc(GetProcessHeap(), 0, (LPVOID) hmem, size);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001271 }
1272 else
1273 {
1274 /* reallocate a moveable block */
1275 pintern=HANDLE_TO_INTERN(hmem);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001276 if(pintern->LockCount>1) {
1277 ERR(global,"handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001278 SetLastError(ERROR_INVALID_HANDLE);
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001279 } else if(size!=0)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001280 {
1281 hnew=hmem;
1282 if(pintern->Pointer)
1283 {
1284 palloc=HeapReAlloc(GetProcessHeap(), 0,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001285 pintern->Pointer-sizeof(HGLOBAL),
1286 size+sizeof(HGLOBAL) );
1287 pintern->Pointer=palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001288 }
1289 else
1290 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001291 palloc=HeapAlloc(GetProcessHeap(), 0, size+sizeof(HGLOBAL));
1292 *(HGLOBAL *)palloc=hmem;
1293 pintern->Pointer=palloc+sizeof(HGLOBAL);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001294 }
1295 }
1296 else
1297 {
1298 if(pintern->Pointer)
1299 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001300 HeapFree(GetProcessHeap(), 0, pintern->Pointer-sizeof(HGLOBAL));
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001301 pintern->Pointer=NULL;
1302 }
1303 }
1304 }
1305 }
1306 /* HeapUnlock(GetProcessHeap()); */
1307 return hnew;
1308}
1309
1310
1311/***********************************************************************
1312 * GlobalFree32 (KERNEL32.322)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001313 * RETURNS
1314 * NULL: Success
1315 * Handle: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001316 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001317HGLOBAL WINAPI GlobalFree(
1318 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001319) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001320 PGLOBAL32_INTERN pintern;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001321 HGLOBAL hreturned = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001322
1323 if(ISPOINTER(hmem)) /* POINTER */
1324 {
Alexandre Julliard02e90081998-01-04 17:49:09 +00001325 if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001326 }
1327 else /* HANDLE */
1328 {
1329 /* HeapLock(GetProcessHeap()); */
1330 pintern=HANDLE_TO_INTERN(hmem);
1331
1332 if(pintern->Magic==MAGIC_GLOBAL_USED)
1333 {
1334 if(pintern->LockCount!=0)
1335 SetLastError(ERROR_INVALID_HANDLE);
1336 if(pintern->Pointer)
1337 if(!HeapFree(GetProcessHeap(), 0,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001338 (char *)(pintern->Pointer)-sizeof(HGLOBAL)))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001339 hreturned=hmem;
1340 if(!HeapFree(GetProcessHeap(), 0, pintern))
1341 hreturned=hmem;
1342 }
1343 /* HeapUnlock(GetProcessHeap()); */
1344 }
1345 return hreturned;
1346}
1347
1348
1349/***********************************************************************
1350 * GlobalSize32 (KERNEL32.329)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001351 * RETURNS
1352 * Size in bytes of the global memory object
1353 * 0: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001354 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001355DWORD WINAPI GlobalSize(
1356 HGLOBAL hmem /* [in] Handle of global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001357) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001358 DWORD retval;
1359 PGLOBAL32_INTERN pintern;
1360
1361 if(ISPOINTER(hmem))
1362 {
1363 retval=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
1364 }
1365 else
1366 {
1367 /* HeapLock(GetProcessHeap()); */
1368 pintern=HANDLE_TO_INTERN(hmem);
1369
1370 if(pintern->Magic==MAGIC_GLOBAL_USED)
1371 {
Guy Albertelli3db8e191999-02-14 17:38:24 +00001372 if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
1373 return 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001374 retval=HeapSize(GetProcessHeap(), 0,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001375 (char *)(pintern->Pointer)-sizeof(HGLOBAL))-4;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001376 }
1377 else
1378 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001379 WARN(global, "invalid handle\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001380 retval=0;
1381 }
1382 /* HeapUnlock(GetProcessHeap()); */
1383 }
Guy Albertelli3db8e191999-02-14 17:38:24 +00001384 /* HeapSize returns 0xffffffff on failure */
1385 if (retval == 0xffffffff) retval = 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001386 return retval;
1387}
1388
1389
1390/***********************************************************************
1391 * GlobalWire32 (KERNEL32.333)
1392 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001393LPVOID WINAPI GlobalWire(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001394{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001395 return GlobalLock( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001396}
1397
1398
1399/***********************************************************************
1400 * GlobalUnWire32 (KERNEL32.330)
1401 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001402BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001403{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001404 return GlobalUnlock( hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001405}
1406
1407
1408/***********************************************************************
1409 * GlobalFix32 (KERNEL32.320)
1410 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001411VOID WINAPI GlobalFix(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001412{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001413 GlobalLock( hmem );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001414}
1415
1416
1417/***********************************************************************
1418 * GlobalUnfix32 (KERNEL32.331)
1419 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001420VOID WINAPI GlobalUnfix(HGLOBAL hmem)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001421{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001422 GlobalUnlock( hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001423}
1424
1425
1426/***********************************************************************
1427 * GlobalFlags32 (KERNEL32.321)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001428 * Returns information about the specified global memory object
1429 *
1430 * NOTES
1431 * Should this return GMEM_INVALID_HANDLE on invalid handle?
1432 *
1433 * RETURNS
1434 * Value specifying allocation flags and lock count
1435 * GMEM_INVALID_HANDLE: Failure
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001436 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001437UINT WINAPI GlobalFlags(
1438 HGLOBAL hmem /* [in] Handle to global memory object */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001439) {
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001440 DWORD retval;
1441 PGLOBAL32_INTERN pintern;
1442
1443 if(ISPOINTER(hmem))
1444 {
1445 retval=0;
1446 }
1447 else
1448 {
1449 /* HeapLock(GetProcessHeap()); */
1450 pintern=HANDLE_TO_INTERN(hmem);
1451 if(pintern->Magic==MAGIC_GLOBAL_USED)
1452 {
1453 retval=pintern->LockCount + (pintern->Flags<<8);
1454 if(pintern->Pointer==0)
1455 retval|= GMEM_DISCARDED;
1456 }
1457 else
1458 {
Alexandre Julliard54c27111998-03-29 19:44:57 +00001459 WARN(global,"Invalid handle: %04x", hmem);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001460 retval=0;
1461 }
1462 /* HeapUnlock(GetProcessHeap()); */
1463 }
1464 return retval;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001465}
1466
1467
1468/***********************************************************************
1469 * GlobalCompact32 (KERNEL32.316)
1470 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001471DWORD WINAPI GlobalCompact( DWORD minfree )
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001472{
1473 return 0; /* GlobalCompact does nothing in Win32 */
1474}
1475
1476
1477/***********************************************************************
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001478 * GlobalMemoryStatus (KERNEL32.327)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001479 * RETURNS
1480 * None
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001481 */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001482VOID WINAPI GlobalMemoryStatus(
1483 LPMEMORYSTATUS lpmem
1484) {
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001485#ifdef linux
1486 FILE *f = fopen( "/proc/meminfo", "r" );
1487 if (f)
1488 {
1489 char buffer[256];
Stephen Crowley59c4a321998-11-24 20:41:02 +00001490 int total, used, free, shared, buffers, cached;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001491
Stephen Crowley59c4a321998-11-24 20:41:02 +00001492 lpmem->dwLength = sizeof(MEMORYSTATUS);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001493 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
1494 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
1495 while (fgets( buffer, sizeof(buffer), f ))
1496 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001497 /* old style /proc/meminfo ... */
Stephen Crowley59c4a321998-11-24 20:41:02 +00001498 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001499 {
1500 lpmem->dwTotalPhys += total;
Stephen Crowley59c4a321998-11-24 20:41:02 +00001501 lpmem->dwAvailPhys += free + buffers + cached;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001502 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001503 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001504 {
1505 lpmem->dwTotalPageFile += total;
1506 lpmem->dwAvailPageFile += free;
1507 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001508
1509 /* new style /proc/meminfo ... */
1510 if (sscanf(buffer, "MemTotal: %d", &total))
1511 lpmem->dwTotalPhys = total*1024;
1512 if (sscanf(buffer, "MemFree: %d", &free))
1513 lpmem->dwAvailPhys = free*1024;
1514 if (sscanf(buffer, "SwapTotal: %d", &total))
1515 lpmem->dwTotalPageFile = total*1024;
1516 if (sscanf(buffer, "SwapFree: %d", &free))
1517 lpmem->dwAvailPageFile = free*1024;
Stephen Crowley59c4a321998-11-24 20:41:02 +00001518 if (sscanf(buffer, "Buffers: %d", &buffers))
1519 lpmem->dwAvailPhys += buffers*1024;
1520 if (sscanf(buffer, "Cached: %d", &cached))
1521 lpmem->dwAvailPhys += cached*1024;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001522 }
1523 fclose( f );
1524
1525 if (lpmem->dwTotalPhys)
1526 {
1527 lpmem->dwTotalVirtual = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
1528 lpmem->dwAvailVirtual = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
1529 lpmem->dwMemoryLoad = (lpmem->dwTotalVirtual-lpmem->dwAvailVirtual)
Alexandre Julliard491502b1997-11-01 19:08:16 +00001530 / (lpmem->dwTotalVirtual / 100);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001531 return;
1532 }
1533 }
1534#endif
1535 /* FIXME: should do something for other systems */
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001536 lpmem->dwMemoryLoad = 0;
1537 lpmem->dwTotalPhys = 16*1024*1024;
1538 lpmem->dwAvailPhys = 16*1024*1024;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001539 lpmem->dwTotalPageFile = 16*1024*1024;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001540 lpmem->dwAvailPageFile = 16*1024*1024;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001541 lpmem->dwTotalVirtual = 32*1024*1024;
1542 lpmem->dwAvailVirtual = 32*1024*1024;
Alexandre Julliard0e270f41996-08-24 18:26:35 +00001543}
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001544
Alexandre Julliard54c27111998-03-29 19:44:57 +00001545
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001546/**********************************************************************
1547 * WOWGlobalAllocLock (KERNEL32.62)
1548 *
1549 * Combined GlobalAlloc and GlobalLock.
1550 */
1551SEGPTR WINAPI WOWGlobalAllocLock16(DWORD flags,DWORD cb,HGLOBAL16 *hmem)
1552{
1553 HGLOBAL16 xhmem;
1554 xhmem = GlobalAlloc16(flags,cb);
1555 if (hmem) *hmem = xhmem;
1556 return WIN16_GlobalLock16(xhmem);
1557}
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001558
Alexandre Julliard54c27111998-03-29 19:44:57 +00001559
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001560/**********************************************************************
1561 * WOWGlobalUnlockFree (KERNEL32.64)
1562 *
1563 * Combined GlobalUnlock and GlobalFree.
1564 */
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001565WORD WINAPI WOWGlobalUnlockFree16(DWORD vpmem) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001566 if (!GlobalUnlock16(HIWORD(vpmem)))
1567 return 0;
1568 return GlobalFree16(HIWORD(vpmem));
1569}