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

Last change on this file since 6286 was 6240, checked in by sandervl, 24 years ago

More pointer checks added to GlobalLock/Unlock

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