Reactos

[GDI32][NTGDI][SETUP] Fix font enumeration part 2 (#1492)

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.

authored by

Katayama Hirofumi MZ and committed by
GitHub
811faed4 cfdf36e4

+250 -94
+10
base/setup/lib/muifonts.h
··· 11 11 { L"Helv", L"Tahoma" }, 12 12 { L"Helvetica", L"Liberation Sans" }, 13 13 { L"Lucida Console", L"DejaVu Sans Mono" }, 14 + { L"Microsoft Sans Serif", L"Tahoma" }, 14 15 { L"MS Sans Serif", L"Tahoma" }, 15 16 { L"MS Shell Dlg", L"Tahoma" }, 16 17 { L"MS Shell Dlg 2", L"Tahoma" }, ··· 37 38 { L"Helv", L"Tahoma" }, 38 39 { L"Helvetica", L"Liberation Sans" }, 39 40 { L"Lucida Console", L"DejaVu Sans Mono" }, 41 + { L"Microsoft Sans Serif", L"Tahoma" }, 40 42 { L"MS Sans Serif", L"Tahoma" }, 41 43 { L"MS Shell Dlg", L"Tahoma" }, 42 44 { L"MS Shell Dlg 2", L"Tahoma" }, ··· 63 65 { L"Helv", L"DejaVu Sans" }, 64 66 { L"Helvetica", L"Liberation Sans" }, 65 67 { L"Lucida Console", L"DejaVu Sans Mono" }, 68 + { L"Microsoft Sans Serif", L"DejaVu Sans" }, 66 69 { L"MS Sans Serif", L"DejaVu Sans" }, 67 70 { L"MS Shell Dlg", L"DejaVu Sans" }, 68 71 { L"MS Shell Dlg 2", L"DejaVu Sans" }, ··· 89 92 { L"Helv", L"Tahoma" }, 90 93 { L"Helvetica", L"Tahoma" }, 91 94 { L"Lucida Console", L"DejaVu Sans Mono" }, 95 + { L"Microsoft Sans Serif", L"Tahoma" }, 92 96 { L"MS Sans Serif", L"Tahoma" }, 93 97 { L"MS Shell Dlg", L"Tahoma" }, 94 98 { L"MS Shell Dlg 2", L"Tahoma" }, ··· 121 125 { L"Helv", L"Droid Sans Fallback" }, 122 126 { L"Helvetica", L"Liberation Sans" }, 123 127 { L"Lucida Console", L"DejaVu Sans Mono" }, 128 + { L"Microsoft Sans Serif", L"Droid Sans Fallback" }, 124 129 { L"MS Sans Serif", L"Droid Sans Fallback" }, 125 130 { L"MS Shell Dlg", L"Droid Sans Fallback" }, 126 131 { L"MS Shell Dlg 2", L"Droid Sans Fallback" }, ··· 163 168 { L"Helv", L"Droid Sans Fallback" }, 164 169 { L"Helvetica", L"Liberation Sans" }, 165 170 { L"Lucida Console", L"DejaVu Sans Mono" }, 171 + { L"Microsoft Sans Serif", L"Droid Sans Fallback" }, 166 172 { L"MS Sans Serif", L"Droid Sans Fallback" }, 167 173 { L"MS Shell Dlg", L"Droid Sans Fallback" }, 168 174 { L"MS Shell Dlg 2", L"Droid Sans Fallback" }, ··· 206 212 { L"Helv", L"Droid Sans Fallback" }, 207 213 { L"Helvetica", L"Liberation Sans" }, 208 214 { L"Lucida Console", L"DejaVu Sans Mono" }, 215 + { L"Microsoft Sans Serif", L"Droid Sans Fallback" }, 209 216 { L"MS Sans Serif", L"Droid Sans Fallback" }, 210 217 { L"MS Shell Dlg", L"Droid Sans Fallback" }, 211 218 { L"MS Shell Dlg 2", L"Droid Sans Fallback" }, ··· 250 257 { L"Helv", L"Droid Sans Fallback" }, 251 258 { L"Helvetica", L"Liberation Sans" }, 252 259 { L"Lucida Console", L"DejaVu Sans Mono" }, 260 + { L"Microsoft Sans Serif", L"Droid Sans Fallback" }, 253 261 { L"MS Sans Serif", L"Droid Sans Fallback" }, 254 262 { L"MS Shell Dlg", L"Droid Sans Fallback" }, 255 263 { L"MS Shell Dlg 2", L"Droid Sans Fallback" }, ··· 293 301 { L"Helv", L"DejaVu Sans" }, 294 302 { L"Helvetica", L"DejaVu Sans" }, 295 303 { L"Lucida Console", L"DejaVu Sans Mono" }, 304 + { L"Microsoft Sans Serif", L"DejaVu Sans" }, 296 305 { L"MS Sans Serif", L"DejaVu Sans" }, 297 306 { L"MS Shell Dlg", L"DejaVu Sans" }, 298 307 { L"MS Shell Dlg 2", L"DejaVu Sans" }, ··· 320 329 { L"Helv", L"Tahoma" }, 321 330 { L"Helvetica", L"Liberation Sans" }, 322 331 { L"Lucida Console", L"DejaVu Sans Mono" }, 332 + { L"Microsoft Sans Serif", L"FreeSans" }, 323 333 { L"MS Sans Serif", L"FreeSans" }, 324 334 { L"MS Shell Dlg", L"FreeSans" }, 325 335 { L"MS Shell Dlg 2", L"FreeSans" },
+1
boot/bootdata/livecd.inf
··· 50 50 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helv",0x00000000,"Tahoma" 51 51 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Helvetica",0x00000000,"Liberation Sans" 52 52 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Lucida Console",0x00000000,"DejaVu Sans Mono" 53 + HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","Microsoft Sans Serif",0x00000000,"Tahoma" 53 54 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Sans Serif",0x00000000,"Tahoma" 54 55 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg",0x00000000,"Tahoma" 55 56 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes","MS Shell Dlg 2",0x00000000,"Tahoma"
+115 -25
win32ss/gdi/gdi32/objects/font.c
··· 218 218 int cmp = _wcsicmp(plf1->lfFaceName, plf2->lfFaceName); 219 219 if (cmp) 220 220 return cmp; 221 + if (dwCompareFlags & IFFCX_CHARSET) 222 + { 223 + if (plf1->lfCharSet < plf2->lfCharSet) 224 + return -1; 225 + if (plf1->lfCharSet > plf2->lfCharSet) 226 + return 1; 227 + } 221 228 if (dwCompareFlags & IFFCX_STYLE) 222 229 { 223 230 WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL); ··· 229 236 if (plf1->lfItalic < plf2->lfItalic) 230 237 return -1; 231 238 if (plf1->lfItalic > plf2->lfItalic) 232 - return 1; 233 - } 234 - if (dwCompareFlags & IFFCX_CHARSET) 235 - { 236 - if (plf1->lfCharSet < plf2->lfCharSet) 237 - return -1; 238 - if (plf1->lfCharSet > plf2->lfCharSet) 239 239 return 1; 240 240 } 241 241 return 0; ··· 267 267 first = InfoList; 268 268 last = &InfoList[nCount]; 269 269 270 - // std::unique(first, last, IntFontFamilyCompareEx); 270 + /* std::unique(first, last, IntFontFamilyCompareEx); */ 271 271 if (first == last) 272 272 return 0; 273 273 ··· 285 285 } 286 286 287 287 static int FASTCALL 288 - IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam, 288 + IntEnumFontFamilies(HDC Dc, const LOGFONTW *LogFont, PVOID EnumProc, LPARAM lParam, 289 289 DWORD dwFlags) 290 290 { 291 291 int FontFamilyCount; 292 - int FontFamilySize; 293 292 PFONTFAMILYINFO Info; 294 293 int Ret = 1; 295 294 int i; 296 295 ENUMLOGFONTEXA EnumLogFontExA; 297 296 NEWTEXTMETRICEXA NewTextMetricExA; 298 297 LOGFONTW lfW; 298 + LONG DataSize, InfoCount; 299 299 300 - Info = RtlAllocateHeap(GetProcessHeap(), 0, 301 - INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO)); 302 - if (NULL == Info) 300 + DataSize = INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO); 301 + Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize); 302 + if (Info == NULL) 303 303 { 304 304 return 1; 305 305 } 306 306 307 + /* Initialize the LOGFONT structure */ 308 + ZeroMemory(&lfW, sizeof(lfW)); 307 309 if (!LogFont) 308 310 { 309 311 lfW.lfCharSet = DEFAULT_CHARSET; 310 - lfW.lfPitchAndFamily = 0; 311 - lfW.lfFaceName[0] = 0; 312 - LogFont = &lfW; 312 + } 313 + else 314 + { 315 + lfW.lfCharSet = LogFont->lfCharSet; 316 + lfW.lfPitchAndFamily = LogFont->lfPitchAndFamily; 317 + StringCbCopyW(lfW.lfFaceName, sizeof(lfW.lfFaceName), LogFont->lfFaceName); 313 318 } 314 319 315 - FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT); 320 + /* Retrieve the font information */ 321 + InfoCount = INITIAL_FAMILY_COUNT; 322 + FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount); 316 323 if (FontFamilyCount < 0) 317 324 { 318 325 RtlFreeHeap(GetProcessHeap(), 0, Info); 319 326 return 1; 320 327 } 321 - if (INITIAL_FAMILY_COUNT < FontFamilyCount) 328 + 329 + /* Resize the buffer if the buffer is too small */ 330 + if (INITIAL_FAMILY_COUNT < InfoCount) 322 331 { 323 - FontFamilySize = FontFamilyCount; 324 332 RtlFreeHeap(GetProcessHeap(), 0, Info); 325 - Info = RtlAllocateHeap(GetProcessHeap(), 0, 326 - FontFamilyCount * sizeof(FONTFAMILYINFO)); 327 - if (NULL == Info) 333 + DataSize = InfoCount * sizeof(FONTFAMILYINFO); 334 + Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize); 335 + if (Info == NULL) 328 336 { 329 337 return 1; 330 338 } 331 - FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize); 332 - if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount) 339 + FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount); 340 + if (FontFamilyCount < 0 || FontFamilyCount < InfoCount) 333 341 { 334 342 RtlFreeHeap(GetProcessHeap(), 0, Info); 335 343 return 1; 336 344 } 337 345 } 338 346 347 + /* Sort and remove redundant information */ 339 348 qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare); 340 - FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, LogFont, dwFlags); 349 + FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, &lfW, dwFlags); 341 350 351 + /* call the callback */ 342 352 for (i = 0; i < FontFamilyCount; i++) 343 353 { 344 354 if (dwFlags & IEFF_UNICODE) ··· 1693 1703 } 1694 1704 1695 1705 1706 + #if DBG 1707 + VOID DumpFamilyInfo(const FONTFAMILYINFO *Info, LONG Count) 1708 + { 1709 + LONG i; 1710 + const LOGFONTW *plf; 1711 + 1712 + DPRINT1("---\n"); 1713 + DPRINT1("Count: %d\n", Count); 1714 + for (i = 0; i < Count; ++i) 1715 + { 1716 + plf = &Info[i].EnumLogFontEx.elfLogFont; 1717 + DPRINT1("%d: '%S',%u,'%S', %ld:%ld, %ld, %d, %d\n", i, 1718 + plf->lfFaceName, plf->lfCharSet, Info[i].EnumLogFontEx.elfFullName, 1719 + plf->lfHeight, plf->lfWidth, plf->lfWeight, plf->lfItalic, plf->lfPitchAndFamily); 1720 + } 1721 + } 1722 + 1723 + VOID DoFontSystemUnittest(VOID) 1724 + { 1725 + LOGFONTW LogFont; 1726 + FONTFAMILYINFO Info[4]; 1727 + UNICODE_STRING Str1, Str2; 1728 + LONG ret, InfoCount; 1729 + 1730 + //DumpFontInfo(TRUE); 1731 + 1732 + /* L"" DEFAULT_CHARSET */ 1733 + RtlZeroMemory(&LogFont, sizeof(LogFont)); 1734 + LogFont.lfCharSet = DEFAULT_CHARSET; 1735 + InfoCount = RTL_NUMBER_OF(Info); 1736 + ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount); 1737 + DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount); 1738 + DumpFamilyInfo(Info, ret); 1739 + ASSERT(ret == RTL_NUMBER_OF(Info)); 1740 + ASSERT(InfoCount > 32); 1741 + 1742 + /* L"Microsoft Sans Serif" ANSI_CHARSET */ 1743 + RtlZeroMemory(&LogFont, sizeof(LogFont)); 1744 + LogFont.lfCharSet = ANSI_CHARSET; 1745 + StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Microsoft Sans Serif"); 1746 + InfoCount = RTL_NUMBER_OF(Info); 1747 + ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount); 1748 + DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount); 1749 + DumpFamilyInfo(Info, ret); 1750 + ASSERT(ret != -1); 1751 + ASSERT(InfoCount > 0); 1752 + ASSERT(InfoCount < 16); 1753 + 1754 + RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfLogFont.lfFaceName); 1755 + RtlInitUnicodeString(&Str2, L"Microsoft Sans Serif"); 1756 + ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE); 1757 + ASSERT(ret == 0); 1758 + 1759 + RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfFullName); 1760 + RtlInitUnicodeString(&Str2, L"Tahoma"); 1761 + ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE); 1762 + ASSERT(ret == 0); 1763 + 1764 + /* L"Non-Existent" DEFAULT_CHARSET */ 1765 + RtlZeroMemory(&LogFont, sizeof(LogFont)); 1766 + LogFont.lfCharSet = ANSI_CHARSET; 1767 + StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Non-Existent"); 1768 + InfoCount = RTL_NUMBER_OF(Info); 1769 + ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount); 1770 + DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount); 1771 + DumpFamilyInfo(Info, ret); 1772 + ASSERT(ret == 0); 1773 + ASSERT(InfoCount == 0); 1774 + } 1775 + #endif 1776 + 1777 + /* EOF */ 1696 1778 /* 1697 1779 * @implemented 1698 1780 */ ··· 1702 1784 CONST LOGFONTW *lplf 1703 1785 ) 1704 1786 { 1787 + #if DBG 1788 + static BOOL bDidTest = FALSE; 1789 + if (!bDidTest) 1790 + { 1791 + DoFontSystemUnittest(); 1792 + bDidTest = TRUE; 1793 + } 1794 + #endif 1705 1795 if (lplf) 1706 1796 { 1707 1797 ENUMLOGFONTEXDVW Logfont;
+121 -65
win32ss/gdi/ntgdi/freetype.c
··· 2675 2675 } 2676 2676 2677 2677 static BOOLEAN FASTCALL 2678 - GetFontFamilyInfoForList(LPLOGFONTW LogFont, 2678 + GetFontFamilyInfoForList(const LOGFONTW *LogFont, 2679 2679 PFONTFAMILYINFO Info, 2680 2680 LPCWSTR NominalName, 2681 - DWORD *pCount, 2682 - DWORD MaxCount, 2681 + LONG *pCount, 2682 + LONG MaxCount, 2683 2683 PLIST_ENTRY Head) 2684 2684 { 2685 2685 PLIST_ENTRY Entry; 2686 2686 PFONT_ENTRY CurrentEntry; 2687 2687 FONTGDI *FontGDI; 2688 2688 FONTFAMILYINFO InfoEntry; 2689 - DWORD Count = *pCount; 2689 + LONG Count = *pCount; 2690 2690 2691 2691 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink) 2692 2692 { ··· 2697 2697 if (LogFont->lfCharSet != DEFAULT_CHARSET && 2698 2698 LogFont->lfCharSet != FontGDI->CharSet) 2699 2699 { 2700 - continue; 2700 + continue; /* charset mismatch */ 2701 2701 } 2702 2702 2703 - if (LogFont->lfFaceName[0] == UNICODE_NULL) 2704 - { 2705 - if (Count < MaxCount) 2706 - { 2707 - FontFamilyFillInfo(&Info[Count], NominalName, NULL, FontGDI); 2708 - } 2709 - Count++; 2710 - continue; 2711 - } 2703 + /* get one info entry */ 2704 + FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI); 2712 2705 2713 - FontFamilyFillInfo(&InfoEntry, NominalName, NULL, FontGDI); 2714 - 2715 - if (NominalName) 2716 - { 2717 - RtlStringCchCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName, 2718 - RTL_NUMBER_OF(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName), 2719 - NominalName); 2720 - } 2721 - else 2706 + if (LogFont->lfFaceName[0] != UNICODE_NULL) 2722 2707 { 2708 + /* check name */ 2723 2709 if (_wcsnicmp(LogFont->lfFaceName, 2724 2710 InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName, 2725 2711 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 && ··· 2731 2717 } 2732 2718 } 2733 2719 2734 - if (Count < MaxCount) 2720 + if (NominalName) 2721 + { 2722 + /* store the nominal name */ 2723 + RtlStringCbCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName, 2724 + sizeof(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName), 2725 + NominalName); 2726 + } 2727 + 2728 + /* store one entry to Info */ 2729 + if (0 <= Count && Count < MaxCount) 2735 2730 { 2736 2731 RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry)); 2737 2732 } ··· 2744 2739 } 2745 2740 2746 2741 static BOOLEAN FASTCALL 2747 - GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont, 2742 + GetFontFamilyInfoForSubstitutes(const LOGFONTW *LogFont, 2748 2743 PFONTFAMILYINFO Info, 2749 - DWORD *pCount, 2750 - DWORD MaxCount) 2744 + LONG *pCount, 2745 + LONG MaxCount) 2751 2746 { 2752 2747 PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead; 2753 2748 PFONTSUBST_ENTRY pCurrentEntry; ··· 2762 2757 pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM]; 2763 2758 if (LogFont->lfFaceName[0] != UNICODE_NULL) 2764 2759 { 2760 + /* check name */ 2765 2761 if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0) 2766 2762 continue; /* mismatch */ 2767 2763 } ··· 2771 2767 pCurrentEntry->CharSets[FONTSUBST_FROM] == 2772 2768 pCurrentEntry->CharSets[FONTSUBST_TO]) 2773 2769 { 2770 + /* identical mapping */ 2774 2771 continue; 2775 2772 } 2776 2773 2774 + /* substitute and get the real name */ 2777 2775 IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW); 2778 2776 SubstituteFontRecurse(&lf); 2779 2777 if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet != lf.lfCharSet) 2780 2778 continue; 2781 2779 2780 + /* search in global fonts */ 2782 2781 IntLockGlobalFonts(); 2783 2782 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, &g_FontListHead); 2784 2783 IntUnLockGlobalFonts(); 2785 2784 2785 + /* search in private fonts */ 2786 2786 IntLockProcessPrivateFonts(Win32Process); 2787 2787 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, 2788 2788 &Win32Process->PrivateFontListHead); ··· 5407 5407 // Functions needing sorting. 5408 5408 // 5409 5409 /////////////////////////////////////////////////////////////////////////// 5410 - int APIENTRY 5410 + 5411 + LONG FASTCALL 5412 + IntGetFontFamilyInfo(HDC Dc, 5413 + const LOGFONTW *SafeLogFont, 5414 + PFONTFAMILYINFO SafeInfo, 5415 + LONG InfoCount) 5416 + { 5417 + LONG AvailCount = 0; 5418 + PPROCESSINFO Win32Process; 5419 + 5420 + /* Enumerate font families in the global list */ 5421 + IntLockGlobalFonts(); 5422 + if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, 5423 + InfoCount, &g_FontListHead)) 5424 + { 5425 + IntUnLockGlobalFonts(); 5426 + return -1; 5427 + } 5428 + IntUnLockGlobalFonts(); 5429 + 5430 + /* Enumerate font families in the process local list */ 5431 + Win32Process = PsGetCurrentProcessWin32Process(); 5432 + IntLockProcessPrivateFonts(Win32Process); 5433 + if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, InfoCount, 5434 + &Win32Process->PrivateFontListHead)) 5435 + { 5436 + IntUnLockProcessPrivateFonts(Win32Process); 5437 + return -1; 5438 + } 5439 + IntUnLockProcessPrivateFonts(Win32Process); 5440 + 5441 + /* Enumerate font families in the registry */ 5442 + if (!GetFontFamilyInfoForSubstitutes(SafeLogFont, SafeInfo, &AvailCount, InfoCount)) 5443 + { 5444 + return -1; 5445 + } 5446 + 5447 + return AvailCount; 5448 + } 5449 + 5450 + LONG NTAPI 5411 5451 NtGdiGetFontFamilyInfo(HDC Dc, 5412 - LPLOGFONTW UnsafeLogFont, 5452 + const LOGFONTW *UnsafeLogFont, 5413 5453 PFONTFAMILYINFO UnsafeInfo, 5414 - DWORD Size) 5454 + LPLONG UnsafeInfoCount) 5415 5455 { 5416 5456 NTSTATUS Status; 5417 5457 LOGFONTW LogFont; 5418 5458 PFONTFAMILYINFO Info; 5419 - DWORD Count; 5420 - PPROCESSINFO Win32Process; 5459 + LONG GotCount, AvailCount, DataSize, SafeInfoCount; 5421 5460 5422 - /* Make a safe copy */ 5423 - Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW)); 5424 - if (! NT_SUCCESS(Status)) 5461 + if (UnsafeLogFont == NULL || UnsafeInfo == NULL || UnsafeInfoCount == NULL) 5425 5462 { 5426 5463 EngSetLastError(ERROR_INVALID_PARAMETER); 5427 5464 return -1; 5428 5465 } 5429 5466 5430 - /* Allocate space for a safe copy */ 5431 - Info = ExAllocatePoolWithTag(PagedPool, Size * sizeof(FONTFAMILYINFO), GDITAG_TEXT); 5432 - if (NULL == Info) 5467 + Status = MmCopyFromCaller(&SafeInfoCount, UnsafeInfoCount, sizeof(SafeInfoCount)); 5468 + if (!NT_SUCCESS(Status)) 5433 5469 { 5434 - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 5470 + EngSetLastError(ERROR_INVALID_PARAMETER); 5435 5471 return -1; 5436 5472 } 5437 - 5438 - /* Enumerate font families in the global list */ 5439 - IntLockGlobalFonts(); 5440 - Count = 0; 5441 - if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size, &g_FontListHead) ) 5473 + GotCount = 0; 5474 + Status = MmCopyToCaller(UnsafeInfoCount, &GotCount, sizeof(*UnsafeInfoCount)); 5475 + if (!NT_SUCCESS(Status)) 5476 + { 5477 + EngSetLastError(ERROR_INVALID_PARAMETER); 5478 + return -1; 5479 + } 5480 + Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW)); 5481 + if (!NT_SUCCESS(Status)) 5442 5482 { 5443 - IntUnLockGlobalFonts(); 5444 - ExFreePoolWithTag(Info, GDITAG_TEXT); 5483 + EngSetLastError(ERROR_INVALID_PARAMETER); 5484 + return -1; 5485 + } 5486 + if (SafeInfoCount <= 0) 5487 + { 5488 + EngSetLastError(ERROR_INVALID_PARAMETER); 5445 5489 return -1; 5446 5490 } 5447 - IntUnLockGlobalFonts(); 5448 5491 5449 - /* Enumerate font families in the process local list */ 5450 - Win32Process = PsGetCurrentProcessWin32Process(); 5451 - IntLockProcessPrivateFonts(Win32Process); 5452 - if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size, 5453 - &Win32Process->PrivateFontListHead)) 5492 + /* Allocate space for a safe copy */ 5493 + DataSize = SafeInfoCount * sizeof(FONTFAMILYINFO); 5494 + if (DataSize <= 0) 5454 5495 { 5455 - IntUnLockProcessPrivateFonts(Win32Process); 5456 - ExFreePoolWithTag(Info, GDITAG_TEXT); 5496 + EngSetLastError(ERROR_INVALID_PARAMETER); 5457 5497 return -1; 5458 5498 } 5459 - IntUnLockProcessPrivateFonts(Win32Process); 5460 - 5461 - /* Enumerate font families in the registry */ 5462 - if (! GetFontFamilyInfoForSubstitutes(&LogFont, Info, &Count, Size)) 5499 + Info = ExAllocatePoolWithTag(PagedPool, DataSize, GDITAG_TEXT); 5500 + if (Info == NULL) 5463 5501 { 5464 - ExFreePoolWithTag(Info, GDITAG_TEXT); 5502 + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 5465 5503 return -1; 5466 5504 } 5467 5505 5506 + /* Retrieve the information */ 5507 + AvailCount = IntGetFontFamilyInfo(Dc, &LogFont, Info, SafeInfoCount); 5508 + GotCount = min(AvailCount, SafeInfoCount); 5509 + SafeInfoCount = AvailCount; 5510 + 5468 5511 /* Return data to caller */ 5469 - if (0 != Count) 5512 + if (GotCount > 0) 5470 5513 { 5471 - Status = MmCopyToCaller(UnsafeInfo, Info, 5472 - (Count < Size ? Count : Size) * sizeof(FONTFAMILYINFO)); 5473 - if (! NT_SUCCESS(Status)) 5514 + DataSize = GotCount * sizeof(FONTFAMILYINFO); 5515 + if (DataSize <= 0) 5516 + { 5517 + ExFreePoolWithTag(Info, GDITAG_TEXT); 5518 + EngSetLastError(ERROR_INVALID_PARAMETER); 5519 + return -1; 5520 + } 5521 + Status = MmCopyToCaller(UnsafeInfo, Info, DataSize); 5522 + if (!NT_SUCCESS(Status)) 5523 + { 5524 + ExFreePoolWithTag(Info, GDITAG_TEXT); 5525 + EngSetLastError(ERROR_INVALID_PARAMETER); 5526 + return -1; 5527 + } 5528 + Status = MmCopyToCaller(UnsafeInfoCount, &SafeInfoCount, sizeof(*UnsafeInfoCount)); 5529 + if (!NT_SUCCESS(Status)) 5474 5530 { 5475 5531 ExFreePoolWithTag(Info, GDITAG_TEXT); 5476 5532 EngSetLastError(ERROR_INVALID_PARAMETER); ··· 5480 5536 5481 5537 ExFreePoolWithTag(Info, GDITAG_TEXT); 5482 5538 5483 - return Count; 5539 + return GotCount; 5484 5540 } 5485 5541 5486 5542 FORCEINLINE ··· 6618 6674 if(Safepwch) 6619 6675 ExFreePoolWithTag(Safepwch , GDITAG_TEXT); 6620 6676 6621 - if (! NT_SUCCESS(Status)) 6677 + if (!NT_SUCCESS(Status)) 6622 6678 { 6623 6679 SetLastNtError(Status); 6624 6680 return FALSE;
+3 -4
win32ss/include/ntgdibad.h
··· 50 50 } FONTFAMILYINFO, *PFONTFAMILYINFO; 51 51 52 52 /* Should be using NtGdiEnumFontChunk */ 53 - INT 53 + LONG 54 54 NTAPI 55 55 NtGdiGetFontFamilyInfo( 56 56 HDC Dc, 57 - LPLOGFONTW LogFont, 57 + const LOGFONTW *LogFont, 58 58 PFONTFAMILYINFO Info, 59 - DWORD Size 60 - ); 59 + LPLONG UnsafeInfoCount); 61 60 62 61 /* Use NtGdiGetDCPoint with GdiGetViewPortExt */ 63 62 BOOL APIENTRY NtGdiGetViewportExtEx(HDC hDC, LPSIZE viewportExt);