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

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

Exported Heap_ProcessHeap to heapstring.cpp and tuned GetProcessHeap() via inlining macro

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