2 * Global heap functions
4 * Copyright 1995 Alexandre Julliard
16 #include "selectors.h"
19 #include "stackframe.h"
25 /* Global arena block */
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 */
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 */
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 /***********************************************************************
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
);
81 for (i
= globalArenaSize
-1 ; i
>=0 ; i
--) {
82 if (pGlobalArena
[i
].size
!=0 && (pGlobalArena
[i
].handle
& 0x8000)){
84 printf("0x%08x, ",pGlobalArena
[i
].handle
);
92 /***********************************************************************
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
,
105 /* Allocate the selector(s) */
107 sel
= SELECTOR_AllocBlock( ptr
, size
,
108 isCode
? SEGMENT_CODE
: SEGMENT_DATA
,
109 is32Bit
, isReadOnly
);
112 selcount
= (size
+ 0xffff) / 0x10000;
114 if (!(pArena
= GLOBAL_GetArena( sel
, selcount
)))
116 SELECTOR_FreeBlock( sel
, selcount
);
120 /* Fill the arena block */
122 pArena
->base
= (DWORD
)ptr
;
123 pArena
->size
= GET_SEL_LIMIT(sel
) + 1;
126 if ((flags
& GMEM_DDESHARE
) && Options
.ipc
)
128 pArena
->handle
= shmdata
->handle
;
129 pArena
->shmid
= shmdata
->shmid
;
134 pArena
->handle
= (flags
& GMEM_MOVEABLE
) ? sel
- 1 : sel
;
138 pArena
->handle
= (flags
& GMEM_MOVEABLE
) ? sel
- 1 : sel
;
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 /***********************************************************************
158 * Free a block allocated by GLOBAL_CreateBlock, without touching
159 * the associated linear memory range.
161 BOOL16
GLOBAL_FreeBlock( HGLOBAL16 handle
)
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
) );
175 /***********************************************************************
178 * Implementation of GlobalAlloc16()
180 HGLOBAL16
GLOBAL_Alloc( UINT16 flags
, DWORD size
, HGLOBAL16 hOwner
,
181 BOOL16 isCode
, BOOL16 is32Bit
, BOOL16 isReadOnly
)
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
);
196 if (size
>= GLOBAL_MAX_ALLOC_SIZE
- 0x1f) return 0;
197 size
= (size
+ 0x1f) & ~0x1f;
199 /* Allocate the linear memory */
202 if ((flags
& GMEM_DDESHARE
) && Options
.ipc
)
203 ptr
= DDE_malloc(flags
, size
, &shmdata
);
205 #endif /* CONFIG_IPC */
207 ptr
= HeapAlloc( SystemHeap
, 0, size
);
211 /* Allocate the selector(s) */
213 handle
= GLOBAL_CreateBlock( flags
, ptr
, size
, hOwner
,
214 isCode
, is32Bit
, isReadOnly
, &shmdata
);
217 HeapFree( SystemHeap
, 0, ptr
);
221 if (flags
& GMEM_ZEROINIT
) memset( ptr
, 0, size
);
227 /***********************************************************************
230 * Find the arena for a given handle
231 * (when handle is not serial - e.g. DDE)
233 static GLOBALARENA
*GLOBAL_FindArena( HGLOBAL16 handle
)
236 for (i
= globalArenaSize
-1 ; i
>=0 ; i
--) {
237 if (pGlobalArena
[i
].size
!=0 && pGlobalArena
[i
].handle
== handle
)
238 return ( &pGlobalArena
[i
] );
244 /***********************************************************************
245 * DDE_GlobalHandleToSel
248 WORD
DDE_GlobalHandleToSel( HGLOBAL16 handle
)
253 pArena
= GLOBAL_FindArena(handle
);
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
)
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;
298 if (Options
.ipc
&& (flags
& GMEM_DDESHARE
|| is_dde_handle(handle
))) {
300 "GlobalReAlloc16: shared memory reallocating unimplemented\n");
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
);
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 );
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
;
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
);
348 SELECTOR_FreeBlock( sel
, (oldsize
+ 0xffff) / 0x10000 );
349 memset( pArena
, 0, sizeof(GLOBALARENA
) );
353 /* Reallocate the selector(s) */
355 sel
= SELECTOR_ReallocBlock( sel
, ptr
, size
, SEGMENT_DATA
, 0, 0 );
358 HeapFree( SystemHeap
, 0, ptr
);
359 memset( pArena
, 0, sizeof(GLOBALARENA
) );
362 selcount
= (size
+ 0xffff) / 0x10000;
364 if (!(pNewArena
= GLOBAL_GetArena( sel
, selcount
)))
366 HeapFree( SystemHeap
, 0, ptr
);
367 SELECTOR_FreeBlock( sel
, selcount
);
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 */
398 if (is_dde_handle(handle
)) return DDE_GlobalFree(handle
);
399 #endif /* CONFIG_IPC */
400 if (ptr
) HeapFree( SystemHeap
, 0, ptr
);
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;
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;
435 if (is_dde_handle(handle
)) return DDE_AttachHandle(handle
, NULL
);
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
);
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
)
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
++;
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
)
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
;
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
;
587 /***********************************************************************
588 * GetFreeSpace16 (KERNEL.169)
590 DWORD
GetFreeSpace16( UINT16 wFlags
)
593 GlobalMemoryStatus( &ms
);
594 return ms
.dwAvailVirtual
;
597 /***********************************************************************
598 * GlobalDOSAlloc (KERNEL.184)
600 DWORD
GlobalDOSAlloc(DWORD size
)
603 LPVOID lpBlock
= DOSMEM_GetBlock( size
, &uParagraph
);
607 HMODULE16 hModule
= GetModuleHandle16("KERNEL");
610 wSelector
= GLOBAL_CreateBlock(GMEM_FIXED
, lpBlock
, size
,
611 hModule
, 0, 0, 0, NULL
);
612 return MAKELONG(wSelector
,uParagraph
);
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
);
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;
700 if (is_dde_handle(handle
)) return DDE_GlobalHandleToSel(handle
);
704 fprintf( stderr
, "Program attempted invalid selector conversion\n" );
711 /***********************************************************************
712 * GlobalFirst (TOOLHELP.51)
714 BOOL16
GlobalFirst( GLOBALENTRY
*pGlobal
, WORD wFlags
)
716 if (wFlags
== GLOBAL_LRU
) return FALSE
;
718 return GlobalNext( pGlobal
, wFlags
);
722 /***********************************************************************
723 * GlobalNext (TOOLHELP.52)
725 BOOL16
GlobalNext( GLOBALENTRY
*pGlobal
, WORD wFlags
)
729 if (pGlobal
->dwNext
>= globalArenaSize
) return FALSE
;
730 pArena
= pGlobalArena
+ pGlobal
->dwNext
;
731 if (wFlags
== GLOBAL_FREE
) /* only free blocks */
734 for (i
= pGlobal
->dwNext
; i
< globalArenaSize
; i
++, pArena
++)
735 if (pArena
->size
== 0) break; /* block is free */
736 if (i
>= globalArenaSize
) return FALSE
;
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
;
755 /***********************************************************************
756 * GlobalInfo (TOOLHELP.53)
758 BOOL16
GlobalInfo( GLOBALINFO
*pInfo
)
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
++;
772 /***********************************************************************
773 * GlobalEntryHandle (TOOLHELP.54)
775 BOOL16
GlobalEntryHandle( GLOBALENTRY
*pGlobal
, HGLOBAL16 hItem
)
781 /***********************************************************************
782 * GlobalEntryModule (TOOLHELP.55)
784 BOOL16
GlobalEntryModule( GLOBALENTRY
*pGlobal
, HMODULE16 hModule
, WORD wSeg
)
790 /***********************************************************************
791 * MemManInfo (TOOLHELP.72)
793 BOOL16
MemManInfo( MEMMANINFO
*info
)
797 if (info
->dwSize
< sizeof(MEMMANINFO
)) return FALSE
;
798 GlobalMemoryStatus( &status
);
800 info
->wPageSize
= sysconf(_SC_PAGESIZE
);
802 info
->wPageSize
= getpagesize();
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
;
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
823 * The handle stuff looks horrible, but it's implemented almost like Win95
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
839 LPVOID Pointer WINE_PACKED
;
842 } GLOBAL32_INTERN
, *PGLOBAL32_INTERN
;
845 /***********************************************************************
846 * GlobalAlloc32 (KERNEL32.315)
848 HGLOBAL32
GlobalAlloc32(UINT32 flags
, DWORD size
)
850 PGLOBAL32_INTERN pintern
;
854 if(flags
&GMEM_ZEROINIT
)
855 hpflags
=HEAP_ZERO_MEMORY
;
859 if((flags
& GMEM_MOVEABLE
)==0) /* POINTER */
861 palloc
=HeapAlloc(GetProcessHeap(), hpflags
, size
);
862 return (HGLOBAL32
) palloc
;
866 /* HeapLock(GetProcessHeap()); */
868 pintern
=HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN
));
871 palloc
=HeapAlloc(GetProcessHeap(), 0, size
+sizeof(HGLOBAL32
));
872 *(HGLOBAL32
*)palloc
=INTERN_TO_HANDLE(pintern
);
873 pintern
->Pointer
=palloc
+sizeof(HGLOBAL32
);
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
;
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
;
910 dprintf_global(stddeb
, "GlobalLock32: invalid handle\n");
911 palloc
=(LPVOID
) NULL
;
913 /* HeapUnlock(GetProcessHeap()); */;
918 /***********************************************************************
919 * GlobalUnlock32 (KERNEL32.332)
921 BOOL32
GlobalUnlock32(HGLOBAL32 hmem
)
923 PGLOBAL32_INTERN pintern
;
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
;
941 dprintf_global(stddeb
, "GlobalUnlock32: invalid handle\n");
944 /* HeapUnlock(GetProcessHeap()); */
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
)
965 PGLOBAL32_INTERN pintern
;
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
);
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);
992 SetLastError(ERROR_INVALID_PARAMETER
);
1000 /* reallocate fixed memory */
1001 hnew
=(HGLOBAL32
)HeapReAlloc(GetProcessHeap(), 0, (LPVOID
) hmem
, size
);
1005 /* reallocate a moveable block */
1006 pintern
=HANDLE_TO_INTERN(hmem
);
1007 if(pintern
->LockCount
!=0)
1008 SetLastError(ERROR_INVALID_HANDLE
);
1012 if(pintern
->Pointer
)
1014 palloc
=HeapReAlloc(GetProcessHeap(), 0,
1015 pintern
->Pointer
-sizeof(HGLOBAL32
),
1016 size
+sizeof(HGLOBAL32
) );
1017 pintern
->Pointer
=palloc
+sizeof(HGLOBAL32
);
1021 palloc
=HeapAlloc(GetProcessHeap(), 0, size
+sizeof(HGLOBAL32
));
1022 *(HGLOBAL32
*)palloc
=hmem
;
1023 pintern
->Pointer
=palloc
+sizeof(HGLOBAL32
);
1028 if(pintern
->Pointer
)
1030 HeapFree(GetProcessHeap(), 0, pintern
->Pointer
-sizeof(HGLOBAL32
));
1031 pintern
->Pointer
=NULL
;
1036 /* HeapUnlock(GetProcessHeap()); */
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
))
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
)))
1067 if(!HeapFree(GetProcessHeap(), 0, pintern
))
1070 /* HeapUnlock(GetProcessHeap()); */
1076 /***********************************************************************
1077 * GlobalSize32 (KERNEL32.329)
1079 DWORD
GlobalSize32(HGLOBAL32 hmem
)
1082 PGLOBAL32_INTERN pintern
;
1086 retval
=HeapSize(GetProcessHeap(), 0, (LPVOID
) hmem
);
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;
1100 dprintf_global(stddeb
, "GlobalSize32: invalid handle\n");
1103 /* HeapUnlock(GetProcessHeap()); */
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
)
1151 PGLOBAL32_INTERN pintern
;
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
;
1169 dprintf_global(stddeb
,"GlobalFlags32: invalid handle\n");
1172 /* HeapUnlock(GetProcessHeap()); */
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
)
1193 FILE *f
= fopen( "/proc/meminfo", "r" );
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
;
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
;
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;