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

Last change on this file since 6189 was 6186, checked in by sandervl, 24 years ago

Better pointer/handle check in GlobalFree

File size: 30.0 KB
Line 
1/* $Id: heap.cpp,v 1.30 2001-07-06 19:03:42 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 if(hmem == NULL || ISPOINTER(hmem)) {
292 dprintf(("KERNEL32: GlobalLock %x returned %x", hmem, hmem));
293 return (LPVOID) hmem;
294 }
295
296 /* HeapLock(GetProcessHeap()); */
297
298 pintern=HANDLE_TO_INTERN(hmem);
299 if(pintern->Magic==MAGIC_GLOBAL_USED)
300 {
301 if(pintern->LockCount<GLOBAL_LOCK_MAX)
302 pintern->LockCount++;
303 palloc=pintern->Pointer;
304 }
305 else
306 {
307 dprintf(("ERROR: GlobalLock invalid handle %x", hmem));
308 palloc=(LPVOID) NULL;
309 SetLastError(ERROR_INVALID_HANDLE);
310 }
311 /* HeapUnlock(GetProcessHeap()); */;
312
313 dprintf(("KERNEL32: GlobalLock %x returned %x", hmem, palloc));
314 return palloc;
315}
316
317
318/***********************************************************************
319 * GlobalUnlock (KERNEL32.@)
320 * RETURNS
321 * TRUE: Object is still locked
322 * FALSE: Object is unlocked
323 */
324BOOL WINAPI GlobalUnlock(
325 HGLOBAL hmem /* [in] Handle of global memory object */
326) {
327 PGLOBAL32_INTERN pintern;
328 BOOL locked;
329
330 dprintf(("KERNEL32: GlobalUnlock %x", hmem));
331
332 if(hmem == NULL || ISPOINTER(hmem))
333 return FALSE;
334
335 /* HeapLock(GetProcessHeap()); */
336 pintern=HANDLE_TO_INTERN(hmem);
337
338 if(pintern->Magic==MAGIC_GLOBAL_USED)
339 {
340 if((pintern->LockCount<GLOBAL_LOCK_MAX)&&(pintern->LockCount>0))
341 pintern->LockCount--;
342
343 locked = (pintern->LockCount != 0);
344 if (!locked) SetLastError(NO_ERROR);
345 }
346 else
347 {
348 dprintf(("ERROR: GlobalUnlock invalid handle %x", hmem));
349 SetLastError(ERROR_INVALID_HANDLE);
350 locked=FALSE;
351 }
352 /* HeapUnlock(GetProcessHeap()); */
353 return locked;
354}
355
356
357/***********************************************************************
358 * GlobalHandle (KERNEL32.@)
359 * Returns the handle associated with the specified pointer.
360 *
361 * RETURNS
362 * Handle: Success
363 * NULL: Failure
364 */
365HGLOBAL WINAPI GlobalHandle(
366 LPCVOID pmem /* [in] Pointer to global memory block */
367) {
368 HGLOBAL handle;
369 PGLOBAL32_INTERN maybe_intern;
370 LPCVOID test;
371
372 dprintf(("KERNEL32: GlobalHandle %x", pmem));
373
374 if (!pmem)
375 {
376 SetLastError( ERROR_INVALID_PARAMETER );
377 return 0;
378 }
379
380#ifdef __WIN32OS2__
381 handle = 0;
382
383 /* note that if pmem is a pointer to a a block allocated by */
384 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
385 /* will fail. */
386 if (ISPOINTER(pmem)) {
387 if (HeapValidate( GetProcessHeap(), 0, pmem )) {
388 handle = (HGLOBAL)pmem; /* valid fixed block */
389 return handle;
390 }
391 handle = POINTER_TO_HANDLE(pmem);
392 } else
393 handle = (HGLOBAL)pmem;
394
395 /* Now test handle either passed in or retrieved from pointer */
396 maybe_intern = HANDLE_TO_INTERN( handle );
397 if(IsBadReadPtr(maybe_intern, sizeof(GLOBAL32_INTERN))) {
398 SetLastError( ERROR_INVALID_HANDLE );
399 return 0;
400 }
401
402 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
403 test = maybe_intern->Pointer;
404 //SvL: -2 for 8 byte alignment
405 if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-2 ) && /* obj(-handle) valid arena? */
406 HeapValidate( GetProcessHeap(), 0, maybe_intern )) /* intern valid arena? */
407 {
408 return handle;
409 }
410 }
411 handle = 0;
412 SetLastError( ERROR_INVALID_HANDLE );
413#else
414 __TRY
415 {
416 handle = 0;
417
418 /* note that if pmem is a pointer to a a block allocated by */
419 /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */
420 /* will fail. */
421 if (ISPOINTER(pmem)) {
422 if (HeapValidate( GetProcessHeap(), 0, pmem )) {
423 handle = (HGLOBAL)pmem; /* valid fixed block */
424 break;
425 }
426 handle = POINTER_TO_HANDLE(pmem);
427 } else
428 handle = (HGLOBAL)pmem;
429
430 /* Now test handle either passed in or retrieved from pointer */
431 maybe_intern = HANDLE_TO_INTERN( handle );
432 if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
433 test = maybe_intern->Pointer;
434 if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
435 HeapValidate( GetProcessHeap(), 0, maybe_intern )) /* intern valid arena? */
436 break; /* valid moveable block */
437 }
438 handle = 0;
439 SetLastError( ERROR_INVALID_HANDLE );
440 }
441 __EXCEPT(page_fault)
442 {
443 SetLastError( ERROR_INVALID_HANDLE );
444 return 0;
445 }
446 __ENDTRY
447#endif
448 return handle;
449}
450
451
452/***********************************************************************
453 * GlobalReAlloc (KERNEL32.@)
454 * RETURNS
455 * Handle: Success
456 * NULL: Failure
457 */
458HGLOBAL WINAPI GlobalReAlloc(
459 HGLOBAL hmem, /* [in] Handle of global memory object */
460 DWORD size, /* [in] New size of block */
461 UINT flags /* [in] How to reallocate object */
462) {
463 LPVOID palloc;
464 HGLOBAL hnew;
465 PGLOBAL32_INTERN pintern;
466 DWORD heap_flags = (flags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
467
468 hnew = 0;
469 /* HeapLock(heap); */
470 if(flags & GMEM_MODIFY) /* modify flags */
471 {
472 if( ISPOINTER(hmem) && (flags & GMEM_MOVEABLE))
473 {
474 /* make a fixed block moveable
475 * actually only NT is able to do this. But it's soo simple
476 */
477 if (hmem == 0)
478 {
479 dprintf(("ERROR: GlobalReAlloc32 with null handle!\n"));
480 SetLastError( ERROR_NOACCESS );
481 return 0;
482 }
483 size=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
484 hnew=GlobalAlloc( flags, size);
485 palloc=GlobalLock(hnew);
486 memcpy(palloc, (LPVOID) hmem, size);
487 GlobalUnlock(hnew);
488 GlobalFree(hmem);
489 }
490 else if( ISPOINTER(hmem) &&(flags & GMEM_DISCARDABLE))
491 {
492 /* change the flags to make our block "discardable" */
493 pintern=HANDLE_TO_INTERN(hmem);
494 pintern->Flags = pintern->Flags | (GMEM_DISCARDABLE >> 8);
495 hnew=hmem;
496 }
497 else
498 {
499 SetLastError(ERROR_INVALID_PARAMETER);
500 hnew = 0;
501 }
502 }
503 else
504 {
505 if(ISPOINTER(hmem))
506 {
507 /* reallocate fixed memory */
508 hnew=(HGLOBAL)HeapReAlloc(GetProcessHeap(), heap_flags, (LPVOID) hmem, size);
509 }
510 else
511 {
512 /* reallocate a moveable block */
513 pintern=HANDLE_TO_INTERN(hmem);
514
515#if 0
516/* Apparently Windows doesn't care whether the handle is locked at this point */
517/* See also the same comment in GlobalFree() */
518 if(pintern->LockCount>1) {
519 ERR("handle 0x%08lx is still locked, cannot realloc!\n",(DWORD)hmem);
520 SetLastError(ERROR_INVALID_HANDLE);
521 } else
522#endif
523 if(size!=0)
524 {
525 hnew=hmem;
526 if(pintern->Pointer)
527 {
528 if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
529 (char *) pintern->Pointer-HGLOBAL_SIZE,
530 size+HGLOBAL_SIZE)) == NULL)
531 return 0; /* Block still valid */
532 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
533 }
534 else
535 {
536 if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+HGLOBAL_SIZE))
537 == NULL)
538 return 0;
539 *(HGLOBAL *)palloc=hmem;
540 pintern->Pointer=(char *) palloc+HGLOBAL_SIZE;
541 }
542 }
543 else
544 {
545 if(pintern->Pointer)
546 {
547 HeapFree(GetProcessHeap(), 0, (char *) pintern->Pointer-HGLOBAL_SIZE);
548 pintern->Pointer=NULL;
549 }
550 }
551 }
552 }
553 /* HeapUnlock(heap); */
554 return hnew;
555}
556
557
558/***********************************************************************
559 * GlobalFree (KERNEL32.@)
560 * RETURNS
561 * NULL: Success
562 * Handle: Failure
563 */
564HGLOBAL WINAPI GlobalFree(
565 HGLOBAL hmem /* [in] Handle of global memory object */
566) {
567 PGLOBAL32_INTERN pintern;
568 HGLOBAL hreturned = 0;
569
570 dprintf(("KERNEL32: GlobalFree %x", hmem));
571
572 /* verify lpMem address */
573 if (hmem >= (HGLOBAL)ulMaxAddr || hmem < (HGLOBAL)0x10000)
574 {
575 dprintf(("GlobalFree ERROR BAD HEAP POINTER:%X\n", hmem));
576 return 0;
577 }
578
579 if(ISPOINTER(hmem)) /* POINTER */
580 {
581 if(!HeapFree(GetProcessHeap(), 0, (LPVOID) hmem)) hmem = 0;
582 }
583 else /* HANDLE */
584 {
585 /* HeapLock(heap); */
586 pintern=HANDLE_TO_INTERN(hmem);
587
588 if(pintern->Magic==MAGIC_GLOBAL_USED)
589 {
590
591/* WIN98 does not make this test. That is you can free a */
592/* block you have not unlocked. Go figure!! */
593 /* if(pintern->LockCount!=0) */
594 /* SetLastError(ERROR_INVALID_HANDLE); */
595
596 if(pintern->Pointer)
597 if(!HeapFree(GetProcessHeap(), 0, (char *)(pintern->Pointer)-HGLOBAL_SIZE))
598 hreturned=hmem;
599 if(!HeapFree(GetProcessHeap(), 0, pintern))
600 hreturned=hmem;
601 }
602 /* HeapUnlock(heap); */
603 }
604 return hreturned;
605}
606
607
608/***********************************************************************
609 * GlobalSize (KERNEL32.@)
610 * RETURNS
611 * Size in bytes of the global memory object
612 * 0: Failure
613 */
614DWORD WINAPI GlobalSize(
615 HGLOBAL hmem /* [in] Handle of global memory object */
616) {
617 DWORD retval;
618 PGLOBAL32_INTERN pintern;
619
620 dprintf(("KERNEL32: GlobalSize %x", hmem));
621
622 if(ISPOINTER(hmem))
623 {
624 retval=HeapSize(GetProcessHeap(), 0, (LPVOID) hmem);
625 }
626 else
627 {
628 /* HeapLock(heap); */
629 pintern=HANDLE_TO_INTERN(hmem);
630
631 if(pintern->Magic==MAGIC_GLOBAL_USED)
632 {
633 if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
634 return 0;
635 retval=HeapSize(GetProcessHeap(), 0,
636 (char *)(pintern->Pointer)-HGLOBAL_SIZE)-HGLOBAL_SIZE;
637 //SvL: ???
638 if (retval == 0xffffffff-HGLOBAL_SIZE) retval = 0;
639 }
640 else
641 {
642 dprintf(("ERROR: GlobalSize invalid handle %x", hmem));
643 retval=0;
644 }
645 /* HeapUnlock(heap); */
646 }
647 /* HeapSize returns 0xffffffff on failure */
648 if (retval == 0xffffffff) retval = 0;
649 dprintf(("KERNEL32: GlobalSize %x = %d", hmem, retval));
650 return retval;
651}
652
653
654/***********************************************************************
655 * GlobalWire (KERNEL32.@)
656 */
657LPVOID WINAPI GlobalWire(HGLOBAL hmem)
658{
659 return GlobalLock( hmem );
660}
661
662
663/***********************************************************************
664 * GlobalUnWire (KERNEL32.@)
665 */
666BOOL WINAPI GlobalUnWire(HGLOBAL hmem)
667{
668 return GlobalUnlock( hmem);
669}
670
671
672/***********************************************************************
673 * GlobalFix (KERNEL32.@)
674 */
675VOID WINAPI GlobalFix(HGLOBAL hmem)
676{
677 GlobalLock( hmem );
678}
679
680
681/***********************************************************************
682 * GlobalUnfix (KERNEL32.@)
683 */
684VOID WINAPI GlobalUnfix(HGLOBAL hmem)
685{
686 GlobalUnlock( hmem);
687}
688
689
690/***********************************************************************
691 * GlobalFlags (KERNEL32.@)
692 * Returns information about the specified global memory object
693 *
694 * NOTES
695 * Should this return GMEM_INVALID_HANDLE on invalid handle?
696 *
697 * RETURNS
698 * Value specifying allocation flags and lock count
699 * GMEM_INVALID_HANDLE: Failure
700 */
701UINT WINAPI GlobalFlags(
702 HGLOBAL hmem /* [in] Handle to global memory object */
703) {
704 DWORD retval;
705 PGLOBAL32_INTERN pintern;
706
707 dprintf(("KERNEL32: GlobalFlags %x", hmem));
708
709 if(ISPOINTER(hmem))
710 {
711 retval=0;
712 }
713 else
714 {
715 /* HeapLock(GetProcessHeap()); */
716 pintern=HANDLE_TO_INTERN(hmem);
717 if(pintern->Magic==MAGIC_GLOBAL_USED)
718 {
719 retval=pintern->LockCount + (pintern->Flags<<8);
720 if(pintern->Pointer==0)
721 retval|= GMEM_DISCARDED;
722 }
723 else
724 {
725 dprintf(("ERROR: GlobalFlags invalid handle %x", hmem));
726 retval=0;
727 }
728 /* HeapUnlock(GetProcessHeap()); */
729 }
730 return retval;
731}
732
733
734/***********************************************************************
735 * GlobalCompact (KERNEL32.@)
736 */
737DWORD WINAPI GlobalCompact( DWORD minfree )
738{
739 dprintf(("KERNEL32: GlobalCompact %d OBSOLETE", minfree));
740
741 return 0; /* GlobalCompact does nothing in Win32 */
742}
743#else
744//******************************************************************************
745#ifdef DEBUG
746static ULONG totalGlobalAlloc = 0;
747#endif
748//******************************************************************************
749HGLOBAL WIN32API GlobalAlloc(UINT fuFlags, DWORD dwBytes)
750{
751 HGLOBAL ret;
752
753 ret = O32_GlobalAlloc(fuFlags, dwBytes);
754#ifdef DEBUG
755 totalGlobalAlloc += dwBytes;
756#endif
757 dprintf(("KERNEL32: GlobalAlloc %x %d returned %x (total %x)", fuFlags, dwBytes, ret, totalGlobalAlloc));
758 return ret;
759}
760//******************************************************************************
761//******************************************************************************
762HGLOBAL WIN32API GlobalFree( HGLOBAL arg1)
763{
764 HGLOBAL ret;
765
766#ifdef DEBUG
767 totalGlobalAlloc -= O32_GlobalSize(arg1);
768#endif
769 ret = O32_GlobalFree(arg1);
770 dprintf(("KERNEL32: GlobalFree %x returned %x (lasterr=%x) total %x", arg1, ret, GetLastError(), totalGlobalAlloc));
771 return ret;
772}
773//******************************************************************************
774//******************************************************************************
775HGLOBAL WIN32API GlobalHandle( LPCVOID lpMem)
776{
777 dprintf(("KERNEL32: GlobalHandle %x", lpMem));
778
779 return O32_GlobalHandle((LPVOID)lpMem);
780}
781//******************************************************************************
782//******************************************************************************
783UINT WIN32API GlobalFlags(HGLOBAL hMem)
784{
785 dprintf(("KERNEL32: GlobalFlags %x", hMem));
786
787 return O32_GlobalFlags(hMem);
788}
789//******************************************************************************
790//******************************************************************************
791DWORD WIN32API GlobalCompact(DWORD dwMinFree)
792{
793 dprintf(("KERNEL32: GlobalCompact, OBSOLETE - stub\n"));
794
795 return(0);
796}
797//******************************************************************************
798//******************************************************************************
799PVOID WIN32API GlobalLock(HGLOBAL hMem)
800{
801 PVOID ret;
802
803 ret = O32_GlobalLock(hMem);
804 dprintf(("KERNEL32: GlobalLock %x returned %x", hMem, ret));
805 return ret;
806}
807//******************************************************************************
808//******************************************************************************
809HGLOBAL WIN32API GlobalReAlloc(HGLOBAL arg1, DWORD arg2, UINT arg3)
810{
811 dprintf(("KERNEL32: GlobalReAlloc %x %x %d", arg1, arg2, arg3));
812
813 return O32_GlobalReAlloc(arg1, arg2, arg3);
814}
815//******************************************************************************
816//******************************************************************************
817DWORD WIN32API GlobalSize(HGLOBAL arg1)
818{
819 dprintf(("KERNEL32: GlobalSize\n"));
820
821 return O32_GlobalSize(arg1);
822}
823//******************************************************************************
824//******************************************************************************
825BOOL WIN32API GlobalUnlock(HGLOBAL arg1)
826{
827 dprintf(("KERNEL32: GlobalUnlock\n"));
828
829 return O32_GlobalUnlock(arg1);
830}
831/***********************************************************************
832 * GlobalWire
833 *
834 * The GlobalWire function is obsolete. It is provided only for compatibility
835 * with 16-bit versions of Windows. Applications that need to lock a global
836 * memory object should use the GlobalLock and GlobalUnlock functions.
837 *
838 */
839LPVOID WIN32API GlobalWire(HGLOBAL hmem)
840{
841 return GlobalLock( hmem );
842}
843/***********************************************************************
844 * GlobalUnWire
845 *
846 * The GlobalUnWire function is obsolete. It is provided only for compatibility
847 * with 16-bit versions of Windows. Applications that need to lock a global
848 * memory object should use the GlobalLock and GlobalUnlock functions.
849 *
850 */
851BOOL WIN32API GlobalUnWire(HGLOBAL hmem)
852{
853 return GlobalUnlock( hmem);
854}
855//******************************************************************************
856//******************************************************************************
857HGLOBAL WIN32API GlobalDiscard(HGLOBAL hGlobal)
858{
859 dprintf(("KERNEL32: GlobalDiscard %x", hGlobal));
860
861 return O32_GlobalDiscard(hGlobal);
862}
863/***********************************************************************
864 * GlobalFix (KERNEL32.@)
865 */
866VOID WINAPI GlobalFix(HGLOBAL hmem)
867{
868 GlobalLock( hmem );
869}
870/***********************************************************************
871 * GlobalUnfix (KERNEL32.@)
872 */
873VOID WINAPI GlobalUnfix(HGLOBAL hmem)
874{
875 GlobalUnlock( hmem);
876}
877#endif
878//******************************************************************************
879//******************************************************************************
880HLOCAL WIN32API LocalAlloc(UINT fuFlags, DWORD cbBytes)
881{
882 HLOCAL hLocal;
883
884 // Check flags
885 if(fuFlags & (~(LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT |
886 LMEM_NODISCARD | LMEM_ZEROINIT)))
887 {
888 dprintf(("LocalAlloc %x %x: INVALID flags!", fuFlags, cbBytes));
889 SetLastError(ERROR_INVALID_PARAMETER);
890 return 0;
891 }
892 // Note: local & global flags are the same (the ones used here), so no need for conversion
893 hLocal = GlobalAlloc(fuFlags, cbBytes);
894 dprintf(("KERNEL32: LocalAlloc flags %X, size %d returned %X", fuFlags, cbBytes, hLocal));
895 return hLocal;
896}
897//******************************************************************************
898//******************************************************************************
899UINT WIN32API LocalFlags(HLOCAL hMem)
900{
901 UINT ret, retG;
902 dprintf(("KERNEL32: LocalFlags %X\n", hMem));
903
904 retG = GlobalFlags(hMem);
905
906 if(retG == GMEM_INVALID_HANDLE)
907 {
908 return LMEM_INVALID_HANDLE;
909 }
910 // Low byte holds lock count.
911 // Hi byte of low word contains some flags.
912 ret = retG & 0xff; // Keep lock count.
913 if (retG & GMEM_DISCARDABLE) ret |= LMEM_DISCARDABLE;
914 if (retG & GMEM_DISCARDED) ret |= LMEM_DISCARDED;
915
916 return ret;
917}
918//******************************************************************************
919//******************************************************************************
920HLOCAL WIN32API LocalFree(HLOCAL hMem)
921{
922 dprintf(("KERNEL32: LocalFree %X", hMem));
923
924 return GlobalFree(hMem);
925}
926//******************************************************************************
927//******************************************************************************
928HLOCAL WIN32API LocalHandle(PCVOID lpMem)
929{
930 dprintf(("KERNEL32: LocalHandle %x", lpMem));
931
932 return GlobalHandle(lpMem);
933}
934//******************************************************************************
935//******************************************************************************
936BOOL WIN32API LocalUnlock(HLOCAL hMem)
937{
938 dprintf(("KERNEL32: LocalUnlock %X", hMem));
939
940 return GlobalUnlock(hMem);
941}
942//******************************************************************************
943//TODO: cbBytes==0 && fuFlags & LMEM_MOVEABLE not handled!!
944//******************************************************************************
945HLOCAL WIN32API LocalReAlloc(HLOCAL hMem, DWORD cbBytes, UINT fuFlags)
946{
947 HLOCAL hLocalNew, hLocalOld;
948 LPVOID lpMem, lpMemOld;
949 DWORD cbOldSize;
950
951 dprintf(("KERNEL32: LocalReAlloc %X %d %X\n", hMem, cbBytes, fuFlags));
952
953 // Check flags
954 if(fuFlags & (~(LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT |
955 LMEM_MODIFY | LMEM_ZEROINIT)))
956 {
957 dprintf(("LocalAlloc %x %x: INVALID flags!", fuFlags, cbBytes));
958 SetLastError(ERROR_INVALID_PARAMETER);
959 return 0;
960 }
961
962 //SvL: 8-8-'98: Notepad bugfix (assumes address is identical when new size < old size)
963 cbOldSize = LocalSize(hMem);
964 if(cbOldSize > cbBytes)
965 return hMem;
966
967 return GlobalReAlloc(hMem, cbBytes, fuFlags);
968}
969//******************************************************************************
970//******************************************************************************
971UINT WIN32API LocalSize(HLOCAL hMem)
972{
973 dprintf(("KERNEL32: LocalSize %X", hMem));
974
975 return GlobalSize(hMem);
976}
977//******************************************************************************
978//******************************************************************************
979PVOID WIN32API LocalLock(HLOCAL hMem)
980{
981 dprintf(("KERNEL32: LocalLock %X\n", hMem));
982
983 return GlobalLock(hMem);
984}
985//******************************************************************************
986//* this function is here for completeness, some stupid software requires it.
987//******************************************************************************
988UINT WIN32API LocalShrink(HLOCAL hMem, UINT cbNewSize)
989{
990 dprintf(("KERNEL32: LocalShrink %X, %08xh - OBSOLETE", hMem, cbNewSize));
991
992 return cbNewSize;
993}
994//******************************************************************************
995//* this function is here for completeness, mIRC/32 requires it.
996//******************************************************************************
997UINT WIN32API LocalCompact(UINT cbNewSize)
998{
999 dprintf(("KERNEL32: LocalCompact %08xh - OBSOLETE", cbNewSize));
1000
1001 return cbNewSize;
1002}
1003//******************************************************************************
1004//******************************************************************************
Note: See TracBrowser for help on using the repository browser.