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

Last change on this file since 6375 was 6354, checked in by sandervl, 24 years ago

heap changes/fixes

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