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

Last change on this file since 6178 was 6176, checked in by sandervl, 24 years ago

Global memory functions ported from Wine; Local memory functions now use Global*

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