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

Last change on this file since 21304 was 21304, checked in by ydario, 16 years ago

Gdi32 updates.

File size: 20.5 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 DWORD objtype = 0;
294
295 objTableMutex.enter();
296 hObject &= OBJHANDLE_MAGIC_MASK;
297 if(hObject < MAX_OBJECT_HANDLES && objHandleTable.objects[hObject].dwType != HNDL_NONE) {
298 objtype = objHandleTable.objects[hObject].dwType;
299 }
300 objTableMutex.leave();
301 return objtype;
302}
303//******************************************************************************
304//******************************************************************************
305#ifdef DEBUG
306void dumpObjectType(char *szType, DWORD dwType)
307{
308 for(int i=0;i<MAX_OBJECT_HANDLES;i++) {
309 if(objHandleTable.objects[i].dwUserData != 0 && objHandleTable.objects[i].dwType == dwType) {
310 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));
311 }
312 }
313}
314//******************************************************************************
315//******************************************************************************
316void WIN32API ObjDumpObjects()
317{
318 dprintf(("Open object handles (%d, max %d): (time %x)", objHandleTable.iAllocated, objHandleTable.dwMaxAllocated, GetCurrentTime()));
319
320 dumpObjectType("HNDL_PEN", HNDL_PEN);
321 dumpObjectType("HNDL_BRUSH", HNDL_BRUSH);
322 dumpObjectType("HNDL_DC", HNDL_DC);
323 dumpObjectType("HNDL_METADC", HNDL_METADC);
324 dumpObjectType("HNDL_PALETTE", HNDL_PALETTE);
325 dumpObjectType("HNDL_FONT", HNDL_FONT);
326 dumpObjectType("HNDL_BITMAP", HNDL_BITMAP);
327 dumpObjectType("HNDL_DIBSECTION", HNDL_DIBSECTION);
328 dumpObjectType("HNDL_REGION", HNDL_REGION);
329 dumpObjectType("HNDL_METAFILE", HNDL_METAFILE);
330 dumpObjectType("HNDL_ENHMETAFILE", HNDL_ENHMETAFILE);
331 dumpObjectType("HNDL_MEMDC", HNDL_MEMDC);
332 dumpObjectType("HNDL_EXTPEN", HNDL_EXTPEN);
333 dumpObjectType("HNDL_ENHMETADC", HNDL_ENHMETADC);
334 dumpObjectType("HNDL_MENU", HNDL_MENU);
335 dumpObjectType("HNDL_ACCEL", HNDL_ACCEL);
336 dumpObjectType("HNDL_CURSORICON", HNDL_CURSORICON);
337 dumpObjectType("HNDL_DDELP", HNDL_DDELP);
338}
339#endif
340//******************************************************************************
341//******************************************************************************
342int WIN32API GetObjectA( HGDIOBJ hObject, int size, void *lpBuffer)
343{
344 int rc;
345
346 if(lpBuffer == NULL)
347 { //return required size if buffer pointer == NULL
348 int objtype = GetObjectType(hObject);
349 switch(objtype)
350 {
351 case OBJ_PEN:
352 return sizeof(LOGPEN);
353
354 case OBJ_EXTPEN:
355 return sizeof(EXTLOGPEN);
356
357 case OBJ_BRUSH:
358 return sizeof(LOGBRUSH);
359
360 case OBJ_PAL:
361 return sizeof(USHORT);
362
363 case OBJ_FONT:
364 return sizeof(LOGFONTA);
365
366 case OBJ_BITMAP:
367 return sizeof(BITMAP); //also default for dib sections??? (TODO: NEED TO CHECK THIS)
368
369 case OBJ_DC:
370 case OBJ_METADC:
371 case OBJ_REGION:
372 case OBJ_METAFILE:
373 case OBJ_MEMDC:
374 case OBJ_ENHMETADC:
375 case OBJ_ENHMETAFILE:
376 dprintf(("warning: GetObjectA not defined for object type %d", objtype));
377 return 0;
378 }
379 }
380 if(DIBSection::getSection() != NULL)
381 {
382 DIBSection *dsect = DIBSection::findObj(hObject);
383 if(dsect)
384 {
385 rc = dsect->GetDIBSection(size, lpBuffer);
386 if(rc == 0) {
387 SetLastError(ERROR_INVALID_PARAMETER);
388 return 0;
389 }
390 SetLastError(ERROR_SUCCESS);
391 return rc;
392 }
393 }
394
395 return O32_GetObject(hObject, size, lpBuffer);
396}
397//******************************************************************************
398//******************************************************************************
399int WIN32API GetObjectW( HGDIOBJ hObject, int size, void *lpBuffer)
400{
401 int ret, objtype;
402
403 objtype = GetObjectType(hObject);
404
405 switch(objtype)
406 {
407 case OBJ_FONT:
408 {
409 LOGFONTA logfonta;
410
411 if(lpBuffer == NULL) {
412 return sizeof(LOGFONTW); //return required size if buffer pointer == NULL
413 }
414 ret = GetObjectA(hObject, sizeof(logfonta), (void *)&logfonta);
415 if(ret == sizeof(logfonta))
416 {
417 LOGFONTW *logfontw = (LOGFONTW *)lpBuffer;
418
419 if(size < sizeof(LOGFONTW)) {
420 dprintf(("GDI32: GetObjectW : buffer not big enough for LOGFONTW struct!!")); //is the correct? or copy only part?
421 return 0;
422 }
423 memcpy(logfontw, &logfonta, sizeof(LOGFONTA));
424 memset(logfontw->lfFaceName, 0, LF_FACESIZE);
425 AsciiToUnicodeN(logfonta.lfFaceName, logfontw->lfFaceName, LF_FACESIZE-1);
426
427 return sizeof(LOGFONTW);
428 }
429 return 0;
430 }
431 default:
432 return GetObjectA(hObject, size, lpBuffer);
433 }
434}
435//******************************************************************************
436//******************************************************************************
437#ifdef DEBUG
438static char *gditypenames[] = {
439"NULL",
440"OBJ_PEN",
441"OBJ_BRUSH",
442"OBJ_DC",
443"OBJ_METADC",
444"OBJ_PAL",
445"OBJ_FONT",
446"OBJ_BITMAP",
447"OBJ_REGION",
448"OBJ_METAFILE",
449"OBJ_MEMDC",
450"OBJ_EXTPEN",
451"OBJ_ENHMETADC",
452"OBJ_ENHMETAFILE"
453};
454
455char *DbgGetGDITypeName(DWORD handleType)
456{
457 if(handleType <= OBJ_ENHMETAFILE) {
458 return gditypenames[handleType];
459 }
460 return "UNKNOWN TYPE";
461}
462#endif
463//******************************************************************************
464//******************************************************************************
465HGDIOBJ WIN32API SelectObject(HDC hdc, HGDIOBJ hObj)
466{
467 HGDIOBJ rc;
468 DWORD handleType;
469
470 //TODO: must use 16 bits gdi object handles
471 if(HIWORD(hObj) == 0) {
472 hObj |= GDIOBJ_PREFIX;
473 }
474
475 handleType = GetObjectType(hObj);
476 dprintf(("GDI32: SelectObject %x %x type %s", hdc, hObj, DbgGetGDITypeName(handleType)));
477 if(handleType == OBJ_REGION) {
478 //Return complexity here; not previously selected clip region
479 return (HGDIOBJ)SelectClipRgn(hdc, hObj);
480 }
481
482 if(handleType == OBJ_BITMAP && DIBSection::getSection() != NULL)
483 {
484 DIBSection *dsect;
485
486 dsect = DIBSection::findHDC(hdc);
487 if(dsect)
488 {
489 //remove previously selected dibsection
490 dsect->UnSelectDIBObject();
491 }
492 dsect = DIBSection::findObj(hObj);
493 if(dsect)
494 {
495 dsect->SelectDIBObject(hdc);
496 }
497 }
498 rc = O32_SelectObject(hdc, hObj);
499 if(rc != 0 && GetObjectType(rc) == OBJ_BITMAP && DIBSection::getSection != NULL)
500 {
501 DIBSection *dsect = DIBSection::findObj(rc);
502 if(dsect)
503 {
504 dsect->UnSelectDIBObject();
505 }
506 }
507 return(rc);
508}
509//******************************************************************************
510//Called from user32 ReleaseDC (for non CS_OWNDC hdcs)
511//******************************************************************************
512VOID WIN32API UnselectGDIObjects(HDC hdc)
513{
514 DIBSection *dsect;
515
516 dsect = DIBSection::findHDC(hdc);
517 if(dsect)
518 {
519 //remove previously selected dibsection
520 dsect->UnSelectDIBObject();
521 }
522}
523//******************************************************************************
524//******************************************************************************
525DWORD WIN32API GetObjectType( HGDIOBJ hObj)
526{
527 DWORD objtype = ObjQueryHandleType(hObj);
528
529 switch(objtype) {
530 case HNDL_PEN:
531 objtype = OBJ_PEN;
532 break;
533 case HNDL_BRUSH:
534 objtype = OBJ_BRUSH;
535 break;
536 case HNDL_DC:
537 objtype = OBJ_DC;
538 break;
539 case HNDL_METADC:
540 objtype = OBJ_METADC;
541 break;
542 case HNDL_PALETTE:
543 objtype = OBJ_PAL;
544 break;
545 case HNDL_FONT:
546 objtype = OBJ_FONT;
547 break;
548 case HNDL_BITMAP:
549 case HNDL_DIBSECTION:
550 objtype = OBJ_BITMAP;
551 break;
552 case HNDL_REGION:
553 objtype = OBJ_REGION;
554 break;
555 case HNDL_METAFILE:
556 objtype = OBJ_METAFILE;
557 break;
558 case HNDL_ENHMETAFILE:
559 objtype = OBJ_ENHMETAFILE;
560 break;
561 case HNDL_MEMDC:
562 objtype = OBJ_MEMDC;
563 break;
564 case HNDL_EXTPEN:
565 objtype = OBJ_EXTPEN;
566 break;
567 case HNDL_ENHMETADC:
568 objtype = OBJ_ENHMETADC;
569 break;
570 default:
571 objtype = 0;
572 break;
573 }
574 dprintf2(("GDI32: GetObjectType %x objtype %d (%s)", hObj, objtype, DbgGetGDITypeName(objtype)));
575 return objtype;
576}
577//******************************************************************************
578//TODO: System objects can't be deleted (TODO: any others?? (fonts?))!!!!)
579//******************************************************************************
580BOOL WIN32API DeleteObject(HANDLE hObj)
581{
582 DWORD objflags;
583
584//hack alert
585 if(HIWORD(hObj) == 0x100)
586 {//most likely a DC handle
587 if(OSLibGpiQueryDCData(hObj) != NULL) {
588 dprintf(("WARNING: DeleteObject used for DC handle!"));
589 return DeleteDC(hObj);
590 }
591 }
592//end hack
593
594 objflags = ObjQueryHandleFlags(hObj);
595 if(objflags & OBJHANDLE_FLAG_NODELETE) {
596 dprintf(("!WARNING!: Can't delete system object"));
597 return TRUE;
598 }
599 STATS_DeleteObject(hObj, GetObjectType(hObj));
600
601 if(ObjQueryHandleType(hObj) == HNDL_REGION)
602 {
603 OSLibDeleteRegion(ObjQueryHandleData(hObj, HNDL_REGION));
604 ObjDeleteHandle(hObj, HNDL_REGION);
605 SetLastError(ERROR_SUCCESS);
606 return TRUE;
607 }
608
609 DIBSection::deleteSection((DWORD)hObj);
610 return O32_DeleteObject(hObj);
611}
612//******************************************************************************
613//******************************************************************************
614int WIN32API EnumObjects( HDC hdc, int objType, GOBJENUMPROC objFunc, LPARAM lParam)
615{
616 //calling convention differences
617 dprintf(("!ERROR!: GDI32: EnumObjects STUB"));
618// return O32_EnumObjects(arg1, arg2, arg3, arg4);
619 return 0;
620}
621//******************************************************************************
622//******************************************************************************
623HANDLE WIN32API GetCurrentObject( HDC hdc, UINT arg2)
624{
625 return (HANDLE)O32_GetCurrentObject(hdc, arg2);
626}
627//******************************************************************************
628//******************************************************************************
629BOOL WIN32API SetObjectOwner( HGDIOBJ arg1, int arg2 )
630{
631 // Here is a guess for a undocumented entry
632 dprintf(("WARNING: GDI32: SetObjectOwner - stub (TRUE)\n"));
633 return TRUE;
634}
635//******************************************************************************
636//******************************************************************************
637BOOL WIN32API UnrealizeObject( HGDIOBJ hObject)
638{
639 return O32_UnrealizeObject(hObject);
640}
641//******************************************************************************
642//******************************************************************************
Note: See TracBrowser for help on using the repository browser.