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

Last change on this file since 21347 was 21337, checked in by vladest, 16 years ago
  1. Fixed Flash10 installer (bad pointer passed to GlobalFree)
  2. Autocommit improoved. Added address and size alignment. Added return code check
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 1
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.