Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/font/fontpath.c
32287 views
/*1* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <windows.h>26#include <stdio.h>2728#include <jni.h>29#include <jni_util.h>30#include <sun_awt_Win32FontManager.h>3132#define BSIZE (max(512, MAX_PATH+1))333435JNIEXPORT jstring JNICALL Java_sun_awt_Win32FontManager_getFontPath(JNIEnv *env, jobject thiz, jboolean noType1)36{37char windir[BSIZE];38char sysdir[BSIZE];39char fontpath[BSIZE*2];40char *end;4142/* Locate fonts directories relative to the Windows System directory.43* If Windows System location is different than the user's window44* directory location, as in a shared Windows installation,45* return both locations as potential font directories46*/47GetSystemDirectory(sysdir, BSIZE);48end = strrchr(sysdir,'\\');49if (end && (stricmp(end,"\\System") || stricmp(end,"\\System32"))) {50*end = 0;51strcat(sysdir, "\\Fonts");52}5354GetWindowsDirectory(windir, BSIZE);55if (strlen(windir) > BSIZE-7) {56*windir = 0;57} else {58strcat(windir, "\\Fonts");59}6061strcpy(fontpath,sysdir);62if (stricmp(sysdir,windir)) {63strcat(fontpath,";");64strcat(fontpath,windir);65}6667return JNU_NewStringPlatform(env, fontpath);68}6970/* The code below is used to obtain information from the windows font APIS71* and registry on which fonts are available and what font files hold those72* fonts. The results are used to speed font lookup.73*/7475typedef struct GdiFontMapInfo {76JNIEnv *env;77jstring family;78jobject fontToFamilyMap;79jobject familyToFontListMap;80jobject list;81jmethodID putMID;82jmethodID containsKeyMID;83jclass arrayListClass;84jmethodID arrayListCtr;85jmethodID addMID;86jmethodID toLowerCaseMID;87jobject locale;88} GdiFontMapInfo;8990/* IS_NT means NT or later OSes which support Unicode.91* We have to painfully deal with the ASCII and non-ASCII case we92* we really want to get the font names as unicode wherever possible.93* UNICODE_OS is 0 to mean uninitialised, 1 to mean not a unicode OS,94* 2 to mean a unicode OS.95*/9697#define UC_UNKNOWN 098#define UC_NO 199#define UC_YES 2100static int UNICODE_OS = UC_UNKNOWN;101static int GetOSVersion () {102OSVERSIONINFO vinfo;103vinfo.dwOSVersionInfoSize = sizeof(vinfo);104GetVersionEx(&vinfo);105if ((int)vinfo.dwMajorVersion > 4) {106UNICODE_OS = UC_YES;107} else if ((int)vinfo.dwMajorVersion < 4) {108UNICODE_OS = UC_NO;109} else {110if ((int)vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {111UNICODE_OS = UC_NO;112} else {113UNICODE_OS = UC_YES;114}115}116return UNICODE_OS;117}118119#define IS_NT ((UNICODE_OS == UC_UNKNOWN) \120? (GetOSVersion() == UC_YES) : (UNICODE_OS == UC_YES))121122/* NT is W2K & XP. WIN is Win9x */123static const char FONTKEY_NT[] =124"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";125static const char FONTKEY_WIN[] =126"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts";127128/* Callback for call to EnumFontFamiliesEx in the EnumFamilyNames function.129* Expects to be called once for each face name in the family specified130* in the call. We extract the full name for the font which is expected131* to be in the "system encoding" and create canonical and lower case132* Java strings for the name which are added to the maps. The lower case133* name is used as key to the family name value in the font to family map,134* the canonical name is one of the"list" of members of the family.135*/136static int CALLBACK EnumFontFacesInFamilyProcA(137ENUMLOGFONTEXA *lpelfe,138NEWTEXTMETRICEX *lpntme,139int FontType,140LPARAM lParam )141{142GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;143JNIEnv *env = fmi->env;144jstring fullname, fullnameLC;145146/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */147if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {148return 1;149}150151/* printf("FULL=%s\n",lpelfe->elfFullName);fflush(stdout); */152153fullname = JNU_NewStringPlatform(env, lpelfe->elfFullName);154if (fullname == NULL) {155(*env)->ExceptionClear(env);156return 1;157}158fullnameLC = (*env)->CallObjectMethod(env, fullname,159fmi->toLowerCaseMID, fmi->locale);160(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);161(*env)->CallObjectMethod(env, fmi->fontToFamilyMap,162fmi->putMID, fullnameLC, fmi->family);163return 1;164}165166typedef struct CheckFamilyInfo {167wchar_t *family;168wchar_t* fullName;169int isDifferent;170} CheckFamilyInfo;171172static int CALLBACK CheckFontFamilyProcW(173ENUMLOGFONTEXW *lpelfe,174NEWTEXTMETRICEX *lpntme,175int FontType,176LPARAM lParam)177{178CheckFamilyInfo *info = (CheckFamilyInfo*)lParam;179info->isDifferent = wcscmp(lpelfe->elfLogFont.lfFaceName, info->family);180181/* if (!info->isDifferent) { */182/* wprintf(LFor font %s expected family=%s instead got %s\n", */183/* lpelfe->elfFullName, */184/* info->family, */185/* lpelfe->elfLogFont.lfFaceName); */186/* fflush(stdout); */187/* } */188return 0;189}190191/* This HDC is initialised and released in the populate family map192* JNI entry point, and used within the call which would otherwise193* create many DCs.194*/195static HDC screenDC = NULL;196197static int DifferentFamily(wchar_t *family, wchar_t* fullName) {198LOGFONTW lfw;199CheckFamilyInfo info;200201/* If fullName can't be stored in the struct, assume correct family */202if (wcslen((LPWSTR)fullName) >= LF_FACESIZE) {203return 0;204}205206memset(&info, 0, sizeof(CheckFamilyInfo));207info.family = family;208info.fullName = fullName;209info.isDifferent = 0;210211memset(&lfw, 0, sizeof(lfw));212wcscpy(lfw.lfFaceName, fullName);213lfw.lfCharSet = DEFAULT_CHARSET;214EnumFontFamiliesExW(screenDC, &lfw,215(FONTENUMPROCW)CheckFontFamilyProcW,216(LPARAM)(&info), 0L);217218return info.isDifferent;219}220221static int CALLBACK EnumFontFacesInFamilyProcW(222ENUMLOGFONTEXW *lpelfe,223NEWTEXTMETRICEX *lpntme,224int FontType,225LPARAM lParam)226{227GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;228JNIEnv *env = fmi->env;229jstring fullname, fullnameLC;230231/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */232if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {233return 1;234}235236/* Windows has font aliases and so may enumerate fonts from237* the aliased family if any actual font of that family is installed.238* To protect against it ignore fonts which aren't enumerated under239* their true family.240*/241if (DifferentFamily(lpelfe->elfLogFont.lfFaceName,242lpelfe->elfFullName)) {243return 1;244}245246fullname = (*env)->NewString(env, lpelfe->elfFullName,247(jsize)wcslen((LPWSTR)lpelfe->elfFullName));248if (fullname == NULL) {249(*env)->ExceptionClear(env);250return 1;251}252fullnameLC = (*env)->CallObjectMethod(env, fullname,253fmi->toLowerCaseMID, fmi->locale);254(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);255(*env)->CallObjectMethod(env, fmi->fontToFamilyMap,256fmi->putMID, fullnameLC, fmi->family);257return 1;258}259260/* Callback for EnumFontFamiliesEx in populateFontFileNameMap.261* Expects to be called for every charset of every font family.262* If this is the first time we have been called for this family,263* add a new mapping to the familyToFontListMap from this family to a264* list of its members. To populate that list, further enumerate all faces265* in this family for the matched charset. This assumes that all fonts266* in a family support the same charset, which is a fairly safe assumption267* and saves time as the call we make here to EnumFontFamiliesEx will268* enumerate the members of this family just once each.269* Because we set fmi->list to be the newly created list the call back270* can safely add to that list without a search.271*/272static int CALLBACK EnumFamilyNamesA(273ENUMLOGFONTEXA *lpelfe, /* pointer to logical-font data */274NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */275int FontType, /* type of font */276LPARAM lParam) /* application-defined data */277{278GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;279JNIEnv *env = fmi->env;280jstring familyLC;281LOGFONTA lfa;282283/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */284if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {285return 1;286}287288/* Windows lists fonts which have a vmtx (vertical metrics) table twice.289* Once using their normal name, and again preceded by '@'. These appear290* in font lists in some windows apps, such as wordpad. We don't want291* these so we skip any font where the first character is '@'292*/293if (lpelfe->elfLogFont.lfFaceName[0] == '@') {294return 1;295}296fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName);297if (fmi->family == NULL) {298(*env)->ExceptionClear(env);299return 1;300}301familyLC = (*env)->CallObjectMethod(env, fmi->family,302fmi->toLowerCaseMID, fmi->locale);303/* check if already seen this family with a different charset */304if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,305fmi->containsKeyMID, familyLC)) {306return 1;307}308fmi->list = (*env)->NewObject(env,309fmi->arrayListClass, fmi->arrayListCtr, 4);310if (fmi->list == NULL) {311(*env)->ExceptionClear(env);312return 1;313}314(*env)->CallObjectMethod(env, fmi->familyToFontListMap,315fmi->putMID, familyLC, fmi->list);316317/* printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */318319memset(&lfa, 0, sizeof(lfa));320strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName);321lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet;322EnumFontFamiliesExA(screenDC, &lfa,323(FONTENUMPROCA)EnumFontFacesInFamilyProcA,324lParam, 0L);325return 1;326}327328static int CALLBACK EnumFamilyNamesW(329ENUMLOGFONTEXW *lpelfe, /* pointer to logical-font data */330NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */331int FontType, /* type of font */332LPARAM lParam ) /* application-defined data */333{334GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;335JNIEnv *env = fmi->env;336jstring familyLC;337size_t slen;338LOGFONTW lfw;339340/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */341if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {342return 1;343}344/* wprintf(L"FAMILY=%s charset=%d FULL=%s\n", */345/* lpelfe->elfLogFont.lfFaceName, */346/* lpelfe->elfLogFont.lfCharSet, */347/* lpelfe->elfFullName); */348/* fflush(stdout); */349350/* Windows lists fonts which have a vmtx (vertical metrics) table twice.351* Once using their normal name, and again preceded by '@'. These appear352* in font lists in some windows apps, such as wordpad. We don't want353* these so we skip any font where the first character is '@'354*/355if (lpelfe->elfLogFont.lfFaceName[0] == L'@') {356return 1;357}358slen = wcslen(lpelfe->elfLogFont.lfFaceName);359fmi->family = (*env)->NewString(env,lpelfe->elfLogFont.lfFaceName, (jsize)slen);360if (fmi->family == NULL) {361(*env)->ExceptionClear(env);362return 1;363}364familyLC = (*env)->CallObjectMethod(env, fmi->family,365fmi->toLowerCaseMID, fmi->locale);366/* check if already seen this family with a different charset */367if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,368fmi->containsKeyMID, familyLC)) {369return 1;370}371fmi->list = (*env)->NewObject(env,372fmi->arrayListClass, fmi->arrayListCtr, 4);373if (fmi->list == NULL) {374(*env)->ExceptionClear(env);375return 1;376}377(*env)->CallObjectMethod(env, fmi->familyToFontListMap,378fmi->putMID, familyLC, fmi->list);379380memset(&lfw, 0, sizeof(lfw));381wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName);382lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet;383EnumFontFamiliesExW(screenDC, &lfw,384(FONTENUMPROCW)EnumFontFacesInFamilyProcW,385lParam, 0L);386return 1;387}388389390/* It looks like TrueType fonts have " (TrueType)" tacked on the end of their391* name, so we can try to use that to distinguish TT from other fonts.392* However if a program "installed" a font in the registry the key may393* not include that. We could also try to "pass" fonts which have no "(..)"394* at the end. But that turns out to pass a few .FON files that MS supply.395* If there's no parenthesized type string, we could next try to infer396* the file type from the file name extension. Since the MS entries that397* have no type string are very few, and have odd names like "MS-DOS CP 437"398* and would never return a Java Font anyway its currently OK to put these399* in the font map, although clearly the returned names must never percolate400* up into a list of available fonts returned to the application.401* Additionally for TTC font files the key looks like402* Font 1 & Font 2 (TrueType)403* or sometimes even :404* Font 1 & Font 2 & Font 3 (TrueType)405* Also if a Font has a name for this locale that name also406* exists in the registry using the appropriate platform encoding.407* What do we do then?408*409* Note: OpenType fonts seems to have " (TrueType)" suffix on Vista410* but " (OpenType)" on XP.411*/412413static BOOL RegistryToBaseTTNameA(LPSTR name) {414static const char TTSUFFIX[] = " (TrueType)";415static const char OTSUFFIX[] = " (OpenType)";416size_t TTSLEN = strlen(TTSUFFIX);417char *suffix;418419size_t len = strlen(name);420if (len == 0) {421return FALSE;422}423if (name[len-1] != ')') {424return FALSE;425}426if (len <= TTSLEN) {427return FALSE;428}429430/* suffix length is the same for truetype and opentype fonts */431suffix = name + len - TTSLEN;432if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) {433suffix[0] = '\0'; /* truncate name */434return TRUE;435}436return FALSE;437}438439static BOOL RegistryToBaseTTNameW(LPWSTR name) {440static const wchar_t TTSUFFIX[] = L" (TrueType)";441static const wchar_t OTSUFFIX[] = L" (OpenType)";442size_t TTSLEN = wcslen(TTSUFFIX);443wchar_t *suffix;444445size_t len = wcslen(name);446if (len == 0) {447return FALSE;448}449if (name[len-1] != L')') {450return FALSE;451}452if (len <= TTSLEN) {453return FALSE;454}455/* suffix length is the same for truetype and opentype fonts */456suffix = name + (len - TTSLEN);457if (wcscmp(suffix, TTSUFFIX) == 0 || wcscmp(suffix, OTSUFFIX) == 0) {458suffix[0] = L'\0'; /* truncate name */459return TRUE;460}461return FALSE;462}463464static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap,465LPCSTR name, LPCSTR data) {466LPSTR ptr1, ptr2;467jstring fontStr;468JNIEnv *env = fmi->env;469size_t dslen = strlen(data);470jstring fileStr = JNU_NewStringPlatform(env, data);471if (fileStr == NULL) {472(*env)->ExceptionClear(env);473return;474}475476/* TTC or ttc means it may be a collection. Need to parse out477* multiple font face names separated by " & "478* By only doing this for fonts which look like collections based on479* file name we are adhering to MS recommendations for font file names480* so it seems that we can be sure that this identifies precisely481* the MS-supplied truetype collections.482* This avoids any potential issues if a TTF file happens to have483* a & in the font name (I can't find anything which prohibits this)484* and also means we only parse the key in cases we know to be485* worthwhile.486*/487if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') &&488(ptr1 = strstr(name, " & ")) != NULL) {489ptr1+=3;490while (ptr1 >= name) { /* marginally safer than while (true) */491while ((ptr2 = strstr(ptr1, " & ")) != NULL) {492ptr1 = ptr2+3;493}494fontStr = JNU_NewStringPlatform(env, ptr1);495if (fontStr == NULL) {496(*env)->ExceptionClear(env);497return;498}499fontStr = (*env)->CallObjectMethod(env, fontStr,500fmi->toLowerCaseMID,501fmi->locale);502(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,503fontStr, fileStr);504if (ptr1 == name) {505break;506} else {507*(ptr1-3) ='\0';508ptr1 = (LPSTR)name;509}510}511} else {512fontStr = JNU_NewStringPlatform(env, name);513if (fontStr == NULL) {514(*env)->ExceptionClear(env);515return;516}517fontStr = (*env)->CallObjectMethod(env, fontStr,518fmi->toLowerCaseMID, fmi->locale);519(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,520fontStr, fileStr);521}522}523524static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,525LPWSTR name, LPWSTR data) {526527wchar_t *ptr1, *ptr2;528jstring fontStr;529JNIEnv *env = fmi->env;530size_t dslen = wcslen(data);531jstring fileStr = (*env)->NewString(env, data, (jsize)dslen);532if (fileStr == NULL) {533(*env)->ExceptionClear(env);534return;535}536537/* TTC or ttc means it may be a collection. Need to parse out538* multiple font face names separated by " & "539* By only doing this for fonts which look like collections based on540* file name we are adhering to MS recommendations for font file names541* so it seems that we can be sure that this identifies precisely542* the MS-supplied truetype collections.543* This avoids any potential issues if a TTF file happens to have544* a & in the font name (I can't find anything which prohibits this)545* and also means we only parse the key in cases we know to be546* worthwhile.547*/548549if ((data[dslen-1] == L'C' || data[dslen-1] == L'c') &&550(ptr1 = wcsstr(name, L" & ")) != NULL) {551ptr1+=3;552while (ptr1 >= name) { /* marginally safer than while (true) */553while ((ptr2 = wcsstr(ptr1, L" & ")) != NULL) {554ptr1 = ptr2+3;555}556fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1));557if (fontStr == NULL) {558(*env)->ExceptionClear(env);559return;560}561fontStr = (*env)->CallObjectMethod(env, fontStr,562fmi->toLowerCaseMID,563fmi->locale);564(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,565fontStr, fileStr);566if (ptr1 == name) {567break;568} else {569*(ptr1-3) = L'\0';570ptr1 = name;571}572}573} else {574fontStr = (*env)->NewString(env, name, (jsize)wcslen(name));575if (fontStr == NULL) {576(*env)->ExceptionClear(env);577return;578}579fontStr = (*env)->CallObjectMethod(env, fontStr,580fmi->toLowerCaseMID, fmi->locale);581(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,582fontStr, fileStr);583}584}585586/* Obtain all the fontname -> filename mappings.587* This is called once and the results returned to Java code which can588* use it for lookups to reduce or avoid the need to search font files.589*/590JNIEXPORT void JNICALL591Java_sun_awt_Win32FontManager_populateFontFileNameMap0592(JNIEnv *env, jclass obj, jobject fontToFileMap,593jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)594{595#define MAX_BUFFER (FILENAME_MAX+1)596const wchar_t wname[MAX_BUFFER];597const char cname[MAX_BUFFER];598const char data[MAX_BUFFER];599600DWORD type;601LONG ret;602HKEY hkeyFonts;603DWORD dwNameSize;604DWORD dwDataValueSize;605DWORD nval;606LPCSTR fontKeyName;607DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen;608DWORD numValues = 0;609jclass classID;610jmethodID putMID;611GdiFontMapInfo fmi;612613/* Check we were passed all the maps we need, and do lookup of614* methods for JNI up-calls615*/616if (fontToFileMap == NULL ||617fontToFamilyMap == NULL ||618familyToFontListMap == NULL) {619return;620}621classID = (*env)->FindClass(env, "java/util/HashMap");622if (classID == NULL) {623return;624}625putMID = (*env)->GetMethodID(env, classID, "put",626"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");627if (putMID == NULL) {628return;629}630631fmi.env = env;632fmi.fontToFamilyMap = fontToFamilyMap;633fmi.familyToFontListMap = familyToFontListMap;634fmi.putMID = putMID;635fmi.locale = locale;636fmi.containsKeyMID = (*env)->GetMethodID(env, classID, "containsKey",637"(Ljava/lang/Object;)Z");638if (fmi.containsKeyMID == NULL) {639return;640}641642fmi.arrayListClass = (*env)->FindClass(env, "java/util/ArrayList");643if (fmi.arrayListClass == NULL) {644return;645}646fmi.arrayListCtr = (*env)->GetMethodID(env, fmi.arrayListClass,647"<init>", "(I)V");648if (fmi.arrayListCtr == NULL) {649return;650}651fmi.addMID = (*env)->GetMethodID(env, fmi.arrayListClass,652"add", "(Ljava/lang/Object;)Z");653if (fmi.addMID == NULL) {654return;655}656classID = (*env)->FindClass(env, "java/lang/String");657if (classID == NULL) {658return;659}660fmi.toLowerCaseMID =661(*env)->GetMethodID(env, classID, "toLowerCase",662"(Ljava/util/Locale;)Ljava/lang/String;");663if (fmi.toLowerCaseMID == NULL) {664return;665}666667screenDC = GetDC(NULL);668if (screenDC == NULL) {669return;670}671/* Enumerate fonts via GDI to build maps of fonts and families */672if (IS_NT) {673LOGFONTW lfw;674memset(&lfw, 0, sizeof(lfw));675lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */676wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */677EnumFontFamiliesExW(screenDC, &lfw,678(FONTENUMPROCW)EnumFamilyNamesW,679(LPARAM)(&fmi), 0L);680} else {681LOGFONT lfa;682memset(&lfa, 0, sizeof(lfa));683lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */684strcpy(lfa.lfFaceName, ""); /* one face per family */685ret = EnumFontFamiliesExA(screenDC, &lfa,686(FONTENUMPROCA)EnumFamilyNamesA,687(LPARAM)(&fmi), 0L);688}689690/* Use the windows registry to map font names to files */691fontKeyName = (IS_NT) ? FONTKEY_NT : FONTKEY_WIN;692ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,693fontKeyName, 0L, KEY_READ, &hkeyFonts);694if (ret != ERROR_SUCCESS) {695ReleaseDC(NULL, screenDC);696screenDC = NULL;697return;698}699700if (IS_NT) {701ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,702&dwNumValues, &dwMaxValueNameLen,703&dwMaxValueDataLen, NULL, NULL);704} else {705ret = RegQueryInfoKeyA(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,706&dwNumValues, &dwMaxValueNameLen,707&dwMaxValueDataLen, NULL, NULL);708}709if (ret != ERROR_SUCCESS ||710dwMaxValueNameLen >= MAX_BUFFER ||711dwMaxValueDataLen >= MAX_BUFFER) {712RegCloseKey(hkeyFonts);713ReleaseDC(NULL, screenDC);714screenDC = NULL;715return;716}717for (nval = 0; nval < dwNumValues; nval++ ) {718dwNameSize = MAX_BUFFER;719dwDataValueSize = MAX_BUFFER;720if (IS_NT) {721ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,722NULL, &type, (LPBYTE)data, &dwDataValueSize);723} else {724ret = RegEnumValueA(hkeyFonts, nval, (LPSTR)cname, &dwNameSize,725NULL, &type, (LPBYTE)data, &dwDataValueSize);726}727if (ret != ERROR_SUCCESS) {728break;729}730if (type != REG_SZ) { /* REG_SZ means a null-terminated string */731continue;732}733if (IS_NT) {734if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {735/* If the filename ends with ".ttf" or ".otf" also accept it.736* Not expecting to need to do this for .ttc files.737* Also note this code is not mirrored in the "A" (win9x) path.738*/739LPWSTR dot = wcsrchr((LPWSTR)data, L'.');740if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)741&& (wcsicmp(dot, L".otf") != 0))) {742continue; /* not a TT font... */743}744}745registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);746} else {747if (!RegistryToBaseTTNameA((LPSTR)cname)) {748continue; /* not a TT font... */749}750registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data);751}752}753RegCloseKey(hkeyFonts);754ReleaseDC(NULL, screenDC);755screenDC = NULL;756}757758759