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

Last change on this file since 1770 was 1770, checked in by bird, 26 years ago

Added pointer check on lpMem in OS2Heap::Free. (This solved the WinZip 7.0
crash.)

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