2 * Global heap functions
4 * Copyright 1995 Alexandre Julliard
16 #include "selectors.h"
19 #include "stackframe.h"
26 /* Global arena block */
29 DWORD base
; /* Base address (0 if discarded) */
30 DWORD size
; /* Size in bytes (0 indicates a free block) */
31 HGLOBAL16 handle
; /* Handle for this block */
32 HGLOBAL16 hOwner
; /* Owner of this block */
33 BYTE lockCount
; /* Count of GlobalFix() calls */
34 BYTE pageLockCount
; /* Count of GlobalPageLock() calls */
35 BYTE flags
; /* Allocation flags */
36 BYTE selCount
; /* Number of selectors allocated for this block */
42 /* Flags definitions */
43 #define GA_MOVEABLE 0x02 /* same as GMEM_MOVEABLE */
44 #define GA_DGROUP 0x04
45 #define GA_DISCARDABLE 0x08
46 #define GA_IPCSHARE 0x10 /* same as GMEM_DDESHARE */
49 static GLOBALARENA
*pGlobalArena
= NULL
;
50 static int globalArenaSize
= 0;
52 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000 /* Largest allocation is 16M - 64K */
54 #define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
56 /***********************************************************************
59 * Return the arena for a given selector, growing the arena array if needed.
61 static GLOBALARENA
*GLOBAL_GetArena( WORD sel
, WORD selcount
)
63 if (((sel
>> __AHSHIFT
) + selcount
) > globalArenaSize
)
65 int newsize
= ((sel
>> __AHSHIFT
) + selcount
+ 0xff) & ~0xff;
66 GLOBALARENA
*pNewArena
= realloc( pGlobalArena
,
67 newsize
* sizeof(GLOBALARENA
) );
68 if (!pNewArena
) return 0;
69 pGlobalArena
= pNewArena
;
70 memset( pGlobalArena
+ globalArenaSize
, 0,
71 (newsize
- globalArenaSize
) * sizeof(GLOBALARENA
) );
72 globalArenaSize
= newsize
;
74 return pGlobalArena
+ (sel
>> __AHSHIFT
);
82 for (i
= globalArenaSize
-1 ; i
>=0 ; i
--) {
83 if (pGlobalArena
[i
].size
!=0 && (pGlobalArena
[i
].handle
& 0x8000)){
85 printf("0x%08x, ",pGlobalArena
[i
].handle
);
93 /***********************************************************************
96 * Create a global heap block for a fixed range of linear memory.
98 HGLOBAL16
GLOBAL_CreateBlock( WORD flags
, const void *ptr
, DWORD size
,
99 HGLOBAL16 hOwner
, BOOL16 isCode
,
100 BOOL16 is32Bit
, BOOL16 isReadOnly
,
106 /* Allocate the selector(s) */
108 sel
= SELECTOR_AllocBlock( ptr
, size
,
109 isCode
? SEGMENT_CODE
: SEGMENT_DATA
,
110 is32Bit
, isReadOnly
);
113 selcount
= (size
+ 0xffff) / 0x10000;
115 if (!(pArena
= GLOBAL_GetArena( sel
, selcount
)))
117 SELECTOR_FreeBlock( sel
, selcount
);
121 /* Fill the arena block */
123 pArena
->base
= (DWORD
)ptr
;
124 pArena
->size
= GET_SEL_LIMIT(sel
) + 1;
127 if ((flags
& GMEM_DDESHARE
) && Options
.ipc
)
129 pArena
->handle
= shmdata
->handle
;
130 pArena
->shmid
= shmdata
->shmid
;
135 pArena
->handle
= (flags
& GMEM_MOVEABLE
) ? sel
- 1 : sel
;
139 pArena
->handle
= (flags
& GMEM_MOVEABLE
) ? sel
- 1 : sel
;
141 pArena
->hOwner
= hOwner
;
142 pArena
->lockCount
= 0;
143 pArena
->pageLockCount
= 0;
144 pArena
->flags
= flags
& GA_MOVEABLE
;
145 if (flags
& GMEM_DISCARDABLE
) pArena
->flags
|= GA_DISCARDABLE
;
146 if (flags
& GMEM_DDESHARE
) pArena
->flags
|= GA_IPCSHARE
;
147 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
) );
152 return pArena
->handle
;
156 /***********************************************************************
159 * Free a block allocated by GLOBAL_CreateBlock, without touching
160 * the associated linear memory range.
162 BOOL16
GLOBAL_FreeBlock( HGLOBAL16 handle
)
167 if (!handle
) return TRUE
;
168 sel
= GlobalHandleToSel( handle
);
169 pArena
= GET_ARENA_PTR(sel
);
170 SELECTOR_FreeBlock( sel
, (pArena
->size
+ 0xffff) / 0x10000 );
171 memset( pArena
, 0, sizeof(GLOBALARENA
) );
176 /***********************************************************************
179 * Implementation of GlobalAlloc16()
181 HGLOBAL16
GLOBAL_Alloc( UINT16 flags
, DWORD size
, HGLOBAL16 hOwner
,
182 BOOL16 isCode
, BOOL16 is32Bit
, BOOL16 isReadOnly
)
188 dprintf_global( stddeb
, "GlobalAlloc: %ld flags=%04x\n", size
, flags
);
190 /* If size is 0, create a discarded block */
192 if (size
== 0) return GLOBAL_CreateBlock( flags
, NULL
, 1, hOwner
, isCode
,
193 is32Bit
, isReadOnly
, NULL
);
197 if (size
>= GLOBAL_MAX_ALLOC_SIZE
- 0x1f) return 0;
198 size
= (size
+ 0x1f) & ~0x1f;
200 /* Allocate the linear memory */
203 if ((flags
& GMEM_DDESHARE
) && Options
.ipc
)
204 ptr
= DDE_malloc(flags
, size
, &shmdata
);
206 #endif /* CONFIG_IPC */
208 ptr
= HeapAlloc( SystemHeap
, 0, size
);
210 /* FIXME: free discardable blocks and try again? */
213 /* Allocate the selector(s) */
215 handle
= GLOBAL_CreateBlock( flags
, ptr
, size
, hOwner
,
216 isCode
, is32Bit
, isReadOnly
, &shmdata
);
219 HeapFree( SystemHeap
, 0, ptr
);
223 if (flags
& GMEM_ZEROINIT
) memset( ptr
, 0, size
);
229 /***********************************************************************
232 * Find the arena for a given handle
233 * (when handle is not serial - e.g. DDE)
235 static GLOBALARENA
*GLOBAL_FindArena( HGLOBAL16 handle
)
238 for (i
= globalArenaSize
-1 ; i
>=0 ; i
--) {
239 if (pGlobalArena
[i
].size
!=0 && pGlobalArena
[i
].handle
== handle
)
240 return ( &pGlobalArena
[i
] );
246 /***********************************************************************
247 * DDE_GlobalHandleToSel
250 WORD
DDE_GlobalHandleToSel( HGLOBAL16 handle
)
255 pArena
= GLOBAL_FindArena(handle
);
257 int ArenaIdx
= pArena
- pGlobalArena
;
259 /* See if synchronized to the shared memory */
260 return DDE_SyncHandle(handle
, ( ArenaIdx
<< __AHSHIFT
) | 7);
263 /* attach the block */
264 DDE_AttachHandle(handle
, &segptr
);
266 return SELECTOROF( segptr
);
268 #endif /* CONFIG_IPC */
271 /***********************************************************************
272 * GlobalAlloc16 (KERNEL.15)
274 HGLOBAL16 WINAPI
GlobalAlloc16( UINT16 flags
, DWORD size
)
276 HANDLE16 owner
= GetCurrentPDB();
278 if (flags
& GMEM_DDESHARE
)
279 owner
= MODULE_HANDLEtoHMODULE16(owner
); /* Make it a module handle */
280 return GLOBAL_Alloc( flags
, size
, owner
, FALSE
, FALSE
, FALSE
);
284 /***********************************************************************
285 * GlobalReAlloc16 (KERNEL.16)
287 HGLOBAL16 WINAPI
GlobalReAlloc16( HGLOBAL16 handle
, DWORD size
, UINT16 flags
)
292 GLOBALARENA
*pArena
, *pNewArena
;
293 WORD sel
= GlobalHandleToSel( handle
);
295 dprintf_global( stddeb
, "GlobalReAlloc16: %04x %ld flags=%04x\n",
296 handle
, size
, flags
);
297 if (!handle
) return 0;
300 if (Options
.ipc
&& (flags
& GMEM_DDESHARE
|| is_dde_handle(handle
))) {
302 "GlobalReAlloc16: shared memory reallocating unimplemented\n");
305 #endif /* CONFIG_IPC */
307 pArena
= GET_ARENA_PTR( handle
);
309 /* Discard the block if requested */
311 if ((size
== 0) && (flags
& GMEM_MOVEABLE
) && !(flags
& GMEM_MODIFY
))
313 if (!(pArena
->flags
& GA_MOVEABLE
) ||
314 !(pArena
->flags
& GA_DISCARDABLE
) ||
315 (pArena
->lockCount
> 0) || (pArena
->pageLockCount
> 0)) return 0;
316 HeapFree( SystemHeap
, 0, (void *)pArena
->base
);
319 /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
320 * change the selector if we are shrinking the block.
321 * FIXME: shouldn't we keep selectors until the block is deleted?
323 SELECTOR_ReallocBlock( sel
, 0, 1, SEGMENT_DATA
, 0, 0 );
329 if (size
> GLOBAL_MAX_ALLOC_SIZE
- 0x20) return 0;
330 if (size
== 0) size
= 0x20;
331 else size
= (size
+ 0x1f) & ~0x1f;
333 /* Change the flags */
335 if (flags
& GMEM_MODIFY
)
337 /* Change the flags, leaving GA_DGROUP alone */
338 pArena
->flags
= (pArena
->flags
& GA_DGROUP
) | (flags
& GA_MOVEABLE
);
339 if (flags
& GMEM_DISCARDABLE
) pArena
->flags
|= GA_DISCARDABLE
;
343 /* Reallocate the linear memory */
345 ptr
= (void *)pArena
->base
;
346 oldsize
= pArena
->size
;
347 dprintf_global(stddeb
,"oldsize %08lx\n",oldsize
);
348 if (ptr
&& (size
== oldsize
)) return handle
; /* Nothing to do */
350 ptr
= HeapReAlloc( SystemHeap
, 0, ptr
, size
);
353 SELECTOR_FreeBlock( sel
, (oldsize
+ 0xffff) / 0x10000 );
354 memset( pArena
, 0, sizeof(GLOBALARENA
) );
358 /* Reallocate the selector(s) */
360 sel
= SELECTOR_ReallocBlock( sel
, ptr
, size
, SEGMENT_DATA
, 0, 0 );
363 HeapFree( SystemHeap
, 0, ptr
);
364 memset( pArena
, 0, sizeof(GLOBALARENA
) );
367 selcount
= (size
+ 0xffff) / 0x10000;
369 if (!(pNewArena
= GLOBAL_GetArena( sel
, selcount
)))
371 HeapFree( SystemHeap
, 0, ptr
);
372 SELECTOR_FreeBlock( sel
, selcount
);
376 /* Fill the new arena block */
378 if (pNewArena
!= pArena
) memcpy( pNewArena
, pArena
, sizeof(GLOBALARENA
) );
379 pNewArena
->base
= (DWORD
)ptr
;
380 pNewArena
->size
= GET_SEL_LIMIT(sel
) + 1;
381 pNewArena
->selCount
= selcount
;
382 pNewArena
->handle
= (pNewArena
->flags
& GA_MOVEABLE
) ? sel
- 1 : sel
;
384 if (selcount
> 1) /* clear the next arena blocks */
385 memset( pNewArena
+ 1, 0, (selcount
- 1) * sizeof(GLOBALARENA
) );
387 if ((oldsize
< size
) && (flags
& GMEM_ZEROINIT
))
388 memset( (char *)ptr
+ oldsize
, 0, size
- oldsize
);
389 return pNewArena
->handle
;
393 /***********************************************************************
394 * GlobalFree16 (KERNEL.17)
396 HGLOBAL16 WINAPI
GlobalFree16( HGLOBAL16 handle
)
398 void *ptr
= (void *)GET_ARENA_PTR(handle
)->base
;
400 dprintf_global( stddeb
, "GlobalFree16: %04x\n", handle
);
401 if (!GLOBAL_FreeBlock( handle
)) return handle
; /* failed */
403 if (is_dde_handle(handle
)) return DDE_GlobalFree(handle
);
404 #endif /* CONFIG_IPC */
405 if (ptr
) HeapFree( SystemHeap
, 0, ptr
);
410 /***********************************************************************
411 * WIN16_GlobalLock16 (KERNEL.18)
413 * This is the GlobalLock16() function used by 16-bit code.
415 SEGPTR WINAPI
WIN16_GlobalLock16( HGLOBAL16 handle
)
417 dprintf_global( stddeb
, "WIN16_GlobalLock16(%04x) -> %08lx\n",
418 handle
, MAKELONG( 0, GlobalHandleToSel(handle
)) );
421 if (handle
== (HGLOBAL16
)-1) handle
= CURRENT_DS
;
424 if (is_dde_handle(handle
))
425 return PTR_SEG_OFF_TO_SEGPTR( DDE_GlobalHandleToSel(handle
), 0 );
426 #endif /* CONFIG_IPC */
428 if (!GET_ARENA_PTR(handle
)->base
) return (SEGPTR
)0;
429 GET_ARENA_PTR(handle
)->lockCount
++;
430 return PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel(handle
), 0 );
431 /* FIXME: put segment value in CX as well */
437 /***********************************************************************
438 * GlobalLock16 (KERNEL.18)
440 * This is the GlobalLock16() function used by 32-bit code.
442 LPVOID WINAPI
GlobalLock16( HGLOBAL16 handle
)
444 if (!handle
) return 0;
445 GET_ARENA_PTR(handle
)->lockCount
++;
447 if (is_dde_handle(handle
)) return DDE_AttachHandle(handle
, NULL
);
449 return (LPVOID
)GET_ARENA_PTR(handle
)->base
;
453 /***********************************************************************
454 * GlobalUnlock16 (KERNEL.19)
456 BOOL16 WINAPI
GlobalUnlock16( HGLOBAL16 handle
)
458 GLOBALARENA
*pArena
= GET_ARENA_PTR(handle
);
459 dprintf_global( stddeb
, "GlobalUnlock16: %04x\n", handle
);
460 if (pArena
->lockCount
) pArena
->lockCount
--;
461 return pArena
->lockCount
;
465 /***********************************************************************
466 * GlobalSize16 (KERNEL.20)
468 DWORD WINAPI
GlobalSize16( HGLOBAL16 handle
)
470 dprintf_global( stddeb
, "GlobalSize16: %04x\n", handle
);
471 if (!handle
) return 0;
472 return GET_ARENA_PTR(handle
)->size
;
476 /***********************************************************************
477 * GlobalHandle16 (KERNEL.21)
479 DWORD WINAPI
GlobalHandle16( WORD sel
)
481 dprintf_global( stddeb
, "GlobalHandle16: %04x\n", sel
);
482 return MAKELONG( GET_ARENA_PTR(sel
)->handle
, GlobalHandleToSel(sel
) );
486 /***********************************************************************
487 * GlobalFlags16 (KERNEL.22)
489 UINT16 WINAPI
GlobalFlags16( HGLOBAL16 handle
)
493 dprintf_global( stddeb
, "GlobalFlags16: %04x\n", handle
);
494 pArena
= GET_ARENA_PTR(handle
);
495 return pArena
->lockCount
|
496 ((pArena
->flags
& GA_DISCARDABLE
) ? GMEM_DISCARDABLE
: 0) |
497 ((pArena
->base
== 0) ? GMEM_DISCARDED
: 0);
501 /***********************************************************************
502 * LockSegment16 (KERNEL.23)
504 HGLOBAL16 WINAPI
LockSegment16( HGLOBAL16 handle
)
506 dprintf_global( stddeb
, "LockSegment: %04x\n", handle
);
507 if (handle
== (HGLOBAL16
)-1) handle
= CURRENT_DS
;
508 GET_ARENA_PTR(handle
)->lockCount
++;
513 /***********************************************************************
514 * UnlockSegment16 (KERNEL.24)
516 void WINAPI
UnlockSegment16( HGLOBAL16 handle
)
518 dprintf_global( stddeb
, "UnlockSegment: %04x\n", handle
);
519 if (handle
== (HGLOBAL16
)-1) handle
= CURRENT_DS
;
520 GET_ARENA_PTR(handle
)->lockCount
--;
521 /* FIXME: this ought to return the lock count in CX (go figure...) */
525 /***********************************************************************
526 * GlobalCompact16 (KERNEL.25)
528 DWORD WINAPI
GlobalCompact16( DWORD desired
)
530 return GLOBAL_MAX_ALLOC_SIZE
;
534 /***********************************************************************
535 * GlobalFreeAll (KERNEL.26)
537 void WINAPI
GlobalFreeAll( HGLOBAL16 owner
)
542 pArena
= pGlobalArena
;
543 for (i
= 0; i
< globalArenaSize
; i
++, pArena
++)
545 if ((pArena
->size
!= 0) && (pArena
->hOwner
== owner
))
546 GlobalFree16( pArena
->handle
);
551 /***********************************************************************
552 * GlobalWire16 (KERNEL.111)
554 SEGPTR WINAPI
GlobalWire16( HGLOBAL16 handle
)
556 return WIN16_GlobalLock16( handle
);
560 /***********************************************************************
561 * GlobalUnWire16 (KERNEL.112)
563 BOOL16 WINAPI
GlobalUnWire16( HGLOBAL16 handle
)
565 return !GlobalUnlock16( handle
);
569 /***********************************************************************
570 * SetSwapAreaSize (KERNEL.106)
572 LONG WINAPI
SetSwapAreaSize( WORD size
)
574 dprintf_global(stdnimp
, "STUB: SetSwapAreaSize(%d)\n", size
);
575 return MAKELONG( size
, 0xffff );
579 /***********************************************************************
580 * GlobalLRUOldest (KERNEL.163)
582 HGLOBAL16 WINAPI
GlobalLRUOldest( HGLOBAL16 handle
)
584 dprintf_global( stddeb
, "GlobalLRUOldest: %04x\n", handle
);
585 if (handle
== (HGLOBAL16
)-1) handle
= CURRENT_DS
;
590 /***********************************************************************
591 * GlobalLRUNewest (KERNEL.164)
593 HGLOBAL16 WINAPI
GlobalLRUNewest( HGLOBAL16 handle
)
595 dprintf_global( stddeb
, "GlobalLRUNewest: %04x\n", handle
);
596 if (handle
== (HGLOBAL16
)-1) handle
= CURRENT_DS
;
601 /***********************************************************************
602 * GetFreeSpace16 (KERNEL.169)
604 DWORD WINAPI
GetFreeSpace16( UINT16 wFlags
)
607 GlobalMemoryStatus( &ms
);
608 return ms
.dwAvailVirtual
;
611 /***********************************************************************
612 * GlobalDOSAlloc (KERNEL.184)
614 DWORD WINAPI
GlobalDOSAlloc(DWORD size
)
617 LPVOID lpBlock
= DOSMEM_GetBlock( size
, &uParagraph
);
621 HMODULE16 hModule
= GetModuleHandle16("KERNEL");
624 wSelector
= GLOBAL_CreateBlock(GMEM_FIXED
, lpBlock
, size
,
625 hModule
, 0, 0, 0, NULL
);
626 return MAKELONG(wSelector
,uParagraph
);
631 /***********************************************************************
632 * GlobalDOSFree (KERNEL.185)
634 WORD WINAPI
GlobalDOSFree(WORD sel
)
636 DWORD block
= GetSelectorBase(sel
);
638 if( block
&& block
< 0x100000 )
640 LPVOID lpBlock
= DOSMEM_MapDosToLinear( block
);
641 if( DOSMEM_FreeBlock( lpBlock
) )
642 GLOBAL_FreeBlock( sel
);
648 /***********************************************************************
649 * GlobalPageLock (KERNEL.191)
651 WORD WINAPI
GlobalPageLock( HGLOBAL16 handle
)
653 dprintf_global( stddeb
, "GlobalPageLock: %04x\n", handle
);
654 return ++(GET_ARENA_PTR(handle
)->pageLockCount
);
658 /***********************************************************************
659 * GlobalPageUnlock (KERNEL.192)
661 WORD WINAPI
GlobalPageUnlock( HGLOBAL16 handle
)
663 dprintf_global( stddeb
, "GlobalPageUnlock: %04x\n", handle
);
664 return --(GET_ARENA_PTR(handle
)->pageLockCount
);
668 /***********************************************************************
669 * GlobalFix16 (KERNEL.197)
671 void WINAPI
GlobalFix16( HGLOBAL16 handle
)
673 dprintf_global( stddeb
, "GlobalFix16: %04x\n", handle
);
674 GET_ARENA_PTR(handle
)->lockCount
++;
678 /***********************************************************************
679 * GlobalUnfix16 (KERNEL.198)
681 void WINAPI
GlobalUnfix16( HGLOBAL16 handle
)
683 dprintf_global( stddeb
, "GlobalUnfix16: %04x\n", handle
);
684 GET_ARENA_PTR(handle
)->lockCount
--;
688 /***********************************************************************
689 * FarSetOwner (KERNEL.403)
691 void WINAPI
FarSetOwner( HGLOBAL16 handle
, HANDLE16 hOwner
)
693 GET_ARENA_PTR(handle
)->hOwner
= hOwner
;
697 /***********************************************************************
698 * FarGetOwner (KERNEL.404)
700 HANDLE16 WINAPI
FarGetOwner( HGLOBAL16 handle
)
702 return GET_ARENA_PTR(handle
)->hOwner
;
706 /***********************************************************************
707 * GlobalHandleToSel (TOOLHELP.50)
709 WORD WINAPI
GlobalHandleToSel( HGLOBAL16 handle
)
711 dprintf_toolhelp( stddeb
, "GlobalHandleToSel: %04x\n", handle
);
712 if (!handle
) return 0;
714 if (is_dde_handle(handle
)) return DDE_GlobalHandleToSel(handle
);
718 fprintf( stderr
, "Program attempted invalid selector conversion\n" );
725 /***********************************************************************
726 * GlobalFirst (TOOLHELP.51)
728 BOOL16 WINAPI
GlobalFirst( GLOBALENTRY
*pGlobal
, WORD wFlags
)
730 if (wFlags
== GLOBAL_LRU
) return FALSE
;
732 return GlobalNext( pGlobal
, wFlags
);
736 /***********************************************************************
737 * GlobalNext (TOOLHELP.52)
739 BOOL16 WINAPI
GlobalNext( GLOBALENTRY
*pGlobal
, WORD wFlags
)
743 if (pGlobal
->dwNext
>= globalArenaSize
) return FALSE
;
744 pArena
= pGlobalArena
+ pGlobal
->dwNext
;
745 if (wFlags
== GLOBAL_FREE
) /* only free blocks */
748 for (i
= pGlobal
->dwNext
; i
< globalArenaSize
; i
++, pArena
++)
749 if (pArena
->size
== 0) break; /* block is free */
750 if (i
>= globalArenaSize
) return FALSE
;
754 pGlobal
->dwAddress
= pArena
->base
;
755 pGlobal
->dwBlockSize
= pArena
->size
;
756 pGlobal
->hBlock
= pArena
->handle
;
757 pGlobal
->wcLock
= pArena
->lockCount
;
758 pGlobal
->wcPageLock
= pArena
->pageLockCount
;
759 pGlobal
->wFlags
= (GetCurrentPDB() == pArena
->hOwner
);
760 pGlobal
->wHeapPresent
= FALSE
;
761 pGlobal
->hOwner
= pArena
->hOwner
;
762 pGlobal
->wType
= GT_UNKNOWN
;
769 /***********************************************************************
770 * GlobalInfo (TOOLHELP.53)
772 BOOL16 WINAPI
GlobalInfo( GLOBALINFO
*pInfo
)
777 pInfo
->wcItems
= globalArenaSize
;
778 pInfo
->wcItemsFree
= 0;
779 pInfo
->wcItemsLRU
= 0;
780 for (i
= 0, pArena
= pGlobalArena
; i
< globalArenaSize
; i
++, pArena
++)
781 if (pArena
->size
== 0) pInfo
->wcItemsFree
++;
786 /***********************************************************************
787 * GlobalEntryHandle (TOOLHELP.54)
789 BOOL16 WINAPI
GlobalEntryHandle( GLOBALENTRY
*pGlobal
, HGLOBAL16 hItem
)
795 /***********************************************************************
796 * GlobalEntryModule (TOOLHELP.55)
798 BOOL16 WINAPI
GlobalEntryModule( GLOBALENTRY
*pGlobal
, HMODULE16 hModule
,
805 /***********************************************************************
806 * MemManInfo (TOOLHELP.72)
808 BOOL16 WINAPI
MemManInfo( MEMMANINFO
*info
)
813 * Not unsurprisingly although the documention says you
814 * _must_ provide the size in the dwSize field, this function
815 * (under Windows) always fills the structure and returns true.
817 GlobalMemoryStatus( &status
);
819 info
->wPageSize
= sysconf(_SC_PAGESIZE
);
821 info
->wPageSize
= getpagesize();
823 info
->dwLargestFreeBlock
= status
.dwAvailVirtual
;
824 info
->dwMaxPagesAvailable
= info
->dwLargestFreeBlock
/ info
->wPageSize
;
825 info
->dwMaxPagesLockable
= info
->dwMaxPagesAvailable
;
826 info
->dwTotalLinearSpace
= status
.dwTotalVirtual
/ info
->wPageSize
;
827 info
->dwTotalUnlockedPages
= info
->dwTotalLinearSpace
;
828 info
->dwFreePages
= info
->dwMaxPagesAvailable
;
829 info
->dwTotalPages
= info
->dwTotalLinearSpace
;
830 info
->dwFreeLinearSpace
= info
->dwMaxPagesAvailable
;
831 info
->dwSwapFilePages
= status
.dwTotalPageFile
/ info
->wPageSize
;
836 * Win32 Global heap functions (GlobalXXX).
837 * These functions included in Win32 for compatibility with 16 bit Windows
838 * Especially the moveable blocks and handles are oldish.
839 * But the ability to directly allocate memory with GPTR and LPTR is widely
842 * The handle stuff looks horrible, but it's implemented almost like Win95
847 #define MAGIC_GLOBAL_USED 0x5342
848 #define GLOBAL_LOCK_MAX 0xFF
849 #define HANDLE_TO_INTERN(h) (PGLOBAL32_INTERN)(((char *)(h))-2)
850 #define INTERN_TO_HANDLE(i) ((HGLOBAL32) &((i)->Pointer))
851 #define POINTER_TO_HANDLE(p) (*(((HGLOBAL32 *)(p))-1))
852 #define ISHANDLE(h) (((DWORD)(h)&2)!=0)
853 #define ISPOINTER(h) (((DWORD)(h)&2)==0)
855 typedef struct __GLOBAL32_INTERN
858 LPVOID Pointer WINE_PACKED
;
861 } GLOBAL32_INTERN
, *PGLOBAL32_INTERN
;
864 /***********************************************************************
865 * GlobalAlloc32 (KERNEL32.315)
867 HGLOBAL32 WINAPI
GlobalAlloc32(UINT32 flags
, DWORD size
)
869 PGLOBAL32_INTERN pintern
;
873 if(flags
&GMEM_ZEROINIT
)
874 hpflags
=HEAP_ZERO_MEMORY
;
878 if((flags
& GMEM_MOVEABLE
)==0) /* POINTER */
880 palloc
=HeapAlloc(GetProcessHeap(), hpflags
, size
);
881 return (HGLOBAL32
) palloc
;
885 /* HeapLock(GetProcessHeap()); */
887 pintern
=HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN
));
890 palloc
=HeapAlloc(GetProcessHeap(), hpflags
, size
+sizeof(HGLOBAL32
));
891 *(HGLOBAL32
*)palloc
=INTERN_TO_HANDLE(pintern
);
892 pintern
->Pointer
=palloc
+sizeof(HGLOBAL32
);
895 pintern
->Pointer
=NULL
;
896 pintern
->Magic
=MAGIC_GLOBAL_USED
;
897 pintern
->Flags
=flags
>>8;
898 pintern
->LockCount
=0;
900 /* HeapUnlock(GetProcessHeap()); */
902 return INTERN_TO_HANDLE(pintern
);
907 /***********************************************************************
908 * GlobalLock32 (KERNEL32.326)
910 LPVOID WINAPI
GlobalLock32(HGLOBAL32 hmem
)
912 PGLOBAL32_INTERN pintern
;
916 return (LPVOID
) hmem
;
918 /* HeapLock(GetProcessHeap()); */
920 pintern
=HANDLE_TO_INTERN(hmem
);
921 if(pintern
->Magic
==MAGIC_GLOBAL_USED
)
923 if(pintern
->LockCount
<GLOBAL_LOCK_MAX
)
924 pintern
->LockCount
++;
925 palloc
=pintern
->Pointer
;
929 dprintf_global(stddeb
, "GlobalLock32: invalid handle\n");
930 palloc
=(LPVOID
) NULL
;
932 /* HeapUnlock(GetProcessHeap()); */;
937 /***********************************************************************
938 * GlobalUnlock32 (KERNEL32.332)
940 BOOL32 WINAPI
GlobalUnlock32(HGLOBAL32 hmem
)
942 PGLOBAL32_INTERN pintern
;
948 /* HeapLock(GetProcessHeap()); */
949 pintern
=HANDLE_TO_INTERN(hmem
);
951 if(pintern
->Magic
==MAGIC_GLOBAL_USED
)
953 if((pintern
->LockCount
<GLOBAL_LOCK_MAX
)&&(pintern
->LockCount
>0))
954 pintern
->LockCount
--;
956 locked
=(pintern
->LockCount
==0) ? FALSE
: TRUE
;
960 dprintf_global(stddeb
, "GlobalUnlock32: invalid handle\n");
963 /* HeapUnlock(GetProcessHeap()); */
968 /***********************************************************************
969 * GlobalHandle32 (KERNEL32.325)
971 HGLOBAL32 WINAPI
GlobalHandle32(LPCVOID pmem
)
973 return (HGLOBAL32
) POINTER_TO_HANDLE(pmem
);
977 /***********************************************************************
978 * GlobalReAlloc32 (KERNEL32.328)
980 HGLOBAL32 WINAPI
GlobalReAlloc32(HGLOBAL32 hmem
, DWORD size
, UINT32 flags
)
984 PGLOBAL32_INTERN pintern
;
987 /* HeapLock(GetProcessHeap()); */
988 if(flags
& GMEM_MODIFY
) /* modify flags */
990 if( ISPOINTER(hmem
) && (flags
& GMEM_MOVEABLE
))
992 /* make a fixed block moveable
993 * actually only NT is able to do this. But it's soo simple
995 size
=HeapSize(GetProcessHeap(), 0, (LPVOID
) hmem
);
996 hnew
=GlobalAlloc32( flags
, size
);
997 palloc
=GlobalLock32(hnew
);
998 memcpy(palloc
, (LPVOID
) hmem
, size
);
999 GlobalUnlock32(hnew
);
1002 else if( ISPOINTER(hmem
) &&(flags
& GMEM_DISCARDABLE
))
1004 /* change the flags to make our block "discardable" */
1005 pintern
=HANDLE_TO_INTERN(hmem
);
1006 pintern
->Flags
= pintern
->Flags
| (GMEM_DISCARDABLE
>> 8);
1011 SetLastError(ERROR_INVALID_PARAMETER
);
1019 /* reallocate fixed memory */
1020 hnew
=(HGLOBAL32
)HeapReAlloc(GetProcessHeap(), 0, (LPVOID
) hmem
, size
);
1024 /* reallocate a moveable block */
1025 pintern
=HANDLE_TO_INTERN(hmem
);
1026 if(pintern
->LockCount
!=0)
1027 SetLastError(ERROR_INVALID_HANDLE
);
1031 if(pintern
->Pointer
)
1033 palloc
=HeapReAlloc(GetProcessHeap(), 0,
1034 pintern
->Pointer
-sizeof(HGLOBAL32
),
1035 size
+sizeof(HGLOBAL32
) );
1036 pintern
->Pointer
=palloc
+sizeof(HGLOBAL32
);
1040 palloc
=HeapAlloc(GetProcessHeap(), 0, size
+sizeof(HGLOBAL32
));
1041 *(HGLOBAL32
*)palloc
=hmem
;
1042 pintern
->Pointer
=palloc
+sizeof(HGLOBAL32
);
1047 if(pintern
->Pointer
)
1049 HeapFree(GetProcessHeap(), 0, pintern
->Pointer
-sizeof(HGLOBAL32
));
1050 pintern
->Pointer
=NULL
;
1055 /* HeapUnlock(GetProcessHeap()); */
1060 /***********************************************************************
1061 * GlobalFree32 (KERNEL32.322)
1063 HGLOBAL32 WINAPI
GlobalFree32(HGLOBAL32 hmem
)
1065 PGLOBAL32_INTERN pintern
;
1066 HGLOBAL32 hreturned
=NULL
;
1068 if(ISPOINTER(hmem
)) /* POINTER */
1070 if(!HeapFree(GetProcessHeap(), 0, (LPVOID
) hmem
))
1075 /* HeapLock(GetProcessHeap()); */
1076 pintern
=HANDLE_TO_INTERN(hmem
);
1078 if(pintern
->Magic
==MAGIC_GLOBAL_USED
)
1080 if(pintern
->LockCount
!=0)
1081 SetLastError(ERROR_INVALID_HANDLE
);
1082 if(pintern
->Pointer
)
1083 if(!HeapFree(GetProcessHeap(), 0,
1084 (char *)(pintern
->Pointer
)-sizeof(HGLOBAL32
)))
1086 if(!HeapFree(GetProcessHeap(), 0, pintern
))
1089 /* HeapUnlock(GetProcessHeap()); */
1095 /***********************************************************************
1096 * GlobalSize32 (KERNEL32.329)
1098 DWORD WINAPI
GlobalSize32(HGLOBAL32 hmem
)
1101 PGLOBAL32_INTERN pintern
;
1105 retval
=HeapSize(GetProcessHeap(), 0, (LPVOID
) hmem
);
1109 /* HeapLock(GetProcessHeap()); */
1110 pintern
=HANDLE_TO_INTERN(hmem
);
1112 if(pintern
->Magic
==MAGIC_GLOBAL_USED
)
1114 retval
=HeapSize(GetProcessHeap(), 0,
1115 (char *)(pintern
->Pointer
)-sizeof(HGLOBAL32
))-4;
1119 dprintf_global(stddeb
, "GlobalSize32: invalid handle\n");
1122 /* HeapUnlock(GetProcessHeap()); */
1128 /***********************************************************************
1129 * GlobalWire32 (KERNEL32.333)
1131 LPVOID WINAPI
GlobalWire32(HGLOBAL32 hmem
)
1133 return GlobalLock32( hmem
);
1137 /***********************************************************************
1138 * GlobalUnWire32 (KERNEL32.330)
1140 BOOL32 WINAPI
GlobalUnWire32(HGLOBAL32 hmem
)
1142 return GlobalUnlock32( hmem
);
1146 /***********************************************************************
1147 * GlobalFix32 (KERNEL32.320)
1149 VOID WINAPI
GlobalFix32(HGLOBAL32 hmem
)
1151 GlobalLock32( hmem
);
1155 /***********************************************************************
1156 * GlobalUnfix32 (KERNEL32.331)
1158 VOID WINAPI
GlobalUnfix32(HGLOBAL32 hmem
)
1160 GlobalUnlock32( hmem
);
1164 /***********************************************************************
1165 * GlobalFlags32 (KERNEL32.321)
1167 UINT32 WINAPI
GlobalFlags32(HGLOBAL32 hmem
)
1170 PGLOBAL32_INTERN pintern
;
1178 /* HeapLock(GetProcessHeap()); */
1179 pintern
=HANDLE_TO_INTERN(hmem
);
1180 if(pintern
->Magic
==MAGIC_GLOBAL_USED
)
1182 retval
=pintern
->LockCount
+ (pintern
->Flags
<<8);
1183 if(pintern
->Pointer
==0)
1184 retval
|= GMEM_DISCARDED
;
1188 dprintf_global(stddeb
,"GlobalFlags32: invalid handle\n");
1191 /* HeapUnlock(GetProcessHeap()); */
1197 /***********************************************************************
1198 * GlobalCompact32 (KERNEL32.316)
1200 DWORD WINAPI
GlobalCompact32( DWORD minfree
)
1202 return 0; /* GlobalCompact does nothing in Win32 */
1206 /***********************************************************************
1207 * GlobalMemoryStatus (KERNEL32.327)
1209 VOID WINAPI
GlobalMemoryStatus( LPMEMORYSTATUS lpmem
)
1212 FILE *f
= fopen( "/proc/meminfo", "r" );
1216 int total
, used
, free
;
1218 lpmem
->dwTotalPhys
= lpmem
->dwAvailPhys
= 0;
1219 lpmem
->dwTotalPageFile
= lpmem
->dwAvailPageFile
= 0;
1220 while (fgets( buffer
, sizeof(buffer
), f
))
1222 /* old style /proc/meminfo ... */
1223 if (sscanf( buffer
, "Mem: %d %d %d", &total
, &used
, &free
))
1225 lpmem
->dwTotalPhys
+= total
;
1226 lpmem
->dwAvailPhys
+= free
;
1228 if (sscanf( buffer
, "Swap: %d %d %d", &total
, &used
, &free
))
1230 lpmem
->dwTotalPageFile
+= total
;
1231 lpmem
->dwAvailPageFile
+= free
;
1234 /* new style /proc/meminfo ... */
1235 if (sscanf(buffer
, "MemTotal: %d", &total
))
1236 lpmem
->dwTotalPhys
= total
*1024;
1237 if (sscanf(buffer
, "MemFree: %d", &free
))
1238 lpmem
->dwAvailPhys
= free
*1024;
1239 if (sscanf(buffer
, "SwapTotal: %d", &total
))
1240 lpmem
->dwTotalPageFile
= total
*1024;
1241 if (sscanf(buffer
, "SwapFree: %d", &free
))
1242 lpmem
->dwAvailPageFile
= free
*1024;
1246 if (lpmem
->dwTotalPhys
)
1248 lpmem
->dwTotalVirtual
= lpmem
->dwTotalPhys
+lpmem
->dwTotalPageFile
;
1249 lpmem
->dwAvailVirtual
= lpmem
->dwAvailPhys
+lpmem
->dwAvailPageFile
;
1250 lpmem
->dwMemoryLoad
= (lpmem
->dwTotalVirtual
-lpmem
->dwAvailVirtual
)
1251 * 100 / lpmem
->dwTotalVirtual
;
1256 /* FIXME: should do something for other systems */
1257 lpmem
->dwMemoryLoad
= 0;
1258 lpmem
->dwTotalPhys
= 16*1024*1024;
1259 lpmem
->dwAvailPhys
= 16*1024*1024;
1260 lpmem
->dwTotalPageFile
= 16*1024*1024;
1261 lpmem
->dwAvailPageFile
= 16*1024*1024;
1262 lpmem
->dwTotalVirtual
= 32*1024*1024;
1263 lpmem
->dwAvailVirtual
= 32*1024*1024;
1266 /**********************************************************************
1267 * WOWGlobalAllocLock (KERNEL32.62)
1269 * Combined GlobalAlloc and GlobalLock.
1271 SEGPTR WINAPI
WOWGlobalAllocLock16(DWORD flags
,DWORD cb
,HGLOBAL16
*hmem
)
1274 xhmem
= GlobalAlloc16(flags
,cb
);
1275 if (hmem
) *hmem
= xhmem
;
1276 return WIN16_GlobalLock16(xhmem
);