/* $Id: objhandle.cpp,v 1.32 2004-01-11 11:42:18 sandervl Exp $ */ /* * Win32 Handle Management Code for OS/2 * * * Copyright 2000-2002 Sander van Leeuwen (sandervl@xs4all.nl) * Copyright 2003 Innotek Systemberatung GmbH (sandervl@innotek.de) * * TODO: The table should be dynamically increased when necessary * This is just a quick and dirty implementation * * System objects can't be deleted (TODO: any others?? (fonts?))!!!!) * * Project Odin Software License can be found in LICENSE.TXT * */ #include #include #include #include #include #include #include #include "oslibgpi.h" #include "dibsect.h" #include "region.h" #include #include "font.h" #include #define DBG_LOCALLOG DBG_objhandle #include "dbglocal.h" //TODO: must use 16 bits gdi object handles #define GDIOBJ_PREFIX 0xe7000000 //****************************************************************************** typedef struct _GdiObject { DWORD dwUserData; DWORD dwGDI32Data; DWORD dwFlags; DWORD dwType; #ifdef DEBUG DWORD dwTime; struct _GdiObject *prev; #endif struct _GdiObject *next; } GdiObject; typedef struct { GdiObject *headfree; GdiObject *tailfree; GdiObject *objects; int iAllocated; #ifdef DEBUG DWORD dwMaxAllocated; #endif } GdiObjectTable; static GdiObjectTable objHandleTable = { 0 }; static VMutex objTableMutex; //****************************************************************************** //****************************************************************************** BOOL WIN32API ObjAllocateHandle(HANDLE *hObject, DWORD dwUserData, DWORD dwType) { DWORD oldlowestidx; BOOL retry = FALSE; objTableMutex.enter(); if(objHandleTable.objects == NULL) { objHandleTable.objects = (GdiObject *)malloc(MAX_OBJECT_HANDLES*sizeof(GdiObject)); if(objHandleTable.objects == NULL) { DebugInt3(); return FALSE; } memset(objHandleTable.objects, 0, MAX_OBJECT_HANDLES*sizeof(GdiObject)); if(objHandleTable.objects[0].dwType == HNDL_NONE) { //first handle can never be used objHandleTable.objects[0].dwType = HNDL_INVALID; objHandleTable.objects[0].dwUserData = -1; objHandleTable.objects[0].dwFlags = OBJHANDLE_FLAG_NODELETE; } objHandleTable.tailfree = &objHandleTable.objects[MAX_OBJECT_HANDLES-1]; for(int i=MAX_OBJECT_HANDLES-1;i>0;i--) { GdiObject *obj = &objHandleTable.objects[i]; #ifdef DEBUG if(objHandleTable.headfree) { objHandleTable.headfree->prev = obj; } obj->prev = NULL; #endif obj->next = objHandleTable.headfree; objHandleTable.headfree = obj; } objHandleTable.iAllocated = 1; //one invalid object } GdiObject *newobj = objHandleTable.headfree; if(newobj == NULL) { //oops, out of handles objTableMutex.leave(); dprintf(("ERROR: GDI: ObjAllocateHandle OUT OF GDI OBJECT HANDLES!!")); DebugInt3(); return FALSE; } objHandleTable.headfree = newobj->next; //if there's nothing left, then there's nothing left if(objHandleTable.headfree == NULL) { dprintf(("WARNING: Just allocated our last GDI handle...")); objHandleTable.tailfree = NULL; } #ifdef DEBUG else objHandleTable.headfree->prev = NULL; newobj->prev = NULL; newobj->dwTime = GetCurrentTime(); #endif newobj->next = NULL; *hObject = MAKE_HANDLE(((char *)newobj - (char *)objHandleTable.objects)/sizeof(*newobj)); newobj->dwUserData = dwUserData; newobj->dwType = dwType; newobj->dwGDI32Data = 0; newobj->dwFlags = 0; objHandleTable.iAllocated++; #ifdef DEBUG if(objHandleTable.iAllocated > objHandleTable.dwMaxAllocated) { objHandleTable.dwMaxAllocated = objHandleTable.iAllocated; } #endif objTableMutex.leave(); dprintf2(("ObjAllocateHandle %x type %d", *hObject, dwType)); return TRUE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API ObjDeleteHandle(HANDLE hObject, DWORD dwType) { hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES) { objTableMutex.enter(); GdiObject *obj = &objHandleTable.objects[hObject]; if(!(obj->dwFlags & OBJHANDLE_FLAG_NODELETE)) { dprintf2(("ObjDeleteHandle %x type %d", MAKE_HANDLE(hObject), obj->dwType)); obj->dwUserData = 0; obj->dwType = HNDL_NONE; obj->next = NULL; //add to the tail of the free object list if(objHandleTable.tailfree) objHandleTable.tailfree->next = obj; #ifdef DEBUG obj->prev = objHandleTable.tailfree; #endif objHandleTable.tailfree = obj; if(objHandleTable.headfree == NULL) objHandleTable.headfree = obj; objHandleTable.iAllocated--; if(objHandleTable.iAllocated < 0) DebugInt3(); } else { dprintf(("ObjDeleteHandle: unable to delete system object %x", MAKE_HANDLE(hObject))); } objTableMutex.leave(); return TRUE; } return FALSE; } //****************************************************************************** //****************************************************************************** DWORD WIN32API ObjQueryHandleData(HANDLE hObject, DWORD dwType) { DWORD dwUserData = HANDLE_INVALID_DATA; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && ((dwType == HNDL_ANY && objHandleTable.objects[hObject].dwType != HNDL_NONE) || dwType == objHandleTable.objects[hObject].dwType)) { dwUserData = objHandleTable.objects[hObject].dwUserData; } objTableMutex.leave(); return dwUserData; } //****************************************************************************** //****************************************************************************** BOOL WIN32API ObjSetHandleData(HANDLE hObject, DWORD dwType, DWORD dwUserData) { BOOL fSuccess = FALSE; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && ((dwType == HNDL_ANY && objHandleTable.objects[hObject].dwType != HNDL_NONE) || dwType == objHandleTable.objects[hObject].dwType)) { objHandleTable.objects[hObject].dwUserData = dwUserData; fSuccess = TRUE; } objTableMutex.leave(); return fSuccess; } //****************************************************************************** //****************************************************************************** DWORD WIN32API ObjQueryHandleGDI32Data(HANDLE hObject, DWORD dwType) { DWORD dwGDI32Data = HANDLE_INVALID_DATA; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && ((dwType == HNDL_ANY && objHandleTable.objects[hObject].dwType != HNDL_NONE) || dwType == objHandleTable.objects[hObject].dwType)) { dwGDI32Data = objHandleTable.objects[hObject].dwGDI32Data; } objTableMutex.leave(); return dwGDI32Data; } //****************************************************************************** //****************************************************************************** BOOL WIN32API ObjSetHandleGDI32Data(HANDLE hObject, DWORD dwType, DWORD dwGDI32Data) { BOOL fSuccess = FALSE; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && ((dwType == HNDL_ANY && objHandleTable.objects[hObject].dwType != HNDL_NONE) || dwType == objHandleTable.objects[hObject].dwType)) { objHandleTable.objects[hObject].dwGDI32Data = dwGDI32Data; fSuccess = TRUE; } objTableMutex.leave(); return fSuccess; } //****************************************************************************** //****************************************************************************** DWORD WIN32API ObjQueryHandleFlags(OBJHANDLE hObject) { DWORD dwFlags = 0; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && objHandleTable.objects[hObject].dwType != HNDL_NONE) { dwFlags = objHandleTable.objects[hObject].dwFlags; } objTableMutex.leave(); return dwFlags; } //****************************************************************************** //****************************************************************************** BOOL WIN32API ObjSetHandleFlag(HANDLE hObject, DWORD dwFlag, BOOL fSet) { BOOL fSuccess = FALSE; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && objHandleTable.objects[hObject].dwType != HNDL_NONE) { if(fSet) { objHandleTable.objects[hObject].dwFlags |= dwFlag; } else objHandleTable.objects[hObject].dwFlags &= ~dwFlag; dprintf(("ObjSetHandleFlag %x -> %x", MAKE_HANDLE(hObject), dwFlag)); fSuccess = TRUE; } objTableMutex.leave(); return fSuccess; } //****************************************************************************** //****************************************************************************** DWORD WIN32API ObjQueryHandleType(HANDLE hObject) { //hack alert if(HIWORD(hObject) == 0x100) {//most likely a DC handle if(OSLibGpiQueryDCData(hObject) != NULL) { return HNDL_DC; } } //end hack DWORD objtype = 0; objTableMutex.enter(); hObject &= OBJHANDLE_MAGIC_MASK; if(hObject < MAX_OBJECT_HANDLES && objHandleTable.objects[hObject].dwType != HNDL_NONE) { objtype = objHandleTable.objects[hObject].dwType; } objTableMutex.leave(); return objtype; } //****************************************************************************** //****************************************************************************** #ifdef DEBUG void dumpObjectType(const char *szType, DWORD dwType) { for(int i=0;iGetDIBSection(size, lpBuffer); if(rc == 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } SetLastError(ERROR_SUCCESS); return rc; } } return O32_GetObject(hObject, size, lpBuffer); } //****************************************************************************** //****************************************************************************** int WIN32API GetObjectW( HGDIOBJ hObject, int size, void *lpBuffer) { int ret, objtype; objtype = GetObjectType(hObject); switch(objtype) { case OBJ_FONT: { LOGFONTA logfonta; if(lpBuffer == NULL) { return sizeof(LOGFONTW); //return required size if buffer pointer == NULL } ret = GetObjectA(hObject, sizeof(logfonta), (void *)&logfonta); if(ret == sizeof(logfonta)) { LOGFONTW *logfontw = (LOGFONTW *)lpBuffer; if(size < sizeof(LOGFONTW)) { dprintf(("GDI32: GetObjectW : buffer not big enough for LOGFONTW struct!!")); //is the correct? or copy only part? return 0; } memcpy(logfontw, &logfonta, sizeof(LOGFONTA)); memset(logfontw->lfFaceName, 0, LF_FACESIZE); AsciiToUnicodeN(logfonta.lfFaceName, logfontw->lfFaceName, LF_FACESIZE-1); return sizeof(LOGFONTW); } return 0; } default: return GetObjectA(hObject, size, lpBuffer); } } //****************************************************************************** //****************************************************************************** #ifdef DEBUG static const char *gditypenames[] = { "NULL", "OBJ_PEN", "OBJ_BRUSH", "OBJ_DC", "OBJ_METADC", "OBJ_PAL", "OBJ_FONT", "OBJ_BITMAP", "OBJ_REGION", "OBJ_METAFILE", "OBJ_MEMDC", "OBJ_EXTPEN", "OBJ_ENHMETADC", "OBJ_ENHMETAFILE" }; const char *DbgGetGDITypeName(DWORD handleType) { if(handleType <= OBJ_ENHMETAFILE) { return gditypenames[handleType]; } return "UNKNOWN TYPE"; } #endif //****************************************************************************** //****************************************************************************** HGDIOBJ WIN32API SelectObject(HDC hdc, HGDIOBJ hObj) { HGDIOBJ rc; DWORD handleType; //TODO: must use 16 bits gdi object handles if(HIWORD(hObj) == 0) { hObj |= GDIOBJ_PREFIX; } handleType = GetObjectType(hObj); dprintf(("GDI32: SelectObject %x %x type %s", hdc, hObj, DbgGetGDITypeName(handleType))); if(handleType == OBJ_REGION) { //Return complexity here; not previously selected clip region return (HGDIOBJ)SelectClipRgn(hdc, hObj); } if(handleType == OBJ_BITMAP && DIBSection::getSection() != NULL) { DIBSection *dsect; dsect = DIBSection::findHDC(hdc); if(dsect) { //remove previously selected dibsection dsect->UnSelectDIBObject(); } dsect = DIBSection::findObj(hObj); if(dsect) { dsect->SelectDIBObject(hdc); } } rc = O32_SelectObject(hdc, hObj); if(rc != 0 && GetObjectType(rc) == OBJ_BITMAP && DIBSection::getSection != NULL) { DIBSection *dsect = DIBSection::findObj(rc); if(dsect) { dsect->UnSelectDIBObject(); } } return(rc); } //****************************************************************************** //Called from user32 ReleaseDC (for non CS_OWNDC hdcs) //****************************************************************************** VOID WIN32API UnselectGDIObjects(HDC hdc) { DIBSection *dsect; dsect = DIBSection::findHDC(hdc); if(dsect) { //remove previously selected dibsection dsect->UnSelectDIBObject(); } } //****************************************************************************** //****************************************************************************** DWORD WIN32API GetObjectType( HGDIOBJ hObj) { DWORD objtype = ObjQueryHandleType(hObj); switch(objtype) { case HNDL_PEN: objtype = OBJ_PEN; break; case HNDL_BRUSH: objtype = OBJ_BRUSH; break; case HNDL_DC: objtype = OBJ_DC; break; case HNDL_METADC: objtype = OBJ_METADC; break; case HNDL_PALETTE: objtype = OBJ_PAL; break; case HNDL_FONT: objtype = OBJ_FONT; break; case HNDL_BITMAP: case HNDL_DIBSECTION: objtype = OBJ_BITMAP; break; case HNDL_REGION: objtype = OBJ_REGION; break; case HNDL_METAFILE: objtype = OBJ_METAFILE; break; case HNDL_ENHMETAFILE: objtype = OBJ_ENHMETAFILE; break; case HNDL_MEMDC: objtype = OBJ_MEMDC; break; case HNDL_EXTPEN: objtype = OBJ_EXTPEN; break; case HNDL_ENHMETADC: objtype = OBJ_ENHMETADC; break; default: objtype = 0; break; } dprintf2(("GDI32: GetObjectType %x objtype %d (%s)", hObj, objtype, DbgGetGDITypeName(objtype))); return objtype; } //****************************************************************************** //TODO: System objects can't be deleted (TODO: any others?? (fonts?))!!!!) //****************************************************************************** BOOL WIN32API DeleteObject(HANDLE hObj) { DWORD objflags; //hack alert if(HIWORD(hObj) == 0x100) {//most likely a DC handle if(OSLibGpiQueryDCData(hObj) != NULL) { dprintf(("WARNING: DeleteObject used for DC handle!")); return DeleteDC(hObj); } } //end hack objflags = ObjQueryHandleFlags(hObj); if(objflags & OBJHANDLE_FLAG_NODELETE) { dprintf(("!WARNING!: Can't delete system object")); return TRUE; } STATS_DeleteObject(hObj, GetObjectType(hObj)); if(ObjQueryHandleType(hObj) == HNDL_REGION) { OSLibDeleteRegion(ObjQueryHandleData(hObj, HNDL_REGION)); ObjDeleteHandle(hObj, HNDL_REGION); SetLastError(ERROR_SUCCESS); return TRUE; } DIBSection::deleteSection((DWORD)hObj); return O32_DeleteObject(hObj); } //****************************************************************************** //****************************************************************************** int WIN32API EnumObjects( HDC hdc, int objType, GOBJENUMPROC objFunc, LPARAM lParam) { //calling convention differences dprintf(("!ERROR!: GDI32: EnumObjects STUB")); // return O32_EnumObjects(arg1, arg2, arg3, arg4); return 0; } //****************************************************************************** //****************************************************************************** HANDLE WIN32API GetCurrentObject( HDC hdc, UINT arg2) { return (HANDLE)O32_GetCurrentObject(hdc, arg2); } //****************************************************************************** //****************************************************************************** BOOL WIN32API SetObjectOwner( HGDIOBJ arg1, int arg2 ) { // Here is a guess for a undocumented entry dprintf(("WARNING: GDI32: SetObjectOwner - stub (TRUE)\n")); return TRUE; } //****************************************************************************** //****************************************************************************** BOOL WIN32API UnrealizeObject( HGDIOBJ hObject) { return O32_UnrealizeObject(hObject); } //****************************************************************************** //******************************************************************************