Release 960611
[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 <unistd.h>
10 #include <string.h>
11
12 #include "windows.h"
13 #include "global.h"
14 #include "heap.h"
15 #include "toolhelp.h"
16 #include "selectors.h"
17 #include "dde_mem.h"
18 #include "stackframe.h"
19 #include "options.h"
20 #include "stddebug.h"
21 #include "debug.h"
22
23   /* Global arena block */
24 typedef struct
25 {
26     DWORD     base;          /* Base address (0 if discarded) */
27     DWORD     size;          /* Size in bytes (0 indicates a free block) */
28     HGLOBAL16 handle;        /* Handle for this block */
29     HGLOBAL16 hOwner;        /* Owner of this block */
30     BYTE      lockCount;     /* Count of GlobalFix() calls */
31     BYTE      pageLockCount; /* Count of GlobalPageLock() calls */
32     BYTE      flags;         /* Allocation flags */
33     BYTE      selCount;      /* Number of selectors allocated for this block */
34 #ifdef CONFIG_IPC
35     int       shmid;
36 #endif
37 } GLOBALARENA;
38
39   /* Flags definitions */
40 #define GA_MOVEABLE     0x02  /* same as GMEM_MOVEABLE */
41 #define GA_DGROUP       0x04
42 #define GA_DISCARDABLE  0x08
43 #define GA_IPCSHARE     0x10  /* same as GMEM_DDESHARE */
44
45   /* Arena array */
46 static GLOBALARENA *pGlobalArena = NULL;
47 static int globalArenaSize = 0;
48
49 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000  /* Largest allocation is 16M - 64K */
50
51 #define GET_ARENA_PTR(handle)  (pGlobalArena + ((handle) >> __AHSHIFT))
52
53 /***********************************************************************
54  *           GLOBAL_GetArena
55  *
56  * Return the arena for a given selector, growing the arena array if needed.
57  */
58 static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
59 {
60     if (((sel >> __AHSHIFT) + selcount) > globalArenaSize)
61     {
62         int newsize = ((sel >> __AHSHIFT) + selcount + 0xff) & ~0xff;
63         GLOBALARENA *pNewArena = realloc( pGlobalArena,
64                                           newsize * sizeof(GLOBALARENA) );
65         if (!pNewArena) return 0;
66         pGlobalArena = pNewArena;
67         memset( pGlobalArena + globalArenaSize, 0,
68                 (newsize - globalArenaSize) * sizeof(GLOBALARENA) );
69         globalArenaSize = newsize;
70     }
71     return pGlobalArena + (sel >> __AHSHIFT);
72 }
73
74
75 void debug_handles()
76 {
77     int printed=0;
78     int i;
79     for (i = globalArenaSize-1 ; i>=0 ; i--) {
80         if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
81             printed=1;
82             printf("0x%08x, ",pGlobalArena[i].handle);
83         }
84     }
85     if (printed)
86         printf("\n");
87 }
88
89
90 /***********************************************************************
91  *           GLOBAL_CreateBlock
92  *
93  * Create a global heap block for a fixed range of linear memory.
94  */
95 HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
96                               HGLOBAL16 hOwner, BOOL16 isCode,
97                               BOOL16 is32Bit, BOOL16 isReadOnly,
98                               SHMDATA *shmdata  )
99 {
100     WORD sel, selcount;
101     GLOBALARENA *pArena;
102
103       /* Allocate the selector(s) */
104
105     sel = SELECTOR_AllocBlock( ptr, size,
106                               isCode ? SEGMENT_CODE : SEGMENT_DATA,
107                               is32Bit, isReadOnly );
108     
109     if (!sel) return 0;
110     selcount = (size + 0xffff) / 0x10000;
111
112     if (!(pArena = GLOBAL_GetArena( sel, selcount )))
113     {
114         FreeSelector( sel );
115         return 0;
116     }
117
118       /* Fill the arena block */
119
120     pArena->base = (DWORD)ptr;
121     pArena->size = GET_SEL_LIMIT(sel) + 1;
122
123 #ifdef CONFIG_IPC
124     if ((flags & GMEM_DDESHARE) && Options.ipc)
125     {
126         pArena->handle = shmdata->handle;
127         pArena->shmid  = shmdata->shmid;
128         shmdata->sel   = sel;
129     }
130     else
131     {
132         pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
133         pArena->shmid  = 0;
134     }
135 #else
136     pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
137 #endif
138     pArena->hOwner = hOwner;
139     pArena->lockCount = 0;
140     pArena->pageLockCount = 0;
141     pArena->flags = flags & GA_MOVEABLE;
142     if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
143     if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
144     if (!isCode) pArena->flags |= GA_DGROUP;
145     pArena->selCount = selcount;
146     if (selcount > 1)  /* clear the next arena blocks */
147         memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
148
149     return pArena->handle;
150 }
151
152
153 /***********************************************************************
154  *           GLOBAL_FreeBlock
155  *
156  * Free a block allocated by GLOBAL_CreateBlock, without touching
157  * the associated linear memory range.
158  */
159 BOOL16 GLOBAL_FreeBlock( HGLOBAL16 handle )
160 {
161     WORD sel;
162
163     if (!handle) return TRUE;
164     sel = GlobalHandleToSel( handle );
165     if (FreeSelector( sel )) return FALSE;  /* failed */
166     memset( GET_ARENA_PTR(sel), 0, sizeof(GLOBALARENA) );
167     return TRUE;
168 }
169
170
171 /***********************************************************************
172  *           GLOBAL_Alloc
173  *
174  * Implementation of GlobalAlloc16()
175  */
176 HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
177                         BOOL16 isCode, BOOL16 is32Bit, BOOL16 isReadOnly )
178 {
179     void *ptr;
180     HGLOBAL16 handle;
181     SHMDATA shmdata;
182
183     dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
184
185     /* If size is 0, create a discarded block */
186
187     if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
188                                               is32Bit, isReadOnly, NULL );
189
190     /* Fixup the size */
191
192     if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
193     size = (size + 0x1f) & ~0x1f;
194
195       /* Allocate the linear memory */
196
197 #ifdef CONFIG_IPC
198     if ((flags & GMEM_DDESHARE) && Options.ipc)
199         ptr = DDE_malloc(flags, size, &shmdata);
200     else 
201 #endif  /* CONFIG_IPC */
202     {
203         ptr = HeapAlloc( SystemHeap, 0, size );
204     }
205     if (!ptr) return 0;
206
207       /* Allocate the selector(s) */
208
209     handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
210                                 isCode, is32Bit, isReadOnly, &shmdata);
211     if (!handle)
212     {
213         HeapFree( SystemHeap, 0, ptr );
214         return 0;
215     }
216
217     if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
218     return handle;
219 }
220
221
222 #ifdef CONFIG_IPC
223 /***********************************************************************
224  *           GLOBAL_FindArena
225  *
226  * Find the arena  for a given handle
227  * (when handle is not serial - e.g. DDE)
228  */
229 static GLOBALARENA *GLOBAL_FindArena( HGLOBAL handle)
230 {
231     int i;
232     for (i = globalArenaSize-1 ; i>=0 ; i--) {
233         if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
234             return ( &pGlobalArena[i] );
235     }
236     return NULL;
237 }
238
239
240 /***********************************************************************
241  *           DDE_GlobalHandleToSel
242  */
243
244 WORD DDE_GlobalHandleToSel( HGLOBAL handle )
245 {
246     GLOBALARENA *pArena;
247     SEGPTR segptr;
248     
249     pArena= GLOBAL_FindArena(handle);
250     if (pArena) {
251         int ArenaIdx = pArena - pGlobalArena;
252
253         /* See if synchronized to the shared memory  */
254         return DDE_SyncHandle(handle, ( ArenaIdx << __AHSHIFT) | 7);
255     }
256
257     /* attach the block */
258     DDE_AttachHandle(handle, &segptr);
259
260     return SELECTOROF( segptr );
261 }
262 #endif  /* CONFIG_IPC */
263
264
265 /***********************************************************************
266  *           GlobalAlloc16   (KERNEL.15)
267  */
268 HGLOBAL16 GlobalAlloc16( UINT16 flags, DWORD size )
269 {
270     HANDLE16 owner = GetCurrentPDB();
271
272     if (flags & GMEM_DDESHARE)
273         owner = GetExePtr(owner);  /* Make it a module handle */
274     return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
275 }
276
277
278 /***********************************************************************
279  *           GlobalReAlloc16   (KERNEL.16)
280  */
281 HGLOBAL16 GlobalReAlloc16( HGLOBAL16 handle, DWORD size, UINT16 flags )
282 {
283     WORD selcount;
284     DWORD oldsize;
285     void *ptr;
286     GLOBALARENA *pArena, *pNewArena;
287     WORD sel = GlobalHandleToSel( handle );
288
289     dprintf_global( stddeb, "GlobalReAlloc16: %04x %ld flags=%04x\n",
290                     handle, size, flags );
291     if (!handle) return 0;
292     
293 #ifdef CONFIG_IPC
294     if (Options.ipc && (flags & GMEM_DDESHARE || is_dde_handle(handle))) {
295         fprintf(stdnimp,
296                "GlobalReAlloc16: shared memory reallocating unimplemented\n"); 
297         return 0;
298     }
299 #endif  /* CONFIG_IPC */
300
301     pArena = GET_ARENA_PTR( handle );
302
303       /* Discard the block if requested */
304
305     if ((size == 0) && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY))
306     {
307         if (!(pArena->flags & GA_MOVEABLE) ||
308             !(pArena->flags & GA_DISCARDABLE) ||
309             (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
310         HeapFree( SystemHeap, 0, (void *)pArena->base );
311         pArena->base = 0;
312         /* Note: we rely on the fact that SELECTOR_ReallocBlock won't */
313         /* change the selector if we are shrinking the block */
314         SELECTOR_ReallocBlock( sel, 0, 1, SEGMENT_DATA, 0, 0 );
315         return handle;
316     }
317
318       /* Fixup the size */
319
320     if (size > GLOBAL_MAX_ALLOC_SIZE - 0x20) return 0;
321     if (size == 0) size = 0x20;
322     else size = (size + 0x1f) & ~0x1f;
323
324       /* Change the flags */
325
326     if (flags & GMEM_MODIFY)
327     {
328           /* Change the flags, leaving GA_DGROUP alone */
329         pArena->flags = (pArena->flags & GA_DGROUP) | (flags & GA_MOVEABLE);
330         if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
331         return handle;
332     }
333
334       /* Reallocate the linear memory */
335
336     ptr = (void *)pArena->base;
337     oldsize = pArena->size;
338     dprintf_global(stddeb,"oldsize %08lx\n",oldsize);
339     if (ptr && (size == oldsize)) return handle;  /* Nothing to do */
340
341     ptr = HeapReAlloc( SystemHeap, 0, ptr, size );
342     if (!ptr)
343     {
344         FreeSelector( sel );
345         memset( pArena, 0, sizeof(GLOBALARENA) );
346         return 0;
347     }
348
349       /* Reallocate the selector(s) */
350
351     sel = SELECTOR_ReallocBlock( sel, ptr, size, SEGMENT_DATA, 0, 0 );
352     if (!sel)
353     {
354         HeapFree( SystemHeap, 0, ptr );
355         memset( pArena, 0, sizeof(GLOBALARENA) );
356         return 0;
357     }
358     selcount = (size + 0xffff) / 0x10000;
359
360     if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
361     {
362         HeapFree( SystemHeap, 0, ptr );
363         FreeSelector( sel );
364         return 0;
365     }
366
367       /* Fill the new arena block */
368
369     if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
370     pNewArena->base = (DWORD)ptr;
371     pNewArena->size = GET_SEL_LIMIT(sel) + 1;
372     pNewArena->selCount = selcount;
373     pNewArena->handle = (pNewArena->flags & GA_MOVEABLE) ? sel - 1 : sel;
374
375     if (selcount > 1)  /* clear the next arena blocks */
376         memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
377
378     if ((oldsize < size) && (flags & GMEM_ZEROINIT))
379         memset( (char *)ptr + oldsize, 0, size - oldsize );
380     return pNewArena->handle;
381 }
382
383
384 /***********************************************************************
385  *           GlobalFree16   (KERNEL.17)
386  */
387 HGLOBAL16 GlobalFree16( HGLOBAL16 handle )
388 {
389     void *ptr = GlobalLock16( handle );
390
391     dprintf_global( stddeb, "GlobalFree16: %04x\n", handle );
392     if (!GLOBAL_FreeBlock( handle )) return handle;  /* failed */
393 #ifdef CONFIG_IPC
394     if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
395 #endif  /* CONFIG_IPC */
396     if (ptr) HeapFree( SystemHeap, 0, ptr );
397     return 0;
398 }
399
400
401 /***********************************************************************
402  *           WIN16_GlobalLock16   (KERNEL.18)
403  *
404  * This is the GlobalLock16() function used by 16-bit code.
405  */
406 SEGPTR WIN16_GlobalLock16( HGLOBAL16 handle )
407 {
408 #ifndef WINELIB
409     dprintf_global( stddeb, "WIN16_GlobalLock16(%04x) -> %08lx\n",
410                     handle, MAKELONG( 0, GlobalHandleToSel(handle)) );
411     if (!handle) return 0;
412
413 #ifdef CONFIG_IPC
414     if (is_dde_handle(handle))
415         return PTR_SEG_OFF_TO_SEGPTR( DDE_GlobalHandleToSel(handle), 0 );
416 #endif  /* CONFIG_IPC */
417
418     if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
419     return PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel(handle), 0 );
420 #else  /* WINELIB */
421     return GlobalLock16( handle );
422 #endif  /* WINELIB */
423 }
424
425
426 /***********************************************************************
427  *           GlobalLock16   (KERNEL.18)
428  *
429  * This is the GlobalLock16() function used by 32-bit code.
430  */
431 LPVOID GlobalLock16( HGLOBAL16 handle )
432 {
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;
438 }
439
440
441 /***********************************************************************
442  *           GlobalUnlock16   (KERNEL.19)
443  */
444 BOOL16 GlobalUnlock16( HGLOBAL16 handle )
445 {
446     dprintf_global( stddeb, "GlobalUnlock16: %04x\n", handle );
447     return 0;
448 }
449
450
451 /***********************************************************************
452  *           GlobalSize16   (KERNEL.20)
453  */
454 DWORD GlobalSize16( HGLOBAL16 handle )
455 {
456     dprintf_global( stddeb, "GlobalSize16: %04x\n", handle );
457     if (!handle) return 0;
458     return GET_ARENA_PTR(handle)->size;
459 }
460
461
462 /***********************************************************************
463  *           GlobalHandle16   (KERNEL.21)
464  */
465 DWORD GlobalHandle16( WORD sel )
466 {
467     dprintf_global( stddeb, "GlobalHandle16: %04x\n", sel );
468     return MAKELONG( GET_ARENA_PTR(sel)->handle, GlobalHandleToSel(sel) );
469 }
470
471
472 /***********************************************************************
473  *           GlobalFlags16   (KERNEL.22)
474  */
475 UINT16 GlobalFlags16( HGLOBAL16 handle )
476 {
477     GLOBALARENA *pArena;
478
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);
484 }
485
486
487 /***********************************************************************
488  *           LockSegment   (KERNEL.23)
489  */
490 HGLOBAL LockSegment( HGLOBAL handle )
491 {
492     dprintf_global( stddeb, "LockSegment: %04x\n", handle );
493     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
494     GET_ARENA_PTR(handle)->lockCount++;
495     return handle;
496 }
497
498
499 /***********************************************************************
500  *           UnlockSegment   (KERNEL.24)
501  */
502 void UnlockSegment( HGLOBAL handle )
503 {
504     dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
505     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
506     GET_ARENA_PTR(handle)->lockCount--;
507     /* FIXME: this ought to return the lock count in CX (go figure...) */
508 }
509
510
511 /***********************************************************************
512  *           GlobalCompact16   (KERNEL.25)
513  */
514 DWORD GlobalCompact16( DWORD desired )
515 {
516     return GLOBAL_MAX_ALLOC_SIZE;
517 }
518
519
520 /***********************************************************************
521  *           GlobalFreeAll   (KERNEL.26)
522  */
523 void GlobalFreeAll( HGLOBAL16 owner )
524 {
525     DWORD i;
526     GLOBALARENA *pArena;
527
528     pArena = pGlobalArena;
529     for (i = 0; i < globalArenaSize; i++, pArena++)
530     {
531         if ((pArena->size != 0) && (pArena->hOwner == owner))
532             GlobalFree16( pArena->handle );
533     }
534 }
535
536
537 /***********************************************************************
538  *           GlobalWire   (KERNEL.111)
539  */
540 SEGPTR GlobalWire( HGLOBAL16 handle )
541 {
542     return WIN16_GlobalLock16( handle );
543 }
544
545
546 /***********************************************************************
547  *           GlobalUnWire   (KERNEL.112)
548  */
549 BOOL GlobalUnWire( HGLOBAL16 handle )
550 {
551     return GlobalUnlock16( handle );
552 }
553
554
555 /***********************************************************************
556  *           GlobalDOSAlloc   (KERNEL.184)
557  */
558 DWORD GlobalDOSAlloc( DWORD size )
559 {
560     WORD sel = GlobalAlloc16( GMEM_FIXED, size );
561     if (!sel) return 0;
562     return MAKELONG( sel, sel /* this one ought to be a real-mode segment */ );
563 }
564
565
566 /***********************************************************************
567  *           GlobalDOSFree   (KERNEL.185)
568  */
569 WORD GlobalDOSFree( WORD sel )
570 {
571     return GlobalFree16( GlobalHandle16(sel) ) ? sel : 0;
572 }
573
574
575 /***********************************************************************
576  *           SetSwapAreaSize   (KERNEL.106)
577  */
578 LONG SetSwapAreaSize( WORD size )
579 {
580     dprintf_global(stdnimp, "STUB: SetSwapAreaSize(%d)\n", size );
581     return MAKELONG( size, 0xffff );
582 }
583
584
585 /***********************************************************************
586  *           GlobalLRUOldest   (KERNEL.163)
587  */
588 HGLOBAL16 GlobalLRUOldest( HGLOBAL16 handle )
589 {
590     dprintf_global( stddeb, "GlobalLRUOldest: %04x\n", handle );
591     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
592     return handle;
593 }
594
595
596 /***********************************************************************
597  *           GlobalLRUNewest   (KERNEL.164)
598  */
599 HGLOBAL16 GlobalLRUNewest( HGLOBAL16 handle )
600 {
601     dprintf_global( stddeb, "GlobalLRUNewest: %04x\n", handle );
602     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
603     return handle;
604 }
605
606
607 /***********************************************************************
608  *           GetFreeSpace   (KERNEL.169)
609  */
610 DWORD GetFreeSpace( UINT16 wFlags )
611 {
612     return GLOBAL_MAX_ALLOC_SIZE;
613 }
614
615
616 /***********************************************************************
617  *           GlobalPageLock   (KERNEL.191)
618  */
619 WORD GlobalPageLock( HGLOBAL16 handle )
620 {
621     dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
622     return ++(GET_ARENA_PTR(handle)->pageLockCount);
623 }
624
625
626 /***********************************************************************
627  *           GlobalPageUnlock   (KERNEL.192)
628  */
629 WORD GlobalPageUnlock( HGLOBAL16 handle )
630 {
631     dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
632     return --(GET_ARENA_PTR(handle)->pageLockCount);
633 }
634
635
636 /***********************************************************************
637  *           GlobalFix   (KERNEL.197)
638  */
639 void GlobalFix( HGLOBAL16 handle )
640 {
641     dprintf_global( stddeb, "GlobalFix: %04x\n", handle );
642     GET_ARENA_PTR(handle)->lockCount++;
643 }
644
645
646 /***********************************************************************
647  *           GlobalUnfix   (KERNEL.198)
648  */
649 void GlobalUnfix( HGLOBAL16 handle )
650 {
651     dprintf_global( stddeb, "GlobalUnfix: %04x\n", handle );
652     GET_ARENA_PTR(handle)->lockCount--;
653 }
654
655
656 /***********************************************************************
657  *           FarSetOwner   (KERNEL.403)
658  */
659 void FarSetOwner( HANDLE handle, HANDLE hOwner )
660 {
661     GET_ARENA_PTR(handle)->hOwner = hOwner;
662 }
663
664
665 /***********************************************************************
666  *           FarGetOwner   (KERNEL.404)
667  */
668 WORD FarGetOwner( HANDLE handle )
669 {
670     return GET_ARENA_PTR(handle)->hOwner;
671 }
672
673
674 /***********************************************************************
675  *           GlobalHandleToSel   (TOOLHELP.50)
676  */
677 WORD GlobalHandleToSel( HGLOBAL16 handle )
678 {
679     dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
680     if (!handle) return 0;
681 #ifdef CONFIG_IPC
682     if (is_dde_handle(handle)) return DDE_GlobalHandleToSel(handle);
683 #endif
684     if (!(handle & 7))
685     {
686         fprintf( stderr, "Program attempted invalid selector conversion\n" );
687         return handle - 1;
688     }
689     return handle | 7;
690 }
691
692
693 /***********************************************************************
694  *           GlobalFirst   (TOOLHELP.51)
695  */
696 BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
697 {
698     if (wFlags == GLOBAL_LRU) return FALSE;
699     pGlobal->dwNext = 0;
700     return GlobalNext( pGlobal, wFlags );
701 }
702
703
704 /***********************************************************************
705  *           GlobalNext   (TOOLHELP.52)
706  */
707 BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
708 {
709     GLOBALARENA *pArena;
710
711     if (pGlobal->dwNext >= globalArenaSize) return FALSE;
712     pArena = pGlobalArena + pGlobal->dwNext;
713     if (wFlags == GLOBAL_FREE)  /* only free blocks */
714     {
715         int i;
716         for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
717             if (pArena->size == 0) break;  /* block is free */
718         if (i >= globalArenaSize) return FALSE;
719         pGlobal->dwNext = i;
720     }
721
722     pGlobal->dwAddress    = pArena->base;
723     pGlobal->dwBlockSize  = pArena->size;
724     pGlobal->hBlock       = pArena->handle;
725     pGlobal->wcLock       = pArena->lockCount;
726     pGlobal->wcPageLock   = pArena->pageLockCount;
727     pGlobal->wFlags       = (GetCurrentPDB() == pArena->hOwner);
728     pGlobal->wHeapPresent = FALSE;
729     pGlobal->hOwner       = pArena->hOwner;
730     pGlobal->wType        = GT_UNKNOWN;
731     pGlobal->wData        = 0;
732     pGlobal->dwNext++;
733     return TRUE;
734 }
735
736
737 /***********************************************************************
738  *           GlobalInfo   (TOOLHELP.53)
739  */
740 BOOL GlobalInfo( GLOBALINFO *pInfo )
741 {
742     int i;
743     GLOBALARENA *pArena;
744
745     pInfo->wcItems = globalArenaSize;
746     pInfo->wcItemsFree = 0;
747     pInfo->wcItemsLRU = 0;
748     for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
749         if (pArena->size == 0) pInfo->wcItemsFree++;
750     return TRUE;
751 }
752
753
754 /***********************************************************************
755  *           GlobalEntryHandle   (TOOLHELP.54)
756  */
757 BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL16 hItem )
758 {
759     return FALSE;
760 }
761
762
763 /***********************************************************************
764  *           GlobalEntryModule   (TOOLHELP.55)
765  */
766 BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE16 hModule, WORD wSeg )
767 {
768     return FALSE;
769 }
770
771
772 /***********************************************************************
773  *           MemManInfo   (TOOLHELP.72)
774  */
775 BOOL MemManInfo( MEMMANINFO *pInfo )
776 {
777 #ifdef linux
778     /* FIXME: does not take into account the dwSize member
779      * could be corrupting memory therefore
780      */
781     /* shamefully stolen from free */
782     DWORD availmem = 0;
783     DWORD totalmem = 0;
784     FILE *meminfo;
785     char buf[80];
786     int col[5];
787     int n;
788
789     if ((meminfo = fopen("/proc/meminfo", "r")) < 0) {
790         perror("wine: open");
791         return FALSE;
792     }
793
794     fgets(buf, 80, meminfo); /* read first line */
795     while ( fgets(buf, 80, meminfo) ) {
796         n = sscanf( buf, "%*s %d %d %d %d %d", &col[0], &col[1], &col[2], &col[3], &col[4]);
797         if ( n < 1 ) continue; /* escape the loop at the top */
798         totalmem += col[0];
799         availmem += col[2] + col[4];
800     }
801
802     fprintf(stderr,"MemManInfo called with dwSize = %ld\n",pInfo->dwSize);
803     if (pInfo->dwSize) {
804         pInfo->wPageSize = getpagesize();
805         pInfo->dwLargestFreeBlock = availmem;
806         pInfo->dwTotalLinearSpace = totalmem / pInfo->wPageSize;
807         pInfo->dwMaxPagesAvailable = pInfo->dwLargestFreeBlock / pInfo->wPageSize;
808         pInfo->dwMaxPagesLockable = pInfo->dwMaxPagesLockable;
809         /* FIXME: the next three are not quite correct */
810         pInfo->dwTotalUnlockedPages = pInfo->dwMaxPagesAvailable;
811         pInfo->dwFreePages = pInfo->dwMaxPagesAvailable;
812         pInfo->dwTotalPages = pInfo->dwMaxPagesAvailable;
813         /* FIXME: the three above are not quite correct */
814         pInfo->dwFreeLinearSpace = pInfo->dwMaxPagesAvailable;
815         pInfo->dwSwapFilePages = 0L;
816     }
817     return TRUE;
818 #else
819     return TRUE;
820 #endif
821 }
822
823
824 /***********************************************************************
825  *           GlobalAlloc32   (KERNEL32.315)
826  */
827 HGLOBAL32 GlobalAlloc32( UINT32 flags, DWORD size )
828 {
829     DWORD heapFlags = 0;
830
831     if (flags & GMEM_MOVEABLE)
832         fprintf( stderr, "GlobalAlloc32: unimplemented flag GMEM_MOVEABLE\n" );
833
834     if (flags & GMEM_ZEROINIT) heapFlags |= HEAP_ZERO_MEMORY;
835     return (HGLOBAL32)HeapAlloc( GetProcessHeap(), heapFlags, size );
836 }
837
838
839 /***********************************************************************
840  *           GlobalCompact32   (KERNEL32.316)
841  */
842 DWORD GlobalCompact32( DWORD minfree )
843 {
844     return 0;  /* GlobalCompact does nothing in Win32 */
845 }
846
847
848 /***********************************************************************
849  *           GlobalFlags32   (KERNEL32.321)
850  */
851 UINT32 GlobalFlags32( HGLOBAL32 handle )
852 {
853     return 0;
854 }
855
856
857 /***********************************************************************
858  *           GlobalFree32   (KERNEL32.322)
859  */
860 HGLOBAL32 GlobalFree32( HGLOBAL32 handle )
861 {
862     return HeapFree( GetProcessHeap(), 0, (LPVOID)handle ) ? 0 : handle;
863 }
864
865
866 /***********************************************************************
867  *           GlobalHandle32   (KERNEL32.325)
868  */
869 HGLOBAL32 GlobalHandle32( LPCVOID ptr )
870 {
871     return (HGLOBAL32)ptr;
872 }
873
874
875 /***********************************************************************
876  *           GlobalLock32   (KERNEL32.326)
877  */
878 LPVOID GlobalLock32( HGLOBAL32 handle )
879 {
880     return (LPVOID)handle;
881 }
882
883
884 /***********************************************************************
885  *           GlobalReAlloc32   (KERNEL32.328)
886  */
887 HGLOBAL32 GlobalReAlloc32( HGLOBAL32 handle, DWORD size, UINT32 flags )
888 {
889     if (flags & GMEM_MODIFY)
890     {
891         fprintf( stderr, "GlobalReAlloc32: GMEM_MODIFY not supported\n" );
892         return 0;
893     }
894
895     return (HGLOBAL32)HeapReAlloc( GetProcessHeap(), 0, (LPVOID)handle, size );
896 }
897
898
899 /***********************************************************************
900  *           GlobalSize32   (KERNEL32.329)
901  */
902 DWORD GlobalSize32( HGLOBAL32 handle )
903 {
904     return HeapSize( GetProcessHeap(), 0, (LPVOID)handle );
905 }
906
907
908 /***********************************************************************
909  *           GlobalUnlock32   (KERNEL32.332)
910  */
911 BOOL32 GlobalUnlock32( HGLOBAL32 handle )
912 {
913     return TRUE;
914 }