From 457642cc4ad7c3db294a509248ff7b9d7331d93e Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 26 Mar 2025 18:58:12 +0900 Subject: [PATCH] [FONTEXT] Refactor (#7821) Improve code flexibility. JIRA issue: CORE-12861 - Delete excessive virtual keywords and add overload keywords. - Add InstallFontFiles helper function. - Add strMsg parameter to DoInstallFontFile function. - Move DoInstallFontFile and DoGetFontTitle functions outside the class. - Delete needless fontext.h. --- dll/shellext/fontext/CDataObject.cpp | 3 - dll/shellext/fontext/CEnumFonts.cpp | 22 ++-- dll/shellext/fontext/CFontCache.cpp | 1 - dll/shellext/fontext/CFontCache.hpp | 5 - dll/shellext/fontext/CFontExt.cpp | 144 ++------------------------- dll/shellext/fontext/CFontExt.hpp | 64 ++++++------ dll/shellext/fontext/CFontMenu.cpp | 4 - dll/shellext/fontext/fontext.cpp | 128 +++++++++++++++++++++++- dll/shellext/fontext/fontext.h | 24 ----- dll/shellext/fontext/fontpidl.cpp | 1 - dll/shellext/fontext/fontpidl.hpp | 2 - dll/shellext/fontext/precomp.h | 27 ++++- 12 files changed, 197 insertions(+), 228 deletions(-) delete mode 100644 dll/shellext/fontext/fontext.h diff --git a/dll/shellext/fontext/CDataObject.cpp b/dll/shellext/fontext/CDataObject.cpp index bff70910043..8c94a5bc4a0 100644 --- a/dll/shellext/fontext/CDataObject.cpp +++ b/dll/shellext/fontext/CDataObject.cpp @@ -9,7 +9,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(fontext); - #if 0 static inline void DumpDataObjectFormats(IDataObject* pObject) { @@ -34,7 +33,6 @@ static inline void DumpDataObjectFormats(IDataObject* pObject) } #endif - HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, LPVOID* ppvOut) { @@ -99,4 +97,3 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl, PCUITEM return hr; } - diff --git a/dll/shellext/fontext/CEnumFonts.cpp b/dll/shellext/fontext/CEnumFonts.cpp index 957e816d322..95d67bc117f 100644 --- a/dll/shellext/fontext/CEnumFonts.cpp +++ b/dll/shellext/fontext/CEnumFonts.cpp @@ -9,8 +9,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(fontext); - - class CEnumFonts : public CComObjectRootEx, public IEnumIDList @@ -21,12 +19,12 @@ private: public: CEnumFonts() - :m_dwFlags(0) - ,m_Index(0) + : m_dwFlags(0) + , m_Index(0) { } - STDMETHODIMP Initialize(CFontExt* folder, DWORD flags) + HRESULT Initialize(CFontExt* folder, DWORD flags) { m_dwFlags = flags; m_Index = 0; @@ -34,7 +32,7 @@ public: } // *** IEnumIDList methods *** - STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) + STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) override { if (!rgelt || (!pceltFetched && celt != 1)) return E_POINTER; @@ -69,22 +67,24 @@ public: *pceltFetched = Fetched; return hr; } - STDMETHODIMP Skip(ULONG celt) + + STDMETHODIMP Skip(ULONG celt) override { m_Index += celt; return S_OK; } - STDMETHODIMP Reset() + + STDMETHODIMP Reset() override { m_Index = 0; return S_OK; } - STDMETHODIMP Clone(IEnumIDList **ppenum) + + STDMETHODIMP Clone(IEnumIDList **ppenum) override { return E_NOTIMPL; } - public: DECLARE_NOT_AGGREGATABLE(CEnumFonts) DECLARE_PROTECT_FINAL_CONSTRUCT() @@ -94,9 +94,7 @@ public: END_COM_MAP() }; - HRESULT _CEnumFonts_CreateInstance(CFontExt* zip, DWORD flags, REFIID riid, LPVOID * ppvOut) { return ShellObjectCreatorInit(zip, flags, riid, ppvOut); } - diff --git a/dll/shellext/fontext/CFontCache.cpp b/dll/shellext/fontext/CFontCache.cpp index 53a7a5a6aec..28413779b54 100644 --- a/dll/shellext/fontext/CFontCache.cpp +++ b/dll/shellext/fontext/CFontCache.cpp @@ -241,4 +241,3 @@ void CFontCache::Read() Index++; } } - diff --git a/dll/shellext/fontext/CFontCache.hpp b/dll/shellext/fontext/CFontCache.hpp index ba9d9e39636..48435bf008c 100644 --- a/dll/shellext/fontext/CFontCache.hpp +++ b/dll/shellext/fontext/CFontCache.hpp @@ -7,7 +7,6 @@ #pragma once - class CFontInfo { private: @@ -34,7 +33,6 @@ public: DWORD FileAttributes(); }; - class CFontCache { private: @@ -61,7 +59,4 @@ public: friend class CFontExtModule; }; - extern CFontCache* g_FontCache; - - diff --git a/dll/shellext/fontext/CFontExt.cpp b/dll/shellext/fontext/CFontExt.cpp index 3a011bb3f77..cf770e21c8e 100644 --- a/dll/shellext/fontext/CFontExt.cpp +++ b/dll/shellext/fontext/CFontExt.cpp @@ -3,11 +3,10 @@ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: CFontExt implementation * COPYRIGHT: Copyright 2019-2021 Mark Jansen - * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + * Copyright 2019-2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) */ #include "precomp.h" -#include "undocgdi.h" // for GetFontResourceInfoW WINE_DEFAULT_DEBUG_CHANNEL(fontext); @@ -41,7 +40,6 @@ static FolderViewColumns g_ColumnDefs[] = { IDS_COL_ATTR, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 12, LVCFMT_RIGHT }, }; - // Helper functions to translate a guid to a readable name bool GetInterfaceName(const WCHAR* InterfaceString, WCHAR* buf, size_t size) { @@ -79,7 +77,6 @@ WCHAR* g2s(REFCLSID iid) return buf[idx]; } - CFontExt::CFontExt() { InterlockedIncrement(&g_ModuleRefCnt); @@ -365,7 +362,6 @@ STDMETHODIMP CFontExt::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, D return S_OK; } - STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) { if (riid == IID_IContextMenu || @@ -456,7 +452,6 @@ STDMETHODIMP CFontExt::GetCurFolder(LPITEMIDLIST *ppidl) return E_POINTER; } - // *** IPersistFolder methods *** STDMETHODIMP CFontExt::Initialize(LPCITEMIDLIST pidl) { @@ -487,7 +482,6 @@ STDMETHODIMP CFontExt::Initialize(LPCITEMIDLIST pidl) return S_OK; } - // *** IPersist methods *** STDMETHODIMP CFontExt::GetClassID(CLSID *lpClassId) { @@ -523,7 +517,7 @@ STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, *pdwEffect = DROPEFFECT_NONE; CDataObjectHIDA cida(pDataObj); - if (!cida) + if (!cida || cida->cidl <= 0) return E_UNEXPECTED; PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(cida); @@ -533,71 +527,23 @@ STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, return E_FAIL; } - BOOL bOK = TRUE; - CAtlArray FontPaths; + CAtlArray apidl; for (UINT n = 0; n < cida->cidl; ++n) { PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(cida, n); if (!pidlRelative) - continue; + return E_FAIL; - PIDLIST_ABSOLUTE pidl = ILCombine(pidlParent, pidlRelative); - if (!pidl) - { - ERR("ILCombine failed\n"); - bOK = FALSE; - break; - } - - WCHAR szPath[MAX_PATH]; - BOOL ret = SHGetPathFromIDListW(pidl, szPath); - ILFree(pidl); - - if (!ret) - { - ERR("SHGetPathFromIDListW failed\n"); - bOK = FALSE; - break; - } - - if (PathIsDirectoryW(szPath)) - { - ERR("PathIsDirectory\n"); - bOK = FALSE; - break; - } - - LPCWSTR pchDotExt = PathFindExtensionW(szPath); - if (!IsFontDotExt(pchDotExt)) - { - ERR("'%S' is not supported\n", pchDotExt); - bOK = FALSE; - break; - } - - FontPaths.Add(szPath); + apidl.Add(pidlRelative); } - if (!bOK) - return E_FAIL; - - CRegKey keyFonts; - if (keyFonts.Open(FONT_HIVE, FONT_KEY, KEY_WRITE) != ERROR_SUCCESS) + CStringW strMessage; + if (InstallFontFiles(strMessage, pidlParent, cida->cidl, &apidl[0]) != S_OK) { - ERR("keyFonts.Open failed\n"); + // TODO: Show message return E_FAIL; } - for (size_t iItem = 0; iItem < FontPaths.GetCount(); ++iItem) - { - HRESULT hr = DoInstallFontFile(FontPaths[iItem], g_FontCache->FontPath(), keyFonts.m_hKey); - if (FAILED_UNEXPECTEDLY(hr)) - { - bOK = FALSE; - break; - } - } - // Invalidate our cache g_FontCache->Read(); @@ -609,79 +555,5 @@ STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, // TODO: Show message - return bOK ? S_OK : E_FAIL; -} - -HRESULT CFontExt::DoInstallFontFile(LPCWSTR pszFontPath, LPCWSTR pszFontsDir, HKEY hkeyFonts) -{ - WCHAR szDestFile[MAX_PATH]; - - // Add this font to the font list, so we can query the name - if (!AddFontResourceW(pszFontPath)) - { - ERR("AddFontResourceW('%S') failed\n", pszFontPath); - DeleteFileW(szDestFile); - return E_FAIL; - } - - CStringW strFontName; - HRESULT hr = DoGetFontTitle(pszFontPath, strFontName); - - // We got the name, remove it again - RemoveFontResourceW(pszFontPath); - - if (!SUCCEEDED(hr)) - { - ERR("DoGetFontTitle failed (err=0x%x)!\n", hr); - return hr; - } - - StringCchCopyW(szDestFile, sizeof(szDestFile), pszFontsDir); - - LPCWSTR pszFileTitle = PathFindFileName(pszFontPath); - PathAppendW(szDestFile, pszFileTitle); - if (!CopyFileW(pszFontPath, szDestFile, FALSE)) - { - ERR("CopyFileW('%S', '%S') failed\n", pszFontPath, szDestFile); - return E_FAIL; - } - - DWORD cbData = (wcslen(pszFileTitle) + 1) * sizeof(WCHAR); - LONG nError = RegSetValueExW(hkeyFonts, strFontName, 0, REG_SZ, - (const BYTE *)pszFileTitle, cbData); - if (nError) - { - ERR("RegSetValueExW failed with %ld\n", nError); - DeleteFileW(szDestFile); - return E_FAIL; - } - - AddFontResourceW(szDestFile); - return S_OK; } - -HRESULT -CFontExt::DoGetFontTitle(IN LPCWSTR pszFontPath, OUT CStringW& strFontName) -{ - DWORD cbInfo = 0; - BOOL ret = GetFontResourceInfoW(pszFontPath, &cbInfo, NULL, 1); - if (!ret || !cbInfo) - { - ERR("GetFontResourceInfoW failed (err: %u)\n", GetLastError()); - return E_FAIL; - } - - LPWSTR pszBuffer = strFontName.GetBuffer(cbInfo / sizeof(WCHAR)); - ret = GetFontResourceInfoW(pszFontPath, &cbInfo, pszBuffer, 1); - DWORD dwErr = GetLastError();; - strFontName.ReleaseBuffer(); - if (ret) - { - TRACE("pszFontName: %S\n", (LPCWSTR)strFontName); - return S_OK; - } - - ERR("GetFontResourceInfoW failed (err: %u)\n", dwErr); - return E_FAIL; -} diff --git a/dll/shellext/fontext/CFontExt.hpp b/dll/shellext/fontext/CFontExt.hpp index a3e5431c90f..c95952d8114 100644 --- a/dll/shellext/fontext/CFontExt.hpp +++ b/dll/shellext/fontext/CFontExt.hpp @@ -3,7 +3,7 @@ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: CFontExt definition * COPYRIGHT: Copyright 2019,2020 Mark Jansen - * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + * Copyright 2019-2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) */ #pragma once @@ -18,46 +18,50 @@ class CFontExt : CComHeapPtr m_Folder; public: - CFontExt(); ~CFontExt(); // *** IShellFolder2 methods *** - virtual STDMETHODIMP GetDefaultSearchGUID(GUID *lpguid); - virtual STDMETHODIMP EnumSearches(IEnumExtraSearch **ppenum); - virtual STDMETHODIMP GetDefaultColumn(DWORD dwReserved, ULONG *pSort, ULONG *pDisplay); - virtual STDMETHODIMP GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags); - virtual STDMETHODIMP GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv); - virtual STDMETHODIMP GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd); - virtual STDMETHODIMP MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid); + STDMETHODIMP GetDefaultSearchGUID(GUID *lpguid) override; + STDMETHODIMP EnumSearches(IEnumExtraSearch **ppenum) override; + STDMETHODIMP GetDefaultColumn(DWORD dwReserved, ULONG *pSort, ULONG *pDisplay) override; + STDMETHODIMP GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags) override; + STDMETHODIMP GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) override; + STDMETHODIMP GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd) override; + STDMETHODIMP MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid) override; // *** IShellFolder methods *** - virtual STDMETHODIMP ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes); - virtual STDMETHODIMP EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList); - virtual STDMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut); - virtual STDMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut); - virtual STDMETHODIMP CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2); - virtual STDMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut); - virtual STDMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut); - virtual STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut); - virtual STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet); - virtual STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut); - + STDMETHODIMP ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, + PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override; + STDMETHODIMP EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override; + STDMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, + LPVOID *ppvOut) override; + STDMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, + LPVOID *ppvOut) override; + STDMETHODIMP CompareIDs(LPARAM lParam, + PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) override; + STDMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) override; + STDMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) override; + STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, + UINT * prgfInOut, LPVOID * ppvOut) override; + STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) override; + STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, + PITEMID_CHILD *pPidlOut) override; // *** IPersistFolder2 methods *** - virtual STDMETHODIMP GetCurFolder(LPITEMIDLIST *ppidl); + STDMETHODIMP GetCurFolder(LPITEMIDLIST *ppidl) override; // *** IPersistFolder methods *** - virtual STDMETHODIMP Initialize(LPCITEMIDLIST pidl); + STDMETHODIMP Initialize(LPCITEMIDLIST pidl) override; // *** IPersist methods *** - virtual STDMETHODIMP GetClassID(CLSID *lpClassId); + STDMETHODIMP GetClassID(CLSID *lpClassId) override; // *** IDropTarget methods *** - virtual STDMETHODIMP DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect); - virtual STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect); - virtual STDMETHODIMP DragLeave(); - virtual STDMETHODIMP Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect); + STDMETHODIMP DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override; + STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override; + STDMETHODIMP DragLeave() override; + STDMETHODIMP Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override; #if 0 static HRESULT WINAPI log_stuff(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw) @@ -72,10 +76,7 @@ public: } #endif -protected: - public: - DECLARE_REGISTRY_RESOURCEID(IDR_FONTEXT) DECLARE_NOT_AGGREGATABLE(CFontExt) @@ -89,7 +90,4 @@ public: COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) //COM_INTERFACE_ENTRY_FUNC_BLIND(0, log_stuff) END_COM_MAP() - - HRESULT DoInstallFontFile(LPCWSTR pszFontPath, LPCWSTR pszFontsDir, HKEY hkeyFonts); - HRESULT DoGetFontTitle(IN LPCWSTR pszFontPath, OUT CStringW& strFontName); }; diff --git a/dll/shellext/fontext/CFontMenu.cpp b/dll/shellext/fontext/CFontMenu.cpp index a57e1843c65..a8c70f359b7 100644 --- a/dll/shellext/fontext/CFontMenu.cpp +++ b/dll/shellext/fontext/CFontMenu.cpp @@ -9,7 +9,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(fontext); - const char* DFM_TO_STR(UINT uMsg) { switch(uMsg) @@ -31,7 +30,6 @@ const char* DFM_TO_STR(UINT uMsg) } } - static void RunFontViewer(HWND hwnd, const FontPidlEntry* fontEntry) { WCHAR FontViewerPath[MAX_PATH] = L"%SystemRoot%\\System32\\fontview.exe"; @@ -110,7 +108,6 @@ static HRESULT CALLBACK FontFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDa return E_NOTIMPL; } - HRESULT _CFontMenu_CreateInstance(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, IShellFolder *psf, REFIID riid, LPVOID* ppvOut) { @@ -133,4 +130,3 @@ HRESULT _CFontMenu_CreateInstance(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY ap // We can't create a background menu return E_FAIL; } - diff --git a/dll/shellext/fontext/fontext.cpp b/dll/shellext/fontext/fontext.cpp index f56a8849830..c72f620515a 100644 --- a/dll/shellext/fontext/fontext.cpp +++ b/dll/shellext/fontext/fontext.cpp @@ -6,12 +6,12 @@ */ #include "precomp.h" +#include "undocgdi.h" // for GetFontResourceInfoW WINE_DEFAULT_DEBUG_CHANNEL(fontext); const GUID CLSID_CFontExt = { 0xbd84b380, 0x8ca2, 0x1069, { 0xab, 0x1d, 0x08, 0x00, 0x09, 0x48, 0xf5, 0x34 } }; - class CFontExtModule : public CComModule { public: @@ -33,11 +33,9 @@ BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_CFontExt, CFontExt) END_OBJECT_MAP() - LONG g_ModuleRefCnt; CFontExtModule gModule; - STDAPI DllCanUnloadNow() { if (g_ModuleRefCnt) @@ -50,7 +48,6 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) return gModule.DllGetClassObject(rclsid, riid, ppv); } - STDAPI DllRegisterServer() { WCHAR Path[MAX_PATH] = { 0 }; @@ -103,6 +100,129 @@ STDAPI DllUnregisterServer() return gModule.DllUnregisterServer(FALSE); } +HRESULT +InstallFontFiles( + _Out_ CStringW& strMsg, + _In_ PCUIDLIST_ABSOLUTE pidlParent, + _In_ UINT cidl, + _In_ PCUITEMID_CHILD_ARRAY apidl) +{ + CAtlArray FontPaths; + for (UINT n = 0; n < cidl; ++n) + { + CComHeapPtr pidl; + pidl.Attach(ILCombine(pidlParent, apidl[n])); + if (!pidl) + { + ERR("Out of memory\n"); + return E_OUTOFMEMORY; + } + + WCHAR szPath[MAX_PATH]; + if (!SHGetPathFromIDListW(pidl, szPath) || PathIsDirectoryW(szPath) || + !IsFontDotExt(PathFindExtensionW(szPath))) + { + ERR("Not font file: %s\n", wine_dbgstr_w(szPath)); + return E_FAIL; + } + + FontPaths.Add(szPath); + } + + CRegKey keyFonts; + if (keyFonts.Open(FONT_HIVE, FONT_KEY, KEY_WRITE) != ERROR_SUCCESS) + { + ERR("CRegKey::Open failed\n"); + return E_FAIL; + } + + for (SIZE_T iItem = 0; iItem < FontPaths.GetCount(); ++iItem) + { + HRESULT hr = DoInstallFontFile(strMsg, FontPaths[iItem], g_FontCache->FontPath(), keyFonts); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + } + + return S_OK; +} + +HRESULT +DoInstallFontFile( + _Out_ CStringW& strMsg, + _In_ PCWSTR pszFontPath, + _In_ PCWSTR pszFontsDir, + _In_ HKEY hkeyFonts) +{ + WCHAR szDestFile[MAX_PATH]; + + // Add this font to the font list, so we can query the name + if (!AddFontResourceW(pszFontPath)) + { + ERR("AddFontResourceW('%S') failed\n", pszFontPath); + return E_FAIL; + } + + CStringW strFontName; + HRESULT hr = DoGetFontTitle(pszFontPath, strFontName); + + // We got the name, remove it again + RemoveFontResourceW(pszFontPath); + + if (!SUCCEEDED(hr)) + { + ERR("DoGetFontTitle failed (err=0x%x)!\n", hr); + return hr; + } + + StringCchCopyW(szDestFile, sizeof(szDestFile), pszFontsDir); + + LPCWSTR pszFileTitle = PathFindFileName(pszFontPath); + PathAppendW(szDestFile, pszFileTitle); + if (!CopyFileW(pszFontPath, szDestFile, FALSE)) + { + ERR("CopyFileW('%S', '%S') failed\n", pszFontPath, szDestFile); + return E_FAIL; + } + + DWORD cbData = (wcslen(pszFileTitle) + 1) * sizeof(WCHAR); + LONG nError = RegSetValueExW(hkeyFonts, strFontName, 0, REG_SZ, + (const BYTE *)pszFileTitle, cbData); + if (nError) + { + ERR("RegSetValueExW failed with %ld\n", nError); + DeleteFileW(szDestFile); + return E_FAIL; + } + + return AddFontResourceW(szDestFile) ? S_OK : E_FAIL; +} + +HRESULT +DoGetFontTitle( + _In_ LPCWSTR pszFontPath, + _Out_ CStringW& strFontName) +{ + DWORD cbInfo = 0; + BOOL ret = GetFontResourceInfoW(pszFontPath, &cbInfo, NULL, 1); + if (!ret || !cbInfo) + { + ERR("GetFontResourceInfoW failed (err: %u)\n", GetLastError()); + return E_FAIL; + } + + LPWSTR pszBuffer = strFontName.GetBuffer(cbInfo / sizeof(WCHAR)); + ret = GetFontResourceInfoW(pszFontPath, &cbInfo, pszBuffer, 1); + DWORD dwErr = GetLastError();; + strFontName.ReleaseBuffer(); + if (ret) + { + TRACE("pszFontName: %S\n", (LPCWSTR)strFontName); + return S_OK; + } + + ERR("GetFontResourceInfoW failed (err: %u)\n", dwErr); + return E_FAIL; +} EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) diff --git a/dll/shellext/fontext/fontext.h b/dll/shellext/fontext/fontext.h deleted file mode 100644 index a5dd1d08839..00000000000 --- a/dll/shellext/fontext/fontext.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef FONTEXT_PRECOMP_H -#define FONTEXT_PRECOMP_H - - -#define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern const GUID CLSID_CFontExt; - -#include "CFontExt.hpp" - - -#endif /* FONTEXT_PRECOMP_H */ diff --git a/dll/shellext/fontext/fontpidl.cpp b/dll/shellext/fontext/fontpidl.cpp index 6354e848bf2..8e7c75dc136 100644 --- a/dll/shellext/fontext/fontpidl.cpp +++ b/dll/shellext/fontext/fontpidl.cpp @@ -28,7 +28,6 @@ LPITEMIDLIST _ILCreate(LPCWSTR lpString, ULONG Index) return (LPITEMIDLIST)pidl; } - const FontPidlEntry* _FontFromIL(LPCITEMIDLIST pidl) { const FontPidlEntry* fontEntry = (const FontPidlEntry*)pidl; diff --git a/dll/shellext/fontext/fontpidl.hpp b/dll/shellext/fontext/fontpidl.hpp index 1546f646f78..4944c3bd498 100644 --- a/dll/shellext/fontext/fontpidl.hpp +++ b/dll/shellext/fontext/fontpidl.hpp @@ -18,7 +18,5 @@ struct FontPidlEntry }; #include - LPITEMIDLIST _ILCreate(LPCWSTR lpString, ULONG Index); const FontPidlEntry* _FontFromIL(LPCITEMIDLIST pidl); - diff --git a/dll/shellext/fontext/precomp.h b/dll/shellext/fontext/precomp.h index 2e46032986d..609a4ce7d2c 100644 --- a/dll/shellext/fontext/precomp.h +++ b/dll/shellext/fontext/precomp.h @@ -1,6 +1,11 @@ -#ifndef FONTEXT_PRECOMP_H -#define FONTEXT_PRECOMP_H +/* + * PROJECT: ReactOS Font Shell Extension + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Font folder shell extension + * COPYRIGHT: Copyright 2019,2020 Mark Jansen + */ +#pragma once #define WIN32_NO_STATUS #define COM_NO_WINDOWS_H @@ -50,4 +55,20 @@ inline BOOL IsFontDotExt(LPCWSTR pchDotExt) return FALSE; } -#endif /* FONTEXT_PRECOMP_H */ +HRESULT +InstallFontFiles( + _Out_ CStringW& strMessage, + _In_ PCUIDLIST_ABSOLUTE pidlParent, + _In_ UINT cidl, + _In_ PCUITEMID_CHILD_ARRAY apidl); + +HRESULT +DoInstallFontFile( + _Out_ CStringW& strMsg, + _In_ PCWSTR pszFontPath, + _In_ PCWSTR pszFontsDir, + _In_ HKEY hkeyFonts); + +HRESULT DoGetFontTitle( + _In_ PCWSTR pszFontPath, + _Out_ CStringW& strFontName);