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

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

logging updates

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