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

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

Heap acceleration

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