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

Last change on this file since 7890 was 7854, checked in by sandervl, 24 years ago

logging updates

File size: 26.0 KB
Line 
1
2/*
3 * Win32 heap API functions for OS/2
4 *
5 * Copyright 1999-2001 Sander van Leeuwen
6 *
7 * Global memory functions ported from Wine
8 * Copyright 1995 Alexandre Julliard
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13
14#include <os2win.h>
15#include <stdlib.h>
16#include <string.h>
17#include <misc.h>
18#define _WIN32
19#include "os2heap.h"
20#include <heap.h>
21#include "os2heap.h"
22#include <odinwrap.h>
23#include "initterm.h"
24
25#define DBG_LOCALLOG DBG_heap
26#include "dbglocal.h"
27
28ODINDEBUGCHANNEL(KERNEL32-HEAP)
29
30//******************************************************************************
31// Local variables
32//******************************************************************************
33
34static OS2Heap *OS2ProcessHeap = NULL;
35
36static HANDLE i_initializeProcessHeap()
37{
38 HANDLE _processheap;
39
40 //SvL: Only one process heap per process
41 OS2ProcessHeap = new OS2Heap(HEAP_GENERATE_EXCEPTIONS, 0x4000, 0);
42
43 if(OS2ProcessHeap == NULL)
44 return(NULL);
45 _processheap = OS2ProcessHeap->getHeapHandle();
46
47 return _processheap;
48}
49
50// Note:
51// variable is exported (i. e. to heapstring)
52HANDLE Heap_ProcessHeap = i_initializeProcessHeap();
53
54// This macro could be mapped to GetProcessHeap() if there
55// is any change in functionality
56#define GETPROCESSHEAP Heap_ProcessHeap
57
58
59//******************************************************************************
60// Fast Heap Handle Management
61//******************************************************************************
62
63extern HANDLE fhhm_lastHandle;
64extern OS2Heap* fhhm_lastHeap;
65
66#define FINDHEAP(curheap, hHeap) \
67 if (fhhm_lastHeap && \
68 hHeap == fhhm_lastHandle) \
69 curheap = fhhm_lastHeap; \
70 else \
71 curheap = OS2Heap::find(hHeap); \
72
73
74
75//******************************************************************************
76//******************************************************************************
77LPVOID WIN32API HeapAlloc(HANDLE hHeap,
78 DWORD dwFlags,
79 DWORD dwBytes)
80{
81 OS2Heap *curheap;
82 FINDHEAP(curheap,hHeap)
83 LPVOID rc;
84
85 if(curheap == NULL)
86 return(NULL);
87
88 rc = curheap->Alloc(dwFlags, dwBytes);
89 dprintf2(("HeapAlloc %d bytes -> %x", dwBytes, rc));
90 return rc;
91}
92//******************************************************************************
93//******************************************************************************
94LPVOID HeapReAlloc(HANDLE hHeap,
95 DWORD dwFlags,
96 LPVOID lpMem,
97 DWORD dwBytes)
98{
99 OS2Heap *curheap;
100 FINDHEAP(curheap,hHeap)
101
102 dprintf2(("HeapReAlloc %x %x %x %X bytes", hHeap, dwFlags, lpMem, dwBytes));
103 if(curheap == NULL)
104 return(NULL);
105
106 //Some apps (i.e. nt's cmd.exe) assume the returned pointer is the same as the old one!
107 if(lpMem && curheap->Size(0, lpMem) > dwBytes)
108 return lpMem;
109
110 return(curheap->ReAlloc(dwFlags, lpMem, dwBytes));
111}
112//******************************************************************************
113//******************************************************************************
114BOOL WIN32API HeapFree(HANDLE hHeap,
115 DWORD dwFlags,
116 LPVOID lpMem)
117{
118 OS2Heap *curheap;
119 FINDHEAP(curheap,hHeap)
120
121 dprintf2(("HeapFree %X", lpMem));
122 if(curheap == NULL)
123 return(FALSE);
124
125 BOOL fResult = curheap->Free(dwFlags, lpMem);
126 if (fResult == FALSE)
127 SetLastError(ERROR_INVALID_HANDLE); /// @@@PH possibly wrong return code!
128
129 return fResult;
130}
131//******************************************************************************
132//******************************************************************************
133HANDLE WIN32API HeapCreate(DWORD flOptions, DWORD dwInitialSize,
134 DWORD dwMaximumSize)
135{
136 OS2Heap *curheap;
137
138 //Create Open32 heap for it's handle
139 dprintf2(("HeapCreate dwInitialSize %X", dwInitialSize));
140
141 curheap = new OS2Heap(flOptions, dwInitialSize, dwMaximumSize);
142
143 if(curheap == NULL)
144 {
145 return(NULL);
146 }
147
148 if(curheap->getHeapHandle() == NULL)
149 {
150 delete(curheap);
151 return(NULL);
152 }
153 return(curheap->getHeapHandle());
154}
155//******************************************************************************
156//******************************************************************************
157BOOL WIN32API HeapDestroy(HANDLE hHeap)
158{
159 OS2Heap *curheap;
160 FINDHEAP(curheap,hHeap)
161
162 dprintf2(("HeapDestroy %X", hHeap));
163 if(curheap == NULL)
164 return(FALSE);
165
166 delete(curheap);
167 return(TRUE);
168}
169//******************************************************************************
170//******************************************************************************
171DWORD WIN32API HeapSize(HANDLE hHeap, DWORD arg2, PVOID lpMem)
172{
173 OS2Heap *curheap;
174 FINDHEAP(curheap,hHeap)
175
176 dprintf2(("HeapSize %X %x %x", hHeap, arg2, lpMem));
177 if(curheap == NULL)
178 return(0);
179 return curheap->Size(arg2, lpMem);
180}
181//******************************************************************************
182//TODO: Check this!!!
183//******************************************************************************
184DWORD WIN32API HeapCompact(HANDLE hHeap, DWORD dwFlags)
185{
186 dprintf(("KERNEL32: HeapCompact: Unknown API - stub\n"));
187 return(0);
188}
189//******************************************************************************
190//******************************************************************************
191BOOL WIN32API HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
192{
193 OS2Heap *curheap;
194 FINDHEAP(curheap,hHeap)
195
196 dprintf2(("KERNEL32: HeapValidate %x %x %x", hHeap, dwFlags, lpMem));
197 if(curheap == NULL)
198 return FALSE;
199
200 return curheap->Validate(dwFlags, lpMem);
201}
202//******************************************************************************
203//******************************************************************************
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 dprintf(("KERNEL32: GlobalLock %x returned %x", hmem, palloc));
359 return palloc;
360}
361
362
363/***********************************************************************
364 * GlobalUnlock (KERNEL32.@)
365 * RETURNS
366 * TRUE: Object is still locked
367 * FALSE: Object is unlocked
368 */
369BOOL WIN32API GlobalUnlock(HGLOBAL hmem)
370{
371 PGLOBAL32_INTERN pintern;
372 BOOL locked;
373
374 if(hmem == NULL || ISPOINTER(hmem))
375 return FALSE;
376
377 /* verify lpMem address */
378 if (hmem >= (HGLOBAL)ulMaxAddr || hmem < (HGLOBAL)0x10000)
379 {
380 dprintf(("GlobalUnlock ERROR BAD HEAP POINTER:%X\n", hmem));
381 DebugInt3();
382 return 0;
383 }
384
385 /* HeapLock(GETPROCESSHEAP); */
386 pintern=HANDLE_TO_INTERN(hmem);
387
388 if(pintern->Magic==MAGIC_GLOBAL_USED)
389 {
390 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
391 pintern->LockCount--;
392
393 locked = (pintern->LockCount != 0);
394 if (!locked) SetLastError(NO_ERROR);
395 }
396 else
397 {
398 dprintf(("ERROR: GlobalUnlock invalid handle %x", hmem));
399 SetLastError(ERROR_INVALID_HANDLE);
400 locked=FALSE;
401 }
402 /* HeapUnlock(GETPROCESSHEAP); */
403 return locked;
404}
405
406
407/***********************************************************************
408 * GlobalHandle (KERNEL32.@)
409 * Returns the handle associated with the specified pointer.
410 *
411 * RETURNS
412 * Handle: Success
413 * NULL: Failure
414 */
415HGLOBAL WIN32API GlobalHandle(LPCVOID pmem)
416{
417 HGLOBAL handle;
418 PGLOBAL32_INTERN maybe_intern;
419 LPCVOID test;
420
421 if (!pmem)
422 {
423 SetLastError( ERROR_INVALID_PARAMETER );
424 return 0;
425 }
426
427#ifdef __WIN32OS2__
428 handle = 0;
429
430 /* note that if pmem is a pointer to a a block allocated by */
431 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
432 /* will fail. */
433 if (ISPOINTER(pmem)) {
434 if (HeapValidate( GETPROCESSHEAP, 0, pmem )) {
435 handle = (HGLOBAL)pmem; /* valid fixed block */
436 return handle;
437 }
438 handle = POINTER_TO_HANDLE(pmem);
439 } else
440 handle = (HGLOBAL)pmem;
441
442 /* Now test handle either passed in or retrieved from pointer */
443 maybe_intern = HANDLE_TO_INTERN( handle );
444 if(IsBadReadPtr(maybe_intern, sizeof(GLOBAL32_INTERN))) {
445 SetLastError( ERROR_INVALID_HANDLE );
446 return 0;
447 }
448
449 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
450 test = maybe_intern->Pointer;
451 //SvL: -2 for 8 byte alignment
452 if (HeapValidate( GETPROCESSHEAP, 0, ((HGLOBAL *)test)-2 ) && /* obj(-handle) valid arena? */
453 HeapValidate( GETPROCESSHEAP, 0, maybe_intern )) /* intern valid arena? */
454 {
455 return handle;
456 }
457 }
458 handle = 0;
459 SetLastError( ERROR_INVALID_HANDLE );
460#else
461 __TRY
462 {
463 handle = 0;
464
465 /* note that if pmem is a pointer to a a block allocated by */
466 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
467 /* will fail. */
468 if (ISPOINTER(pmem)) {
469 if (HeapValidate( GETPROCESSHEAP, 0, pmem )) {
470 handle = (HGLOBAL)pmem; /* valid fixed block */
471 break;
472 }
473 handle = POINTER_TO_HANDLE(pmem);
474 } else
475 handle = (HGLOBAL)pmem;
476
477 /* Now test handle either passed in or retrieved from pointer */
478 maybe_intern = HANDLE_TO_INTERN( handle );
479 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
480 test = maybe_intern->Pointer;
481 if (HeapValidate( GETPROCESSHEAP, 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
482 HeapValidate( GETPROCESSHEAP, 0, maybe_intern )) /* intern valid arena? */
483 break; /* valid moveable block */
484 }
485 handle = 0;
486 SetLastError( ERROR_INVALID_HANDLE );
487 }
488 __EXCEPT(page_fault)
489 {
490 SetLastError( ERROR_INVALID_HANDLE );
491 return 0;
492 }
493 __ENDTRY
494#endif
495 return handle;
496}
497
498
499/***********************************************************************
500 * GlobalReAlloc (KERNEL32.@)
501 * RETURNS
502 * Handle: Success
503 * NULL: Failure
504 */
505HGLOBAL WIN32API GlobalReAlloc(HGLOBAL hmem, DWORD size, UINT flags)
506{
507 LPVOID palloc;
508 HGLOBAL hnew;
509 PGLOBAL32_INTERN pintern;
510 DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
511
512#ifdef __WIN32OS2__
513/* @@@PH 20011017
514 convert a handle to a handle ???
515 hmem = GlobalHandle((LPCVOID)hmem);
516 */
517#endif
518
519 hnew = 0;
520 /* HeapLock(heap); */
521 if(flags & GMEM_MODIFY) /* modify flags */
522 {
523 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
524 {
525 /* make a fixed block moveable
526 * actually only NT is able to do this. But it's soo simple
527 */
528 if (hmem == 0)
529 {
530 dprintf(("ERROR: GlobalReAlloc32 with null handle!\n"));
531 SetLastError( ERROR_NOACCESS );
532 return 0;
533 }
534 size=HeapSize(GETPROCESSHEAP, 0, (LPVOID) hmem);
535 hnew=GlobalAlloc( flags, size);
536 palloc=GlobalLock(hnew);
537 memcpy(palloc, (LPVOID) hmem, size);
538 GlobalUnlock(hnew);
539 GlobalFree(hmem);
540 }
541 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
542 {
543 /* change the flags to make our block "discardable" */
544 pintern=HANDLE_TO_INTERN(hmem);
545 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
546 hnew=hmem;
547 }
548 else
549 {
550 SetLastError(ERROR_INVALID_PARAMETER);
551 hnew = 0;
552 }
553 }
554 else
555 {
556 if(ISPOINTER(hmem))
557 {
558 /* reallocate fixed memory */
559 hnew=(HGLOBAL)HeapReAlloc(GETPROCESSHEAP, heap_flags, (LPVOID) hmem, size);
560 }
561 else
562 {
563 /* reallocate a moveable block */
564 pintern=HANDLE_TO_INTERN(hmem);
565
566#if 0
567/* Apparently Windows doesn't care whether the handle is locked at this point */
568/* See also the same comment in GlobalFree() */
569 if(pintern->LockCount>1) {
570 ERR("handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
571 SetLastError(ERROR_INVALID_HANDLE);
572 } else
573#endif
574 if(size!=0)
575 {
576 hnew=hmem;
577 if(pintern->Pointer)
578 {
579 if((palloc = HeapReAlloc(GETPROCESSHEAP, heap_flags,
580 (char *) pintern->Pointer-HGLOBAL_SIZE,
581 size+HGLOBAL_SIZE)) == NULL)
582 return 0; /* Block still valid */
583 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
584 }
585 else
586 {
587 if((palloc=HeapAlloc(GETPROCESSHEAP, heap_flags, size+HGLOBAL_SIZE))
588 == NULL)
589 return 0;
590 *(HGLOBAL *)palloc=hmem;
591 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
592 }
593 }
594 else
595 {
596 if(pintern->Pointer)
597 {
598 HeapFree(GETPROCESSHEAP, 0, (char *) pintern->Pointer-HGLOBAL_SIZE);
599 pintern->Pointer=NULL;
600 }
601 }
602 }
603 }
604 /* HeapUnlock(heap); */
605 return hnew;
606}
607
608
609/***********************************************************************
610 * GlobalFree (KERNEL32.@)
611 * RETURNS
612 * NULL: Success
613 * Handle: Failure
614 */
615HGLOBAL WIN32API GlobalFree(HGLOBAL hmem)
616{
617 PGLOBAL32_INTERN pintern;
618 HGLOBAL hreturned = 0;
619
620 // 2001-10-17 PH
621 // Note: we do have a *HANDLE* here still ...
622 // any may not terminate w/o setting SetLastError()
623 // plus returning 0 means "OK"!
624#if 0
625 /* verify lpMem address */
626 if (hmem >= (HGLOBAL)ulMaxAddr || hmem < (HGLOBAL)0x10000)
627 {
628 dprintf(("GlobalFree ERROR BAD HEAP POINTER:%X\n", hmem));
629// DebugInt3();
630 return 0;
631 }
632#endif
633
634 if(ISPOINTER(hmem)) /* POINTER */
635 {
636 if(HeapFree(GETPROCESSHEAP, 0, (LPVOID) hmem) == TRUE)
637 hreturned = 0; // success
638 else
639 hreturned = hmem; // failure
640 }
641 else /* HANDLE */
642 {
643 /* HeapLock(heap); */
644 pintern=HANDLE_TO_INTERN(hmem);
645
646 if(pintern->Magic==MAGIC_GLOBAL_USED)
647 {
648
649/* WIN98 does not make this test. That is you can free a */
650/* block you have not unlocked. Go figure!! */
651 /* if(pintern->LockCount!=0) */
652 /* SetLastError(ERROR_INVALID_HANDLE); */
653
654 if(pintern->Pointer)
655 if(!HeapFree(GETPROCESSHEAP, 0, (char *)(pintern->Pointer)-HGLOBAL_SIZE))
656 hreturned=hmem;
657 if(!HeapFree(GETPROCESSHEAP, 0, pintern))
658 hreturned=hmem;
659 }
660 else
661 {
662 // this was not a heap handle!
663 SetLastError(ERROR_INVALID_HANDLE);
664 hreturned = hmem;
665 }
666
667 /* HeapUnlock(heap); */
668 }
669
670 return hreturned;
671}
672
673
674/***********************************************************************
675 * GlobalSize (KERNEL32.@)
676 * RETURNS
677 * Size in bytes of the global memory object
678 * 0: Failure
679 */
680DWORD WIN32API GlobalSize(HGLOBAL hmem)
681{
682 DWORD retval;
683 PGLOBAL32_INTERN pintern;
684
685 if(ISPOINTER(hmem))
686 {
687 retval=HeapSize(GETPROCESSHEAP, 0, (LPVOID) hmem);
688 }
689 else
690 {
691 /* HeapLock(heap); */
692 pintern=HANDLE_TO_INTERN(hmem);
693
694 if(pintern->Magic==MAGIC_GLOBAL_USED)
695 {
696 if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
697 return 0;
698 retval=HeapSize(GETPROCESSHEAP, 0,
699 (char *)(pintern->Pointer)-HGLOBAL_SIZE)-HGLOBAL_SIZE;
700 //SvL: ???
701 if (retval == 0xffffffff-HGLOBAL_SIZE) retval = 0;
702 }
703 else
704 {
705 dprintf(("ERROR: GlobalSize invalid handle %x", hmem));
706 retval=0;
707 }
708 /* HeapUnlock(heap); */
709 }
710 /* HeapSize returns 0xffffffff on failure */
711 if (retval == 0xffffffff) retval = 0;
712 dprintf(("KERNEL32: GlobalSize %x = %d", hmem, retval));
713 return retval;
714}
715
716
717/***********************************************************************
718 * GlobalWire (KERNEL32.@)
719 */
720LPVOID WIN32API GlobalWire(HGLOBAL hmem)
721{
722 return GlobalLock( hmem );
723}
724
725
726/***********************************************************************
727 * GlobalUnWire (KERNEL32.@)
728 */
729BOOL WIN32API GlobalUnWire(HGLOBAL hmem)
730{
731 return GlobalUnlock( hmem);
732}
733
734
735/***********************************************************************
736 * GlobalFix (KERNEL32.@)
737 */
738void WIN32API GlobalFix(HGLOBAL hmem)
739{
740 GlobalLock( hmem );
741}
742
743
744/***********************************************************************
745 * GlobalUnfix (KERNEL32.@)
746 */
747void WIN32API GlobalUnfix(HGLOBAL hmem)
748{
749 GlobalUnlock( hmem);
750}
751
752
753/***********************************************************************
754 * GlobalFlags (KERNEL32.@)
755 * Returns information about the specified global memory object
756 *
757 * NOTES
758 * Should this return GMEM_INVALID_HANDLE on invalid handle?
759 *
760 * RETURNS
761 * Value specifying allocation flags and lock count
762 * GMEM_INVALID_HANDLE: Failure
763 */
764UINT WIN32API GlobalFlags(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 */
797DWORD WIN32API GlobalCompact(DWORD minfree)
798{
799 return 0; /* GlobalCompact does nothing in Win32 */
800}
801//******************************************************************************
802//******************************************************************************
803HLOCAL WIN32API LocalAlloc(UINT fuFlags, DWORD cbBytes)
804{
805 HLOCAL hLocal;
806
807 // Check flags
808 if(fuFlags & (~(LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT |
809 LMEM_NODISCARD | LMEM_ZEROINIT)))
810 {
811 dprintf(("LocalAlloc %x %x: INVALID flags!", fuFlags, cbBytes));
812 SetLastError(ERROR_INVALID_PARAMETER);
813 return 0;
814 }
815 // Note: local & global flags are the same (the ones used here), so no need for conversion
816 hLocal = GlobalAlloc(fuFlags, cbBytes);
817 dprintf(("KERNEL32: LocalAlloc flags %X, size %d returned %X", fuFlags, cbBytes, hLocal));
818 return hLocal;
819}
820//******************************************************************************
821//******************************************************************************
822UINT WIN32API LocalFlags(HLOCAL hMem)
823{
824 UINT ret, retG;
825 dprintf(("KERNEL32: LocalFlags %X\n", hMem));
826
827 retG = GlobalFlags(hMem);
828
829 if(retG == GMEM_INVALID_HANDLE)
830 {
831 return LMEM_INVALID_HANDLE;
832 }
833 // Low byte holds lock count.
834 // Hi byte of low word contains some flags.
835 ret = retG & 0xff; // Keep lock count.
836 if (retG & GMEM_DISCARDABLE) ret |= LMEM_DISCARDABLE;
837 if (retG & GMEM_DISCARDED) ret |= LMEM_DISCARDED;
838
839 return ret;
840}
841//******************************************************************************
842//******************************************************************************
843HLOCAL WIN32API LocalFree(HLOCAL hMem)
844{
845 dprintf(("KERNEL32: LocalFree %X", hMem));
846
847 return GlobalFree(hMem);
848}
849//******************************************************************************
850//******************************************************************************
851HLOCAL WIN32API LocalHandle(PCVOID lpMem)
852{
853 dprintf(("KERNEL32: LocalHandle %x", lpMem));
854
855 return GlobalHandle(lpMem);
856}
857//******************************************************************************
858//******************************************************************************
859BOOL WIN32API LocalUnlock(HLOCAL hMem)
860{
861 dprintf(("KERNEL32: LocalUnlock %X", hMem));
862
863 return GlobalUnlock(hMem);
864}
865//******************************************************************************
866//TODO: cbBytes==0 && fuFlags & LMEM_MOVEABLE not handled!!
867//******************************************************************************
868HLOCAL WIN32API LocalReAlloc(HLOCAL hMem, DWORD cbBytes, UINT fuFlags)
869{
870 HLOCAL hLocalNew, hLocalOld;
871 LPVOID lpMem, lpMemOld;
872 DWORD cbOldSize;
873
874 dprintf(("KERNEL32: LocalReAlloc %X %d %X\n", hMem, cbBytes, fuFlags));
875
876 // Check flags
877 if(fuFlags & (~(LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT |
878 LMEM_MODIFY | LMEM_ZEROINIT)))
879 {
880 dprintf(("LocalAlloc %x %x: INVALID flags!", fuFlags, cbBytes));
881 SetLastError(ERROR_INVALID_PARAMETER);
882 return 0;
883 }
884
885 //SvL: 8-8-'98: Notepad bugfix (assumes address is identical when new size < old size)
886 cbOldSize = LocalSize(hMem);
887 if(cbOldSize > cbBytes)
888 return hMem;
889
890 return GlobalReAlloc(hMem, cbBytes, fuFlags);
891}
892//******************************************************************************
893//******************************************************************************
894UINT WIN32API LocalSize(HLOCAL hMem)
895{
896 dprintf(("KERNEL32: LocalSize %X", hMem));
897
898 return GlobalSize(hMem);
899}
900//******************************************************************************
901//******************************************************************************
902PVOID WIN32API LocalLock(HLOCAL hMem)
903{
904 dprintf(("KERNEL32: LocalLock %X\n", hMem));
905
906 return GlobalLock(hMem);
907}
908//******************************************************************************
909//* this function is here for completeness, some stupid software requires it.
910//******************************************************************************
911UINT WIN32API LocalShrink(HLOCAL hMem, UINT cbNewSize)
912{
913 dprintf(("KERNEL32: LocalShrink %X, %08xh - OBSOLETE", hMem, cbNewSize));
914
915 return cbNewSize;
916}
917//******************************************************************************
918//* this function is here for completeness, mIRC/32 requires it.
919//******************************************************************************
920UINT WIN32API LocalCompact(UINT cbNewSize)
921{
922 dprintf(("KERNEL32: LocalCompact %08xh - OBSOLETE", cbNewSize));
923
924 return cbNewSize;
925}
926//******************************************************************************
927//******************************************************************************
Note: See TracBrowser for help on using the repository browser.