Release 950901
[wine] / memory / global.c
1 /*
2  * Global heap functions
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include <sys/types.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "windows.h"
12 #include "global.h"
13 #include "toolhelp.h"
14 #include "selectors.h"
15 #include "dde_mem.h"
16 #include "stackframe.h"
17 #include "options.h"
18 #include "stddebug.h"
19 #include "debug.h"
20
21   /* Global arena block */
22 typedef struct
23 {
24     DWORD    base;           /* Base address  */
25     DWORD    size;           /* Size in bytes (0 indicates a free block) */
26     HGLOBAL  handle;         /* Handle for this block */
27     HGLOBAL  hOwner;         /* Owner of this block */
28     BYTE     lockCount;      /* Count of GlobalFix() calls */
29     BYTE     pageLockCount;  /* Count of GlobalPageLock() calls */
30     BYTE     flags;          /* Allocation flags */
31     BYTE     selCount;       /* Number of selectors allocated for this block */
32     int      shmid;
33 } GLOBALARENA;
34
35   /* Flags definitions */
36 #define GA_MOVEABLE     0x02  /* same as GMEM_MOVEABLE */
37 #define GA_DGROUP       0x04
38 #define GA_DISCARDABLE  0x08
39 #define GA_IPCSHARE     0x10  /* same as GMEM_DDESHARE */
40
41   /* Arena array */
42 static GLOBALARENA *pGlobalArena = NULL;
43 static int globalArenaSize = 0;
44
45 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000  /* Largest allocation is 16M - 64K */
46
47 #define GET_ARENA_PTR(handle)  (pGlobalArena + ((handle) >> __AHSHIFT))
48
49 /***********************************************************************
50  *           GLOBAL_GetArena
51  *
52  * Return the arena for a given selector, growing the arena array if needed.
53  */
54 static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
55 {
56     if (((sel >> __AHSHIFT) + selcount) > globalArenaSize)
57     {
58         int newsize = ((sel >> __AHSHIFT) + selcount + 0xff) & ~0xff;
59         GLOBALARENA *pNewArena = realloc( pGlobalArena,
60                                           newsize * sizeof(GLOBALARENA) );
61         if (!pNewArena) return 0;
62         pGlobalArena = pNewArena;
63         memset( pGlobalArena + globalArenaSize, 0,
64                 (newsize - globalArenaSize) * sizeof(GLOBALARENA) );
65         globalArenaSize = newsize;
66     }
67     return pGlobalArena + (sel >> __AHSHIFT);
68 }
69
70
71 void debug_handles()
72 {
73     int printed=0;
74     int i;
75     for (i = globalArenaSize-1 ; i>=0 ; i--) {
76         if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
77             printed=1;
78             printf("0x%08x, ",pGlobalArena[i].handle);
79         }
80     }
81     if (printed)
82         printf("\n");
83 }
84
85
86 /***********************************************************************
87  *           GLOBAL_CreateBlock
88  *
89  * Create a global heap block for a fixed range of linear memory.
90  */
91 HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
92                             HGLOBAL hOwner, BOOL isCode,
93                             BOOL is32Bit, BOOL isReadOnly,
94                             SHMDATA *shmdata  )
95 {
96     WORD sel, selcount;
97     GLOBALARENA *pArena;
98
99       /* Allocate the selector(s) */
100
101     sel = SELECTOR_AllocBlock( ptr, size,
102                               isCode ? SEGMENT_CODE : SEGMENT_DATA,
103                               is32Bit, isReadOnly );
104     
105     if (!sel) return 0;
106     selcount = (size + 0xffff) / 0x10000;
107
108     if (!(pArena = GLOBAL_GetArena( sel, selcount )))
109     {
110         FreeSelector( sel );
111         return 0;
112     }
113
114       /* Fill the arena block */
115
116     pArena->base = (DWORD)ptr;
117     pArena->size = GET_SEL_LIMIT(sel) + 1;
118     if ((flags & GMEM_DDESHARE) && Options.ipc)
119     {
120         pArena->handle = shmdata->handle;
121         pArena->shmid  = shmdata->shmid;
122         shmdata->sel   = sel;
123     }
124     else
125     {
126         pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
127         pArena->shmid  = 0;
128     }
129     pArena->hOwner = hOwner;
130     pArena->lockCount = 0;
131     pArena->pageLockCount = 0;
132     pArena->flags = flags & GA_MOVEABLE;
133     if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
134     if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
135     if (!isCode) pArena->flags |= GA_DGROUP;
136     pArena->selCount = selcount;
137     if (selcount > 1)  /* clear the next arena blocks */
138         memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
139
140     return pArena->handle;
141 }
142
143
144 /***********************************************************************
145  *           GLOBAL_FreeBlock
146  *
147  * Free a block allocated by GLOBAL_CreateBlock, without touching
148  * the associated linear memory range.
149  */
150 BOOL GLOBAL_FreeBlock( HGLOBAL handle )
151 {
152     WORD sel;
153
154     if (!handle) return TRUE;
155     sel = GlobalHandleToSel( handle );
156     if (FreeSelector( sel )) return FALSE;  /* failed */
157     memset( GET_ARENA_PTR(sel), 0, sizeof(GLOBALARENA) );
158     return TRUE;
159 }
160
161
162 /***********************************************************************
163  *           GLOBAL_Alloc
164  *
165  * Implementation of GlobalAlloc()
166  */
167 HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
168                       BOOL isCode, BOOL is32Bit, BOOL isReadOnly )
169 {
170     void *ptr;
171     HGLOBAL handle;
172     SHMDATA shmdata;
173
174     dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
175
176       /* Fixup the size */
177
178     if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
179     if (size == 0) size = 0x20;
180     else size = (size + 0x1f) & ~0x1f;
181
182       /* Allocate the linear memory */
183
184 #ifdef CONFIG_IPC
185     if ((flags & GMEM_DDESHARE) && Options.ipc)
186         ptr = DDE_malloc(flags, size, &shmdata);
187     else 
188 #endif  /* CONFIG_IPC */
189         ptr = malloc( size );
190     if (!ptr) return 0;
191
192       /* Allocate the selector(s) */
193
194     handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
195                                 isCode, is32Bit, isReadOnly, &shmdata);
196     if (!handle)
197     {
198         free( ptr );
199         return 0;
200     }
201
202     if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
203     return handle;
204 }
205
206
207 #ifdef CONFIG_IPC
208 /***********************************************************************
209  *           GLOBAL_FindArena
210  *
211  * Find the arena  for a given handle
212  * (when handle is not serial - e.g. DDE)
213  */
214 static GLOBALARENA *GLOBAL_FindArena( HGLOBAL handle)
215 {
216     int i;
217     for (i = globalArenaSize-1 ; i>=0 ; i--) {
218         if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
219             return ( &pGlobalArena[i] );
220     }
221     return NULL;
222 }
223
224
225 /***********************************************************************
226  *           DDE_GlobalHandleToSel
227  */
228
229 WORD DDE_GlobalHandleToSel( HGLOBAL handle )
230 {
231     GLOBALARENA *pArena;
232     SEGPTR segptr;
233     
234     pArena= GLOBAL_FindArena(handle);
235     if (pArena) {
236         int ArenaIdx = pArena - pGlobalArena;
237
238         /* See if synchronized to the shared memory  */
239         return DDE_SyncHandle(handle, ( ArenaIdx << __AHSHIFT) | 7);
240     }
241
242     /* attach the block */
243     DDE_AttachHandle(handle, &segptr);
244
245     return SELECTOROF( segptr );
246 }
247 #endif  /* CONFIG_IPC */
248
249
250 /***********************************************************************
251  *           GlobalAlloc   (KERNEL.15)
252  */
253 HGLOBAL GlobalAlloc( WORD flags, DWORD size )
254 {
255     HANDLE owner = GetCurrentPDB();
256
257     if (flags & GMEM_DDESHARE)
258         owner = GetExePtr(owner);  /* Make it a module handle */
259     return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
260 }
261
262
263 /***********************************************************************
264  *           GlobalReAlloc   (KERNEL.16)
265  */
266 HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
267 {
268     WORD selcount;
269     DWORD oldsize;
270     void *ptr;
271     GLOBALARENA *pArena, *pNewArena;
272     WORD sel = GlobalHandleToSel( handle );
273
274     dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
275                     handle, size, flags );
276     if (!handle) return 0;
277     
278 #ifdef CONFIG_IPC
279     if (Options.ipc && (flags & GMEM_DDESHARE || is_dde_handle(handle))) {
280         fprintf(stdnimp,
281                 "GlobalReAlloc: shared memory reallocating unimplemented\n"); 
282         return 0;
283     }
284 #endif  /* CONFIG_IPC */
285
286     pArena = GET_ARENA_PTR( handle );
287
288       /* Discard the block if requested */
289
290     if ((size == 0) && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY))
291     {
292         if (!(pArena->flags & GA_MOVEABLE) ||
293             !(pArena->flags & GA_DISCARDABLE) ||
294             (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
295         free( (void *)pArena->base );
296         pArena->base = 0;
297         /* Note: we rely on the fact that SELECTOR_ReallocBlock won't */
298         /* change the selector if we are shrinking the block */
299         SELECTOR_ReallocBlock( sel, 0, 1, SEGMENT_DATA, 0, 0 );
300         return handle;
301     }
302
303       /* Fixup the size */
304
305     if (size > GLOBAL_MAX_ALLOC_SIZE - 0x20) return 0;
306     if (size == 0) size = 0x20;
307     else size = (size + 0x1f) & ~0x1f;
308
309       /* Change the flags */
310
311     if (flags & GMEM_MODIFY)
312     {
313           /* Change the flags, leaving GA_DGROUP alone */
314         pArena->flags = (pArena->flags & GA_DGROUP) | (flags & GA_MOVEABLE);
315         if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
316         return handle;
317     }
318
319       /* Reallocate the linear memory */
320
321     ptr = (void *)pArena->base;
322     oldsize = pArena->size;
323     dprintf_global(stddeb,"oldsize %08lx\n",oldsize);
324     if (size == oldsize) return handle;  /* Nothing to do */
325
326     ptr = realloc( ptr, size );
327     if (!ptr)
328     {
329         FreeSelector( sel );
330         memset( pArena, 0, sizeof(GLOBALARENA) );
331         return 0;
332     }
333
334       /* Reallocate the selector(s) */
335
336     sel = SELECTOR_ReallocBlock( sel, ptr, size, SEGMENT_DATA, 0, 0 );
337     if (!sel)
338     {
339         free( ptr );
340         memset( pArena, 0, sizeof(GLOBALARENA) );
341         return 0;
342     }
343     selcount = (size + 0xffff) / 0x10000;
344
345     if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
346     {
347         free( ptr );
348         FreeSelector( sel );
349         return 0;
350     }
351
352       /* Fill the new arena block */
353
354     if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
355     pNewArena->base = (DWORD)ptr;
356     pNewArena->size = GET_SEL_LIMIT(sel) + 1;
357     pNewArena->selCount = selcount;
358     pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
359
360     if (selcount > 1)  /* clear the next arena blocks */
361         memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
362
363     if ((oldsize < size) && (flags & GMEM_ZEROINIT))
364         memset( (char *)ptr + oldsize, 0, size - oldsize );
365     return pNewArena->handle;
366 }
367
368
369 /***********************************************************************
370  *           GlobalFree   (KERNEL.17)
371  */
372 HGLOBAL GlobalFree( HGLOBAL handle )
373 {
374     void *ptr = GlobalLock( handle );
375
376     dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
377     if (!GLOBAL_FreeBlock( handle )) return handle;  /* failed */
378 #ifdef CONFIG_IPC
379     if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
380 #endif  /* CONFIG_IPC */
381     if (ptr) free( ptr );
382     return 0;
383 }
384
385
386 /***********************************************************************
387  *           WIN16_GlobalLock   (KERNEL.18)
388  *
389  * This is the GlobalLock() function used by 16-bit code.
390  */
391 SEGPTR WIN16_GlobalLock( HGLOBAL handle )
392 {
393     dprintf_global( stddeb, "WIN16_GlobalLock(%04x) -> %08lx\n",
394                     handle, MAKELONG( 0, GlobalHandleToSel(handle)) );
395     if (!handle) return 0;
396
397 #ifdef CONFIG_IPC
398     if (is_dde_handle(handle))
399         return (SEGPTR)MAKELONG( 0, DDE_GlobalHandleToSel(handle) );
400 #endif  /* CONFIG_IPC */
401
402     if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
403     return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
404 }
405
406
407 /***********************************************************************
408  *           GlobalLock   (KERNEL.18)
409  *
410  * This is the GlobalLock() function used by 32-bit code.
411  */
412 LPSTR GlobalLock( HGLOBAL handle )
413 {
414     if (!handle) return 0;
415 #ifdef CONFIG_IPC
416     if (is_dde_handle(handle)) return DDE_AttachHandle(handle, NULL);
417 #endif
418     return (LPSTR)GET_ARENA_PTR(handle)->base;
419 }
420
421
422 /***********************************************************************
423  *           GlobalUnlock   (KERNEL.19)
424  */
425 BOOL GlobalUnlock( HGLOBAL handle )
426 {
427     dprintf_global( stddeb, "GlobalUnlock: %04x\n", handle );
428     return 0;
429 }
430
431
432 /***********************************************************************
433  *           GlobalSize   (KERNEL.20)
434  */
435 DWORD GlobalSize( HGLOBAL handle )
436 {
437     dprintf_global( stddeb, "GlobalSize: %04x\n", handle );
438     if (!handle) return 0;
439     return GET_ARENA_PTR(handle)->size;
440 }
441
442
443 /***********************************************************************
444  *           GlobalHandle   (KERNEL.21)
445  */
446 DWORD GlobalHandle( WORD sel )
447 {
448     dprintf_global( stddeb, "GlobalHandle: %04x\n", sel );
449     return MAKELONG( GET_ARENA_PTR(sel)->handle, sel );
450 }
451
452
453 /***********************************************************************
454  *           GlobalFlags   (KERNEL.22)
455  */
456 WORD GlobalFlags( HGLOBAL handle )
457 {
458     GLOBALARENA *pArena;
459
460     dprintf_global( stddeb, "GlobalFlags: %04x\n", handle );
461     pArena = GET_ARENA_PTR(handle);
462     return pArena->lockCount |
463            ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0) |
464            ((pArena->base == 0) ? GMEM_DISCARDED : 0);
465 }
466
467
468 /***********************************************************************
469  *           LockSegment   (KERNEL.23)
470  */
471 HGLOBAL LockSegment( HGLOBAL handle )
472 {
473     dprintf_global( stddeb, "LockSegment: %04x\n", handle );
474     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
475     GET_ARENA_PTR(handle)->lockCount++;
476     return handle;
477 }
478
479
480 /***********************************************************************
481  *           UnlockSegment   (KERNEL.24)
482  */
483 void UnlockSegment( HGLOBAL handle )
484 {
485     dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
486     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
487     GET_ARENA_PTR(handle)->lockCount--;
488     /* FIXME: this ought to return the lock count in CX (go figure...) */
489 }
490
491
492 /***********************************************************************
493  *           GlobalCompact   (KERNEL.25)
494  */
495 DWORD GlobalCompact( DWORD desired )
496 {
497     return GLOBAL_MAX_ALLOC_SIZE;
498 }
499
500
501 /***********************************************************************
502  *           GlobalFreeAll   (KERNEL.26)
503  */
504 void GlobalFreeAll( HANDLE owner )
505 {
506     DWORD i;
507     GLOBALARENA *pArena;
508
509     pArena = pGlobalArena;
510     for (i = 0; i < globalArenaSize; i++, pArena++)
511     {
512         if ((pArena->size != 0) && (pArena->hOwner == owner))
513             GlobalFree( pArena->handle );
514     }
515 }
516
517
518 /***********************************************************************
519  *           GlobalWire   (KERNEL.111)
520  */
521 SEGPTR GlobalWire( HGLOBAL handle )
522 {
523     return WIN16_GlobalLock( handle );
524 }
525
526
527 /***********************************************************************
528  *           GlobalUnWire   (KERNEL.112)
529  */
530 BOOL GlobalUnWire( HGLOBAL handle )
531 {
532     return GlobalUnlock( handle );
533 }
534
535
536 /***********************************************************************
537  *           GlobalDOSAlloc   (KERNEL.184)
538  */
539 DWORD GlobalDOSAlloc( DWORD size )
540 {
541     WORD sel = GlobalAlloc( GMEM_FIXED, size );
542     if (!sel) return 0;
543     return MAKELONG( sel, sel /* this one ought to be a real-mode segment */ );
544 }
545
546
547 /***********************************************************************
548  *           GlobalDOSFree   (KERNEL.185)
549  */
550 WORD GlobalDOSFree( WORD sel )
551 {
552     return GlobalFree( GlobalHandle(sel) ) ? sel : 0;
553 }
554
555
556 /***********************************************************************
557  *           SetSwapAreaSize   (KERNEL.106)
558  */
559 LONG SetSwapAreaSize( WORD size )
560 {
561     dprintf_global(stdnimp, "STUB: SetSwapAreaSize(%d)\n", size );
562     return MAKELONG( size, 0xffff );
563 }
564
565
566 /***********************************************************************
567  *           GlobalLRUOldest   (KERNEL.163)
568  */
569 HGLOBAL GlobalLRUOldest( HGLOBAL handle )
570 {
571     dprintf_global( stddeb, "GlobalLRUOldest: %04x\n", handle );
572     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
573     return handle;
574 }
575
576
577 /***********************************************************************
578  *           GlobalLRUNewest   (KERNEL.164)
579  */
580 HGLOBAL GlobalLRUNewest( HGLOBAL handle )
581 {
582     dprintf_global( stddeb, "GlobalLRUNewest: %04x\n", handle );
583     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
584     return handle;
585 }
586
587
588 /***********************************************************************
589  *           GetFreeSpace   (KERNEL.169)
590  */
591 DWORD GetFreeSpace( UINT wFlags )
592 {
593     return GLOBAL_MAX_ALLOC_SIZE;
594 }
595
596
597 /***********************************************************************
598  *           GlobalPageLock   (KERNEL.191)
599  */
600 WORD GlobalPageLock( HGLOBAL handle )
601 {
602     dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
603     return ++(GET_ARENA_PTR(handle)->pageLockCount);
604 }
605
606
607 /***********************************************************************
608  *           GlobalPageUnlock   (KERNEL.192)
609  */
610 WORD GlobalPageUnlock( HGLOBAL handle )
611 {
612     dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
613     return --(GET_ARENA_PTR(handle)->pageLockCount);
614 }
615
616
617 /***********************************************************************
618  *           GlobalFix   (KERNEL.197)
619  */
620 void GlobalFix( HGLOBAL handle )
621 {
622     dprintf_global( stddeb, "GlobalFix: %04x\n", handle );
623     GET_ARENA_PTR(handle)->lockCount++;
624 }
625
626
627 /***********************************************************************
628  *           GlobalUnfix   (KERNEL.198)
629  */
630 void GlobalUnfix( HGLOBAL handle )
631 {
632     dprintf_global( stddeb, "GlobalUnfix: %04x\n", handle );
633     GET_ARENA_PTR(handle)->lockCount--;
634 }
635
636
637 /***********************************************************************
638  *           FarSetOwner   (KERNEL.403)
639  */
640 void FarSetOwner( HANDLE handle, WORD hOwner )
641 {
642     GET_ARENA_PTR(handle)->hOwner = hOwner;
643 }
644
645
646 /***********************************************************************
647  *           FarGetOwner   (KERNEL.404)
648  */
649 WORD FarGetOwner( HANDLE handle )
650 {
651     return GET_ARENA_PTR(handle)->hOwner;
652 }
653
654
655 /***********************************************************************
656  *           GlobalHandleToSel   (TOOLHELP.50)
657  */
658 WORD GlobalHandleToSel( HGLOBAL handle )
659 {
660     dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
661     if (!handle) return 0;
662 #ifdef CONFIG_IPC
663     if (is_dde_handle(handle)) return DDE_GlobalHandleToSel(handle);
664 #endif
665     if (!(handle & 7))
666     {
667         fprintf( stderr, "Program attempted invalid selector conversion\n" );
668         return handle - 1;
669     }
670     return handle | 7;
671 }
672
673
674 /***********************************************************************
675  *           GlobalFirst   (TOOLHELP.51)
676  */
677 BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
678 {
679     if (wFlags == GLOBAL_LRU) return FALSE;
680     pGlobal->dwNext = 0;
681     return GlobalNext( pGlobal, wFlags );
682 }
683
684
685 /***********************************************************************
686  *           GlobalNext   (TOOLHELP.52)
687  */
688 BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
689 {
690     GLOBALARENA *pArena;
691
692     if (pGlobal->dwNext >= globalArenaSize) return FALSE;
693     pArena = pGlobalArena + pGlobal->dwNext;
694     if (wFlags == GLOBAL_FREE)  /* only free blocks */
695     {
696         int i;
697         for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
698             if (pArena->size == 0) break;  /* block is free */
699         if (i >= globalArenaSize) return FALSE;
700         pGlobal->dwNext = i;
701     }
702
703     pGlobal->dwAddress    = pArena->base;
704     pGlobal->dwBlockSize  = pArena->size;
705     pGlobal->hBlock       = pArena->handle;
706     pGlobal->wcLock       = pArena->lockCount;
707     pGlobal->wcPageLock   = pArena->pageLockCount;
708     pGlobal->wFlags       = (GetCurrentPDB() == pArena->hOwner);
709     pGlobal->wHeapPresent = FALSE;
710     pGlobal->hOwner       = pArena->hOwner;
711     pGlobal->wType        = GT_UNKNOWN;
712     pGlobal->wData        = 0;
713     pGlobal->dwNext++;
714     return TRUE;
715 }
716
717
718 /***********************************************************************
719  *           GlobalInfo   (TOOLHELP.53)
720  */
721 BOOL GlobalInfo( GLOBALINFO *pInfo )
722 {
723     int i;
724     GLOBALARENA *pArena;
725
726     pInfo->wcItems = globalArenaSize;
727     pInfo->wcItemsFree = 0;
728     pInfo->wcItemsLRU = 0;
729     for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
730         if (pArena->size == 0) pInfo->wcItemsFree++;
731     return TRUE;
732 }
733
734
735 /***********************************************************************
736  *           GlobalEntryHandle   (TOOLHELP.54)
737  */
738 BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL hItem )
739 {
740     return FALSE;
741 }
742
743
744 /***********************************************************************
745  *           GlobalEntryModule   (TOOLHELP.55)
746  */
747 BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg )
748 {
749     return FALSE;
750 }
751
752
753 /***********************************************************************
754  *           MemManInfo   (TOOLHELP.72)
755  */
756 BOOL MemManInfo( MEMMANINFO *pInfo )
757 {
758     return TRUE;
759 }
760
761 /***********************************************************************
762  *               GlobalAlloc32
763  * implements    GlobalAlloc        (KERNEL32.316)
764  *               LocalAlloc         (KERNEL32.372)
765  */
766 void *GlobalAlloc32(int flags,int size)
767 {
768     dprintf_global(stddeb,"GlobalAlloc32(%x,%x)\n",flags,size);
769     return malloc(size);
770 }