source: trunk/src/kernel32/heap.cpp@ 6185

Last change on this file since 6185 was 6184, checked in by sandervl, 24 years ago

heap updates/fixes

File size: 29.8 KB
Line 
1/* $Id: heap.cpp,v 1.29 2001-07-06 13:47:18 sandervl Exp $ */
2
3/*
4 * Win32 heap API functions for OS/2
5 *
6 * Copyright 1999-2001 Sander van Leeuwen
7 *
8 * Global memory functions ported from Wine
9 * Copyright 1995 Alexandre Julliard
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14
15#include <os2win.h>
16#include <stdlib.h>
17#include <string.h>
18#include <misc.h>
19#define _WIN32
20#include "os2heap.h"
21#include <heap.h>
22#include <odinwrap.h>
23
24#define DBG_LOCALLOG DBG_heap
25#include "dbglocal.h"
26
27static HANDLE processheap = NULL;
28OS2Heap *OS2ProcessHeap = NULL;
29
30//******************************************************************************
31//******************************************************************************
32ODINFUNCTIONNODBG3(LPVOID, HeapAlloc, HANDLE, hHeap, DWORD, dwFlags,
33 DWORD, dwBytes)
34{
35 OS2Heap *curheap = OS2Heap::find(hHeap);
36 LPVOID rc;
37
38 if(curheap == NULL)
39 return(NULL);
40
41 rc = curheap->Alloc(dwFlags, dwBytes);
42 dprintf2(("HeapAlloc %d bytes -> %x", dwBytes, rc));
43 return rc;
44}
45//******************************************************************************
46//******************************************************************************
47ODINFUNCTIONNODBG4(LPVOID, HeapReAlloc, HANDLE, hHeap, DWORD, dwFlags, LPVOID,
48 lpMem, DWORD, dwBytes)
49{
50 OS2Heap *curheap = OS2Heap::find(hHeap);
51
52 dprintf2(("HeapReAlloc %x %x %x %X bytes", hHeap, dwFlags, lpMem, dwBytes));
53 if(curheap == NULL)
54 return(NULL);
55
56 //Some apps (i.e. nt's cmd.exe) assume the returned pointer is the same as the old one!
57 if(lpMem && curheap->Size(0, lpMem) > dwBytes)
58 return lpMem;
59
60 return(curheap->ReAlloc(dwFlags, lpMem, dwBytes));
61}
62//******************************************************************************
63//******************************************************************************
64ODINFUNCTIONNODBG3(BOOL, HeapFree, HANDLE, hHeap, DWORD, dwFlags, LPVOID, lpMem)
65{
66 OS2Heap *curheap = OS2Heap::find(hHeap);
67
68 dprintf2(("HeapFree %X", lpMem));
69 if(curheap == NULL)
70 return(FALSE);
71
72 return(curheap->Free(dwFlags, lpMem));
73}
74//******************************************************************************
75//******************************************************************************
76ODINFUNCTIONNODBG3(HANDLE, HeapCreate, DWORD, flOptions, DWORD, dwInitialSize,
77 DWORD, dwMaximumSize)
78{
79 OS2Heap *curheap;
80
81 //Create Open32 heap for it's handle
82 dprintf2(("HeapCreate dwInitialSize %X", dwInitialSize));
83 HANDLE hHeap = O32_HeapCreate(flOptions, 0, 4096);
84 if(hHeap == NULL)
85 return(NULL);
86
87 curheap = new OS2Heap(hHeap, flOptions, dwInitialSize, dwMaximumSize);
88
89 if(curheap == NULL)
90 {
91 O32_HeapDestroy(hHeap);
92 return(NULL);
93 }
94
95 if(curheap->getHeapHandle() == NULL)
96 {
97 O32_HeapDestroy(hHeap);
98 delete(curheap);
99 return(NULL);
100 }
101 return(curheap->getHeapHandle());
102}
103//******************************************************************************
104//******************************************************************************
105ODINFUNCTIONNODBG1(BOOL, HeapDestroy, HANDLE, hHeap)
106{
107 OS2Heap *curheap = OS2Heap::find(hHeap);
108
109 dprintf2(("HeapDestroy %X", hHeap));
110 if(curheap == NULL)
111 return(FALSE);
112
113 O32_HeapDestroy(curheap->getHeapHandle());
114 delete(curheap);
115 return(TRUE);
116}
117//******************************************************************************
118//******************************************************************************
119ODINFUNCTIONNODBG3(DWORD, HeapSize, HANDLE, hHeap, DWORD, arg2, PVOID, lpMem)
120{
121 OS2Heap *curheap = OS2Heap::find(hHeap);
122
123 dprintf2(("HeapSize %X %x %x", hHeap, arg2, lpMem));
124 if(curheap == NULL)
125 return(0);
126 return curheap->Size(arg2, lpMem);
127}
128//******************************************************************************
129//TODO: Check this!!!
130//******************************************************************************
131ODINFUNCTIONNODBG2(DWORD, HeapCompact, HANDLE, hHeap, DWORD, dwFlags)
132{
133 dprintf(("KERNEL32: HeapCompact: Unknown API - stub\n"));
134 return(0);
135}
136//******************************************************************************
137//******************************************************************************
138ODINFUNCTIONNODBG3(BOOL, HeapValidate, HANDLE, hHeap, DWORD, dwFlags, LPCVOID, lpMem)
139{
140 dprintf(("KERNEL32: HeapValidate - stub\n"));
141 return(TRUE);
142}
143//******************************************************************************
144//******************************************************************************
145ODINFUNCTIONNODBG1(BOOL, HeapUnlock, HANDLE, hHeap)
146{
147 dprintf(("KERNEL32: HeapUnlock - stub (TRUE)\n"));
148 return(TRUE);
149}
150//******************************************************************************
151//******************************************************************************
152ODINFUNCTIONNODBG1(BOOL, HeapLock, HANDLE, hHeap)
153{
154 dprintf(("KERNEL32: HeapLock - stub (TRUE)\n"));
155 return(TRUE);
156}
157//******************************************************************************
158// LPPROCESS_HEAP_ENTRY lpEntry
159//******************************************************************************
160ODINFUNCTIONNODBG2(BOOL, HeapWalk, HANDLE, hHeap, LPVOID, lpEntry)
161{
162 dprintf(("KERNEL32: HeapWalk - stub (TRUE)\n"));
163 return(TRUE);
164}
165//******************************************************************************
166//******************************************************************************
167ODINFUNCTIONNODBG0(HANDLE, GetProcessHeap)
168{
169 HANDLE hHeap;
170
171// dprintf2(("KERNEL32: GetProcessHeap\n"));
172 //SvL: Only one process heap per process
173 if(processheap == NULL) {
174 //TODO: I haven't thought real hard about this. I added it just to make "hdr.exe" happy.
175 hHeap = O32_HeapCreate(HEAP_GENERATE_EXCEPTIONS, 1, 0x4000);
176
177 OS2ProcessHeap = new OS2Heap(hHeap, HEAP_GENERATE_EXCEPTIONS, 0x4000, 0);
178
179 if(OS2ProcessHeap == NULL) {
180 O32_HeapDestroy(hHeap);
181 return(NULL);
182 }
183 processheap = hHeap;
184 }
185 return(processheap);
186}
187#if 1
188/*
189 * Win32 Global heap functions (GlobalXXX).
190 * These functions included in Win32 for compatibility with 16 bit Windows
191 * Especially the moveable blocks and handles are oldish.
192 * But the ability to directly allocate memory with GPTR and LPTR is widely
193 * used.
194 *
195 * The handle stuff looks horrible, but it's implemented almost like Win95
196 * does it.
197 *
198 */
199
200#define MAGIC_GLOBAL_USED 0x5342
201#define GLOBAL_LOCK_MAX 0xFF
202#define HANDLE_TO_INTERN(h) ((PGLOBAL32_INTERN)(((char *)(h))-2))
203#define INTERN_TO_HANDLE(i) ((HGLOBAL) &((i)->Pointer))
204#define ISHANDLE(h) (((DWORD)(h)&2)!=0)
205#define ISPOINTER(h) (((DWORD)(h)&2)==0)
206
207//SvL: -2 for 8 byte alignment
208#define POINTER_TO_HANDLE(p) (*(((HGLOBAL *)(p))-2))
209#define HGLOBAL_SIZE 2*sizeof(HGLOBAL)
210
211#pragma pack(1)
212
213typedef struct __GLOBAL32_INTERN
214{
215 WORD Magic;
216 LPVOID Pointer;
217 BYTE Flags;
218 BYTE LockCount;
219} GLOBAL32_INTERN, *PGLOBAL32_INTERN;
220
221#pragma pack()
222
223/***********************************************************************
224 * GlobalAlloc (KERNEL32.@)
225 * RETURNS
226 * Handle: Success
227 * NULL: Failure
228 */
229HGLOBAL WINAPI GlobalAlloc(
230 UINT flags, /* [in] Object allocation attributes */
231 DWORD size /* [in] Number of bytes to allocate */
232) {
233 PGLOBAL32_INTERN pintern;
234 DWORD hpflags;
235 LPVOID palloc;
236
237 if(flags&GMEM_ZEROINIT)
238 hpflags=HEAP_ZERO_MEMORY;
239 else
240 hpflags=0;
241
242 if((flags & GMEM_MOVEABLE)==0) /* POINTER */
243 {
244 palloc=HeapAlloc(GetProcessHeap(), hpflags, size);
245 dprintf(("KERNEL32: GlobalAlloc %x %d returned %x", flags, size, palloc));
246 return (HGLOBAL) palloc;
247 }
248 else /* HANDLE */
249 {
250 /* HeapLock(heap); */
251
252 pintern=(PGLOBAL32_INTERN)HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL32_INTERN));
253 if (!pintern) return 0;
254 if(size)
255 {
256 //SvL: 2*sizeof for 8 byte alignment
257 if (!(palloc=HeapAlloc(GetProcessHeap(), hpflags, size+HGLOBAL_SIZE))) {
258 HeapFree(GetProcessHeap(), 0, pintern);
259 return 0;
260 }
261 *(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
262 //SvL: 2*sizeof for 8 byte alignment
263 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
264 }
265 else
266 pintern->Pointer=NULL;
267 pintern->Magic=MAGIC_GLOBAL_USED;
268 pintern->Flags=flags>>8;
269 pintern->LockCount=0;
270
271 /* HeapUnlock(heap); */
272
273 dprintf(("KERNEL32: GlobalAlloc %x %d returned %x", flags, size, INTERN_TO_HANDLE(pintern)));
274 return INTERN_TO_HANDLE(pintern);
275 }
276}
277/***********************************************************************
278 * GlobalLock (KERNEL32.@)
279 * RETURNS
280 * Pointer to first byte of block
281 * NULL: Failure
282 */
283LPVOID WINAPI GlobalLock(
284 HGLOBAL hmem /* [in] Handle of global memory object */
285) {
286 PGLOBAL32_INTERN pintern;
287 LPVOID palloc;
288
289
290 if(hmem == NULL || ISPOINTER(hmem)) {
291 dprintf(("KERNEL32: GlobalLock %x returned %x", hmem, hmem));
292 return (LPVOID) hmem;
293 }
294
295 /* HeapLock(GetProcessHeap()); */
296
297 pintern=HANDLE_TO_INTERN(hmem);
298 if(pintern->Magic==MAGIC_GLOBAL_USED)
299 {
300 if(pintern->LockCount<GLOBAL_LOCK_MAX)
301 pintern->LockCount++;
302 palloc=pintern->Pointer;
303 }
304 else
305 {
306 dprintf(("ERROR: GlobalLock invalid handle %x", hmem));
307 palloc=(LPVOID) NULL;
308 SetLastError(ERROR_INVALID_HANDLE);
309 }
310 /* HeapUnlock(GetProcessHeap()); */;
311
312 dprintf(("KERNEL32: GlobalLock %x returned %x", hmem, palloc));
313 return palloc;
314}
315
316
317/***********************************************************************
318 * GlobalUnlock (KERNEL32.@)
319 * RETURNS
320 * TRUE: Object is still locked
321 * FALSE: Object is unlocked
322 */
323BOOL WINAPI GlobalUnlock(
324 HGLOBAL hmem /* [in] Handle of global memory object */
325) {
326 PGLOBAL32_INTERN pintern;
327 BOOL locked;
328
329 dprintf(("KERNEL32: GlobalUnlock %x", hmem));
330
331 if(hmem == NULL || ISPOINTER(hmem))
332 return FALSE;
333
334 /* HeapLock(GetProcessHeap()); */
335 pintern=HANDLE_TO_INTERN(hmem);
336
337 if(pintern->Magic==MAGIC_GLOBAL_USED)
338 {
339 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
340 pintern->LockCount--;
341
342 locked = (pintern->LockCount != 0);
343 if (!locked) SetLastError(NO_ERROR);
344 }
345 else
346 {
347 dprintf(("ERROR: GlobalUnlock invalid handle %x", hmem));
348 SetLastError(ERROR_INVALID_HANDLE);
349 locked=FALSE;
350 }
351 /* HeapUnlock(GetProcessHeap()); */
352 return locked;
353}
354
355
356/***********************************************************************
357 * GlobalHandle (KERNEL32.@)
358 * Returns the handle associated with the specified pointer.
359 *
360 * RETURNS
361 * Handle: Success
362 * NULL: Failure
363 */
364HGLOBAL WINAPI GlobalHandle(
365 LPCVOID pmem /* [in] Pointer to global memory block */
366) {
367 HGLOBAL handle;
368 PGLOBAL32_INTERN maybe_intern;
369 LPCVOID test;
370
371 dprintf(("KERNEL32: GlobalHandle %x", pmem));
372
373 if (!pmem)
374 {
375 SetLastError( ERROR_INVALID_PARAMETER );
376 return 0;
377 }
378
379#ifdef __WIN32OS2__
380 handle = 0;
381
382 /* note that if pmem is a pointer to a a block allocated by */
383 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
384 /* will fail. */
385 if (ISPOINTER(pmem)) {
386 if (HeapValidate( GetProcessHeap(), 0, pmem )) {
387 handle = (HGLOBAL)pmem; /* valid fixed block */
388 return handle;
389 }
390 handle = POINTER_TO_HANDLE(pmem);
391 } else
392 handle = (HGLOBAL)pmem;
393
394 /* Now test handle either passed in or retrieved from pointer */
395 maybe_intern = HANDLE_TO_INTERN( handle );
396 if(IsBadReadPtr(maybe_intern, sizeof(GLOBAL32_INTERN))) {
397 SetLastError( ERROR_INVALID_HANDLE );
398 return 0;
399 }
400
401 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
402 test = maybe_intern->Pointer;
403 //SvL: -2 for 8 byte alignment
404 if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-2 ) && /* obj(-handle) valid arena? */
405 HeapValidate( GetProcessHeap(), 0, maybe_intern )) /* intern valid arena? */
406 {
407 return handle;
408 }
409 }
410 handle = 0;
411 SetLastError( ERROR_INVALID_HANDLE );
412#else
413 __TRY
414 {
415 handle = 0;
416
417 /* note that if pmem is a pointer to a a block allocated by */
418 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
419 /* will fail. */
420 if (ISPOINTER(pmem)) {
421 if (HeapValidate( GetProcessHeap(), 0, pmem )) {
422 handle = (HGLOBAL)pmem; /* valid fixed block */
423 break;
424 }
425 handle = POINTER_TO_HANDLE(pmem);
426 } else
427 handle = (HGLOBAL)pmem;
428
429 /* Now test handle either passed in or retrieved from pointer */
430 maybe_intern = HANDLE_TO_INTERN( handle );
431 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
432 test = maybe_intern->Pointer;
433 if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
434 HeapValidate( GetProcessHeap(), 0, maybe_intern )) /* intern valid arena? */
435 break; /* valid moveable block */
436 }
437 handle = 0;
438 SetLastError( ERROR_INVALID_HANDLE );
439 }
440 __EXCEPT(page_fault)
441 {
442 SetLastError( ERROR_INVALID_HANDLE );
443 return 0;
444 }
445 __ENDTRY
446#endif
447 return handle;
448}
449
450
451/***********************************************************************
452 * GlobalReAlloc (KERNEL32.@)
453 * RETURNS
454 * Handle: Success
455 * NULL: Failure
456 */
457HGLOBAL WINAPI GlobalReAlloc(
458 HGLOBAL hmem, /* [in] Handle of global memory object */
459 DWORD size, /* [in] New size of block */
460 UINT flags /* [in] How to reallocate object */
461) {
462 LPVOID palloc;
463 HGLOBAL hnew;
464 PGLOBAL32_INTERN pintern;
465 DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
466
467 hnew = 0;
468 /* HeapLock(heap); */
469 if(flags & GMEM_MODIFY) /* modify flags */
470 {
471 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
472 {
473 /* make a fixed block moveable
474 * actually only NT is able to do this. But it's soo simple
475 */
476 if (hmem == 0)
477 {
478 dprintf(("ERROR: GlobalReAlloc32 with null handle!\n"));
479 SetLastError( ERROR_NOACCESS );
480 return 0;
481 }
482 size=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
483 hnew=GlobalAlloc( flags, size);
484 palloc=GlobalLock(hnew);
485 memcpy(palloc, (LPVOID) hmem, size);
486 GlobalUnlock(hnew);
487 GlobalFree(hmem);
488 }
489 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
490 {
491 /* change the flags to make our block "discardable" */
492 pintern=HANDLE_TO_INTERN(hmem);
493 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
494 hnew=hmem;
495 }
496 else
497 {
498 SetLastError(ERROR_INVALID_PARAMETER);
499 hnew = 0;
500 }
501 }
502 else
503 {
504 if(ISPOINTER(hmem))
505 {
506 /* reallocate fixed memory */
507 hnew=(HGLOBAL)HeapReAlloc(GetProcessHeap(), heap_flags, (LPVOID) hmem, size);
508 }
509 else
510 {
511 /* reallocate a moveable block */
512 pintern=HANDLE_TO_INTERN(hmem);
513
514#if 0
515/* Apparently Windows doesn't care whether the handle is locked at this point */
516/* See also the same comment in GlobalFree() */
517 if(pintern->LockCount>1) {
518 ERR("handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
519 SetLastError(ERROR_INVALID_HANDLE);
520 } else
521#endif
522 if(size!=0)
523 {
524 hnew=hmem;
525 if(pintern->Pointer)
526 {
527 if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
528 (char *) pintern->Pointer-HGLOBAL_SIZE,
529 size+HGLOBAL_SIZE)) == NULL)
530 return 0; /* Block still valid */
531 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
532 }
533 else
534 {
535 if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+HGLOBAL_SIZE))
536 == NULL)
537 return 0;
538 *(HGLOBAL *)palloc=hmem;
539 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
540 }
541 }
542 else
543 {
544 if(pintern->Pointer)
545 {
546 HeapFree(GetProcessHeap(), 0, (char *) pintern->Pointer-HGLOBAL_SIZE);
547 pintern->Pointer=NULL;
548 }
549 }
550 }
551 }
552 /* HeapUnlock(heap); */
553 return hnew;
554}
555
556
557/***********************************************************************
558 * GlobalFree (KERNEL32.@)
559 * RETURNS
560 * NULL: Success
561 * Handle: Failure
562 */
563HGLOBAL WINAPI GlobalFree(
564 HGLOBAL hmem /* [in] Handle of global memory object */
565) {
566 PGLOBAL32_INTERN pintern;
567 HGLOBAL hreturned = 0;
568
569 dprintf(("KERNEL32: GlobalFree %x", hmem));
570
571 if(ISPOINTER(hmem)) /* POINTER */
572 {
573 if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
574 }
575 else /* HANDLE */
576 {
577 /* HeapLock(heap); */
578 pintern=HANDLE_TO_INTERN(hmem);
579
580 if(pintern->Magic==MAGIC_GLOBAL_USED)
581 {
582
583/* WIN98 does not make this test. That is you can free a */
584/* block you have not unlocked. Go figure!! */
585 /* if(pintern->LockCount!=0) */
586 /* SetLastError(ERROR_INVALID_HANDLE); */
587
588 if(pintern->Pointer)
589 if(!HeapFree(GetProcessHeap(), 0, (char *)(pintern->Pointer)-HGLOBAL_SIZE))
590 hreturned=hmem;
591 if(!HeapFree(GetProcessHeap(), 0, pintern))
592 hreturned=hmem;
593 }
594 /* HeapUnlock(heap); */
595 }
596 return hreturned;
597}
598
599
600/***********************************************************************
601 * GlobalSize (KERNEL32.@)
602 * RETURNS
603 * Size in bytes of the global memory object
604 * 0: Failure
605 */
606DWORD WINAPI GlobalSize(
607 HGLOBAL hmem /* [in] Handle of global memory object */
608) {
609 DWORD retval;
610 PGLOBAL32_INTERN pintern;
611
612 dprintf(("KERNEL32: GlobalSize %x", hmem));
613
614 if(ISPOINTER(hmem))
615 {
616 retval=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
617 }
618 else
619 {
620 /* HeapLock(heap); */
621 pintern=HANDLE_TO_INTERN(hmem);
622
623 if(pintern->Magic==MAGIC_GLOBAL_USED)
624 {
625 if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
626 return 0;
627 retval=HeapSize(GetProcessHeap(), 0,
628 (char *)(pintern->Pointer)-HGLOBAL_SIZE)-HGLOBAL_SIZE;
629 //SvL: ???
630 if (retval == 0xffffffff-HGLOBAL_SIZE) retval = 0;
631 }
632 else
633 {
634 dprintf(("ERROR: GlobalSize invalid handle %x", hmem));
635 retval=0;
636 }
637 /* HeapUnlock(heap); */
638 }
639 /* HeapSize returns 0xffffffff on failure */
640 if (retval == 0xffffffff) retval = 0;
641 dprintf(("KERNEL32: GlobalSize %x = %d", hmem, retval));
642 return retval;
643}
644
645
646/***********************************************************************
647 * GlobalWire (KERNEL32.@)
648 */
649LPVOID WINAPI GlobalWire(HGLOBAL hmem)
650{
651 return GlobalLock( hmem );
652}
653
654
655/***********************************************************************
656 * GlobalUnWire (KERNEL32.@)
657 */
658BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
659{
660 return GlobalUnlock( hmem);
661}
662
663
664/***********************************************************************
665 * GlobalFix (KERNEL32.@)
666 */
667VOID WINAPI GlobalFix(HGLOBAL hmem)
668{
669 GlobalLock( hmem );
670}
671
672
673/***********************************************************************
674 * GlobalUnfix (KERNEL32.@)
675 */
676VOID WINAPI GlobalUnfix(HGLOBAL hmem)
677{
678 GlobalUnlock( hmem);
679}
680
681
682/***********************************************************************
683 * GlobalFlags (KERNEL32.@)
684 * Returns information about the specified global memory object
685 *
686 * NOTES
687 * Should this return GMEM_INVALID_HANDLE on invalid handle?
688 *
689 * RETURNS
690 * Value specifying allocation flags and lock count
691 * GMEM_INVALID_HANDLE: Failure
692 */
693UINT WINAPI GlobalFlags(
694 HGLOBAL hmem /* [in] Handle to global memory object */
695) {
696 DWORD retval;
697 PGLOBAL32_INTERN pintern;
698
699 dprintf(("KERNEL32: GlobalFlags %x", hmem));
700
701 if(ISPOINTER(hmem))
702 {
703 retval=0;
704 }
705 else
706 {
707 /* HeapLock(GetProcessHeap()); */
708 pintern=HANDLE_TO_INTERN(hmem);
709 if(pintern->Magic==MAGIC_GLOBAL_USED)
710 {
711 retval=pintern->LockCount + (pintern->Flags<<8);
712 if(pintern->Pointer==0)
713 retval|= GMEM_DISCARDED;
714 }
715 else
716 {
717 dprintf(("ERROR: GlobalFlags invalid handle %x", hmem));
718 retval=0;
719 }
720 /* HeapUnlock(GetProcessHeap()); */
721 }
722 return retval;
723}
724
725
726/***********************************************************************
727 * GlobalCompact (KERNEL32.@)
728 */
729DWORD WINAPI GlobalCompact( DWORD minfree )
730{
731 dprintf(("KERNEL32: GlobalCompact %d OBSOLETE", minfree));
732
733 return 0; /* GlobalCompact does nothing in Win32 */
734}
735#else
736//******************************************************************************
737#ifdef DEBUG
738static ULONG totalGlobalAlloc = 0;
739#endif
740//******************************************************************************
741HGLOBAL WIN32API GlobalAlloc(UINT fuFlags, DWORD dwBytes)
742{
743 HGLOBAL ret;
744
745 ret = O32_GlobalAlloc(fuFlags, dwBytes);
746#ifdef DEBUG
747 totalGlobalAlloc += dwBytes;
748#endif
749 dprintf(("KERNEL32: GlobalAlloc %x %d returned %x (total %x)", fuFlags, dwBytes, ret, totalGlobalAlloc));
750 return ret;
751}
752//******************************************************************************
753//******************************************************************************
754HGLOBAL WIN32API GlobalFree( HGLOBAL arg1)
755{
756 HGLOBAL ret;
757
758#ifdef DEBUG
759 totalGlobalAlloc -= O32_GlobalSize(arg1);
760#endif
761 ret = O32_GlobalFree(arg1);
762 dprintf(("KERNEL32: GlobalFree %x returned %x (lasterr=%x) total %x", arg1, ret, GetLastError(), totalGlobalAlloc));
763 return ret;
764}
765//******************************************************************************
766//******************************************************************************
767HGLOBAL WIN32API GlobalHandle( LPCVOID lpMem)
768{
769 dprintf(("KERNEL32: GlobalHandle %x", lpMem));
770
771 return O32_GlobalHandle((LPVOID)lpMem);
772}
773//******************************************************************************
774//******************************************************************************
775UINT WIN32API GlobalFlags(HGLOBAL hMem)
776{
777 dprintf(("KERNEL32: GlobalFlags %x", hMem));
778
779 return O32_GlobalFlags(hMem);
780}
781//******************************************************************************
782//******************************************************************************
783DWORD WIN32API GlobalCompact(DWORD dwMinFree)
784{
785 dprintf(("KERNEL32: GlobalCompact, OBSOLETE - stub\n"));
786
787 return(0);
788}
789//******************************************************************************
790//******************************************************************************
791PVOID WIN32API GlobalLock(HGLOBAL hMem)
792{
793 PVOID ret;
794
795 ret = O32_GlobalLock(hMem);
796 dprintf(("KERNEL32: GlobalLock %x returned %x", hMem, ret));
797 return ret;
798}
799//******************************************************************************
800//******************************************************************************
801HGLOBAL WIN32API GlobalReAlloc(HGLOBAL arg1, DWORD arg2, UINT arg3)
802{
803 dprintf(("KERNEL32: GlobalReAlloc %x %x %d", arg1, arg2, arg3));
804
805 return O32_GlobalReAlloc(arg1, arg2, arg3);
806}
807//******************************************************************************
808//******************************************************************************
809DWORD WIN32API GlobalSize(HGLOBAL arg1)
810{
811 dprintf(("KERNEL32: GlobalSize\n"));
812
813 return O32_GlobalSize(arg1);
814}
815//******************************************************************************
816//******************************************************************************
817BOOL WIN32API GlobalUnlock(HGLOBAL arg1)
818{
819 dprintf(("KERNEL32: GlobalUnlock\n"));
820
821 return O32_GlobalUnlock(arg1);
822}
823/***********************************************************************
824 * GlobalWire
825 *
826 * The GlobalWire function is obsolete. It is provided only for compatibility
827 * with 16-bit versions of Windows. Applications that need to lock a global
828 * memory object should use the GlobalLock and GlobalUnlock functions.
829 *
830 */
831LPVOID WIN32API GlobalWire(HGLOBAL hmem)
832{
833 return GlobalLock( hmem );
834}
835/***********************************************************************
836 * GlobalUnWire
837 *
838 * The GlobalUnWire function is obsolete. It is provided only for compatibility
839 * with 16-bit versions of Windows. Applications that need to lock a global
840 * memory object should use the GlobalLock and GlobalUnlock functions.
841 *
842 */
843BOOL WIN32API GlobalUnWire(HGLOBAL hmem)
844{
845 return GlobalUnlock( hmem);
846}
847//******************************************************************************
848//******************************************************************************
849HGLOBAL WIN32API GlobalDiscard(HGLOBAL hGlobal)
850{
851 dprintf(("KERNEL32: GlobalDiscard %x", hGlobal));
852
853 return O32_GlobalDiscard(hGlobal);
854}
855/***********************************************************************
856 * GlobalFix (KERNEL32.@)
857 */
858VOID WINAPI GlobalFix(HGLOBAL hmem)
859{
860 GlobalLock( hmem );
861}
862/***********************************************************************
863 * GlobalUnfix (KERNEL32.@)
864 */
865VOID WINAPI GlobalUnfix(HGLOBAL hmem)
866{
867 GlobalUnlock( hmem);
868}
869#endif
870//******************************************************************************
871//******************************************************************************
872HLOCAL WIN32API LocalAlloc(UINT fuFlags, DWORD cbBytes)
873{
874 HLOCAL hLocal;
875
876 // Check flags
877 if(fuFlags & (~(LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT |
878 LMEM_NODISCARD | LMEM_ZEROINIT)))
879 {
880 dprintf(("LocalAlloc %x %x: INVALID flags!", fuFlags, cbBytes));
881 SetLastError(ERROR_INVALID_PARAMETER);
882 return 0;
883 }
884 // Note: local & global flags are the same (the ones used here), so no need for conversion
885 hLocal = GlobalAlloc(fuFlags, cbBytes);
886 dprintf(("KERNEL32: LocalAlloc flags %X, size %d returned %X", fuFlags, cbBytes, hLocal));
887 return hLocal;
888}
889//******************************************************************************
890//******************************************************************************
891UINT WIN32API LocalFlags(HLOCAL hMem)
892{
893 UINT ret, retG;
894 dprintf(("KERNEL32: LocalFlags %X\n", hMem));
895
896 retG = GlobalFlags(hMem);
897
898 if(retG == GMEM_INVALID_HANDLE)
899 {
900 return LMEM_INVALID_HANDLE;
901 }
902 // Low byte holds lock count.
903 // Hi byte of low word contains some flags.
904 ret = retG & 0xff; // Keep lock count.
905 if (retG & GMEM_DISCARDABLE) ret |= LMEM_DISCARDABLE;
906 if (retG & GMEM_DISCARDED) ret |= LMEM_DISCARDED;
907
908 return ret;
909}
910//******************************************************************************
911//******************************************************************************
912HLOCAL WIN32API LocalFree(HLOCAL hMem)
913{
914 dprintf(("KERNEL32: LocalFree %X", hMem));
915
916 return GlobalFree(hMem);
917}
918//******************************************************************************
919//******************************************************************************
920HLOCAL WIN32API LocalHandle(PCVOID lpMem)
921{
922 dprintf(("KERNEL32: LocalHandle %x", lpMem));
923
924 return GlobalHandle(lpMem);
925}
926//******************************************************************************
927//******************************************************************************
928BOOL WIN32API LocalUnlock(HLOCAL hMem)
929{
930 dprintf(("KERNEL32: LocalUnlock %X", hMem));
931
932 return GlobalUnlock(hMem);
933}
934//******************************************************************************
935//TODO: cbBytes==0 && fuFlags & LMEM_MOVEABLE not handled!!
936//******************************************************************************
937HLOCAL WIN32API LocalReAlloc(HLOCAL hMem, DWORD cbBytes, UINT fuFlags)
938{
939 HLOCAL hLocalNew, hLocalOld;
940 LPVOID lpMem, lpMemOld;
941 DWORD cbOldSize;
942
943 dprintf(("KERNEL32: LocalReAlloc %X %d %X\n", hMem, cbBytes, fuFlags));
944
945 // Check flags
946 if(fuFlags & (~(LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT |
947 LMEM_MODIFY | LMEM_ZEROINIT)))
948 {
949 dprintf(("LocalAlloc %x %x: INVALID flags!", fuFlags, cbBytes));
950 SetLastError(ERROR_INVALID_PARAMETER);
951 return 0;
952 }
953
954 //SvL: 8-8-'98: Notepad bugfix (assumes address is identical when new size < old size)
955 cbOldSize = LocalSize(hMem);
956 if(cbOldSize > cbBytes)
957 return hMem;
958
959 return GlobalReAlloc(hMem, cbBytes, fuFlags);
960}
961//******************************************************************************
962//******************************************************************************
963UINT WIN32API LocalSize(HLOCAL hMem)
964{
965 dprintf(("KERNEL32: LocalSize %X", hMem));
966
967 return GlobalSize(hMem);
968}
969//******************************************************************************
970//******************************************************************************
971PVOID WIN32API LocalLock(HLOCAL hMem)
972{
973 dprintf(("KERNEL32: LocalLock %X\n", hMem));
974
975 return GlobalLock(hMem);
976}
977//******************************************************************************
978//* this function is here for completeness, some stupid software requires it.
979//******************************************************************************
980UINT WIN32API LocalShrink(HLOCAL hMem, UINT cbNewSize)
981{
982 dprintf(("KERNEL32: LocalShrink %X, %08xh - OBSOLETE", hMem, cbNewSize));
983
984 return cbNewSize;
985}
986//******************************************************************************
987//* this function is here for completeness, mIRC/32 requires it.
988//******************************************************************************
989UINT WIN32API LocalCompact(UINT cbNewSize)
990{
991 dprintf(("KERNEL32: LocalCompact %08xh - OBSOLETE", cbNewSize));
992
993 return cbNewSize;
994}
995//******************************************************************************
996//******************************************************************************
Note: See TracBrowser for help on using the repository browser.