1 /* 2 * PROJECT: ReactOS Font Shell Extension 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: font list cache handling 5 * COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 WINE_DEFAULT_DEBUG_CHANNEL(fontext); 11 12 CFontCache* g_FontCache = NULL; 13 14 CFontInfo::CFontInfo(LPCWSTR name) 15 : m_Name(name) 16 , m_FileRead(false) 17 { 18 } 19 20 const CStringW& CFontInfo::Name() const 21 { 22 return m_Name; 23 } 24 25 const bool CFontInfo::Valid() const 26 { 27 return !m_Name.IsEmpty(); 28 } 29 30 const CStringW& CFontInfo::File() 31 { 32 if (!m_FileRead) 33 { 34 if (Valid()) 35 { 36 // Read the filename stored in the registry. 37 // This can be either a filename or a full path 38 CRegKey key; 39 if (key.Open(FONT_HIVE, FONT_KEY, KEY_READ) == ERROR_SUCCESS) 40 { 41 CStringW Value; 42 DWORD dwAllocated = 128; 43 LSTATUS Status; 44 do 45 { 46 DWORD dwSize = dwAllocated; 47 PWSTR Buffer = Value.GetBuffer(dwSize); 48 Status = key.QueryStringValue(m_Name, Buffer, &dwSize); 49 Value.ReleaseBuffer(dwSize); 50 if (Status == ERROR_SUCCESS) 51 { 52 // Ensure we do not re-use the same string object, by passing it a PCWSTR 53 m_File = Value.GetString(); 54 break; 55 } 56 dwAllocated += 128; 57 } while (Status == ERROR_MORE_DATA); 58 } 59 } 60 m_FileRead = true; 61 } 62 return m_File; 63 } 64 65 66 67 CFontCache::CFontCache() 68 { 69 } 70 71 void CFontCache::SetFontDir(const LPCWSTR Path) 72 { 73 if (m_FontFolderPath.IsEmpty()) 74 m_FontFolderPath = Path; 75 } 76 77 size_t CFontCache::Size() 78 { 79 if (m_Fonts.GetCount() == 0u) 80 Read(); 81 82 return m_Fonts.GetCount(); 83 } 84 85 CStringW CFontCache::Name(size_t Index) 86 { 87 if (m_Fonts.GetCount() == 0u) 88 Read(); 89 90 if (Index >= m_Fonts.GetCount()) 91 return CStringW(); 92 93 return m_Fonts[Index].Name(); 94 } 95 96 CStringW CFontCache::Filename(const FontPidlEntry* fontEntry, bool alwaysFullPath) 97 { 98 CStringW File; 99 100 if (fontEntry->Index < m_Fonts.GetCount()) 101 { 102 CFontInfo& info = m_Fonts[fontEntry->Index]; 103 104 if (info.Name().CompareNoCase(fontEntry->Name) == 0) 105 File = info.File(); 106 } 107 108 for (UINT n = 0; File.IsEmpty() && n < Size(); ++n) 109 { 110 if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0) 111 File = m_Fonts[n].File(); 112 } 113 114 if (!File.IsEmpty() && alwaysFullPath) 115 { 116 // Ensure this is a full path 117 if (PathIsRelativeW(File)) 118 { 119 File = m_FontFolderPath + File; 120 } 121 } 122 123 return File; 124 } 125 126 void CFontCache::Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName) 127 { 128 POSITION it = fonts.GetHeadPosition(); 129 while (it != NULL) 130 { 131 POSITION lastit = it; 132 const CFontInfo& info = fonts.GetNext(it); 133 if (info.Name().CompareNoCase(KeyName) >= 0) 134 { 135 fonts.InsertBefore(lastit, CFontInfo(KeyName)); 136 return; 137 } 138 } 139 fonts.AddTail(CFontInfo(KeyName)); 140 } 141 142 void CFontCache::Read() 143 { 144 CAtlList<CFontInfo> fonts; 145 CRegKey key; 146 147 // Enumerate all registered font names 148 if (key.Open(FONT_HIVE, FONT_KEY, KEY_READ) == ERROR_SUCCESS) 149 { 150 LSTATUS Status; 151 DWORD dwAllocated = 128; 152 DWORD ilIndex = 0; 153 CStringW KeyName; 154 do 155 { 156 DWORD dwSize = dwAllocated; 157 PWSTR Buffer = KeyName.GetBuffer(dwSize); 158 Status = RegEnumValueW(key.m_hKey, ilIndex, Buffer, &dwSize, NULL, NULL, NULL, NULL); 159 KeyName.ReleaseBuffer(dwSize); 160 if (Status == ERROR_SUCCESS) 161 { 162 // Insert will create an ordered list 163 Insert(fonts, KeyName); 164 ilIndex++; 165 continue; 166 } 167 if (Status == ERROR_NO_MORE_ITEMS) 168 break; 169 else if (Status == ERROR_MORE_DATA) 170 { 171 dwAllocated += 128; 172 } 173 } while (Status == ERROR_MORE_DATA || Status == ERROR_SUCCESS); 174 } 175 176 // Move the fonts from a list to an array (for easy indexing) 177 m_Fonts.SetCount(fonts.GetCount()); 178 size_t Index = 0; 179 POSITION it = fonts.GetHeadPosition(); 180 while (it != NULL) 181 { 182 m_Fonts[Index] = fonts.GetNext(it); 183 Index++; 184 } 185 } 186 187