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

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

Fixed: GetObjectType() on DC handles would return wrong values.

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