source: trunk/src/kernel32/os2heap.cpp@ 3464

Last change on this file since 3464 was 3464, checked in by sandervl, 25 years ago

LocalGetFlags bugfix + some extra checks for invalid pointers

File size: 10.9 KB
Line 
1/* $Id: os2heap.cpp,v 1.15 2000-04-30 16:31:47 sandervl Exp $ */
2
3/*
4 * Heap class for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 *
9 * NOTE: ReAlloc allocates memory using Alloc if memory pointer == NULL
10 * WINE controls depend on this, even though it apparently
11 * doesn't work like this in Windows.
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#define INCL_DOSMEMMGR
17#define INCL_DOSSEMAPHORES
18#define INCL_DOSERRORS
19#include <os2wrap.h> //Odin32 OS/2 api wrappers
20#include <builtin.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "win32type.h"
25#include "os2heap.h"
26#include "misc.h"
27#include "vmutex.h"
28#include "initterm.h"
29#include <odin32validate.h>
30
31#define DBG_LOCALLOG DBG_os2heap
32#include "dbglocal.h"
33
34#ifndef HEAP_NO_SERIALIZE
35 #define HEAP_NO_SERIALIZE 1
36#endif
37
38#ifndef HEAP_ZERO_MEMORY
39 #define HEAP_ZERO_MEMORY 8
40#endif
41
42VMutex heaplistmutex; //protects linked lists of heaps
43
44//******************************************************************************
45//******************************************************************************
46OS2Heap::OS2Heap(HANDLE hHeap, DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize)
47{
48 OS2Heap *curheap = OS2Heap::heap;
49
50 hPrimaryHeap = hHeap;
51 totalAlloc = 0;
52 fInitialized = 0;
53 nrHeaps = 0;
54 heapelem = NULL;
55
56 this->dwMaximumSize = dwMaximumSize;
57 this->dwInitialSize = dwInitialSize;
58 this->flOptions = flOptions;
59
60 dprintf(("KERNEL32: HeapCreate: initial size %d, max size %d (flags %X) returned %X\n", dwInitialSize, dwMaximumSize, flOptions, hPrimaryHeap));
61
62 if(!(flOptions & HEAP_NO_SERIALIZE))
63 {
64 hmutex = new VMutex();
65 dassert(hmutex, ("ERROR: new VMutex\n"));
66 }
67 else hmutex = NULL;
68
69 heaplistmutex.enter();
70 if(curheap != NULL) {
71 while(curheap->next != NULL) {
72 curheap = curheap->next;
73 }
74 curheap->next = this;
75 }
76 else heap = this;
77 next = NULL;
78
79 heaplistmutex.leave();
80}
81//******************************************************************************
82//******************************************************************************
83OS2Heap::~OS2Heap()
84{
85 OS2Heap *curheap = OS2Heap::heap;
86 HEAPELEM *hnext;
87 int i;
88
89 dprintf(("dtr OS2Heap, hPrimaryHeap = %X\n", hPrimaryHeap));
90
91 if(hmutex)
92 hmutex->enter();
93
94 while(heapelem) {
95 hnext = heapelem->next;
96 free(heapelem);
97 heapelem = hnext;
98 }
99 if(hmutex)
100 {
101 hmutex->leave();
102 delete(hmutex);
103 }
104
105 heaplistmutex.enter();
106 if(heap == this) {
107 heap = next;
108 }
109 else {
110 while(curheap->next != NULL) {
111 if(curheap->next == this) {
112 curheap->next = next;
113 break;
114 }
115 curheap = curheap->next;
116 }
117 }
118 heaplistmutex.leave();
119 dprintf(("dtr OS2Heap, hPrimaryHeap = %X done\n", hPrimaryHeap));
120}
121//******************************************************************************
122//******************************************************************************
123LPVOID OS2Heap::Alloc(DWORD dwFlags, DWORD dwBytes)
124{
125 LPVOID lpMem;
126
127// dprintf(("OS2Heap::Alloc\n"));
128 lpMem = malloc(dwBytes + HEAP_OVERHEAD);
129 if(lpMem == NULL) {
130 dprintf(("OS2Heap::Alloc, lpMem == NULL"));
131 return(NULL);
132 }
133 if(dwFlags & HEAP_ZERO_MEMORY) {
134 memset((char *)lpMem, 0, dwBytes+HEAP_OVERHEAD);
135 }
136 totalAlloc += dwBytes;
137
138 if(hmutex)
139 hmutex->enter();
140
141 if(heapelem) {
142 HEAPELEM *hnext;
143
144 hnext = heapelem;
145
146 heapelem = (HEAPELEM *)lpMem;
147 hnext->prev = heapelem;
148 heapelem->next = hnext;
149 }
150 else {
151 heapelem = (HEAPELEM *)lpMem;
152 heapelem->next = NULL;
153 }
154 heapelem->prev = NULL;
155 heapelem->flags = 0; //only used when allocated with LocalAlloc
156 heapelem->lockCnt = 0; //.. ..
157 heapelem->magic = MAGIC_NR_HEAP;
158
159 if(hmutex) {
160 hmutex->leave();
161 }
162 return(LPVOID)((char *)lpMem+sizeof(HEAPELEM));
163}
164//******************************************************************************
165//******************************************************************************
166LPVOID OS2Heap::Alloc(DWORD dwFlags, DWORD dwBytes, DWORD LocalAllocFlags)
167{
168 HEAPELEM *helem;
169 LPVOID lpMem = Alloc(dwFlags, dwBytes);
170
171 if(lpMem == NULL)
172 return(NULL);
173
174 helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
175 helem->flags = LocalAllocFlags;
176 return(lpMem);
177}
178//******************************************************************************
179//******************************************************************************
180BOOL OS2Heap::Lock(LPVOID lpMem)
181{
182 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
183
184 if((ULONG)lpMem > ADDRESS_SPACE_LIMIT) {
185 //SvL: Some apps lock and unlock gdi handles; just ignore this here
186 dprintf(("Lock: invalid address %x", lpMem));
187 return FALSE;
188 }
189
190 if(lpMem == NULL)
191 return(FALSE);
192
193 if(helem->magic != MAGIC_NR_HEAP)
194 {
195 dprintf(("OS2Heap::Lock ERROR BAD HEAP POINTER:%X\n", lpMem));
196 return FALSE;
197 }
198
199 helem->lockCnt++;
200
201 return(TRUE);
202}
203//******************************************************************************
204//******************************************************************************
205BOOL OS2Heap::Unlock(LPVOID lpMem)
206{
207 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
208
209 if((ULONG)lpMem > ADDRESS_SPACE_LIMIT) {
210 //SvL: Some apps lock and unlock gdi handles; just ignore this here
211 dprintf(("Unlock: invalid address %x", lpMem));
212 return FALSE;
213 }
214
215 if(lpMem == NULL)
216 return(FALSE);
217
218 if(helem->lockCnt == 0)
219 return(FALSE);
220
221 if(helem->magic != MAGIC_NR_HEAP)
222 {
223 dprintf(("OS2Heap::UnLock ERROR BAD HEAP POINTER:%X\n", lpMem));
224 return FALSE;
225 }
226
227 helem->lockCnt--;
228
229 return(TRUE);
230}
231//******************************************************************************
232//******************************************************************************
233DWORD OS2Heap::GetFlags(LPVOID lpMem)
234{
235 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
236
237 if(lpMem == NULL)
238 return(0);
239
240 if(helem->magic != MAGIC_NR_HEAP)
241 {
242 dprintf(("OS2Heap::GetFlags ERROR BAD HEAP POINTER:%X\n", lpMem));
243 return 0;
244 }
245
246 return(helem->lockCnt | (helem->flags << 8));
247}
248//******************************************************************************
249//******************************************************************************
250int OS2Heap::GetLockCnt(LPVOID lpMem)
251{
252 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
253
254 if((ULONG)lpMem > ADDRESS_SPACE_LIMIT) {
255 //SvL: Some apps lock and unlock gdi handles; just ignore this here
256 dprintf(("GetLockCnt: invalid address %x", lpMem));
257 return FALSE;
258 }
259
260 if(lpMem == NULL)
261 return(0);
262
263 if(helem->magic != MAGIC_NR_HEAP)
264 {
265 dprintf(("OS2Heap::GetLockCnt ERROR BAD HEAP POINTER:%X\n", lpMem));
266 return 0;
267 }
268
269 return(helem->lockCnt);
270}
271//******************************************************************************
272//******************************************************************************
273DWORD OS2Heap::Size(DWORD dwFlags, PVOID lpMem)
274{
275// dprintf(("OS2Heap::Size, %X\n", lpMem));
276 if(lpMem == NULL)
277 return(0);
278
279 return(_msize((char *)lpMem - sizeof(HEAPELEM)) - HEAP_OVERHEAD);
280}
281//******************************************************************************
282//******************************************************************************
283LPVOID OS2Heap::ReAlloc(DWORD dwFlags, LPVOID lpMem, DWORD dwBytes)
284{
285 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
286 LPVOID lpNewMem;
287 int i, oldSize;
288
289 if (dwBytes == 0) return NULL; // intercept stupid parameters
290
291 //NOTE: Allocate memory using Alloc -> WINE controls depend on this, even
292 // though it apparently doesn't work in Windows.
293 if (lpMem == 0) return Alloc(dwFlags, dwBytes);
294// if (lpMem == 0) return NULL;
295
296 if (helem->magic != MAGIC_NR_HEAP)
297 {
298 dprintf(("OS2Heap::ReAlloc ERROR BAD HEAP POINTER:%X\n", lpMem));
299 return lpMem;
300 }
301
302 oldSize = Size(0,lpMem);
303 if (oldSize == dwBytes) return lpMem; // if reallocation with same size
304 // don't do anything
305 lpNewMem = Alloc(dwFlags, dwBytes);
306 memcpy(lpNewMem, lpMem, dwBytes < oldSize ? dwBytes : oldSize);
307 Free(0, lpMem);
308
309 if(lpNewMem == NULL)
310 {
311 dprintf(("OS2Heap::ReAlloc, no more memory left\n"));
312 }
313
314 return(lpNewMem);
315}
316//******************************************************************************
317//******************************************************************************
318BOOL OS2Heap::Free(DWORD dwFlags, LPVOID lpMem)
319{
320 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
321
322 if(lpMem == NULL) {
323 dprintf(("OS2Heap::Free lpMem == NULL\n"));
324 return(FALSE);
325 }
326 /* verify lpMem address */
327 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
328 {
329 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
330 return FALSE;
331 }
332
333 if(helem->magic != MAGIC_NR_HEAP)
334 {
335 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
336 return FALSE;
337 }
338
339#ifdef DEBUG1
340 int size = Size(0, lpMem);
341 dprintf(("OS2Heap::Free lpMem = %X, size %d\n", lpMem, size));
342 totalAlloc -= size;
343#endif
344 if(hmutex)
345 hmutex->enter();
346
347 if(helem->prev)
348 helem->prev->next = helem->next;
349 if(helem->next)
350 helem->next->prev = helem->prev;
351 if(heapelem == helem)
352 heapelem = heapelem->next;
353
354 if(hmutex) {
355 hmutex->leave();
356 }
357
358 free((void *)helem);
359 return(TRUE);
360}
361//******************************************************************************
362//******************************************************************************
363DWORD OS2Heap::Compact(DWORD dwFlags)
364{
365 dprintf(("OS2Heap::Compact, %X- stub\n", dwFlags));
366 return(0);
367}
368//******************************************************************************
369//******************************************************************************
370BOOL OS2Heap::Validate(DWORD dwFlags, LPCVOID lpMem)
371{
372 dprintf(("OS2Heap::Validate, %X %X - stub? (TRUE)\n", dwFlags, lpMem));
373 return(TRUE);
374}
375//******************************************************************************
376//******************************************************************************
377BOOL OS2Heap::Walk(void *lpEntry)
378{
379 dprintf(("OS2Heap::Walk, %X - stub? (TRUE)\n", lpEntry));
380 return(TRUE);
381}
382//******************************************************************************
383//******************************************************************************
384OS2Heap *OS2Heap::find(HANDLE hHeap)
385{
386 OS2Heap *curheap = OS2Heap::heap;
387
388 //@@@PH NT programs seem to assume heap 0 is always valid?!
389 if (hHeap == 0)
390 if (curheap != NULL)
391 return curheap;
392
393 while(curheap != NULL) {
394 if(curheap->hPrimaryHeap == hHeap) {
395 return(curheap);
396 }
397 curheap = curheap->next;
398 }
399 dprintf(("Heap %X not found!\n", hHeap));
400 return(NULL);
401}
402//******************************************************************************
403//******************************************************************************
404OS2Heap *OS2Heap::heap = NULL;
Note: See TracBrowser for help on using the repository browser.