[GDI32][NTGDI][SETUP] Fix font enumeration part 2 (#1492)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Thu, 11 Apr 2019 02:46:52 +0000 (11:46 +0900)
committerGitHub <noreply@github.com>
Thu, 11 Apr 2019 02:46:52 +0000 (11:46 +0900)
Eliminate some bugs about font enumeration. CORE-15755

- Add "Microsoft Sans Serif" font substitution.
- Fix and improve the treatment of the nominal font names.
- Split IntGetFontFamilyInfo function from NtGdiGetFontFamilyInfo.
- Add DoFontSystemUnittest function for font system unittest to GDI32.
- Call DoFontSystemUnittest function at CreateFontIndirectW first call.

base/setup/lib/muifonts.h
boot/bootdata/livecd.inf
win32ss/gdi/gdi32/objects/font.c
win32ss/gdi/ntgdi/freetype.c
win32ss/include/ntgdibad.h

index 72292af..826d512 100644 (file)
@@ -11,6 +11,7 @@ MUI_SUBFONT LatinFonts[] =
     { L"Helv",                   L"Tahoma" },
     { L"Helvetica",              L"Liberation Sans" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Tahoma" },
     { L"MS Sans Serif",          L"Tahoma" },
     { L"MS Shell Dlg",           L"Tahoma" },
     { L"MS Shell Dlg 2",         L"Tahoma" },
@@ -37,6 +38,7 @@ MUI_SUBFONT CyrillicFonts[] =
     { L"Helv",                   L"Tahoma" },
     { L"Helvetica",              L"Liberation Sans" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Tahoma" },
     { L"MS Sans Serif",          L"Tahoma" },
     { L"MS Shell Dlg",           L"Tahoma" },
     { L"MS Shell Dlg 2",         L"Tahoma" },
@@ -63,6 +65,7 @@ MUI_SUBFONT GreekFonts[] =
     { L"Helv",                   L"DejaVu Sans" },
     { L"Helvetica",              L"Liberation Sans" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"DejaVu Sans" },
     { L"MS Sans Serif",          L"DejaVu Sans" },
     { L"MS Shell Dlg",           L"DejaVu Sans" },
     { L"MS Shell Dlg 2",         L"DejaVu Sans" },
@@ -89,6 +92,7 @@ MUI_SUBFONT HebrewFonts[] =
     { L"Helv",                   L"Tahoma" },
     { L"Helvetica",              L"Tahoma" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Tahoma" },
     { L"MS Sans Serif",          L"Tahoma" },
     { L"MS Shell Dlg",           L"Tahoma" },
     { L"MS Shell Dlg 2",         L"Tahoma" },
@@ -121,6 +125,7 @@ MUI_SUBFONT ChineseSimplifiedFonts[] =
     { L"Helv",                   L"Droid Sans Fallback" },
     { L"Helvetica",              L"Liberation Sans" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Sans Serif",          L"Droid Sans Fallback" },
     { L"MS Shell Dlg",           L"Droid Sans Fallback" },
     { L"MS Shell Dlg 2",         L"Droid Sans Fallback" },
@@ -163,6 +168,7 @@ MUI_SUBFONT ChineseTraditionalFonts[] =
     { L"Helv",            L"Droid Sans Fallback" },
     { L"Helvetica",       L"Liberation Sans" },
     { L"Lucida Console",  L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Shell Dlg",    L"Droid Sans Fallback" },
     { L"MS Shell Dlg 2",  L"Droid Sans Fallback" },
@@ -206,6 +212,7 @@ MUI_SUBFONT JapaneseFonts[] =
     { L"Helv",            L"Droid Sans Fallback" },
     { L"Helvetica",       L"Liberation Sans" },
     { L"Lucida Console",  L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Shell Dlg",    L"Droid Sans Fallback" },
     { L"MS Shell Dlg 2",  L"Droid Sans Fallback" },
@@ -250,6 +257,7 @@ MUI_SUBFONT KoreanFonts[] =
     { L"Helv",            L"Droid Sans Fallback" },
     { L"Helvetica",       L"Liberation Sans" },
     { L"Lucida Console",  L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Sans Serif",   L"Droid Sans Fallback" },
     { L"MS Shell Dlg",    L"Droid Sans Fallback" },
     { L"MS Shell Dlg 2",  L"Droid Sans Fallback" },
@@ -293,6 +301,7 @@ MUI_SUBFONT UnicodeFonts[] =
     { L"Helv",                   L"DejaVu Sans" },
     { L"Helvetica",              L"DejaVu Sans" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"DejaVu Sans" },
     { L"MS Sans Serif",          L"DejaVu Sans" },
     { L"MS Shell Dlg",           L"DejaVu Sans" },
     { L"MS Shell Dlg 2",         L"DejaVu Sans" },
@@ -320,6 +329,7 @@ MUI_SUBFONT HindiFonts[] =
     { L"Helv",                   L"Tahoma" },
     { L"Helvetica",              L"Liberation Sans" },
     { L"Lucida Console",         L"DejaVu Sans Mono" },
+    { L"Microsoft Sans Serif",   L"FreeSans" },
     { L"MS Sans Serif",          L"FreeSans" },
     { L"MS Shell Dlg",           L"FreeSans" },
     { L"MS Shell Dlg 2",         L"FreeSans" },
index fda2356..dd44f0e 100644 (file)
@@ -50,6 +50,7 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Fixedsys",0
 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helv",0x00000000,"Tahoma"
 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helvetica",0x00000000,"Liberation Sans"
 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Lucida Console",0x00000000,"DejaVu Sans Mono"
+HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Microsoft Sans Serif",0x00000000,"Tahoma"
 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Sans Serif",0x00000000,"Tahoma"
 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg",0x00000000,"Tahoma"
 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg 2",0x00000000,"Tahoma"
index 2f187b0..e20c070 100644 (file)
@@ -218,6 +218,13 @@ IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
     int cmp = _wcsicmp(plf1->lfFaceName, plf2->lfFaceName);
     if (cmp)
         return cmp;
+    if (dwCompareFlags & IFFCX_CHARSET)
+    {
+        if (plf1->lfCharSet < plf2->lfCharSet)
+            return -1;
+        if (plf1->lfCharSet > plf2->lfCharSet)
+            return 1;
+    }
     if (dwCompareFlags & IFFCX_STYLE)
     {
         WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL);
@@ -231,13 +238,6 @@ IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
         if (plf1->lfItalic > plf2->lfItalic)
             return 1;
     }
-    if (dwCompareFlags & IFFCX_CHARSET)
-    {
-        if (plf1->lfCharSet < plf2->lfCharSet)
-            return -1;
-        if (plf1->lfCharSet > plf2->lfCharSet)
-            return 1;
-    }
     return 0;
 }
 
@@ -267,7 +267,7 @@ IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
     first = InfoList;
     last = &InfoList[nCount];
 
-    // std::unique(first, last, IntFontFamilyCompareEx);
+    /* std::unique(first, last, IntFontFamilyCompareEx); */
     if (first == last)
         return 0;
 
@@ -285,60 +285,70 @@ IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
 }
 
 static int FASTCALL
-IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
+IntEnumFontFamilies(HDC Dc, const LOGFONTW *LogFont, PVOID EnumProc, LPARAM lParam,
                     DWORD dwFlags)
 {
     int FontFamilyCount;
-    int FontFamilySize;
     PFONTFAMILYINFO Info;
     int Ret = 1;
     int i;
     ENUMLOGFONTEXA EnumLogFontExA;
     NEWTEXTMETRICEXA NewTextMetricExA;
     LOGFONTW lfW;
+    LONG DataSize, InfoCount;
 
-    Info = RtlAllocateHeap(GetProcessHeap(), 0,
-                           INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO));
-    if (NULL == Info)
+    DataSize = INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO);
+    Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
+    if (Info == NULL)
     {
         return 1;
     }
 
+    /* Initialize the LOGFONT structure */
+    ZeroMemory(&lfW, sizeof(lfW));
     if (!LogFont)
     {
         lfW.lfCharSet = DEFAULT_CHARSET;
-        lfW.lfPitchAndFamily = 0;
-        lfW.lfFaceName[0] = 0;
-        LogFont = &lfW;
+    }
+    else
+    {
+        lfW.lfCharSet = LogFont->lfCharSet;
+        lfW.lfPitchAndFamily = LogFont->lfPitchAndFamily;
+        StringCbCopyW(lfW.lfFaceName, sizeof(lfW.lfFaceName), LogFont->lfFaceName);
     }
 
-    FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT);
+    /* Retrieve the font information */
+    InfoCount = INITIAL_FAMILY_COUNT;
+    FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
     if (FontFamilyCount < 0)
     {
         RtlFreeHeap(GetProcessHeap(), 0, Info);
         return 1;
     }
-    if (INITIAL_FAMILY_COUNT < FontFamilyCount)
+
+    /* Resize the buffer if the buffer is too small */
+    if (INITIAL_FAMILY_COUNT < InfoCount)
     {
-        FontFamilySize = FontFamilyCount;
         RtlFreeHeap(GetProcessHeap(), 0, Info);
-        Info = RtlAllocateHeap(GetProcessHeap(), 0,
-                               FontFamilyCount * sizeof(FONTFAMILYINFO));
-        if (NULL == Info)
+        DataSize = InfoCount * sizeof(FONTFAMILYINFO);
+        Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
+        if (Info == NULL)
         {
             return 1;
         }
-        FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize);
-        if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount)
+        FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
+        if (FontFamilyCount < 0 || FontFamilyCount < InfoCount)
         {
             RtlFreeHeap(GetProcessHeap(), 0, Info);
             return 1;
         }
     }
 
+    /* Sort and remove redundant information */
     qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare);
-    FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, LogFont, dwFlags);
+    FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, &lfW, dwFlags);
 
+    /* call the callback */
     for (i = 0; i < FontFamilyCount; i++)
     {
         if (dwFlags & IEFF_UNICODE)
@@ -1693,6 +1703,78 @@ CreateFontIndirectA(
 }
 
 
+#if DBG
+VOID DumpFamilyInfo(const FONTFAMILYINFO *Info, LONG Count)
+{
+    LONG i;
+    const LOGFONTW *plf;
+
+    DPRINT1("---\n");
+    DPRINT1("Count: %d\n", Count);
+    for (i = 0; i < Count; ++i)
+    {
+        plf = &Info[i].EnumLogFontEx.elfLogFont;
+        DPRINT1("%d: '%S',%u,'%S', %ld:%ld, %ld, %d, %d\n", i,
+            plf->lfFaceName, plf->lfCharSet, Info[i].EnumLogFontEx.elfFullName,
+            plf->lfHeight, plf->lfWidth, plf->lfWeight, plf->lfItalic, plf->lfPitchAndFamily);
+    }
+}
+
+VOID DoFontSystemUnittest(VOID)
+{
+    LOGFONTW LogFont;
+    FONTFAMILYINFO Info[4];
+    UNICODE_STRING Str1, Str2;
+    LONG ret, InfoCount;
+
+    //DumpFontInfo(TRUE);
+
+    /* L"" DEFAULT_CHARSET */
+    RtlZeroMemory(&LogFont, sizeof(LogFont));
+    LogFont.lfCharSet = DEFAULT_CHARSET;
+    InfoCount = RTL_NUMBER_OF(Info);
+    ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
+    DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
+    DumpFamilyInfo(Info, ret);
+    ASSERT(ret == RTL_NUMBER_OF(Info));
+    ASSERT(InfoCount > 32);
+
+    /* L"Microsoft Sans Serif" ANSI_CHARSET */
+    RtlZeroMemory(&LogFont, sizeof(LogFont));
+    LogFont.lfCharSet = ANSI_CHARSET;
+    StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Microsoft Sans Serif");
+    InfoCount = RTL_NUMBER_OF(Info);
+    ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
+    DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
+    DumpFamilyInfo(Info, ret);
+    ASSERT(ret != -1);
+    ASSERT(InfoCount > 0);
+    ASSERT(InfoCount < 16);
+
+    RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfLogFont.lfFaceName);
+    RtlInitUnicodeString(&Str2, L"Microsoft Sans Serif");
+    ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE);
+    ASSERT(ret == 0);
+
+    RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfFullName);
+    RtlInitUnicodeString(&Str2, L"Tahoma");
+    ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE);
+    ASSERT(ret == 0);
+
+    /* L"Non-Existent" DEFAULT_CHARSET */
+    RtlZeroMemory(&LogFont, sizeof(LogFont));
+    LogFont.lfCharSet = ANSI_CHARSET;
+    StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Non-Existent");
+    InfoCount = RTL_NUMBER_OF(Info);
+    ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
+    DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
+    DumpFamilyInfo(Info, ret);
+    ASSERT(ret == 0);
+    ASSERT(InfoCount == 0);
+}
+#endif
+
+/* EOF */
 /*
  * @implemented
  */
@@ -1702,6 +1784,14 @@ CreateFontIndirectW(
     CONST LOGFONTW             *lplf
 )
 {
+#if DBG
+    static BOOL bDidTest = FALSE;
+    if (!bDidTest)
+    {
+        DoFontSystemUnittest();
+        bDidTest = TRUE;
+    }
+#endif
     if (lplf)
     {
         ENUMLOGFONTEXDVW Logfont;
index a5f93e9..298c1fa 100644 (file)
@@ -2675,18 +2675,18 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, LPCWSTR FaceName,
 }
 
 static BOOLEAN FASTCALL
-GetFontFamilyInfoForList(LPLOGFONTW LogFont,
+GetFontFamilyInfoForList(const LOGFONTW *LogFont,
                          PFONTFAMILYINFO Info,
                          LPCWSTR NominalName,
-                         DWORD *pCount,
-                         DWORD MaxCount,
+                         LONG *pCount,
+                         LONG MaxCount,
                          PLIST_ENTRY Head)
 {
     PLIST_ENTRY Entry;
     PFONT_ENTRY CurrentEntry;
     FONTGDI *FontGDI;
     FONTFAMILYINFO InfoEntry;
-    DWORD Count = *pCount;
+    LONG Count = *pCount;
 
     for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
     {
@@ -2697,29 +2697,15 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
         if (LogFont->lfCharSet != DEFAULT_CHARSET &&
             LogFont->lfCharSet != FontGDI->CharSet)
         {
-            continue;
-        }
-
-        if (LogFont->lfFaceName[0] == UNICODE_NULL)
-        {
-            if (Count < MaxCount)
-            {
-                FontFamilyFillInfo(&Info[Count], NominalName, NULL, FontGDI);
-            }
-            Count++;
-            continue;
+            continue;   /* charset mismatch */
         }
 
-        FontFamilyFillInfo(&InfoEntry, NominalName, NULL, FontGDI);
+        /* get one info entry */
+        FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI);
 
-        if (NominalName)
-        {
-            RtlStringCchCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
-                              RTL_NUMBER_OF(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
-                              NominalName);
-        }
-        else
+        if (LogFont->lfFaceName[0] != UNICODE_NULL)
         {
+            /* check name */
             if (_wcsnicmp(LogFont->lfFaceName,
                           InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
                           RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 &&
@@ -2731,7 +2717,16 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
             }
         }
 
-        if (Count < MaxCount)
+        if (NominalName)
+        {
+            /* store the nominal name */
+            RtlStringCbCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
+                             sizeof(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
+                             NominalName);
+        }
+
+        /* store one entry to Info */
+        if (0 <= Count && Count < MaxCount)
         {
             RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
         }
@@ -2744,10 +2739,10 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
 }
 
 static BOOLEAN FASTCALL
-GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
+GetFontFamilyInfoForSubstitutes(const LOGFONTW *LogFont,
                                 PFONTFAMILYINFO Info,
-                                DWORD *pCount,
-                                DWORD MaxCount)
+                                LONG *pCount,
+                                LONG MaxCount)
 {
     PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead;
     PFONTSUBST_ENTRY pCurrentEntry;
@@ -2762,6 +2757,7 @@ GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
         pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM];
         if (LogFont->lfFaceName[0] != UNICODE_NULL)
         {
+            /* check name */
             if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0)
                 continue;   /* mismatch */
         }
@@ -2771,18 +2767,22 @@ GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
             pCurrentEntry->CharSets[FONTSUBST_FROM] ==
             pCurrentEntry->CharSets[FONTSUBST_TO])
         {
+            /* identical mapping */
             continue;
         }
 
+        /* substitute and get the real name */
         IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW);
         SubstituteFontRecurse(&lf);
         if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet != lf.lfCharSet)
             continue;
 
+        /* search in global fonts */
         IntLockGlobalFonts();
         GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, &g_FontListHead);
         IntUnLockGlobalFonts();
 
+        /* search in private fonts */
         IntLockProcessPrivateFonts(Win32Process);
         GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
                                  &Win32Process->PrivateFontListHead);
@@ -5407,70 +5407,126 @@ ftGdiGetKerningPairs( PFONTGDI Font,
 // Functions needing sorting.
 //
 ///////////////////////////////////////////////////////////////////////////
-int APIENTRY
+
+LONG FASTCALL
+IntGetFontFamilyInfo(HDC Dc,
+                     const LOGFONTW *SafeLogFont,
+                     PFONTFAMILYINFO SafeInfo,
+                     LONG InfoCount)
+{
+    LONG AvailCount = 0;
+    PPROCESSINFO Win32Process;
+
+    /* Enumerate font families in the global list */
+    IntLockGlobalFonts();
+    if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount,
+                                  InfoCount, &g_FontListHead))
+    {
+        IntUnLockGlobalFonts();
+        return -1;
+    }
+    IntUnLockGlobalFonts();
+
+    /* Enumerate font families in the process local list */
+    Win32Process = PsGetCurrentProcessWin32Process();
+    IntLockProcessPrivateFonts(Win32Process);
+    if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, InfoCount,
+                                  &Win32Process->PrivateFontListHead))
+    {
+        IntUnLockProcessPrivateFonts(Win32Process);
+        return -1;
+    }
+    IntUnLockProcessPrivateFonts(Win32Process);
+
+    /* Enumerate font families in the registry */
+    if (!GetFontFamilyInfoForSubstitutes(SafeLogFont, SafeInfo, &AvailCount, InfoCount))
+    {
+        return -1;
+    }
+
+    return AvailCount;
+}
+
+LONG NTAPI
 NtGdiGetFontFamilyInfo(HDC Dc,
-                       LPLOGFONTW UnsafeLogFont,
+                       const LOGFONTW *UnsafeLogFont,
                        PFONTFAMILYINFO UnsafeInfo,
-                       DWORD Size)
+                       LPLONG UnsafeInfoCount)
 {
     NTSTATUS Status;
     LOGFONTW LogFont;
     PFONTFAMILYINFO Info;
-    DWORD Count;
-    PPROCESSINFO Win32Process;
+    LONG GotCount, AvailCount, DataSize, SafeInfoCount;
 
-    /* Make a safe copy */
-    Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
-    if (! NT_SUCCESS(Status))
+    if (UnsafeLogFont == NULL || UnsafeInfo == NULL || UnsafeInfoCount == NULL)
     {
         EngSetLastError(ERROR_INVALID_PARAMETER);
         return -1;
     }
 
-    /* Allocate space for a safe copy */
-    Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), GDITAG_TEXT);
-    if (NULL == Info)
+    Status = MmCopyFromCaller(&SafeInfoCount, UnsafeInfoCount, sizeof(SafeInfoCount));
+    if (!NT_SUCCESS(Status))
     {
-        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return -1;
     }
-
-    /* Enumerate font families in the global list */
-    IntLockGlobalFonts();
-    Count = 0;
-    if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size, &g_FontListHead) )
+    GotCount = 0;
+    Status = MmCopyToCaller(UnsafeInfoCount, &GotCount, sizeof(*UnsafeInfoCount));
+    if (!NT_SUCCESS(Status))
     {
-        IntUnLockGlobalFonts();
-        ExFreePoolWithTag(Info, GDITAG_TEXT);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return -1;
     }
-    IntUnLockGlobalFonts();
-
-    /* Enumerate font families in the process local list */
-    Win32Process = PsGetCurrentProcessWin32Process();
-    IntLockProcessPrivateFonts(Win32Process);
-    if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size,
-                                   &Win32Process->PrivateFontListHead))
+    Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
+    if (!NT_SUCCESS(Status))
     {
-        IntUnLockProcessPrivateFonts(Win32Process);
-        ExFreePoolWithTag(Info, GDITAG_TEXT);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
+        return -1;
+    }
+    if (SafeInfoCount <= 0)
+    {
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return -1;
     }
-    IntUnLockProcessPrivateFonts(Win32Process);
 
-    /* Enumerate font families in the registry */
-    if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size))
+    /* Allocate space for a safe copy */
+    DataSize = SafeInfoCount * sizeof(FONTFAMILYINFO);
+    if (DataSize <= 0)
+    {
+        EngSetLastError(ERROR_INVALID_PARAMETER);
+        return -1;
+    }
+    Info = ExAllocatePoolWithTag(PagedPool, DataSize, GDITAG_TEXT);
+    if (Info == NULL)
     {
-        ExFreePoolWithTag(Info, GDITAG_TEXT);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return -1;
     }
 
+    /* Retrieve the information */
+    AvailCount = IntGetFontFamilyInfo(Dc, &LogFont, Info, SafeInfoCount);
+    GotCount = min(AvailCount, SafeInfoCount);
+    SafeInfoCount = AvailCount;
+
     /* Return data to caller */
-    if (0 != Count)
+    if (GotCount > 0)
     {
-        Status = MmCopyToCaller(UnsafeInfo, Info,
-                                (Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO));
-        if (! NT_SUCCESS(Status))
+        DataSize = GotCount * sizeof(FONTFAMILYINFO);
+        if (DataSize <= 0)
+        {
+            ExFreePoolWithTag(Info, GDITAG_TEXT);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
+            return -1;
+        }
+        Status = MmCopyToCaller(UnsafeInfo, Info, DataSize);
+        if (!NT_SUCCESS(Status))
+        {
+            ExFreePoolWithTag(Info, GDITAG_TEXT);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
+            return -1;
+        }
+        Status = MmCopyToCaller(UnsafeInfoCount, &SafeInfoCount, sizeof(*UnsafeInfoCount));
+        if (!NT_SUCCESS(Status))
         {
             ExFreePoolWithTag(Info, GDITAG_TEXT);
             EngSetLastError(ERROR_INVALID_PARAMETER);
@@ -5480,7 +5536,7 @@ NtGdiGetFontFamilyInfo(HDC Dc,
 
     ExFreePoolWithTag(Info, GDITAG_TEXT);
 
-    return Count;
+    return GotCount;
 }
 
 FORCEINLINE
@@ -6618,7 +6674,7 @@ NtGdiGetCharABCWidthsW(
     if(Safepwch)
         ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
 
-    if (! NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
         SetLastNtError(Status);
         return FALSE;
index ba8588f..58d644e 100644 (file)
@@ -50,14 +50,13 @@ typedef struct tagFONTFAMILYINFO
 } FONTFAMILYINFO, *PFONTFAMILYINFO;
 
 /* Should be using NtGdiEnumFontChunk */
-INT
+LONG
 NTAPI
 NtGdiGetFontFamilyInfo(
     HDC Dc,
-    LPLOGFONTW LogFont,
+    const LOGFONTW *LogFont,
     PFONTFAMILYINFO Info,
-    DWORD Size
-);
+    LPLONG UnsafeInfoCount);
 
 /* Use NtGdiGetDCPoint with GdiGetViewPortExt */
 BOOL APIENTRY  NtGdiGetViewportExtEx(HDC  hDC, LPSIZE viewportExt);