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

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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