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

Last change on this file since 21435 was 21435, checked in by dmik, 15 years ago

kernel32: Return FALSE and set ERROR_CALL_NOT_IMPLEMENTED in HeapWalk() to prevent applications using this API to walk the heap from looping forever.

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