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

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

* empty log message *

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