source: trunk/src/gdi32/objhandle.cpp@ 9251

Last change on this file since 9251 was 9251, checked in by sandervl, 23 years ago

Statistics fixes & print leaked gdi handles when unloaded; don't recycle gdi handles too soon

File size: 16.9 KB
Line 
1/* $Id: objhandle.cpp,v 1.28 2002-09-16 13:58:25 sandervl Exp $ */
2/*
3 * Win32 Handle Management Code for OS/2
4 *
5 *
6 * Copyright 2000-2002 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * TODO: The table should be dynamically increased when necessary
9 * This is just a quick and dirty implementation
10 *
11 * System objects can't be deleted (TODO: any others?? (fonts?))!!!!)
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16
17#include <os2win.h>
18#include <stdlib.h>
19#include <string.h>
20#include <vmutex.h>
21#include <objhandle.h>
22#include <dcdata.h>
23#include <winuser32.h>
24#include "oslibgpi.h"
25#include "dibsect.h"
26#include "region.h"
27#include <unicode.h>
28#include "font.h"
29#include <stats.h>
30
31#define DBG_LOCALLOG DBG_objhandle
32#include "dbglocal.h"
33
34//TODO: must use 16 bits gdi object handles
35#define GDIOBJ_PREFIX 0xe7000000
36
37//******************************************************************************
38
39typedef struct {
40 DWORD dwUserData;
41 DWORD dwGDI32Data;
42 DWORD dwFlags;
43 DWORD dwType;
44} GdiObject;
45
46static GdiObject *objHandleTable = NULL;
47static ULONG lowestFreeIndex = 1;
48static VMutex objTableMutex;
49
50//******************************************************************************
51//******************************************************************************
52BOOL WIN32API ObjAllocateHandle(HANDLE *hObject, DWORD dwUserData, DWORD dwType)
53{
54 DWORD oldlowestidx;
55
56 objTableMutex.enter();
57 if(objHandleTable == NULL) {
58 objHandleTable = (GdiObject *)malloc(MAX_OBJECT_HANDLES*sizeof(GdiObject));
59 if(objHandleTable == NULL) {
60 DebugInt3();
61 }
62 memset(objHandleTable, 0, MAX_OBJECT_HANDLES*sizeof(GdiObject));
63 }
64
65 if(lowestFreeIndex == -1) {
66 //oops, out of handles
67 objTableMutex.leave();
68 dprintf(("ERROR: GDI: ObjAllocateHandle OUT OF GDI OBJECT HANDLES!!"));
69 DebugInt3();
70 return FALSE;
71 }
72 if(objHandleTable[0].dwType == HNDL_NONE) {
73 //first handle can never be used
74 objHandleTable[0].dwType = HNDL_INVALID;
75 objHandleTable[0].dwUserData = -1;
76 }
77 *hObject = lowestFreeIndex;
78 *hObject = MAKE_HANDLE(*hObject);
79 objHandleTable[lowestFreeIndex].dwUserData = dwUserData;
80 objHandleTable[lowestFreeIndex].dwType = dwType;
81 objHandleTable[lowestFreeIndex].dwGDI32Data = 0;
82 objHandleTable[lowestFreeIndex].dwFlags = 0;
83
84 oldlowestidx = lowestFreeIndex+1;
85
86 lowestFreeIndex = -1;
87
88 //find next free handle
89findhandle:
90 for(int i=oldlowestidx;i<MAX_OBJECT_HANDLES;i++) {
91 if(objHandleTable[i].dwUserData == 0) {
92 lowestFreeIndex = i;
93 break;
94 }
95 }
96 if(lowestFreeIndex == -1) {
97 oldlowestidx = 0; //search from the start
98 goto findhandle;
99 }
100 objTableMutex.leave();
101 return TRUE;
102}
103//******************************************************************************
104//******************************************************************************
105BOOL WIN32API ObjDeleteHandle(HANDLE hObject, DWORD dwType)
106{
107 hObject &= OBJHANDLE_MAGIC_MASK;
108 if(hObject < MAX_OBJECT_HANDLES) {
109 objTableMutex.enter();
110 if(!(objHandleTable[hObject].dwFlags & OBJHANDLE_FLAG_NODELETE))
111 {
112 objHandleTable[hObject].dwUserData = 0;
113 objHandleTable[hObject].dwType = HNDL_NONE;
114//// if(lowestFreeIndex == -1 || hObject < lowestFreeIndex)
115 if(lowestFreeIndex == -1)
116 lowestFreeIndex = hObject;
117 }
118 else {
119 dprintf(("ObjDeleteHandle: unable to delete system object %x", MAKE_HANDLE(hObject)));
120 }
121 objTableMutex.leave();
122 return TRUE;
123 }
124 return FALSE;
125}
126//******************************************************************************
127//******************************************************************************
128DWORD WIN32API ObjQueryHandleData(HANDLE hObject, DWORD dwType)
129{
130 DWORD dwUserData = HANDLE_INVALID_DATA;
131
132 objTableMutex.enter();
133 hObject &= OBJHANDLE_MAGIC_MASK;
134 if(hObject < MAX_OBJECT_HANDLES &&
135 ((dwType == HNDL_ANY && objHandleTable[hObject].dwType != HNDL_NONE) ||
136 dwType == objHandleTable[hObject].dwType))
137 {
138 dwUserData = objHandleTable[hObject].dwUserData;
139 }
140 objTableMutex.leave();
141 return dwUserData;
142}
143//******************************************************************************
144//******************************************************************************
145BOOL WIN32API ObjSetHandleData(HANDLE hObject, DWORD dwType, DWORD dwUserData)
146{
147 BOOL fSuccess = FALSE;
148
149 objTableMutex.enter();
150 hObject &= OBJHANDLE_MAGIC_MASK;
151 if(hObject < MAX_OBJECT_HANDLES &&
152 ((dwType == HNDL_ANY && objHandleTable[hObject].dwType != HNDL_NONE) ||
153 dwType == objHandleTable[hObject].dwType))
154 {
155 objHandleTable[hObject].dwUserData = dwUserData;
156 fSuccess = TRUE;
157 }
158 objTableMutex.leave();
159 return fSuccess;
160}
161//******************************************************************************
162//******************************************************************************
163DWORD WIN32API ObjQueryHandleGDI32Data(HANDLE hObject, DWORD dwType)
164{
165 DWORD dwGDI32Data = HANDLE_INVALID_DATA;
166
167 objTableMutex.enter();
168 hObject &= OBJHANDLE_MAGIC_MASK;
169 if(hObject < MAX_OBJECT_HANDLES &&
170 ((dwType == HNDL_ANY && objHandleTable[hObject].dwType != HNDL_NONE) ||
171 dwType == objHandleTable[hObject].dwType))
172 {
173 dwGDI32Data = objHandleTable[hObject].dwGDI32Data;
174 }
175 objTableMutex.leave();
176 return dwGDI32Data;
177}
178//******************************************************************************
179//******************************************************************************
180BOOL WIN32API ObjSetHandleGDI32Data(HANDLE hObject, DWORD dwType, DWORD dwGDI32Data)
181{
182 BOOL fSuccess = FALSE;
183
184 objTableMutex.enter();
185 hObject &= OBJHANDLE_MAGIC_MASK;
186 if(hObject < MAX_OBJECT_HANDLES &&
187 ((dwType == HNDL_ANY && objHandleTable[hObject].dwType != HNDL_NONE) ||
188 dwType == objHandleTable[hObject].dwType))
189 {
190 objHandleTable[hObject].dwGDI32Data = dwGDI32Data;
191 fSuccess = TRUE;
192 }
193 objTableMutex.leave();
194 return fSuccess;
195}
196//******************************************************************************
197//******************************************************************************
198DWORD WIN32API ObjQueryHandleFlags(OBJHANDLE hObject)
199{
200 DWORD dwFlags = 0;
201
202 objTableMutex.enter();
203 hObject &= OBJHANDLE_MAGIC_MASK;
204 if(hObject < MAX_OBJECT_HANDLES && objHandleTable[hObject].dwType != HNDL_NONE)
205 {
206 dwFlags = objHandleTable[hObject].dwFlags;
207 }
208 objTableMutex.leave();
209 return dwFlags;
210}
211//******************************************************************************
212//******************************************************************************
213BOOL WIN32API ObjSetHandleFlag(HANDLE hObject, DWORD dwFlag, BOOL fSet)
214{
215 BOOL fSuccess = FALSE;
216
217 objTableMutex.enter();
218 hObject &= OBJHANDLE_MAGIC_MASK;
219 if(hObject < MAX_OBJECT_HANDLES && objHandleTable[hObject].dwType != HNDL_NONE) {
220 if(fSet) {
221 objHandleTable[hObject].dwFlags |= dwFlag;
222 }
223 else objHandleTable[hObject].dwFlags &= ~dwFlag;
224
225 dprintf(("ObjSetHandleFlag %x -> %x", MAKE_HANDLE(hObject), dwFlag));
226
227 fSuccess = TRUE;
228 }
229 objTableMutex.leave();
230 return fSuccess;
231}
232//******************************************************************************
233//******************************************************************************
234DWORD WIN32API ObjQueryHandleType(HANDLE hObject)
235{
236 DWORD objtype = 0;
237
238 objTableMutex.enter();
239 hObject &= OBJHANDLE_MAGIC_MASK;
240 if(hObject < MAX_OBJECT_HANDLES && objHandleTable[hObject].dwType != HNDL_NONE) {
241 objtype = objHandleTable[hObject].dwType;
242 }
243 objTableMutex.leave();
244 return objtype;
245}
246//******************************************************************************
247//******************************************************************************
248int WIN32API GetObjectA( HGDIOBJ hObject, int size, void *lpBuffer)
249{
250 int rc;
251
252 dprintf(("GDI32: GetObject %X %X %X\n", hObject, size, lpBuffer));
253
254 if(lpBuffer == NULL)
255 { //return required size if buffer pointer == NULL
256 int objtype = GetObjectType(hObject);
257 switch(objtype)
258 {
259 case OBJ_PEN:
260 return sizeof(LOGPEN);
261
262 case OBJ_EXTPEN:
263 return sizeof(EXTLOGPEN);
264
265 case OBJ_BRUSH:
266 return sizeof(LOGBRUSH);
267
268 case OBJ_PAL:
269 return sizeof(USHORT);
270
271 case OBJ_FONT:
272 return sizeof(LOGFONTA);
273
274 case OBJ_BITMAP:
275 return sizeof(BITMAP); //also default for dib sections??? (TODO: NEED TO CHECK THIS)
276
277 case OBJ_DC:
278 case OBJ_METADC:
279 case OBJ_REGION:
280 case OBJ_METAFILE:
281 case OBJ_MEMDC:
282 case OBJ_ENHMETADC:
283 case OBJ_ENHMETAFILE:
284 dprintf(("warning: GetObjectA not defined for object type %d", objtype));
285 return 0;
286 }
287 }
288 if(DIBSection::getSection() != NULL)
289 {
290 DIBSection *dsect = DIBSection::findObj(hObject);
291 if(dsect)
292 {
293 rc = dsect->GetDIBSection(size, lpBuffer);
294 if(rc == 0) {
295 SetLastError(ERROR_INVALID_PARAMETER);
296 return 0;
297 }
298 SetLastError(ERROR_SUCCESS);
299 return rc;
300 }
301 }
302
303 return O32_GetObject(hObject, size, lpBuffer);
304}
305//******************************************************************************
306//******************************************************************************
307int WIN32API GetObjectW( HGDIOBJ hObject, int size, void *lpBuffer)
308{
309 int ret, objtype;
310
311 dprintf(("GDI32: GetObjectW %X, %d %X", hObject, size, lpBuffer));
312
313 objtype = GetObjectType(hObject);
314
315 switch(objtype)
316 {
317 case OBJ_FONT:
318 {
319 LOGFONTA logfonta;
320
321 if(lpBuffer == NULL) {
322 return sizeof(LOGFONTW); //return required size if buffer pointer == NULL
323 }
324 ret = GetObjectA(hObject, sizeof(logfonta), (void *)&logfonta);
325 if(ret == sizeof(logfonta))
326 {
327 LOGFONTW *logfontw = (LOGFONTW *)lpBuffer;
328
329 if(size < sizeof(LOGFONTW)) {
330 dprintf(("GDI32: GetObjectW : buffer not big enough for LOGFONTW struct!!")); //is the correct? or copy only part?
331 return 0;
332 }
333 memcpy(logfontw, &logfonta, sizeof(LOGFONTA));
334 memset(logfontw->lfFaceName, 0, LF_FACESIZE);
335 AsciiToUnicodeN(logfonta.lfFaceName, logfontw->lfFaceName, LF_FACESIZE-1);
336
337 return sizeof(LOGFONTW);
338 }
339 return 0;
340 }
341 default:
342 return GetObjectA(hObject, size, lpBuffer);
343 }
344}
345//******************************************************************************
346//******************************************************************************
347#ifdef DEBUG
348static char *gditypenames[] = {
349"NULL",
350"OBJ_PEN",
351"OBJ_BRUSH",
352"OBJ_DC",
353"OBJ_METADC",
354"OBJ_PAL",
355"OBJ_FONT",
356"OBJ_BITMAP",
357"OBJ_REGION",
358"OBJ_METAFILE",
359"OBJ_MEMDC",
360"OBJ_EXTPEN",
361"OBJ_ENHMETADC",
362"OBJ_ENHMETAFILE"
363};
364
365char *DbgGetGDITypeName(DWORD handleType)
366{
367 if(handleType <= OBJ_ENHMETAFILE) {
368 return gditypenames[handleType];
369 }
370 return "UNKNOWN TYPE";
371}
372#endif
373//******************************************************************************
374//******************************************************************************
375HGDIOBJ WIN32API SelectObject(HDC hdc, HGDIOBJ hObj)
376{
377 HGDIOBJ rc;
378 DWORD handleType;
379
380 //TODO: must use 16 bits gdi object handles
381 if(HIWORD(hObj) == 0) {
382 hObj |= GDIOBJ_PREFIX;
383 }
384
385 handleType = GetObjectType(hObj);
386 dprintf2(("GDI32: SelectObject %x %x type %s", hdc, hObj, DbgGetGDITypeName(handleType)));
387 if(handleType == OBJ_REGION) {
388 //Return complexity here; not previously selected clip region
389 return (HGDIOBJ)SelectClipRgn(hdc, hObj);
390 }
391
392 if(handleType == OBJ_BITMAP && DIBSection::getSection() != NULL)
393 {
394 DIBSection *dsect;
395
396 dsect = DIBSection::findHDC(hdc);
397 if(dsect)
398 {
399 //remove previously selected dibsection
400 dsect->UnSelectDIBObject();
401 }
402 dsect = DIBSection::findObj(hObj);
403 if(dsect)
404 {
405 dsect->SelectDIBObject(hdc);
406 }
407 }
408 rc = O32_SelectObject(hdc, hObj);
409 if(rc != 0 && GetObjectType(rc) == OBJ_BITMAP && DIBSection::getSection != NULL)
410 {
411 DIBSection *dsect = DIBSection::findObj(rc);
412 if(dsect)
413 {
414 dsect->UnSelectDIBObject();
415 }
416 }
417 dprintf2(("GDI32: SelectObject %x %x returned %x", hdc, hObj, rc));
418
419 return(rc);
420}
421//******************************************************************************
422//Called from user32 ReleaseDC (for non CS_OWNDC hdcs)
423//******************************************************************************
424VOID WIN32API UnselectGDIObjects(HDC hdc)
425{
426 DIBSection *dsect;
427
428 dsect = DIBSection::findHDC(hdc);
429 if(dsect)
430 {
431 //remove previously selected dibsection
432 dsect->UnSelectDIBObject();
433 }
434}
435//******************************************************************************
436//******************************************************************************
437DWORD WIN32API GetObjectType( HGDIOBJ hObj)
438{
439 DWORD objtype = ObjQueryHandleType(hObj);
440
441 switch(objtype) {
442 case HNDL_PEN:
443 objtype = OBJ_PEN;
444 break;
445 case HNDL_BRUSH:
446 objtype = OBJ_BRUSH;
447 break;
448 case HNDL_DC:
449 objtype = OBJ_DC;
450 break;
451 case HNDL_METADC:
452 objtype = OBJ_METADC;
453 break;
454 case HNDL_PALETTE:
455 objtype = OBJ_PAL;
456 break;
457 case HNDL_FONT:
458 objtype = OBJ_FONT;
459 break;
460 case HNDL_BITMAP:
461 case HNDL_DIBSECTION:
462 objtype = OBJ_BITMAP;
463 break;
464 case HNDL_REGION:
465 objtype = OBJ_REGION;
466 break;
467 case HNDL_METAFILE:
468 objtype = OBJ_METAFILE;
469 break;
470 case HNDL_ENHMETAFILE:
471 objtype = OBJ_ENHMETAFILE;
472 break;
473 case HNDL_MEMDC:
474 objtype = OBJ_MEMDC;
475 break;
476 case HNDL_EXTPEN:
477 objtype = OBJ_EXTPEN;
478 break;
479 case HNDL_ENHMETADC:
480 objtype = OBJ_ENHMETADC;
481 break;
482 default:
483 objtype = 0;
484 break;
485 }
486 dprintf2(("GDI32: GetObjectType %x objtype %d (%s)", hObj, objtype, DbgGetGDITypeName(objtype)));
487 return objtype;
488}
489//******************************************************************************
490//TODO: System objects can't be deleted (TODO: any others?? (fonts?))!!!!)
491//******************************************************************************
492BOOL WIN32API DeleteObject(HANDLE hObj)
493{
494 DWORD objtype, objflags;
495
496 dprintf(("GDI32: DeleteObject %x", hObj));
497 objflags = ObjQueryHandleFlags(hObj);
498 if(objflags & OBJHANDLE_FLAG_NODELETE) {
499 dprintf(("!WARNING!: Can't delete system object"));
500 return TRUE;
501 }
502 STATS_DeleteObject(hObj, GetObjectType(hObj));
503
504 if(ObjQueryHandleType(hObj) == HNDL_REGION)
505 {
506 OSLibDeleteRegion(ObjQueryHandleData(hObj, HNDL_REGION));
507 ObjDeleteHandle(hObj, HNDL_REGION);
508 SetLastError(ERROR_SUCCESS);
509 return TRUE;
510 }
511
512 DIBSection::deleteSection((DWORD)hObj);
513 return O32_DeleteObject(hObj);
514}
515//******************************************************************************
516//******************************************************************************
517int WIN32API EnumObjects( HDC hdc, int objType, GOBJENUMPROC objFunc, LPARAM lParam)
518{
519 //calling convention differences
520 dprintf(("!ERROR!: GDI32: EnumObjects STUB"));
521// return O32_EnumObjects(arg1, arg2, arg3, arg4);
522 return 0;
523}
524//******************************************************************************
525//******************************************************************************
526HANDLE WIN32API GetCurrentObject( HDC hdc, UINT arg2)
527{
528 dprintf(("GDI32: GetCurrentObject %x %x", hdc, arg2));
529 return (HANDLE)O32_GetCurrentObject(hdc, arg2);
530}
531//******************************************************************************
532//******************************************************************************
533BOOL WIN32API SetObjectOwner( HGDIOBJ arg1, int arg2 )
534{
535 // Here is a guess for a undocumented entry
536 dprintf(("WARNING: GDI32: SetObjectOwner - stub (TRUE)\n"));
537 return TRUE;
538}
539//******************************************************************************
540//******************************************************************************
541BOOL WIN32API UnrealizeObject( HGDIOBJ hObject)
542{
543 dprintf(("GDI32: UnrealizeObject %x", hObject));
544 return O32_UnrealizeObject(hObject);
545}
546//******************************************************************************
547//******************************************************************************
Note: See TracBrowser for help on using the repository browser.