[GDI32/WIN32K]

- Rewrite GetCurrentObject and GetObject, fixes a lot of tests

svn path=/trunk/; revision=56400
This commit is contained in:
Timo Kreuzer 2012-04-23 19:22:17 +00:00
parent 3b3feb61a8
commit 4bc462e69c
11 changed files with 251 additions and 252 deletions

View file

@ -130,7 +130,6 @@ BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, DWORD ObjectType, PVOID *UserData)
((Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK) != ObjectType ||
(Entry->Type & GDI_ENTRY_BASETYPE_MASK) != (ObjectType & GDI_ENTRY_BASETYPE_MASK))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}

View file

@ -1131,7 +1131,7 @@ GetETM(HDC hdc,
BOOL Ret = NtGdiGetETM(hdc, petm);
if (Ret && petm)
petm->emKernPairs = GetKerningPairsA(hdc, 0, 0);
petm->emKernPairs = (WORD)GetKerningPairsA(hdc, 0, 0);
return Ret;
}

View file

@ -61,7 +61,7 @@ GetICMProfileA(
if (GetICMProfileW(hdc, &buflen, filenameW))
{
int len = WideCharToMultiByte(CP_ACP, 0, filenameW, -1, NULL, 0, NULL, NULL);
ULONG len = WideCharToMultiByte(CP_ACP, 0, filenameW, -1, NULL, 0, NULL, NULL);
if (*pBufSize >= len)
{
WideCharToMultiByte(CP_ACP, 0, filenameW, -1, pszFilename, *pBufSize, NULL, NULL);

View file

@ -554,7 +554,7 @@ SetDIBits(HDC hDC,
if ( hOldBitmap )
{
if ( hDC )
hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
hPal = SelectPalette(SavehDC, (HPALETTE)GetCurrentObject(hDC, OBJ_PAL), FALSE);
if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
{

View file

@ -412,83 +412,62 @@ SetArcDirection( HDC hdc, INT nDirection )
return GetAndSetDCDWord( hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0 );
}
HGDIOBJ
WINAPI
GetDCObject( HDC hDC, INT iType)
{
if((iType == GDI_OBJECT_TYPE_BRUSH) ||
(iType == GDI_OBJECT_TYPE_EXTPEN)||
(iType == GDI_OBJECT_TYPE_PEN) ||
(iType == GDI_OBJECT_TYPE_COLORSPACE))
{
HGDIOBJ hGO = NULL;
PDC_ATTR Dc_Attr;
if (!hDC) return hGO;
if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return NULL;
switch (iType)
{
case GDI_OBJECT_TYPE_BRUSH:
hGO = Dc_Attr->hbrush;
break;
case GDI_OBJECT_TYPE_EXTPEN:
case GDI_OBJECT_TYPE_PEN:
hGO = Dc_Attr->hpen;
break;
case GDI_OBJECT_TYPE_COLORSPACE:
hGO = Dc_Attr->hColorSpace;
break;
}
return hGO;
}
return NtGdiGetDCObject( hDC, iType );
}
/*
* @implemented
*
*/
HGDIOBJ
WINAPI
GetCurrentObject(HDC hdc,
UINT uObjectType)
GetCurrentObject(
_In_ HDC hdc,
_In_ UINT uObjectType)
{
switch(uObjectType)
PDC_ATTR pdcattr;
/* Check if this is a user mode object */
if ((uObjectType == OBJ_PEN) ||
(uObjectType == OBJ_EXTPEN) ||
(uObjectType == OBJ_BRUSH) ||
(uObjectType == OBJ_COLORSPACE))
{
case OBJ_EXTPEN:
case OBJ_PEN:
uObjectType = GDI_OBJECT_TYPE_PEN;
break;
case OBJ_BRUSH:
uObjectType = GDI_OBJECT_TYPE_BRUSH;
break;
case OBJ_PAL:
uObjectType = GDI_OBJECT_TYPE_PALETTE;
break;
case OBJ_FONT:
uObjectType = GDI_OBJECT_TYPE_FONT;
break;
case OBJ_BITMAP:
uObjectType = GDI_OBJECT_TYPE_BITMAP;
break;
case OBJ_COLORSPACE:
uObjectType = GDI_OBJECT_TYPE_COLORSPACE;
break;
/* tests show that OBJ_REGION is explicitly ignored */
case OBJ_REGION:
return NULL;
/* the SDK only mentions those above */
default:
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
/* Get the dc attribute */
pdcattr = GdiGetDcAttr(hdc);
if (!pdcattr) return NULL;
}
return GetDCObject(hdc, uObjectType);
/* Check what object was requested */
switch (uObjectType)
{
case OBJ_EXTPEN:
case OBJ_PEN:
return pdcattr->hpen;
case OBJ_BRUSH:
return pdcattr->hbrush;
case OBJ_COLORSPACE:
return pdcattr->hColorSpace;
case OBJ_PAL:
uObjectType = GDI_OBJECT_TYPE_PALETTE;
break;
case OBJ_FONT:
uObjectType = GDI_OBJECT_TYPE_FONT;
break;
case OBJ_BITMAP:
uObjectType = GDI_OBJECT_TYPE_BITMAP;
break;
/* All others are invalid */
default:
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Pass the request to win32k */
return NtGdiGetDCObject(hdc, uObjectType);
}
/*
@ -774,8 +753,7 @@ GetDCOrgEx(
LONG
WINAPI
GetDCOrg(
HDC hdc
)
HDC hdc)
{
// Officially obsolete by Microsoft
POINT Pt;
@ -784,117 +762,86 @@ GetDCOrg(
return(MAKELONG(Pt.x, Pt.y));
}
int
GetNonFontObject(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
{
INT dwType;
hGdiObj = (HANDLE)GdiFixUpHandle(hGdiObj);
dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
if (!lpBuffer) // Should pass it all to Win32k and let god sort it out. ;^)
{
switch(dwType)
{
case GDI_OBJECT_TYPE_PEN:
return sizeof(LOGPEN);
case GDI_OBJECT_TYPE_BRUSH:
return sizeof(LOGBRUSH);
case GDI_OBJECT_TYPE_BITMAP:
return sizeof(BITMAP);
case GDI_OBJECT_TYPE_PALETTE:
return sizeof(WORD);
case GDI_OBJECT_TYPE_EXTPEN: /* we don't know the size, ask win32k */
break;
}
}
switch(dwType)
{
case GDI_OBJECT_TYPE_PEN: //Check the structures and see if A & W are the same.
case GDI_OBJECT_TYPE_EXTPEN:
case GDI_OBJECT_TYPE_BRUSH: // Mixing Apples and Oranges?
case GDI_OBJECT_TYPE_BITMAP:
case GDI_OBJECT_TYPE_PALETTE:
return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
case GDI_OBJECT_TYPE_DC:
case GDI_OBJECT_TYPE_REGION:
case GDI_OBJECT_TYPE_METAFILE:
case GDI_OBJECT_TYPE_ENHMETAFILE:
case GDI_OBJECT_TYPE_EMF:
SetLastError(ERROR_INVALID_HANDLE);
}
return 0;
}
/*
* @implemented
*/
int
ULONG
WINAPI
GetObjectA(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
GetFontObjectW(HGDIOBJ hfont, ULONG cbSize, LPVOID lpBuffer)
{
ENUMLOGFONTEXDVW LogFont;
DWORD dwType;
INT Result = 0;
ENUMLOGFONTEXDVW elfedvW;
ULONG cbResult, cbMaxSize;
dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
/* Check if size only is requested */
if (!lpBuffer) return sizeof(LOGFONTW);
if(dwType == GDI_OBJECT_TYPE_COLORSPACE) //Stays here, processes struct A
/* Check for size 0 */
if (cbSize == 0)
{
SetLastError(ERROR_NOT_SUPPORTED);
/* Windows does not SetLastError() */
return 0;
}
if (dwType == GDI_OBJECT_TYPE_FONT)
/* Call win32k to get the logfont (widechar) */
cbResult = NtGdiExtGetObjectW(hfont, sizeof(ENUMLOGFONTEXDVW), &elfedvW);
if (cbResult == 0)
{
if (!lpBuffer)
{
return sizeof(LOGFONTA);
}
if (cbSize == 0)
{
/* Windows does not SetLastError() */
return 0;
}
// ENUMLOGFONTEXDVW is the default size and should be the structure for
// Entry->KernelData for Font objects.
Result = NtGdiExtGetObjectW(hGdiObj, sizeof(ENUMLOGFONTEXDVW), &LogFont);
if (0 == Result)
{
return 0;
}
switch (cbSize)
{
case sizeof(ENUMLOGFONTEXDVA):
// need to move more here.
case sizeof(ENUMLOGFONTEXA):
EnumLogFontExW2A( (LPENUMLOGFONTEXA) lpBuffer, &LogFont.elfEnumLogfontEx );
break;
case sizeof(ENUMLOGFONTA):
// Same here, maybe? Check the structures.
case sizeof(EXTLOGFONTA):
// Same here
case sizeof(LOGFONTA):
LogFontW2A((LPLOGFONTA) lpBuffer, &LogFont.elfEnumLogfontEx.elfLogFont);
break;
default:
SetLastError(ERROR_BUFFER_OVERFLOW);
return 0;
}
return cbSize;
return 0;
}
return GetNonFontObject(hGdiObj, cbSize, lpBuffer);
/* Calculate the maximum size according to number of axes */
cbMaxSize = FIELD_OFFSET(ENUMLOGFONTEXDVW,
elfDesignVector.dvValues[elfedvW.elfDesignVector.dvNumAxes]);
/* Don't copy more than the maximum */
if (cbSize > cbMaxSize) cbSize = cbMaxSize;
if (cbSize > cbResult) cbSize = cbResult;
/* Copy the number of bytes requested */
memcpy(lpBuffer, &elfedvW, cbSize);
/* Return the number of bytes copied */
return cbSize;
}
ULONG
WINAPI
GetFontObjectA(HGDIOBJ hfont, ULONG cbSize, 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
@ -903,47 +850,100 @@ int
WINAPI
GetObjectW(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
{
DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
INT Result = 0;
DWORD dwType;
INT cbResult = 0;
/*
Check List:
MSDN, "This can be a handle to one of the following: logical bitmap, a brush,
a font, a palette, a pen, or a device independent bitmap created by calling
the CreateDIBSection function."
*/
if(dwType == GDI_OBJECT_TYPE_COLORSPACE) //Stays here, processes struct W
hGdiObj = GdiFixUpHandle(hGdiObj);
/* Get the object type */
dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
/* Check what kind of object we have */
switch(dwType)
{
SetLastError(ERROR_NOT_SUPPORTED); // Not supported yet.
return 0;
case GDI_OBJECT_TYPE_PEN:
if (!lpBuffer) return sizeof(LOGPEN);
cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
if (cbResult == 0)
SetLastError(ERROR_INVALID_PARAMETER);
return cbResult;
case GDI_OBJECT_TYPE_BRUSH:
if (!lpBuffer) return sizeof(LOGBRUSH);
cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
if (cbResult == 0)
SetLastError(ERROR_INVALID_PARAMETER);
return cbResult;
case GDI_OBJECT_TYPE_BITMAP:
if (!lpBuffer) return sizeof(BITMAP);
return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
case GDI_OBJECT_TYPE_PALETTE:
if (!lpBuffer) return sizeof(WORD);
return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
case GDI_OBJECT_TYPE_FONT:
return GetFontObjectW(hGdiObj, cbSize, lpBuffer);
case GDI_OBJECT_TYPE_EXTPEN:
/* we don't know the size, ask win32k */
cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
if (cbResult == 0)
{
if (!GdiIsHandleValid(hGdiObj))
SetLastError(ERROR_INVALID_PARAMETER);
else if (cbSize == 0)
SetLastError(ERROR_NOACCESS);
}
return cbResult;
case GDI_OBJECT_TYPE_COLORSPACE:
if ((cbSize < 328) || !lpBuffer)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
if (cbResult == 0)
SetLastError(ERROR_INVALID_PARAMETER);
return cbResult;
case GDI_OBJECT_TYPE_METADC:
return 0;
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;
}
return 0;
}
/*
* @implemented
*/
int
WINAPI
GetObjectA(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
{
DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
/* Chjeck if this is anything else but a font */
if (dwType == GDI_OBJECT_TYPE_FONT)
{
if (!lpBuffer)
{
return sizeof(LOGFONTW);
}
if (cbSize == 0)
{
/* Windows does not SetLastError() */
return 0;
}
// Poorly written apps are not ReactOS problem!
// We fix it here if the size is larger than the default size.
if( cbSize > (int)sizeof(ENUMLOGFONTEXDVW) ) cbSize = sizeof(ENUMLOGFONTEXDVW);
Result = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer); // Should handle the copy.
if (0 == Result)
{
return 0;
}
return cbSize;
return GetFontObjectA(hGdiObj, cbSize, lpBuffer);
}
else
{
/* Simply pass it to the widechar version */
return GetObjectW(hGdiObj, cbSize, lpBuffer);
}
return GetNonFontObject(hGdiObj, cbSize, lpBuffer);
}

View file

@ -88,8 +88,8 @@ FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
}
ptmA->tmDefaultChar = ptmW->tmDefaultChar;
ptmA->tmBreakChar = ptmW->tmBreakChar;
ptmA->tmDefaultChar = (CHAR)ptmW->tmDefaultChar;
ptmA->tmBreakChar = (CHAR)ptmW->tmBreakChar;
ptmA->tmItalic = ptmW->tmItalic;
ptmA->tmUnderlined = ptmW->tmUnderlined;
ptmA->tmStruckOut = ptmW->tmStruckOut;
@ -503,7 +503,7 @@ NewGetCharacterPlacementW(
DWORD dwFlags
)
{
INT nSet;
ULONG nSet;
SIZE Size = {0,0};
if ( !lpString || uCount <= 0 || (nMaxExtent < 0 && nMaxExtent != -1 ) )
@ -1497,14 +1497,14 @@ CreateFontW(
logfont.lfEscapement = nEscapement;
logfont.lfOrientation = nOrientation;
logfont.lfWeight = nWeight;
logfont.lfItalic = fnItalic;
logfont.lfUnderline = fdwUnderline;
logfont.lfStrikeOut = fdwStrikeOut;
logfont.lfCharSet = fdwCharSet;
logfont.lfOutPrecision = fdwOutputPrecision;
logfont.lfClipPrecision = fdwClipPrecision;
logfont.lfQuality = fdwQuality;
logfont.lfPitchAndFamily = fdwPitchAndFamily;
logfont.lfItalic = (BYTE)fnItalic;
logfont.lfUnderline = (BYTE)fdwUnderline;
logfont.lfStrikeOut = (BYTE)fdwStrikeOut;
logfont.lfCharSet = (BYTE)fdwCharSet;
logfont.lfOutPrecision = (BYTE)fdwOutputPrecision;
logfont.lfClipPrecision = (BYTE)fdwClipPrecision;
logfont.lfQuality = (BYTE)fdwQuality;
logfont.lfPitchAndFamily = (BYTE)fdwPitchAndFamily;
if (NULL != lpszFace)
{

View file

@ -382,7 +382,7 @@ PaintRgn( HDC hDC, HRGN hRgn )
}
#endif
// Could just use Dc_Attr->hbrush? No.
HBRUSH hBrush = (HBRUSH) GetDCObject( hDC, GDI_OBJECT_TYPE_BRUSH);
HBRUSH hBrush = (HBRUSH)GetCurrentObject(hDC, OBJ_BRUSH);
return NtGdiFillRgn( hDC, hRgn, hBrush);
}

View file

@ -145,7 +145,7 @@ RealizePalette(HDC hDC) /* [in] Handle of device context */
return MFDRV_(hDC);
else
{
HPALETTE Pal = GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
HPALETTE Pal = GetCurrentObject(hDC, OBJ_PAL);
PLDC pLDC = GdiGetLDC((HDC) Pal);
if ( !pLDC ) return FALSE;
if (pLDC->iType == LDC_EMFLDC) return EMFDRV_(Pal);

View file

@ -461,7 +461,6 @@ NtGdiGetDCObject(HDC hDC, INT ObjectType)
if(!(pdc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
pdcattr = pdc->pdcattr;

View file

@ -74,7 +74,7 @@ GreGetKerningPairs(
}
/*
It is recommended that an application use the GetFontLanguageInfo function
to determine whether the GCP_DIACRITIC, GCP_DBCS, GCP_USEKERNING, GCP_LIGATE,
GCP_REORDER, GCP_GLYPHSHAPE, and GCP_KASHIDA values are valid for the
@ -102,7 +102,7 @@ GreGetCharacterPlacementW(
INT *tmpDxCaretPos;
LONG Cx;
SIZE Size = {0,0};
DPRINT1("GreGCPW Start\n");
if (!pgcpw)
@ -126,7 +126,7 @@ GreGetCharacterPlacementW(
if ( !gcpwSave.lpDx && gcpwSave.lpCaretPos )
tmpDxCaretPos = gcpwSave.lpCaretPos;
else
tmpDxCaretPos = gcpwSave.lpDx;
tmpDxCaretPos = gcpwSave.lpDx;
if ( !GreGetTextExtentExW( hdc,
pwsz,
@ -145,7 +145,7 @@ GreGetCharacterPlacementW(
nSet = cSet;
if ( tmpDxCaretPos && nSet > 0)
{
{
for (i = (nSet - 1); i > 0; i--)
{
tmpDxCaretPos[i] -= tmpDxCaretPos[i - 1];
@ -161,7 +161,7 @@ GreGetCharacterPlacementW(
{
DWORD Count;
LPKERNINGPAIR pKP;
Count = GreGetKerningPairs( hdc, 0, NULL);
if (Count)
{
@ -262,41 +262,43 @@ GreGetCharacterPlacementW(
INT
FASTCALL
FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
FontGetObject(PTEXTOBJ TFont, INT cjBuffer, PVOID pvBuffer)
{
if( Buffer == NULL ) return sizeof(LOGFONTW);
if (pvBuffer == NULL) return sizeof(LOGFONTW);
switch (Count)
{
case sizeof(ENUMLOGFONTEXDVW):
RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
&TFont->logfont,
sizeof(ENUMLOGFONTEXDVW));
break;
case sizeof(ENUMLOGFONTEXW):
RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
&TFont->logfont.elfEnumLogfontEx,
sizeof(ENUMLOGFONTEXW));
switch (cjBuffer)
{
case sizeof(ENUMLOGFONTEXDVW):
RtlCopyMemory(pvBuffer,
&TFont->logfont,
sizeof(ENUMLOGFONTEXDVW));
break;
case sizeof(ENUMLOGFONTEXW):
RtlCopyMemory(pvBuffer,
&TFont->logfont.elfEnumLogfontEx,
sizeof(ENUMLOGFONTEXW));
break;
case sizeof(EXTLOGFONTW):
case sizeof(ENUMLOGFONTW):
RtlCopyMemory((LPENUMLOGFONTW) Buffer,
case sizeof(EXTLOGFONTW):
case sizeof(ENUMLOGFONTW):
RtlCopyMemory((LPENUMLOGFONTW) pvBuffer,
&TFont->logfont.elfEnumLogfontEx.elfLogFont,
sizeof(ENUMLOGFONTW));
break;
break;
case sizeof(LOGFONTW):
RtlCopyMemory((LPLOGFONTW) Buffer,
case sizeof(LOGFONTW):
RtlCopyMemory((LPLOGFONTW) pvBuffer,
&TFont->logfont.elfEnumLogfontEx.elfLogFont,
sizeof(LOGFONTW));
break;
break;
default:
EngSetLastError(ERROR_BUFFER_OVERFLOW);
return 0;
}
return Count;
default:
EngSetLastError(ERROR_BUFFER_OVERFLOW);
return 0;
}
return cjBuffer;
}
DWORD
@ -928,7 +930,7 @@ NtGdiGetFontResourceInfoInternalW(
/* Allocate a safe unicode string buffer */
cbStringSize = cwc * sizeof(WCHAR);
SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
SafeFileNames.MaximumLength = SafeFileNames.Length = (USHORT)cbStringSize - sizeof(WCHAR);
SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
cbStringSize,
'RTSU');

View file

@ -1021,7 +1021,6 @@ GreGetObject(
if (!pvObj)
{
DPRINT("GreGetObject: Could not lock object\n");
EngSetLastError(ERROR_INVALID_HANDLE);
return 0;
}