gdi32: Update the Windows font registry keys only when they have changed.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-11-03 11:28:20 +01:00
parent a6f0349e84
commit 000e32f183
3 changed files with 176 additions and 236 deletions

View File

@ -38,6 +38,7 @@
#include "resource.h"
#include "wine/exception.h"
#include "wine/heap.h"
#include "wine/rbtree.h"
#include "wine/unicode.h"
#include "wine/debug.h"
@ -3583,42 +3584,6 @@ static void init_font_options(void)
}
}
/***********************************************************************
* font_init
*/
void font_init(void)
{
static const WCHAR mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_',0};
HANDLE mutex;
DWORD disposition;
if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &wine_fonts_key, NULL ))
return;
init_font_options();
update_codepage();
if (!WineEngInit( &font_funcs )) return;
if (!(mutex = CreateMutexW( NULL, FALSE, mutex_nameW ))) return;
WaitForSingleObject( mutex, INFINITE );
RegCreateKeyExA( wine_fonts_key, "Cache", 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &wine_fonts_cache_key, &disposition );
if (disposition == REG_CREATED_NEW_KEY) font_funcs->load_fonts();
else load_font_list_from_cache();
ReleaseMutex( mutex );
reorder_font_list();
load_gdi_font_subst();
load_gdi_font_replacements();
load_system_links();
dump_gdi_font_list();
dump_gdi_font_subst();
}
static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
{
@ -7441,7 +7406,7 @@ static BOOL remove_font_resource( LPCWSTR file, DWORD flags )
return ret;
}
void load_system_bitmap_fonts(void)
static void load_system_bitmap_fonts(void)
{
static const WCHAR keyW[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s',0};
static const WCHAR fontsW[] = {'F','O','N','T','S','.','F','O','N',0};
@ -7482,7 +7447,7 @@ static void load_directory_fonts( WCHAR *path, UINT flags )
FindClose( handle );
}
void load_file_system_fonts(void)
static void load_file_system_fonts(void)
{
static const WCHAR pathW[] = {'P','a','t','h',0};
static const WCHAR slashstarW[] = {'\\','*',0};
@ -7513,7 +7478,121 @@ void load_file_system_fonts(void)
}
}
void load_registry_fonts(void)
struct external_key
{
struct wine_rb_entry entry;
BOOL found;
WCHAR value[LF_FULLFACESIZE + 12];
WCHAR path[1];
};
static int compare_external_key( const void *key, const struct wine_rb_entry *entry )
{
return strcmpiW( key, WINE_RB_ENTRY_VALUE( entry, struct external_key, entry )->value );
}
static struct wine_rb_tree external_keys = { compare_external_key };
static HKEY load_external_font_keys(void)
{
static const WCHAR externalW[] = {'E','x','t','e','r','n','a','l',' ','F','o','n','t','s',0};
WCHAR value[LF_FULLFACESIZE + 12], path[MAX_PATH];
DWORD i = 0, type, dlen, vlen;
struct external_key *key;
HKEY hkey;
if (RegCreateKeyW( wine_fonts_key, externalW, &hkey )) return 0;
vlen = ARRAY_SIZE(value);
dlen = sizeof(path);
while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (BYTE *)path, &dlen ))
{
if (type != REG_SZ) goto next;
dlen /= sizeof(WCHAR);
if (!(key = HeapAlloc( GetProcessHeap(), 0, offsetof(struct external_key, path[dlen]) ))) break;
key->found = FALSE;
strcpyW( key->value, value );
strcpyW( key->path, path );
wine_rb_put( &external_keys, value, &key->entry );
next:
vlen = ARRAY_SIZE(value);
dlen = sizeof(path);
}
return hkey;
}
static void update_external_font_keys( HKEY hkey )
{
static const WCHAR win9x_keyW[] = {'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','s',0};
static const WCHAR winnt_keyW[] = {'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s',' ','N','T','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','s',0};
static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')',0};
HKEY winnt_key = 0, win9x_key = 0;
struct gdi_font_family *family;
struct gdi_font_face *face;
struct wine_rb_entry *entry;
struct external_key *key, *next;
DWORD len;
BOOL skip;
WCHAR value[LF_FULLFACESIZE + 12], path[MAX_PATH];
WCHAR *file;
RegCreateKeyExW( HKEY_LOCAL_MACHINE, winnt_keyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL );
RegCreateKeyExW( HKEY_LOCAL_MACHINE, win9x_keyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL );
/* enumerate the fonts and add external ones to the two keys */
LIST_FOR_EACH_ENTRY( family, &font_list, struct gdi_font_family, entry )
{
LIST_FOR_EACH_ENTRY( face, &family->faces, struct gdi_font_face, entry )
{
if (!(face->flags & ADDFONT_EXTERNAL_FONT)) continue;
strcpyW( value, face->full_name );
if (face->scalable) strcatW( value, TrueType );
if (GetFullPathNameW( face->file, MAX_PATH, path, NULL ))
file = path;
else if ((file = strrchrW( face->file, '\\' )))
file++;
else
file = face->file;
skip = FALSE;
if ((entry = wine_rb_get( &external_keys, value )))
{
struct external_key *key = WINE_RB_ENTRY_VALUE( entry, struct external_key, entry );
skip = key->found && !strcmpiW( key->path, file );
wine_rb_remove_key( &external_keys, value );
HeapFree( GetProcessHeap(), 0, key );
}
if (skip) continue;
len = (strlenW(file) + 1) * sizeof(WCHAR);
RegSetValueExW( winnt_key, value, 0, REG_SZ, (BYTE *)file, len );
RegSetValueExW( win9x_key, value, 0, REG_SZ, (BYTE *)file, len );
RegSetValueExW( hkey, value, 0, REG_SZ, (BYTE *)file, len );
}
}
WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR( key, next, &external_keys, struct external_key, entry )
{
RegDeleteValueW( win9x_key, key->value );
RegDeleteValueW( winnt_key, key->value );
RegDeleteValueW( hkey, key->value );
wine_rb_remove_key( &external_keys, key->value );
HeapFree( GetProcessHeap(), 0, key );
}
RegCloseKey( win9x_key );
RegCloseKey( winnt_key );
}
static void load_registry_fonts(void)
{
static const WCHAR dot_fonW[] = {'.','f','o','n',0};
static const WCHAR win9x_key[] = {'S','o','f','t','w','a','r','e','\\',
@ -7526,8 +7605,9 @@ void load_registry_fonts(void)
'W','i','n','d','o','w','s',' ','N','T','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','s',0};
WCHAR value[MAX_PATH], data[MAX_PATH];
WCHAR value[LF_FULLFACESIZE + 12], data[MAX_PATH];
DWORD i = 0, type, dlen, vlen;
struct wine_rb_entry *entry;
HKEY hkey;
/* Look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
@ -7541,18 +7621,73 @@ void load_registry_fonts(void)
dlen = sizeof(data);
while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (LPBYTE)data, &dlen ))
{
if (type != REG_SZ) goto next;
dlen /= sizeof(WCHAR);
if ((entry = wine_rb_get( &external_keys, value )))
{
struct external_key *key = WINE_RB_ENTRY_VALUE( entry, struct external_key, entry );
if (!strcmpiW( key->path, data ))
{
key->found = TRUE;
goto next;
}
}
if (data[0] && data[1] == ':')
add_font_resource( data, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_TO_CACHE );
else if (dlen >= 6 && !strcmpiW( data + dlen - 5, dot_fonW ))
add_system_font_resource( data, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_TO_CACHE );
next:
vlen = ARRAY_SIZE(value);
dlen = sizeof(data);
}
RegCloseKey( hkey );
}
/***********************************************************************
* font_init
*/
void font_init(void)
{
static const WCHAR mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_',0};
HANDLE mutex;
DWORD disposition;
if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &wine_fonts_key, NULL ))
return;
init_font_options();
update_codepage();
if (!WineEngInit( &font_funcs )) return;
if (!(mutex = CreateMutexW( NULL, FALSE, mutex_nameW ))) return;
WaitForSingleObject( mutex, INFINITE );
RegCreateKeyExA( wine_fonts_key, "Cache", 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &wine_fonts_cache_key, &disposition );
if (disposition == REG_CREATED_NEW_KEY)
{
HKEY key = load_external_font_keys();
load_system_bitmap_fonts();
load_file_system_fonts();
load_registry_fonts();
font_funcs->load_fonts();
update_external_font_keys( key );
RegCloseKey( key );
}
else load_font_list_from_cache();
ReleaseMutex( mutex );
reorder_font_list();
load_gdi_font_subst();
load_gdi_font_replacements();
load_system_links();
dump_gdi_font_list();
dump_gdi_font_subst();
}
/***********************************************************************
* AddFontResourceExW (GDI32.@)
*/

View File

@ -250,19 +250,6 @@ static inline FT_Face get_ft_face( struct gdi_font *font )
static const struct font_backend_funcs font_funcs;
static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','s','\0'};
static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s',' ','N','T','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','s','\0'};
static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
static const WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
struct font_mapping
@ -1511,177 +1498,6 @@ static void load_mac_fonts(void)
#endif
static WCHAR *get_full_path_name(const WCHAR *name)
{
WCHAR *full_path;
DWORD len;
if (!(len = GetFullPathNameW(name, 0, NULL, NULL)))
{
ERR("GetFullPathNameW() failed, name %s.\n", debugstr_w(name));
return NULL;
}
if (!(full_path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*full_path))))
{
ERR("Could not get memory.\n");
return NULL;
}
if (GetFullPathNameW(name, len, full_path, NULL) != len - 1)
{
ERR("Unexpected GetFullPathNameW() result, name %s.\n", debugstr_w(name));
HeapFree(GetProcessHeap(), 0, full_path);
return NULL;
}
return full_path;
}
/*************************************************************
*
* This adds registry entries for any externally loaded fonts
* (fonts from fontconfig or FontDirs). It also deletes entries
* of no longer existing fonts.
*
*/
static void update_reg_entries(void)
{
HKEY winnt_key = 0, win9x_key = 0, external_key = 0;
LPWSTR valueW;
DWORD len;
Family *family;
Face *face;
WCHAR *file, *path;
static const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL) != ERROR_SUCCESS) {
ERR("Can't create Windows font reg key\n");
goto end;
}
if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL) != ERROR_SUCCESS) {
ERR("Can't create Windows font reg key\n");
goto end;
}
if(RegCreateKeyExW(HKEY_CURRENT_USER, external_fonts_reg_key,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &external_key, NULL) != ERROR_SUCCESS) {
ERR("Can't create external font reg key\n");
goto end;
}
/* enumerate the fonts and add external ones to the two keys */
LIST_FOR_EACH_ENTRY( family, &font_list, Family, entry ) {
LIST_FOR_EACH_ENTRY( face, &family->faces, Face, entry ) {
if (!(face->flags & ADDFONT_EXTERNAL_FONT)) continue;
len = strlenW( face->full_name ) + 1;
if (face->scalable)
len += ARRAY_SIZE(TrueType);
valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
strcpyW( valueW, face->full_name );
if (face->scalable)
strcatW(valueW, TrueType);
if ((path = get_full_path_name(face->file)))
{
file = path;
}
else if ((file = strrchrW(face->file, '\\')))
{
file++;
}
else
{
file = face->file;
}
len = strlenW(file) + 1;
RegSetValueExW(winnt_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
RegSetValueExW(win9x_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
RegSetValueExW(external_key, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
HeapFree(GetProcessHeap(), 0, path);
HeapFree(GetProcessHeap(), 0, valueW);
}
}
end:
if(external_key) RegCloseKey(external_key);
if(win9x_key) RegCloseKey(win9x_key);
if(winnt_key) RegCloseKey(winnt_key);
}
static void delete_external_font_keys(void)
{
HKEY winnt_key = 0, win9x_key = 0, external_key = 0;
DWORD dlen, plen, vlen, datalen, valuelen, i, type, path_type;
LPWSTR valueW;
LPVOID data;
BYTE *path;
if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, winnt_font_reg_key,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL) != ERROR_SUCCESS) {
ERR("Can't create Windows font reg key\n");
goto end;
}
if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, win9x_font_reg_key,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL) != ERROR_SUCCESS) {
ERR("Can't create Windows font reg key\n");
goto end;
}
if(RegCreateKeyW(HKEY_CURRENT_USER, external_fonts_reg_key, &external_key) != ERROR_SUCCESS) {
ERR("Can't create external font reg key\n");
goto end;
}
/* Delete all external fonts added last time */
RegQueryInfoKeyW(external_key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&valuelen, &datalen, NULL, NULL);
valuelen++; /* returned value doesn't include room for '\0' */
valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
data = HeapAlloc(GetProcessHeap(), 0, datalen);
path = HeapAlloc(GetProcessHeap(), 0, datalen);
dlen = datalen;
vlen = valuelen;
i = 0;
while(RegEnumValueW(external_key, i++, valueW, &vlen, NULL, &type, data,
&dlen) == ERROR_SUCCESS) {
plen = dlen;
if (RegQueryValueExW(winnt_key, valueW, 0, &path_type, path, &plen) == ERROR_SUCCESS &&
type == path_type && dlen == plen && !memcmp(data, path, plen))
RegDeleteValueW(winnt_key, valueW);
plen = dlen;
if (RegQueryValueExW(win9x_key, valueW, 0, &path_type, path, &plen) == ERROR_SUCCESS &&
type == path_type && dlen == plen && !memcmp(data, path, plen))
RegDeleteValueW(win9x_key, valueW);
/* reset dlen and vlen */
dlen = datalen;
vlen = valuelen;
}
HeapFree(GetProcessHeap(), 0, path);
HeapFree(GetProcessHeap(), 0, data);
HeapFree(GetProcessHeap(), 0, valueW);
/* Delete the old external fonts key */
RegCloseKey(external_key);
RegDeleteKeyW(HKEY_CURRENT_USER, external_fonts_reg_key);
end:
if(win9x_key) RegCloseKey(win9x_key);
if(winnt_key) RegCloseKey(winnt_key);
}
static BOOL init_freetype(void)
{
@ -1772,11 +1588,6 @@ sym_not_found:
*/
static void CDECL freetype_load_fonts(void)
{
delete_external_font_keys();
load_system_bitmap_fonts();
load_file_system_fonts();
load_registry_fonts();
#ifdef SONAME_LIBFONTCONFIG
load_fontconfig_fonts();
#elif defined(HAVE_CARBON_CARBON_H)
@ -1784,8 +1595,6 @@ static void CDECL freetype_load_fonts(void)
#elif defined(__ANDROID__)
ReadFontDir("/system/fonts", TRUE);
#endif
update_reg_entries();
}
/*************************************************************

View File

@ -449,10 +449,6 @@ struct font_backend_funcs
void (CDECL *destroy_font)( struct gdi_font *font );
};
extern void load_system_bitmap_fonts(void) DECLSPEC_HIDDEN;
extern void load_file_system_fonts(void) DECLSPEC_HIDDEN;
extern void load_registry_fonts(void) DECLSPEC_HIDDEN;
extern const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset ) DECLSPEC_HIDDEN;
extern struct list font_list DECLSPEC_HIDDEN;