Release 970305
[wine/multimedia.git] / memory / global.c
blob1a5c12e7f8b454fad18cee9dfa07b347c5e3e94e
1 /*
2 * Global heap functions
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <sys/types.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
12 #include "windows.h"
13 #include "global.h"
14 #include "heap.h"
15 #include "toolhelp.h"
16 #include "selectors.h"
17 #include "miscemu.h"
18 #include "dde_mem.h"
19 #include "stackframe.h"
20 #include "options.h"
21 #include "stddebug.h"
22 #include "debug.h"
23 #include "winerror.h"
25 /* Global arena block */
26 typedef struct
28 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 */
36 #ifdef CONFIG_IPC
37 int shmid;
38 #endif
39 } GLOBALARENA;
41 /* Flags definitions */
42 #define GA_MOVEABLE 0x02 /* same as GMEM_MOVEABLE */
43 #define GA_DGROUP 0x04
44 #define GA_DISCARDABLE 0x08
45 #define GA_IPCSHARE 0x10 /* same as GMEM_DDESHARE */
47 /* Arena array */
48 static GLOBALARENA *pGlobalArena = NULL;
49 static int globalArenaSize = 0;
51 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
53 #define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
55 /***********************************************************************
56 * GLOBAL_GetArena
58 * Return the arena for a given selector, growing the arena array if needed.
60 static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
62 if (((sel >> __AHSHIFT) + selcount) > globalArenaSize)
64 int newsize = ((sel >> __AHSHIFT) + selcount + 0xff) & ~0xff;
65 GLOBALARENA *pNewArena = realloc( pGlobalArena,
66 newsize * sizeof(GLOBALARENA) );
67 if (!pNewArena) return 0;
68 pGlobalArena = pNewArena;
69 memset( pGlobalArena + globalArenaSize, 0,
70 (newsize - globalArenaSize) * sizeof(GLOBALARENA) );
71 globalArenaSize = newsize;
73 return pGlobalArena + (sel >> __AHSHIFT);
77 void debug_handles()
79 int printed=0;
80 int i;
81 for (i = globalArenaSize-1 ; i>=0 ; i--) {
82 if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
83 printed=1;
84 printf("0x%08x, ",pGlobalArena[i].handle);
87 if (printed)
88 printf("\n");
92 /***********************************************************************
93 * GLOBAL_CreateBlock
95 * Create a global heap block for a fixed range of linear memory.
97 HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
98 HGLOBAL16 hOwner, BOOL16 isCode,
99 BOOL16 is32Bit, BOOL16 isReadOnly,
100 SHMDATA *shmdata )
102 WORD sel, selcount;
103 GLOBALARENA *pArena;
105 /* Allocate the selector(s) */
107 sel = SELECTOR_AllocBlock( ptr, size,
108 isCode ? SEGMENT_CODE : SEGMENT_DATA,
109 is32Bit, isReadOnly );
111 if (!sel) return 0;
112 selcount = (size + 0xffff) / 0x10000;
114 if (!(pArena = GLOBAL_GetArena( sel, selcount )))
116 SELECTOR_FreeBlock( sel, selcount );
117 return 0;
120 /* Fill the arena block */
122 pArena->base = (DWORD)ptr;
123 pArena->size = GET_SEL_LIMIT(sel) + 1;
125 #ifdef CONFIG_IPC
126 if ((flags & GMEM_DDESHARE) && Options.ipc)
128 pArena->handle = shmdata->handle;
129 pArena->shmid = shmdata->shmid;
130 shmdata->sel = sel;
132 else
134 pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
135 pArena->shmid = 0;
137 #else
138 pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
139 #endif
140 pArena->hOwner = hOwner;
141 pArena->lockCount = 0;
142 pArena->pageLockCount = 0;
143 pArena->flags = flags & GA_MOVEABLE;
144 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
145 if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
146 if (!isCode) pArena->flags |= GA_DGROUP;
147 pArena->selCount = selcount;
148 if (selcount > 1) /* clear the next arena blocks */
149 memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
151 return pArena->handle;
155 /***********************************************************************
156 * GLOBAL_FreeBlock
158 * Free a block allocated by GLOBAL_CreateBlock, without touching
159 * the associated linear memory range.
161 BOOL16 GLOBAL_FreeBlock( HGLOBAL16 handle )
163 WORD sel;
164 GLOBALARENA *pArena;
166 if (!handle) return TRUE;
167 sel = GlobalHandleToSel( handle );
168 pArena = GET_ARENA_PTR(sel);
169 SELECTOR_FreeBlock( sel, (pArena->size + 0xffff) / 0x10000 );
170 memset( pArena, 0, sizeof(GLOBALARENA) );
171 return TRUE;
175 /***********************************************************************
176 * GLOBAL_Alloc
178 * Implementation of GlobalAlloc16()
180 HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
181 BOOL16 isCode, BOOL16 is32Bit, BOOL16 isReadOnly )
183 void *ptr;
184 HGLOBAL16 handle;
185 SHMDATA shmdata;
187 dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
189 /* If size is 0, create a discarded block */
191 if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
192 is32Bit, isReadOnly, NULL );
194 /* Fixup the size */
196 if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
197 size = (size + 0x1f) & ~0x1f;
199 /* Allocate the linear memory */
201 #ifdef CONFIG_IPC
202 if ((flags & GMEM_DDESHARE) && Options.ipc)
203 ptr = DDE_malloc(flags, size, &shmdata);
204 else
205 #endif /* CONFIG_IPC */
207 ptr = HeapAlloc( SystemHeap, 0, size );
209 if (!ptr) return 0;
211 /* Allocate the selector(s) */
213 handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
214 isCode, is32Bit, isReadOnly, &shmdata);
215 if (!handle)
217 HeapFree( SystemHeap, 0, ptr );
218 return 0;
221 if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
222 return handle;
226 #ifdef CONFIG_IPC
227 /***********************************************************************
228 * GLOBAL_FindArena
230 * Find the arena for a given handle
231 * (when handle is not serial - e.g. DDE)
233 static GLOBALARENA *GLOBAL_FindArena( HGLOBAL16 handle)
235 int i;
236 for (i = globalArenaSize-1 ; i>=0 ; i--) {
237 if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
238 return ( &pGlobalArena[i] );
240 return NULL;
244 /***********************************************************************
245 * DDE_GlobalHandleToSel
248 WORD DDE_GlobalHandleToSel( HGLOBAL16 handle )
250 GLOBALARENA *pArena;
251 SEGPTR segptr;
253 pArena= GLOBAL_FindArena(handle);
254 if (pArena) {
255 int ArenaIdx = pArena - pGlobalArena;
257 /* See if synchronized to the shared memory */
258 return DDE_SyncHandle(handle, ( ArenaIdx << __AHSHIFT) | 7);
261 /* attach the block */
262 DDE_AttachHandle(handle, &segptr);
264 return SELECTOROF( segptr );
266 #endif /* CONFIG_IPC */
269 /***********************************************************************
270 * GlobalAlloc16 (KERNEL.15)
272 HGLOBAL16 GlobalAlloc16( UINT16 flags, DWORD size )
274 HANDLE16 owner = GetCurrentPDB();
276 if (flags & GMEM_DDESHARE)
277 owner = GetExePtr(owner); /* Make it a module handle */
278 return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
282 /***********************************************************************
283 * GlobalReAlloc16 (KERNEL.16)
285 HGLOBAL16 GlobalReAlloc16( HGLOBAL16 handle, DWORD size, UINT16 flags )
287 WORD selcount;
288 DWORD oldsize;
289 void *ptr;
290 GLOBALARENA *pArena, *pNewArena;
291 WORD sel = GlobalHandleToSel( handle );
293 dprintf_global( stddeb, "GlobalReAlloc16: %04x %ld flags=%04x\n",
294 handle, size, flags );
295 if (!handle) return 0;
297 #ifdef CONFIG_IPC
298 if (Options.ipc && (flags & GMEM_DDESHARE || is_dde_handle(handle))) {
299 fprintf(stdnimp,
300 "GlobalReAlloc16: shared memory reallocating unimplemented\n");
301 return 0;
303 #endif /* CONFIG_IPC */
305 pArena = GET_ARENA_PTR( handle );
307 /* Discard the block if requested */
309 if ((size == 0) && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY))
311 if (!(pArena->flags & GA_MOVEABLE) ||
312 !(pArena->flags & GA_DISCARDABLE) ||
313 (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
314 HeapFree( SystemHeap, 0, (void *)pArena->base );
315 pArena->base = 0;
316 /* Note: we rely on the fact that SELECTOR_ReallocBlock won't */
317 /* change the selector if we are shrinking the block */
318 SELECTOR_ReallocBlock( sel, 0, 1, SEGMENT_DATA, 0, 0 );
319 return handle;
322 /* Fixup the size */
324 if (size > GLOBAL_MAX_ALLOC_SIZE - 0x20) return 0;
325 if (size == 0) size = 0x20;
326 else size = (size + 0x1f) & ~0x1f;
328 /* Change the flags */
330 if (flags & GMEM_MODIFY)
332 /* Change the flags, leaving GA_DGROUP alone */
333 pArena->flags = (pArena->flags & GA_DGROUP) | (flags & GA_MOVEABLE);
334 if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
335 return handle;
338 /* Reallocate the linear memory */
340 ptr = (void *)pArena->base;
341 oldsize = pArena->size;
342 dprintf_global(stddeb,"oldsize %08lx\n",oldsize);
343 if (ptr && (size == oldsize)) return handle; /* Nothing to do */
345 ptr = HeapReAlloc( SystemHeap, 0, ptr, size );
346 if (!ptr)
348 SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
349 memset( pArena, 0, sizeof(GLOBALARENA) );
350 return 0;
353 /* Reallocate the selector(s) */
355 sel = SELECTOR_ReallocBlock( sel, ptr, size, SEGMENT_DATA, 0, 0 );
356 if (!sel)
358 HeapFree( SystemHeap, 0, ptr );
359 memset( pArena, 0, sizeof(GLOBALARENA) );
360 return 0;
362 selcount = (size + 0xffff) / 0x10000;
364 if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
366 HeapFree( SystemHeap, 0, ptr );
367 SELECTOR_FreeBlock( sel, selcount );
368 return 0;
371 /* Fill the new arena block */
373 if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
374 pNewArena->base = (DWORD)ptr;
375 pNewArena->size = GET_SEL_LIMIT(sel) + 1;
376 pNewArena->selCount = selcount;
377 pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
379 if (selcount > 1) /* clear the next arena blocks */
380 memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
382 if ((oldsize < size) && (flags & GMEM_ZEROINIT))
383 memset( (char *)ptr + oldsize, 0, size - oldsize );
384 return pNewArena->handle;
388 /***********************************************************************
389 * GlobalFree16 (KERNEL.17)
391 HGLOBAL16 GlobalFree16( HGLOBAL16 handle )
393 void *ptr = GlobalLock16( handle );
395 dprintf_global( stddeb, "GlobalFree16: %04x\n", handle );
396 if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
397 #ifdef CONFIG_IPC
398 if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
399 #endif /* CONFIG_IPC */
400 if (ptr) HeapFree( SystemHeap, 0, ptr );
401 return 0;
405 /***********************************************************************
406 * WIN16_GlobalLock16 (KERNEL.18)
408 * This is the GlobalLock16() function used by 16-bit code.
410 SEGPTR WIN16_GlobalLock16( HGLOBAL16 handle )
412 dprintf_global( stddeb, "WIN16_GlobalLock16(%04x) -> %08lx\n",
413 handle, MAKELONG( 0, GlobalHandleToSel(handle)) );
414 if (!handle) return 0;
416 #ifdef CONFIG_IPC
417 if (is_dde_handle(handle))
418 return PTR_SEG_OFF_TO_SEGPTR( DDE_GlobalHandleToSel(handle), 0 );
419 #endif /* CONFIG_IPC */
421 if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
422 return PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel(handle), 0 );
426 /***********************************************************************
427 * GlobalLock16 (KERNEL.18)
429 * This is the GlobalLock16() function used by 32-bit code.
431 LPVOID GlobalLock16( HGLOBAL16 handle )
433 if (!handle) return 0;
434 #ifdef CONFIG_IPC
435 if (is_dde_handle(handle)) return DDE_AttachHandle(handle, NULL);
436 #endif
437 return (LPVOID)GET_ARENA_PTR(handle)->base;
441 /***********************************************************************
442 * GlobalUnlock16 (KERNEL.19)
444 BOOL16 GlobalUnlock16( HGLOBAL16 handle )
446 dprintf_global( stddeb, "GlobalUnlock16: %04x\n", handle );
447 return 0;
451 /***********************************************************************
452 * GlobalSize16 (KERNEL.20)
454 DWORD GlobalSize16( HGLOBAL16 handle )
456 dprintf_global( stddeb, "GlobalSize16: %04x\n", handle );
457 if (!handle) return 0;
458 return GET_ARENA_PTR(handle)->size;
462 /***********************************************************************
463 * GlobalHandle16 (KERNEL.21)
465 DWORD GlobalHandle16( WORD sel )
467 dprintf_global( stddeb, "GlobalHandle16: %04x\n", sel );
468 return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel(sel) );
472 /***********************************************************************
473 * GlobalFlags16 (KERNEL.22)
475 UINT16 GlobalFlags16( HGLOBAL16 handle )
477 GLOBALARENA *pArena;
479 dprintf_global( stddeb, "GlobalFlags16: %04x\n", handle );
480 pArena = GET_ARENA_PTR(handle);
481 return pArena->lockCount |
482 ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0) |
483 ((pArena->base == 0) ? GMEM_DISCARDED : 0);
487 /***********************************************************************
488 * LockSegment16 (KERNEL.23)
490 HGLOBAL16 LockSegment16( HGLOBAL16 handle )
492 dprintf_global( stddeb, "LockSegment: %04x\n", handle );
493 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
494 GET_ARENA_PTR(handle)->lockCount++;
495 return handle;
499 /***********************************************************************
500 * UnlockSegment16 (KERNEL.24)
502 void UnlockSegment16( HGLOBAL16 handle )
504 dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
505 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
506 GET_ARENA_PTR(handle)->lockCount--;
507 /* FIXME: this ought to return the lock count in CX (go figure...) */
511 /***********************************************************************
512 * GlobalCompact16 (KERNEL.25)
514 DWORD GlobalCompact16( DWORD desired )
516 return GLOBAL_MAX_ALLOC_SIZE;
520 /***********************************************************************
521 * GlobalFreeAll (KERNEL.26)
523 void GlobalFreeAll( HGLOBAL16 owner )
525 DWORD i;
526 GLOBALARENA *pArena;
528 pArena = pGlobalArena;
529 for (i = 0; i < globalArenaSize; i++, pArena++)
531 if ((pArena->size != 0) && (pArena->hOwner == owner))
532 GlobalFree16( pArena->handle );
537 /***********************************************************************
538 * GlobalWire16 (KERNEL.111)
540 SEGPTR GlobalWire16( HGLOBAL16 handle )
542 return WIN16_GlobalLock16( handle );
546 /***********************************************************************
547 * GlobalUnWire16 (KERNEL.112)
549 BOOL16 GlobalUnWire16( HGLOBAL16 handle )
551 return GlobalUnlock16( handle );
555 /***********************************************************************
556 * SetSwapAreaSize (KERNEL.106)
558 LONG SetSwapAreaSize( WORD size )
560 dprintf_global(stdnimp, "STUB: SetSwapAreaSize(%d)\n", size );
561 return MAKELONG( size, 0xffff );
565 /***********************************************************************
566 * GlobalLRUOldest (KERNEL.163)
568 HGLOBAL16 GlobalLRUOldest( HGLOBAL16 handle )
570 dprintf_global( stddeb, "GlobalLRUOldest: %04x\n", handle );
571 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
572 return handle;
576 /***********************************************************************
577 * GlobalLRUNewest (KERNEL.164)
579 HGLOBAL16 GlobalLRUNewest( HGLOBAL16 handle )
581 dprintf_global( stddeb, "GlobalLRUNewest: %04x\n", handle );
582 if (handle == (HGLOBAL16)-1) handle = CURRENT_DS;
583 return handle;
587 /***********************************************************************
588 * GetFreeSpace16 (KERNEL.169)
590 DWORD GetFreeSpace16( UINT16 wFlags )
592 MEMORYSTATUS ms;
593 GlobalMemoryStatus( &ms );
594 return ms.dwAvailVirtual;
597 /***********************************************************************
598 * GlobalDOSAlloc (KERNEL.184)
600 DWORD GlobalDOSAlloc(DWORD size)
602 UINT16 uParagraph;
603 LPVOID lpBlock = DOSMEM_GetBlock( size, &uParagraph );
605 if( lpBlock )
607 HMODULE16 hModule = GetModuleHandle16("KERNEL");
608 WORD wSelector;
610 wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size,
611 hModule, 0, 0, 0, NULL );
612 return MAKELONG(wSelector,uParagraph);
614 return 0;
617 /***********************************************************************
618 * GlobalDOSFree (KERNEL.185)
620 WORD GlobalDOSFree(WORD sel)
622 DWORD block = GetSelectorBase(sel);
624 if( block && block < 0x100000 )
626 LPVOID lpBlock = DOSMEM_MapDosToLinear( block );
627 if( DOSMEM_FreeBlock( lpBlock ) )
628 GLOBAL_FreeBlock( sel );
629 sel = 0;
631 return sel;
634 /***********************************************************************
635 * GlobalPageLock (KERNEL.191)
637 WORD GlobalPageLock( HGLOBAL16 handle )
639 dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
640 return ++(GET_ARENA_PTR(handle)->pageLockCount);
644 /***********************************************************************
645 * GlobalPageUnlock (KERNEL.192)
647 WORD GlobalPageUnlock( HGLOBAL16 handle )
649 dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
650 return --(GET_ARENA_PTR(handle)->pageLockCount);
654 /***********************************************************************
655 * GlobalFix16 (KERNEL.197)
657 void GlobalFix16( HGLOBAL16 handle )
659 dprintf_global( stddeb, "GlobalFix16: %04x\n", handle );
660 GET_ARENA_PTR(handle)->lockCount++;
664 /***********************************************************************
665 * GlobalUnfix16 (KERNEL.198)
667 void GlobalUnfix16( HGLOBAL16 handle )
669 dprintf_global( stddeb, "GlobalUnfix16: %04x\n", handle );
670 GET_ARENA_PTR(handle)->lockCount--;
674 /***********************************************************************
675 * FarSetOwner (KERNEL.403)
677 void FarSetOwner( HGLOBAL16 handle, HANDLE16 hOwner )
679 GET_ARENA_PTR(handle)->hOwner = hOwner;
683 /***********************************************************************
684 * FarGetOwner (KERNEL.404)
686 HANDLE16 FarGetOwner( HGLOBAL16 handle )
688 return GET_ARENA_PTR(handle)->hOwner;
692 /***********************************************************************
693 * GlobalHandleToSel (TOOLHELP.50)
695 WORD GlobalHandleToSel( HGLOBAL16 handle )
697 dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
698 if (!handle) return 0;
699 #ifdef CONFIG_IPC
700 if (is_dde_handle(handle)) return DDE_GlobalHandleToSel(handle);
701 #endif
702 if (!(handle & 7))
704 fprintf( stderr, "Program attempted invalid selector conversion\n" );
705 return handle - 1;
707 return handle | 7;
711 /***********************************************************************
712 * GlobalFirst (TOOLHELP.51)
714 BOOL16 GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
716 if (wFlags == GLOBAL_LRU) return FALSE;
717 pGlobal->dwNext = 0;
718 return GlobalNext( pGlobal, wFlags );
722 /***********************************************************************
723 * GlobalNext (TOOLHELP.52)
725 BOOL16 GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
727 GLOBALARENA *pArena;
729 if (pGlobal->dwNext >= globalArenaSize) return FALSE;
730 pArena = pGlobalArena + pGlobal->dwNext;
731 if (wFlags == GLOBAL_FREE) /* only free blocks */
733 int i;
734 for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
735 if (pArena->size == 0) break; /* block is free */
736 if (i >= globalArenaSize) return FALSE;
737 pGlobal->dwNext = i;
740 pGlobal->dwAddress = pArena->base;
741 pGlobal->dwBlockSize = pArena->size;
742 pGlobal->hBlock = pArena->handle;
743 pGlobal->wcLock = pArena->lockCount;
744 pGlobal->wcPageLock = pArena->pageLockCount;
745 pGlobal->wFlags = (GetCurrentPDB() == pArena->hOwner);
746 pGlobal->wHeapPresent = FALSE;
747 pGlobal->hOwner = pArena->hOwner;
748 pGlobal->wType = GT_UNKNOWN;
749 pGlobal->wData = 0;
750 pGlobal->dwNext++;
751 return TRUE;
755 /***********************************************************************
756 * GlobalInfo (TOOLHELP.53)
758 BOOL16 GlobalInfo( GLOBALINFO *pInfo )
760 int i;
761 GLOBALARENA *pArena;
763 pInfo->wcItems = globalArenaSize;
764 pInfo->wcItemsFree = 0;
765 pInfo->wcItemsLRU = 0;
766 for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
767 if (pArena->size == 0) pInfo->wcItemsFree++;
768 return TRUE;
772 /***********************************************************************
773 * GlobalEntryHandle (TOOLHELP.54)
775 BOOL16 GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
777 return FALSE;
781 /***********************************************************************
782 * GlobalEntryModule (TOOLHELP.55)
784 BOOL16 GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE16 hModule, WORD wSeg )
786 return FALSE;
790 /***********************************************************************
791 * MemManInfo (TOOLHELP.72)
793 BOOL16 MemManInfo( MEMMANINFO *info )
795 MEMORYSTATUS status;
797 if (info->dwSize < sizeof(MEMMANINFO)) return FALSE;
798 GlobalMemoryStatus( &status );
799 #ifdef __svr4__
800 info->wPageSize = sysconf(_SC_PAGESIZE);
801 #else
802 info->wPageSize = getpagesize();
803 #endif
804 info->dwLargestFreeBlock = status.dwAvailVirtual;
805 info->dwMaxPagesAvailable = info->dwLargestFreeBlock / info->wPageSize;
806 info->dwMaxPagesLockable = info->dwMaxPagesAvailable;
807 info->dwTotalLinearSpace = status.dwTotalVirtual / info->wPageSize;
808 info->dwTotalUnlockedPages = info->dwTotalLinearSpace;
809 info->dwFreePages = info->dwMaxPagesAvailable;
810 info->dwTotalPages = info->dwTotalLinearSpace;
811 info->dwFreeLinearSpace = info->dwMaxPagesAvailable;
812 info->dwSwapFilePages = status.dwTotalPageFile / info->wPageSize;
813 return TRUE;
817 * Win32 Global heap functions (GlobalXXX).
818 * These functions included in Win32 for compatibility with 16 bit Windows
819 * Especially the moveable blocks and handles are oldish.
820 * But the ability to directly allocate memory with GPTR and LPTR is widely
821 * used.
823 * The handle stuff looks horrible, but it's implemented almost like Win95
824 * does it.
828 #define MAGIC_GLOBAL_USED 0x5342
829 #define GLOBAL_LOCK_MAX 0xFF
830 #define HANDLE_TO_INTERN(h) (PGLOBAL32_INTERN)(((char *)(h))-2)
831 #define INTERN_TO_HANDLE(i) ((HGLOBAL32) &((i)->Pointer))
832 #define POINTER_TO_HANDLE(p) (*(((HGLOBAL32 *)(p))-1))
833 #define ISHANDLE(h) (((DWORD)(h)&2)!=0)
834 #define ISPOINTER(h) (((DWORD)(h)&2)==0)
836 typedef struct __GLOBAL32_INTERN
838 WORD Magic;
839 LPVOID Pointer WINE_PACKED;
840 BYTE Flags;
841 BYTE LockCount;
842 } GLOBAL32_INTERN, *PGLOBAL32_INTERN;
845 /***********************************************************************
846 * GlobalAlloc32 (KERNEL32.315)
848 HGLOBAL32 GlobalAlloc32(UINT32 flags, DWORD size)
850 PGLOBAL32_INTERN pintern;
851 DWORD hpflags;
852 LPVOID palloc;
854 if(flags&GMEM_ZEROINIT)
855 hpflags=HEAP_ZERO_MEMORY;
856 else
857 hpflags=0;
859 if((flags & GMEM_MOVEABLE)==0) /* POINTER */
861 palloc=HeapAlloc(GetProcessHeap(), hpflags, size);
862 return (HGLOBAL32) palloc;
864 else /* HANDLE */
866 /* HeapLock(GetProcessHeap()); */
868 pintern=HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
869 if(size)
871 palloc=HeapAlloc(GetProcessHeap(), 0, size+sizeof(HGLOBAL32));
872 *(HGLOBAL32 *)palloc=INTERN_TO_HANDLE(pintern);
873 pintern->Pointer=palloc+sizeof(HGLOBAL32);
875 else
876 pintern->Pointer=NULL;
877 pintern->Magic=MAGIC_GLOBAL_USED;
878 pintern->Flags=flags>>8;
879 pintern->LockCount=0;
881 /* HeapUnlock(GetProcessHeap()); */
883 return INTERN_TO_HANDLE(pintern);
888 /***********************************************************************
889 * GlobalLock32 (KERNEL32.326)
891 LPVOID GlobalLock32(HGLOBAL32 hmem)
893 PGLOBAL32_INTERN pintern;
894 LPVOID palloc;
896 if(ISPOINTER(hmem))
897 return (LPVOID) hmem;
899 /* HeapLock(GetProcessHeap()); */
901 pintern=HANDLE_TO_INTERN(hmem);
902 if(pintern->Magic==MAGIC_GLOBAL_USED)
904 if(pintern->LockCount<GLOBAL_LOCK_MAX)
905 pintern->LockCount++;
906 palloc=pintern->Pointer;
908 else
910 dprintf_global(stddeb, "GlobalLock32: invalid handle\n");
911 palloc=(LPVOID) NULL;
913 /* HeapUnlock(GetProcessHeap()); */;
914 return palloc;
918 /***********************************************************************
919 * GlobalUnlock32 (KERNEL32.332)
921 BOOL32 GlobalUnlock32(HGLOBAL32 hmem)
923 PGLOBAL32_INTERN pintern;
924 BOOL32 locked;
926 if(ISPOINTER(hmem))
927 return FALSE;
929 /* HeapLock(GetProcessHeap()); */
930 pintern=HANDLE_TO_INTERN(hmem);
932 if(pintern->Magic==MAGIC_GLOBAL_USED)
934 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
935 pintern->LockCount--;
937 locked=(pintern->LockCount==0) ? FALSE : TRUE;
939 else
941 dprintf_global(stddeb, "GlobalUnlock32: invalid handle\n");
942 locked=FALSE;
944 /* HeapUnlock(GetProcessHeap()); */
945 return locked;
949 /***********************************************************************
950 * GlobalHandle32 (KERNEL32.325)
952 HGLOBAL32 GlobalHandle32(LPCVOID pmem)
954 return (HGLOBAL32) POINTER_TO_HANDLE(pmem);
958 /***********************************************************************
959 * GlobalReAlloc32 (KERNEL32.328)
961 HGLOBAL32 GlobalReAlloc32(HGLOBAL32 hmem, DWORD size, UINT32 flags)
963 LPVOID palloc;
964 HGLOBAL32 hnew;
965 PGLOBAL32_INTERN pintern;
967 hnew=NULL;
968 /* HeapLock(GetProcessHeap()); */
969 if(flags & GMEM_MODIFY) /* modify flags */
971 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
973 /* make a fixed block moveable
974 * actually only NT is able to do this. But it's soo simple
976 size=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
977 hnew=GlobalAlloc32( flags, size);
978 palloc=GlobalLock32(hnew);
979 memcpy(palloc, (LPVOID) hmem, size);
980 GlobalUnlock32(hnew);
981 GlobalFree32(hmem);
983 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
985 /* change the flags to make our block "discardable" */
986 pintern=HANDLE_TO_INTERN(hmem);
987 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
988 hnew=hmem;
990 else
992 SetLastError(ERROR_INVALID_PARAMETER);
993 hnew=NULL;
996 else
998 if(ISPOINTER(hmem))
1000 /* reallocate fixed memory */
1001 hnew=(HGLOBAL32)HeapReAlloc(GetProcessHeap(), 0, (LPVOID) hmem, size);
1003 else
1005 /* reallocate a moveable block */
1006 pintern=HANDLE_TO_INTERN(hmem);
1007 if(pintern->LockCount!=0)
1008 SetLastError(ERROR_INVALID_HANDLE);
1009 else if(size!=0)
1011 hnew=hmem;
1012 if(pintern->Pointer)
1014 palloc=HeapReAlloc(GetProcessHeap(), 0,
1015 pintern->Pointer-sizeof(HGLOBAL32),
1016 size+sizeof(HGLOBAL32) );
1017 pintern->Pointer=palloc+sizeof(HGLOBAL32);
1019 else
1021 palloc=HeapAlloc(GetProcessHeap(), 0, size+sizeof(HGLOBAL32));
1022 *(HGLOBAL32 *)palloc=hmem;
1023 pintern->Pointer=palloc+sizeof(HGLOBAL32);
1026 else
1028 if(pintern->Pointer)
1030 HeapFree(GetProcessHeap(), 0, pintern->Pointer-sizeof(HGLOBAL32));
1031 pintern->Pointer=NULL;
1036 /* HeapUnlock(GetProcessHeap()); */
1037 return hnew;
1041 /***********************************************************************
1042 * GlobalFree32 (KERNEL32.322)
1044 HGLOBAL32 GlobalFree32(HGLOBAL32 hmem)
1046 PGLOBAL32_INTERN pintern;
1047 HGLOBAL32 hreturned=NULL;
1049 if(ISPOINTER(hmem)) /* POINTER */
1051 if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem))
1052 hmem=NULL;
1054 else /* HANDLE */
1056 /* HeapLock(GetProcessHeap()); */
1057 pintern=HANDLE_TO_INTERN(hmem);
1059 if(pintern->Magic==MAGIC_GLOBAL_USED)
1061 if(pintern->LockCount!=0)
1062 SetLastError(ERROR_INVALID_HANDLE);
1063 if(pintern->Pointer)
1064 if(!HeapFree(GetProcessHeap(), 0,
1065 (char *)(pintern->Pointer)-sizeof(HGLOBAL32)))
1066 hreturned=hmem;
1067 if(!HeapFree(GetProcessHeap(), 0, pintern))
1068 hreturned=hmem;
1070 /* HeapUnlock(GetProcessHeap()); */
1072 return hreturned;
1076 /***********************************************************************
1077 * GlobalSize32 (KERNEL32.329)
1079 DWORD GlobalSize32(HGLOBAL32 hmem)
1081 DWORD retval;
1082 PGLOBAL32_INTERN pintern;
1084 if(ISPOINTER(hmem))
1086 retval=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
1088 else
1090 /* HeapLock(GetProcessHeap()); */
1091 pintern=HANDLE_TO_INTERN(hmem);
1093 if(pintern->Magic==MAGIC_GLOBAL_USED)
1095 retval=HeapSize(GetProcessHeap(), 0,
1096 (char *)(pintern->Pointer)-sizeof(HGLOBAL32))-4;
1098 else
1100 dprintf_global(stddeb, "GlobalSize32: invalid handle\n");
1101 retval=0;
1103 /* HeapUnlock(GetProcessHeap()); */
1105 return retval;
1109 /***********************************************************************
1110 * GlobalWire32 (KERNEL32.333)
1112 LPVOID GlobalWire32(HGLOBAL32 hmem)
1114 return GlobalLock32( hmem );
1118 /***********************************************************************
1119 * GlobalUnWire32 (KERNEL32.330)
1121 BOOL32 GlobalUnWire32(HGLOBAL32 hmem)
1123 return GlobalUnlock32( hmem);
1127 /***********************************************************************
1128 * GlobalFix32 (KERNEL32.320)
1130 VOID GlobalFix32(HGLOBAL32 hmem)
1132 GlobalLock32( hmem );
1136 /***********************************************************************
1137 * GlobalUnfix32 (KERNEL32.331)
1139 VOID GlobalUnfix32(HGLOBAL32 hmem)
1141 GlobalUnlock32( hmem);
1145 /***********************************************************************
1146 * GlobalFlags32 (KERNEL32.321)
1148 UINT32 GlobalFlags32(HGLOBAL32 hmem)
1150 DWORD retval;
1151 PGLOBAL32_INTERN pintern;
1153 if(ISPOINTER(hmem))
1155 retval=0;
1157 else
1159 /* HeapLock(GetProcessHeap()); */
1160 pintern=HANDLE_TO_INTERN(hmem);
1161 if(pintern->Magic==MAGIC_GLOBAL_USED)
1163 retval=pintern->LockCount + (pintern->Flags<<8);
1164 if(pintern->Pointer==0)
1165 retval|= GMEM_DISCARDED;
1167 else
1169 dprintf_global(stddeb,"GlobalFlags32: invalid handle\n");
1170 retval=0;
1172 /* HeapUnlock(GetProcessHeap()); */
1174 return retval;
1178 /***********************************************************************
1179 * GlobalCompact32 (KERNEL32.316)
1181 DWORD GlobalCompact32( DWORD minfree )
1183 return 0; /* GlobalCompact does nothing in Win32 */
1187 /***********************************************************************
1188 * GlobalMemoryStatus (KERNEL32.327)
1190 VOID GlobalMemoryStatus( LPMEMORYSTATUS lpmem )
1192 #ifdef linux
1193 FILE *f = fopen( "/proc/meminfo", "r" );
1194 if (f)
1196 char buffer[256];
1197 int total, used, free;
1199 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
1200 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
1201 while (fgets( buffer, sizeof(buffer), f ))
1203 if (sscanf( buffer, "Mem: %d %d %d", &total, &used, &free ))
1205 lpmem->dwTotalPhys += total;
1206 lpmem->dwAvailPhys += free;
1208 else if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
1210 lpmem->dwTotalPageFile += total;
1211 lpmem->dwAvailPageFile += free;
1214 fclose( f );
1216 if (lpmem->dwTotalPhys)
1218 lpmem->dwTotalVirtual = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
1219 lpmem->dwAvailVirtual = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
1220 lpmem->dwMemoryLoad = (lpmem->dwTotalVirtual-lpmem->dwAvailVirtual)
1221 * 100 / lpmem->dwTotalVirtual;
1222 return;
1225 #endif
1226 /* FIXME: should do something for other systems */
1227 lpmem->dwMemoryLoad = 0;
1228 lpmem->dwTotalPhys = 16*1024*1024;
1229 lpmem->dwAvailPhys = 16*1024*1024;
1230 lpmem->dwTotalPageFile = 16*1024*1024;
1231 lpmem->dwAvailPageFile = 16*1024*1024;
1232 lpmem->dwTotalVirtual = 32*1024*1024;
1233 lpmem->dwAvailVirtual = 32*1024*1024;