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

Last change on this file since 8327 was 8327, checked in by sandervl, 23 years ago

PH: memory leak fixes; extra checks for NULL pointers; CreateProcess changes for debug option; GetModuleFileName doesn't count 0 terminator

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