[NtGDI]
[reactos.git] / reactos / win32ss / gdi / ntgdi / freetype.c
index 86f3ae8..85eae03 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * PROJECT:         ReactOS win32 kernel mode subsystem
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            subsystems/win32/win32k/objects/freetype.c
+ * FILE:            win32ss/gdi/ntgdi/freetype.c
  * PURPOSE:         FreeType font engine interface
  * PROGRAMMER:      Copyright 2001 Huw D M Davies for CodeWeavers.
  *                  Copyright 2006 Dmitry Timoshkov for CodeWeavers.
 
 #include FT_GLYPH_H
 #include FT_TYPE1_TABLES_H
-#include <tttables.h>
-#include <fttrigon.h>
-#include <ftbitmap.h>
-#include <ftoutln.h>
-#include <ftwinfnt.h>
+#include FT_TRUETYPE_TABLES_H
+#include FT_TRIGONOMETRY_H
+#include FT_BITMAP_H
+#include FT_OUTLINE_H
+#include FT_WINFONTS_H
 
 #include <gdi/eng/floatobj.h>
 
        ((DWORD)(BYTE)(ch2) << 8) | (DWORD)(BYTE)(ch3) )
 #endif
 
+extern const MATRIX gmxWorldToDeviceDefault;
+extern const MATRIX gmxWorldToPageDefault;
+
+// HACK!! Fix XFORMOBJ then use 1:16 / 16:1
+#define gmxWorldToDeviceDefault gmxWorldToPageDefault
+
 FT_Library  library;
 
 typedef struct _FONT_ENTRY
@@ -153,8 +159,17 @@ InitFontSupport(VOID)
     FontCacheNumEntries = 0;
     /* Fast Mutexes must be allocated from non paged pool */
     FontListLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_INTERNAL_SYNC);
+    if (FontListLock == NULL)
+    {
+        return FALSE;
+    }
+
     ExInitializeFastMutex(FontListLock);
     FreeTypeLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_INTERNAL_SYNC);
+    if (FreeTypeLock == NULL)
+    {
+        return FALSE;
+    }
     ExInitializeFastMutex(FreeTypeLock);
 
     ulError = FT_Init_FreeType(&library);
@@ -223,7 +238,7 @@ IntLoadSystemFonts(VOID)
     InitializeObjectAttributes(
         &ObjectAttributes,
         &Directory,
-        OBJ_CASE_INSENSITIVE,
+        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
         NULL,
         NULL);
 
@@ -417,7 +432,15 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
     Entry->Font = FontGDI;
     Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
     RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name);
-    RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+    Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
+        EngFreeMem(FontGDI);
+        FT_Done_Face(Face);
+        ExFreePoolWithTag(Entry, TAG_FONT);
+        return 0;
+    }
 
     if (Characteristics & FR_PRIVATE)
     {
@@ -430,7 +453,7 @@ IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
     {
         IntLockGlobalFonts;
         InsertTailList(&FontListHead, &Entry->ListEntry);
-        InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+        InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
         Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
         if (NT_SUCCESS(Status))
         {
@@ -471,6 +494,7 @@ IntGetFontRenderMode(LOGFONTW *logfont)
 {
     switch (logfont->lfQuality)
     {
+    case ANTIALIASED_QUALITY:
     case NONANTIALIASED_QUALITY:
         return FT_RENDER_MODE_MONO;
     case DRAFT_QUALITY:
@@ -786,14 +810,24 @@ IntGetOutlineTextMetrics(PFONTGDI FontGDI,
     FT_WinFNT_HeaderRec Win;
     FT_Error Error;
     char *Cp;
+    NTSTATUS status;
 
     Needed = sizeof(OUTLINETEXTMETRICW);
 
     RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name);
-    RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+    status = RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+    if (!NT_SUCCESS(status))
+    {
+        return 0;
+    }
 
     RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name);
-    RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+    status = RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+    if (!NT_SUCCESS(status))
+    {
+        RtlFreeUnicodeString(&FamilyNameW);
+        return 0;
+    }
 
     /* These names should be read from the TT name table */
 
@@ -939,6 +973,7 @@ FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head)
     ANSI_STRING EntryFaceNameA;
     UNICODE_STRING EntryFaceNameW;
     FONTGDI *FontGDI;
+    NTSTATUS status;
 
     Entry = Head->Flink;
     while (Entry != Head)
@@ -949,7 +984,12 @@ FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head)
         ASSERT(FontGDI);
 
         RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
-        RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+        status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+        if (!NT_SUCCESS(status))
+        {
+            break;
+        }
+
         if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
         {
             EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
@@ -1007,6 +1047,7 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI)
     TEXTMETRICW *TM;
     NEWTEXTMETRICW *Ntm;
     DWORD fs0;
+    NTSTATUS status;
 
     RtlZeroMemory(Info, sizeof(FONTFAMILYINFO));
     Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
@@ -1078,7 +1119,11 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, PCWSTR FaceName, PFONTGDI FontGDI)
     RtlInitAnsiString(&StyleA, FontGDI->face->style_name);
     StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
     StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
-    RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
+    status = RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
+    if (!NT_SUCCESS(status))
+    {
+        return;
+    }
 
     Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET;
     Info->EnumLogFontEx.elfScript[0] = L'\0';
@@ -1192,6 +1237,7 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
     ANSI_STRING EntryFaceNameA;
     UNICODE_STRING EntryFaceNameW;
     FONTGDI *FontGDI;
+    NTSTATUS status;
 
     Entry = Head->Flink;
     while (Entry != Head)
@@ -1202,7 +1248,12 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
         ASSERT(FontGDI);
 
         RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
-        RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+        status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+        if (!NT_SUCCESS(status))
+        {
+            return FALSE;
+        }
+
         if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
         {
             EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
@@ -1232,6 +1283,7 @@ typedef struct FontFamilyInfoCallbackContext
     DWORD Size;
 } FONT_FAMILY_INFO_CALLBACK_CONTEXT, *PFONT_FAMILY_INFO_CALLBACK_CONTEXT;
 
+_Function_class_(RTL_QUERY_REGISTRY_ROUTINE)
 static NTSTATUS APIENTRY
 FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType,
                                     IN PVOID ValueData, IN ULONG ValueLength,
@@ -1463,9 +1515,7 @@ ftGdiGlyphCacheSet(
 }
 
 
-static
-void
-FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
+static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
 {
     pt->x.value = vec->x >> 6;
     pt->x.fract = (vec->x & 0x3f) << 10;
@@ -1473,7 +1523,6 @@ FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
     pt->y.value = vec->y >> 6;
     pt->y.fract = (vec->y & 0x3f) << 10;
     pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
-    return;
 }
 
 /*
@@ -1779,7 +1828,7 @@ ftGdiGetGlyphOutline(
         for (n = 0; n < ft_face->num_charmaps; n++)
         {
             charmap = ft_face->charmaps[n];
-            DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+            DPRINT("Found charmap encoding: %i\n", charmap->encoding);
             if (charmap->encoding != 0)
             {
                 found = charmap;
@@ -1985,11 +2034,11 @@ ftGdiGetGlyphOutline(
 
     IntUnLockFreeType;
 
-    if (pgm) RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
 
     if (iFormat == GGO_METRICS)
     {
         DPRINT("GGO_METRICS Exit!\n");
+        *pgm = gm;
         return 1; /* FIXME */
     }
 
@@ -2008,14 +2057,17 @@ ftGdiGetGlyphOutline(
         needed = pitch * height;
 
         if (!pvBuf || !cjBuf) break;
+        if (!needed) return GDI_ERROR;  /* empty glyph */
+        if (needed > cjBuf)
+            return GDI_ERROR;
 
         switch (ft_face->glyph->format)
         {
         case ft_glyph_format_bitmap:
         {
             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
-            INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
-            INT h = ft_face->glyph->bitmap.rows;
+            INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
+            INT h = min( height, ft_face->glyph->bitmap.rows );
             while (h--)
             {
                 RtlCopyMemory(dst, src, w);
@@ -2063,13 +2115,16 @@ ftGdiGetGlyphOutline(
         needed = pitch * height;
 
         if (!pvBuf || !cjBuf) break;
+        if (!needed) return GDI_ERROR;  /* empty glyph */
+        if (needed > cjBuf)
+            return GDI_ERROR;
 
         switch (ft_face->glyph->format)
         {
         case ft_glyph_format_bitmap:
         {
             BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
-            INT h = ft_face->glyph->bitmap.rows;
+            INT h = min( height, ft_face->glyph->bitmap.rows );
             INT x;
             while (h--)
             {
@@ -2186,6 +2241,7 @@ ftGdiGetGlyphOutline(
     }
 
     DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
+    *pgm = gm;
     return needed;
 }
 
@@ -2230,7 +2286,7 @@ TextIntGetTextExtentPoint(PDC dc,
         for (n = 0; n < face->num_charmaps; n++)
         {
             charmap = face->charmaps[n];
-            DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+            DPRINT("Found charmap encoding: %i\n", charmap->encoding);
             if (charmap->encoding != 0)
             {
                 found = charmap;
@@ -2505,13 +2561,14 @@ ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
         }
     }
     else
-        DPRINT1("Encoding %u not supported\n", face->charmap->encoding);
+        DPRINT1("Encoding %i not supported\n", face->charmap->encoding);
 
     size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
     if (glyphset)
     {
         glyphset->cbThis = size;
         glyphset->cRanges = num_ranges;
+        glyphset->flAccel = 0;
     }
     return size;
 }
@@ -2944,7 +3001,7 @@ IntGetFullFileName(
 
     InitializeObjectAttributes(&ObjectAttributes,
                                FileName,
-                               OBJ_CASE_INSENSITIVE,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
 
@@ -3260,7 +3317,7 @@ GreExtTextOutW(
     IN INT YStart,
     IN UINT fuOptions,
     IN OPTIONAL PRECTL lprc,
-    IN LPWSTR String,
+    IN LPCWSTR String,
     IN INT Count,
     IN OPTIONAL LPINT Dx,
     IN DWORD dwCodePage)
@@ -3352,11 +3409,17 @@ GreExtTextOutW(
         IntLPtoDP(dc, (POINT *)lprc, 2);
     }
 
-    Start.x = XStart;
-    Start.y = YStart;
-    IntLPtoDP(dc, &Start, 1);
+    if(pdcattr->lTextAlign & TA_UPDATECP)
+    {
+        Start.x = pdcattr->ptlCurrent.x;
+        Start.y = pdcattr->ptlCurrent.y;
+    } else {
+        Start.x = XStart;
+        Start.y = YStart;
+        IntLPtoDP(dc, &Start, 1);
+    }
 
-    RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;
+    RealXStart = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6;
     YStart = Start.y + dc->ptlDCOrig.y;
 
     SourcePoint.x = 0;
@@ -3433,7 +3496,7 @@ GreExtTextOutW(
         for (n = 0; n < face->num_charmaps; n++)
         {
             charmap = face->charmaps[n];
-            DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+            DPRINT("Found charmap encoding: %i\n", charmap->encoding);
             if (charmap->encoding != 0)
             {
                 found = charmap;
@@ -3470,16 +3533,27 @@ GreExtTextOutW(
         goto fail;
     }
 
-    pmxWorldToDevice = DC_pmxWorldToDevice(dc);
-    FtSetCoordinateTransform(face, pmxWorldToDevice);
+    if (dc->pdcattr->iGraphicsMode == GM_ADVANCED)
+    {
+        pmxWorldToDevice = DC_pmxWorldToDevice(dc);
+        FtSetCoordinateTransform(face, pmxWorldToDevice);
+
+        fixAscender = ScaleLong(face->size->metrics.ascender, &pmxWorldToDevice->efM22);
+        fixDescender = ScaleLong(face->size->metrics.descender, &pmxWorldToDevice->efM22);
+    }
+    else
+    {
+        pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
+        FtSetCoordinateTransform(face, pmxWorldToDevice);
+
+        fixAscender = face->size->metrics.ascender;
+        fixDescender = face->size->metrics.descender;
+    }
 
     /*
      * Process the vertical alignment and determine the yoff.
      */
 
-    fixAscender = ScaleLong(face->size->metrics.ascender, &pmxWorldToDevice->efM22);
-    fixDescender = ScaleLong(face->size->metrics.descender, &pmxWorldToDevice->efM22);
-
     if (pdcattr->lTextAlign & TA_BASELINE)
         yoff = 0;
     else if (pdcattr->lTextAlign & TA_BOTTOM)
@@ -3498,7 +3572,7 @@ GreExtTextOutW(
     {
         ULONGLONG TextWidth = 0;
         LPCWSTR TempText = String;
-        int Start;
+        int iStart;
 
         /*
          * Calculate width of the text.
@@ -3506,16 +3580,16 @@ GreExtTextOutW(
 
         if (NULL != Dx)
         {
-            Start = Count < 2 ? 0 : Count - 2;
+            iStart = Count < 2 ? 0 : Count - 2;
             TextWidth = Count < 2 ? 0 : (Dx[(Count-2)<<DxShift] << 6);
         }
         else
         {
-            Start = 0;
+            iStart = 0;
         }
-        TempText = String + Start;
+        TempText = String + iStart;
 
-        for (i = Start; i < Count; i++)
+        for (i = iStart; i < Count; i++)
         {
             if (fuOptions & ETO_GLYPH_INDEX)
                 glyph_index = *TempText;
@@ -3775,6 +3849,11 @@ GreExtTextOutW(
 
         String++;
     }
+
+    if (pdcattr->lTextAlign & TA_UPDATECP) {
+        pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x;
+    }
+
     IntUnLockFreeType;
 
     DC_vFinishBlit(dc, NULL) ;
@@ -3818,7 +3897,7 @@ NtGdiExtTextOutW(
     RECTL SafeRect;
     BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
     PVOID Buffer = LocalBuffer;
-    LPWSTR SafeString = NULL;
+    LPCWSTR SafeString = NULL;
     LPINT SafeDx = NULL;
     ULONG BufSize, StringSize, DxSize = 0;
 
@@ -3855,7 +3934,7 @@ NtGdiExtTextOutW(
         _SEH2_TRY
         {
             /* Put the Dx before the String to assure alignment of 4 */
-            SafeString = (LPWSTR)(((ULONG_PTR)Buffer) + DxSize);
+            SafeString = (LPCWSTR)(((ULONG_PTR)Buffer) + DxSize);
 
             /* Probe and copy the string */
             ProbeForRead(UnsafeString, StringSize, 1);
@@ -4301,110 +4380,20 @@ NtGdiGetCharWidthW(
     return TRUE;
 }
 
-DWORD
-FASTCALL
-GreGetGlyphIndicesW(
-    HDC hdc,
-    LPWSTR pwc,
-    INT cwc,
-    LPWORD pgi,
-    DWORD iMode,
-    DWORD Unknown)
-{
-    PDC dc;
-    PDC_ATTR pdcattr;
-    PTEXTOBJ TextObj;
-    PFONTGDI FontGDI;
-    HFONT hFont = 0;
-    OUTLINETEXTMETRICW *potm;
-    INT i;
-    FT_Face face;
-    WCHAR DefChar = 0xffff;
-    PWSTR Buffer = NULL;
-    ULONG Size;
-
-    if ((!pwc) && (!pgi)) return cwc;
-
-    dc = DC_LockDc(hdc);
-    if (!dc)
-    {
-        EngSetLastError(ERROR_INVALID_HANDLE);
-        return GDI_ERROR;
-    }
-    pdcattr = dc->pdcattr;
-    hFont = pdcattr->hlfntNew;
-    TextObj = RealizeFontInit(hFont);
-    DC_UnlockDc(dc);
-    if (!TextObj)
-    {
-        EngSetLastError(ERROR_INVALID_HANDLE);
-        return GDI_ERROR;
-    }
-
-    FontGDI = ObjToGDI(TextObj->Font, FONT);
-    TEXTOBJ_UnlockText(TextObj);
-
-    Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), GDITAG_TEXT);
-    if (!Buffer)
-    {
-        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return GDI_ERROR;
-    }
-
-    if (iMode & GGI_MARK_NONEXISTING_GLYPHS) DefChar = 0x001f;  /* Indicate non existence */
-    else
-    {
-        Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-        potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
-        if (!potm)
-        {
-            EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            cwc = GDI_ERROR;
-            goto ErrorRet;
-        }
-        IntGetOutlineTextMetrics(FontGDI, Size, potm);
-        DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
-        ExFreePoolWithTag(potm, GDITAG_TEXT);
-    }
-
-    IntLockFreeType;
-    face = FontGDI->face;
-
-    for (i = 0; i < cwc; i++)
-    {
-        Buffer[i] = FT_Get_Char_Index(face, pwc[i]);
-        if (Buffer[i] == 0)
-        {
-            if (DefChar == 0xffff && FT_IS_SFNT(face))
-            {
-                TT_OS2 *pOS2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
-                DefChar = (pOS2->usDefaultChar ? FT_Get_Char_Index(face, pOS2->usDefaultChar) : 0);
-            }
-            Buffer[i] = DefChar;
-        }
-    }
-
-    IntUnLockFreeType;
-
-    RtlCopyMemory( pgi, Buffer, cwc*sizeof(WORD));
-
-ErrorRet:
-    if (Buffer) ExFreePoolWithTag(Buffer, GDITAG_TEXT);
-    return cwc;
-}
-
 
 /*
 * @implemented
 */
+__kernel_entry
+W32KAPI
 DWORD
 APIENTRY
 NtGdiGetGlyphIndicesW(
-    IN HDC hdc,
-    IN OPTIONAL LPWSTR UnSafepwc,
-    IN INT cwc,
-    OUT OPTIONAL LPWORD UnSafepgi,
-    IN DWORD iMode)
+    _In_ HDC hdc,
+    _In_reads_opt_(cwc) LPCWSTR pwc,
+    _In_ INT cwc,
+    _Out_writes_opt_(cwc) LPWORD pgi,
+    _In_ DWORD iMode)
 {
     PDC dc;
     PDC_ATTR pdcattr;
@@ -4414,18 +4403,24 @@ NtGdiGetGlyphIndicesW(
     NTSTATUS Status = STATUS_SUCCESS;
     OUTLINETEXTMETRICW *potm;
     INT i;
-    FT_Face face;
     WCHAR DefChar = 0xffff;
     PWSTR Buffer = NULL;
     ULONG Size, pwcSize;
     PWSTR Safepwc = NULL;
+    LPCWSTR UnSafepwc = pwc;
+    LPWORD UnSafepgi = pgi;
 
     if ((!UnSafepwc) && (!UnSafepgi)) return cwc;
 
+    if ((UnSafepwc == NULL) || (UnSafepgi == NULL))
+    {
+        DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
+        return -1;
+    }
+
     dc = DC_LockDc(hdc);
     if (!dc)
     {
-        EngSetLastError(ERROR_INVALID_HANDLE);
         return GDI_ERROR;
     }
     pdcattr = dc->pdcattr;
@@ -4434,7 +4429,6 @@ NtGdiGetGlyphIndicesW(
     DC_UnlockDc(dc);
     if (!TextObj)
     {
-        EngSetLastError(ERROR_INVALID_HANDLE);
         return GDI_ERROR;
     }
 
@@ -4444,23 +4438,33 @@ NtGdiGetGlyphIndicesW(
     Buffer = ExAllocatePoolWithTag(PagedPool, cwc*sizeof(WORD), GDITAG_TEXT);
     if (!Buffer)
     {
-        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return GDI_ERROR;
     }
 
-    if (iMode & GGI_MARK_NONEXISTING_GLYPHS) DefChar = 0x001f;  /* Indicate non existence */
+    if (iMode & GGI_MARK_NONEXISTING_GLYPHS)
+    {
+        DefChar = 0xffff;
+    }
     else
     {
-        Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
-        potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
-        if (!potm)
+        if (FT_IS_SFNT(FontGDI->face))
         {
-            Status = ERROR_NOT_ENOUGH_MEMORY;
-            goto ErrorRet;
+            TT_OS2 *pOS2 = FT_Get_Sfnt_Table(FontGDI->face, ft_sfnt_os2);
+            DefChar = (pOS2->usDefaultChar ? FT_Get_Char_Index(FontGDI->face, pOS2->usDefaultChar) : 0);
+        }
+        else
+        {
+            Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
+            potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
+            if (!potm)
+            {
+                cwc = GDI_ERROR;
+                goto ErrorRet;
+            }
+            IntGetOutlineTextMetrics(FontGDI, Size, potm);
+            DefChar = potm->otmTextMetrics.tmDefaultChar;
+            ExFreePoolWithTag(potm, GDITAG_TEXT);
         }
-        IntGetOutlineTextMetrics(FontGDI, Size, potm);
-        DefChar = potm->otmTextMetrics.tmDefaultChar; // May need this.
-        ExFreePoolWithTag(potm, GDITAG_TEXT);
     }
 
     pwcSize = cwc * sizeof(WCHAR);
@@ -4468,8 +4472,8 @@ NtGdiGetGlyphIndicesW(
 
     if (!Safepwc)
     {
-        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return GDI_ERROR;
+        Status = STATUS_NO_MEMORY;
+        goto ErrorRet;
     }
 
     _SEH2_TRY
@@ -4486,17 +4490,10 @@ NtGdiGetGlyphIndicesW(
     if (!NT_SUCCESS(Status)) goto ErrorRet;
 
     IntLockFreeType;
-    face = FontGDI->face;
-
-    if (DefChar == 0xffff && FT_IS_SFNT(face))
-    {
-        TT_OS2 *pOS2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
-        DefChar = (pOS2->usDefaultChar ? FT_Get_Char_Index(face, pOS2->usDefaultChar) : 0);
-    }
 
     for (i = 0; i < cwc; i++)
     {
-        Buffer[i] = FT_Get_Char_Index(face, Safepwc[i]);
+        Buffer[i] = FT_Get_Char_Index(FontGDI->face, Safepwc[i]);
         if (Buffer[i] == 0)
         {
             Buffer[i] = DefChar;
@@ -4518,9 +4515,11 @@ NtGdiGetGlyphIndicesW(
 
 ErrorRet:
     ExFreePoolWithTag(Buffer, GDITAG_TEXT);
-    ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+    if (Safepwc != NULL)
+    {
+        ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+    }
     if (NT_SUCCESS(Status)) return cwc;
-    EngSetLastError(Status);
     return GDI_ERROR;
 }