reactos/win32ss/gdi/gdi32/objects/gdiobj.c
James Tabor fc16259faf [GDI32] Update Wine Metafile Code
Sync/Port: Metafile code from wine.

Patches by Jacek Caban, Daniel Lehman, Zhiyi Zhang. Gabriel Ivancescu, Michael Stefaniuc, Francois Gouget, Nikolay Sivov Dmitry Timoshkov, Andrew EiKum, Piotr Caban and Alexandre Julliard.

This commit is dedicated to George Bisoc!
2021-09-27 16:18:20 -05:00

369 lines
8.5 KiB
C

#include <precomp.h>
#define NDEBUG
#include <debug.h>
HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
/*
* @implemented
*/
HGDIOBJ
WINAPI
GetStockObject(
INT fnObject)
{
HGDIOBJ hobj;
if ((fnObject < 0) || (fnObject >= NB_STOCK_OBJECTS))
return NULL;
hobj = stock_objects[fnObject];
if (hobj == NULL)
{
hobj = NtGdiGetStockObject(fnObject);
if (!GdiValidateHandle(hobj))
{
return NULL;
}
stock_objects[fnObject] = hobj;
}
return hobj;
}
/*
* @implemented
*/
DWORD
WINAPI
GetObjectType(
HGDIOBJ h)
{
DWORD Ret = 0;
if (GdiValidateHandle(h))
{
LONG Type = GDI_HANDLE_GET_TYPE(h);
switch(Type)
{
case GDI_OBJECT_TYPE_PEN:
Ret = OBJ_PEN;
break;
case GDI_OBJECT_TYPE_BRUSH:
Ret = OBJ_BRUSH;
break;
case GDI_OBJECT_TYPE_BITMAP:
Ret = OBJ_BITMAP;
break;
case GDI_OBJECT_TYPE_FONT:
Ret = OBJ_FONT;
break;
case GDI_OBJECT_TYPE_PALETTE:
Ret = OBJ_PAL;
break;
case GDI_OBJECT_TYPE_REGION:
Ret = OBJ_REGION;
break;
case GDI_OBJECT_TYPE_DC:
if ( GetDCDWord( h, GdiGetIsMemDc, 0))
{
Ret = OBJ_MEMDC;
}
else
Ret = OBJ_DC;
break;
case GDI_OBJECT_TYPE_COLORSPACE:
Ret = OBJ_COLORSPACE;
break;
case GDI_OBJECT_TYPE_METAFILE:
Ret = OBJ_METAFILE;
break;
case GDI_OBJECT_TYPE_ENHMETAFILE:
Ret = OBJ_ENHMETAFILE;
break;
case GDI_OBJECT_TYPE_METADC:
Ret = OBJ_METADC;
break;
case GDI_OBJECT_TYPE_EXTPEN:
Ret = OBJ_EXTPEN;
break;
case GDILoObjType_LO_ALTDC_TYPE:
// FIXME: could be something else?
Ret = OBJ_ENHMETADC;
break;
default:
DPRINT1("GetObjectType: Magic 0x%08x not implemented\n", Type);
break;
}
}
else
/* From Wine: GetObjectType does SetLastError() on a null object */
SetLastError(ERROR_INVALID_HANDLE);
return Ret;
}
ULONG
WINAPI
GetFontObjectA(
_In_ HGDIOBJ hfont,
_In_ ULONG cbSize,
_Out_ LPVOID lpBuffer)
{
ENUMLOGFONTEXDVW elfedvW;
ENUMLOGFONTEXDVA elfedvA;
ULONG cbResult;
/* Check if size only is requested */
if (!lpBuffer) return sizeof(LOGFONTA);
/* Check for size 0 */
if (cbSize == 0)
{
/* Windows does not SetLastError() */
return 0;
}
/* Windows does this ... */
if (cbSize == sizeof(LOGFONTW)) cbSize = sizeof(LOGFONTA);
/* Call win32k to get the logfont (widechar) */
cbResult = NtGdiExtGetObjectW(hfont, sizeof(ENUMLOGFONTEXDVW), &elfedvW);
if (cbResult == 0)
{
return 0;
}
/* Convert the logfont from widechar to ansi */
EnumLogFontExW2A(&elfedvA.elfEnumLogfontEx, &elfedvW.elfEnumLogfontEx);
elfedvA.elfDesignVector = elfedvW.elfDesignVector;
/* Don't copy more than maximum */
if (cbSize > sizeof(ENUMLOGFONTEXDVA)) cbSize = sizeof(ENUMLOGFONTEXDVA);
/* Copy the number of bytes requested */
memcpy(lpBuffer, &elfedvA, cbSize);
/* Return the number of bytes copied */
return cbSize;
}
/*
* @implemented
*/
int
WINAPI
GetObjectA(
_In_ HGDIOBJ hGdiObj,
_In_ int cbSize,
_Out_ LPVOID lpBuffer)
{
DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
/* Chjeck if this is anything else but a font */
if (dwType == GDI_OBJECT_TYPE_FONT)
{
return GetFontObjectA(hGdiObj, cbSize, lpBuffer);
}
else
{
/* Simply pass it to the widechar version */
return GetObjectW(hGdiObj, cbSize, lpBuffer);
}
}
/*
* @implemented
*/
int
WINAPI
GetObjectW(
_In_ HGDIOBJ hGdiObj,
_In_ int cbSize,
_Out_ LPVOID lpBuffer)
{
DWORD dwType;
INT cbResult = 0;
/* Fixup handles with upper 16 bits masked */
hGdiObj = GdiFixUpHandle(hGdiObj);
/* Get the object type */
dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
/* Check what kind of object we have */
switch (dwType)
{
case GDI_OBJECT_TYPE_PEN:
if (!lpBuffer) return sizeof(LOGPEN);
break;
case GDI_OBJECT_TYPE_BRUSH:
if (!lpBuffer || !cbSize) return sizeof(LOGBRUSH);
break;
case GDI_OBJECT_TYPE_BITMAP:
if (!lpBuffer) return sizeof(BITMAP);
break;
case GDI_OBJECT_TYPE_PALETTE:
if (!lpBuffer) return sizeof(WORD);
break;
case GDI_OBJECT_TYPE_FONT:
if (!lpBuffer) return sizeof(LOGFONTW);
break;
case GDI_OBJECT_TYPE_EXTPEN:
/* we don't know the size, ask win32k */
break;
case GDI_OBJECT_TYPE_COLORSPACE:
if ((cbSize < 328) || !lpBuffer)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
break;
case GDI_OBJECT_TYPE_DC:
case GDI_OBJECT_TYPE_REGION:
case GDI_OBJECT_TYPE_EMF:
case GDI_OBJECT_TYPE_METAFILE:
case GDI_OBJECT_TYPE_ENHMETAFILE:
SetLastError(ERROR_INVALID_HANDLE);
default:
return 0;
}
/* Call win32k */
cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
/* Handle error */
if (cbResult == 0)
{
if (!GdiValidateHandle(hGdiObj))
{
if ((dwType == GDI_OBJECT_TYPE_PEN) ||
(dwType == GDI_OBJECT_TYPE_EXTPEN) ||
(dwType == GDI_OBJECT_TYPE_BRUSH) ||
(dwType == GDI_OBJECT_TYPE_COLORSPACE))
{
SetLastError(ERROR_INVALID_PARAMETER);
}
}
else
{
if ((dwType == GDI_OBJECT_TYPE_PEN) ||
(dwType == GDI_OBJECT_TYPE_BRUSH) ||
(dwType == GDI_OBJECT_TYPE_COLORSPACE) ||
( (dwType == GDI_OBJECT_TYPE_EXTPEN) &&
( (cbSize >= sizeof(EXTLOGPEN)) || (cbSize == 0) ) ) ||
( (dwType == GDI_OBJECT_TYPE_BITMAP) && (cbSize >= sizeof(BITMAP)) ))
{
SetLastError(ERROR_NOACCESS);
}
}
}
return cbResult;
}
static
BOOL
GdiDeleteBrushOrPen(
HGDIOBJ hobj)
{
GDILOOBJTYPE eObjectType;
PBRUSH_ATTR pbrattr;
PTEB pTeb;
PGDIBSOBJECT pgO;
eObjectType = GDI_HANDLE_GET_TYPE(hobj);
if ((GdiGetHandleUserData(hobj, eObjectType, (PVOID*)&pbrattr)) &&
(pbrattr != NULL))
{
pTeb = NtCurrentTeb();
if (pTeb->Win32ThreadInfo != NULL)
{
pgO = GdiAllocBatchCommand(NULL, GdiBCDelObj);
if (pgO)
{
/// FIXME: we need to mark the object as deleted!
pgO->hgdiobj = hobj;
return TRUE;
}
}
}
return NtGdiDeleteObjectApp(hobj);
}
/*
* @implemented
*/
BOOL
WINAPI
DeleteObject(HGDIOBJ hObject)
{
/* Check if the handle is valid (FIXME: we need some special
sauce for the stock object flag) */
if (!GdiValidateHandle(hObject))
return FALSE;
/* Check if this is a stock object */
if ((DWORD_PTR)hObject & GDI_HANDLE_STOCK_MASK)
{
/* Ignore the attempt to delete a stock object */
DPRINT1("Trying to delete system object 0x%p\n", hObject);
return TRUE;
}
/* If we have any METAFILE objects, we need to check them */
if (gcClientObj > 0)
{
DPRINT("Going Glue\n");
METADC_RosGlueDeleteObject(hObject);
}
/* Switch by object type */
switch (GDI_HANDLE_GET_TYPE(hObject))
{
case GDILoObjType_LO_METAFILE16_TYPE:
case GDILoObjType_LO_METAFILE_TYPE:
return FALSE;
case GDILoObjType_LO_DC_TYPE:
case GDILoObjType_LO_ALTDC_TYPE:
return DeleteDC(hObject);
case GDILoObjType_LO_ICMLCS_TYPE:
return NtGdiDeleteColorSpace(hObject);
case GDILoObjType_LO_REGION_TYPE:
return DeleteRegion(hObject);
case GDILoObjType_LO_BRUSH_TYPE:
case GDILoObjType_LO_PEN_TYPE:
case GDILoObjType_LO_EXTPEN_TYPE:
return GdiDeleteBrushOrPen(hObject);
case GDILoObjType_LO_FONT_TYPE:
case GDILoObjType_LO_BITMAP_TYPE:
default:
break;
}
return NtGdiDeleteObjectApp(hObject);
}