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

Last change on this file since 7461 was 7360, checked in by phaller, 24 years ago

slightly more tuning

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