https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c214c0496477a9f3e7aa6…
commit c214c0496477a9f3e7aa65c063cbf0cdf66f175a
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Nov 12 20:26:56 2019 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Nov 12 20:26:56 2019 +0900
[SHELLEXT][FONTEXT] An attempt to implement IDropTarget (#2019)
CORE-12861
---
dll/shellext/fontext/CFontCache.cpp | 4 -
dll/shellext/fontext/CFontExt.cpp | 173 +++++++++++++++++++++++++++++++++++-
dll/shellext/fontext/CFontExt.hpp | 13 ++-
dll/shellext/fontext/CFontMenu.cpp | 12 +--
dll/shellext/fontext/CMakeLists.txt | 2 +-
dll/shellext/fontext/precomp.h | 26 ++++++
6 files changed, 211 insertions(+), 19 deletions(-)
diff --git a/dll/shellext/fontext/CFontCache.cpp b/dll/shellext/fontext/CFontCache.cpp
index 4d3ae5fcdf5..8bccf346582 100644
--- a/dll/shellext/fontext/CFontCache.cpp
+++ b/dll/shellext/fontext/CFontCache.cpp
@@ -9,10 +9,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(fontext);
-
-#define FONT_HIVE HKEY_LOCAL_MACHINE
-#define FONT_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
-
CFontCache* g_FontCache = NULL;
CFontInfo::CFontInfo(LPCWSTR name)
diff --git a/dll/shellext/fontext/CFontExt.cpp b/dll/shellext/fontext/CFontExt.cpp
index de502a43fdb..1ce5325500a 100644
--- a/dll/shellext/fontext/CFontExt.cpp
+++ b/dll/shellext/fontext/CFontExt.cpp
@@ -3,6 +3,7 @@
* LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontExt implementation
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen(a)reactos.org)
+ * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
*/
#include "precomp.h"
@@ -196,9 +197,10 @@ STDMETHODIMP CFontExt::CreateViewObject(HWND hwndOwner, REFIID riid,
LPVOID *ppv
if (IsEqualIID(riid, IID_IDropTarget))
{
- // Needed to drop files into the fonts folder, we should probably install them?
ERR("IDropTarget not implemented\n");
- hr = E_NOTIMPL;
+ *ppvOut = static_cast<IDropTarget *>(this);
+ AddRef();
+ hr = S_OK;
}
else if (IsEqualIID(riid, IID_IContextMenu))
{
@@ -363,3 +365,170 @@ STDMETHODIMP CFontExt::GetClassID(CLSID *lpClassId)
return S_OK;
}
+// *** IDropTarget methods ***
+STDMETHODIMP CFontExt::DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt,
DWORD* pdwEffect)
+{
+ *pdwEffect = DROPEFFECT_NONE;
+
+ CComHeapPtr<CIDA> cida;
+ HRESULT hr = _GetCidlFromDataObject(pDataObj, &cida);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+#if 1 // Please implement DoGetFontTitle
+ return DRAGDROP_S_CANCEL;
+#else
+ *pdwEffect = DROPEFFECT_COPY;
+ return S_OK;
+#endif
+}
+
+STDMETHODIMP CFontExt::DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CFontExt::DragLeave()
+{
+ return S_OK;
+}
+
+STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD*
pdwEffect)
+{
+ *pdwEffect = DROPEFFECT_NONE;
+
+ WCHAR szFontsDir[MAX_PATH];
+ HRESULT hr = SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, szFontsDir);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return E_FAIL;
+
+ CComHeapPtr<CIDA> cida;
+ hr = _GetCidlFromDataObject(pDataObj, &cida);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(cida);
+ if (!pidlParent)
+ {
+ ERR("pidlParent is NULL\n");
+ return E_FAIL;
+ }
+
+ BOOL bOK = TRUE;
+ CAtlArray<CStringW> FontPaths;
+ for (UINT n = 0; n < cida->cidl; ++n)
+ {
+ PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(cida, n);
+ if (!pidlRelative)
+ continue;
+
+ 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);
+ }
+
+ if (!bOK)
+ return E_FAIL;
+
+ CRegKey keyFonts;
+ if (keyFonts.Open(FONT_HIVE, FONT_KEY, KEY_WRITE) != ERROR_SUCCESS)
+ {
+ ERR("keyFonts.Open failed\n");
+ return E_FAIL;
+ }
+
+ for (size_t iItem = 0; iItem < FontPaths.GetCount(); ++iItem)
+ {
+ HRESULT hr = DoInstallFontFile(FontPaths[iItem], szFontsDir, keyFonts.m_hKey);
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ bOK = FALSE;
+ break;
+ }
+ }
+
+ // TODO: update g_FontCache
+
+ SendMessageW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
+
+ // TODO: Show message
+
+ return bOK ? S_OK : E_FAIL;
+}
+
+HRESULT CFontExt::DoInstallFontFile(LPCWSTR pszFontPath, LPCWSTR pszFontsDir, HKEY
hkeyFonts)
+{
+ WCHAR szDestFile[MAX_PATH];
+ LPCWSTR pszFileTitle = PathFindFileName(pszFontPath);
+
+ WCHAR szFontName[512];
+ if (!DoGetFontTitle(pszFontPath, szFontName))
+ return E_FAIL;
+
+ RemoveFontResourceW(pszFileTitle);
+
+ StringCchCopyW(szDestFile, sizeof(szDestFile), pszFontsDir);
+ PathAppendW(szDestFile, pszFileTitle);
+ if (!CopyFileW(pszFontPath, szDestFile, FALSE))
+ {
+ ERR("CopyFileW('%S', '%S') failed\n", pszFontPath,
szDestFile);
+ return E_FAIL;
+ }
+
+ if (!AddFontResourceW(pszFileTitle))
+ {
+ ERR("AddFontResourceW('%S') failed\n", pszFileTitle);
+ DeleteFileW(szDestFile);
+ return E_FAIL;
+ }
+
+ DWORD cbData = (wcslen(pszFileTitle) + 1) * sizeof(WCHAR);
+ LONG nError = RegSetValueExW(hkeyFonts, szFontName, 0, REG_SZ, (const BYTE
*)szFontName, cbData);
+ if (nError)
+ {
+ ERR("RegSetValueExW failed with %ld\n", nError);
+ RemoveFontResourceW(pszFileTitle);
+ DeleteFileW(szDestFile);
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+HRESULT CFontExt::DoGetFontTitle(LPCWSTR pszFontPath, LPCWSTR pszFontName)
+{
+ // TODO:
+ return E_FAIL;
+}
diff --git a/dll/shellext/fontext/CFontExt.hpp b/dll/shellext/fontext/CFontExt.hpp
index 0e7a04482d9..19d94f6fa1c 100644
--- a/dll/shellext/fontext/CFontExt.hpp
+++ b/dll/shellext/fontext/CFontExt.hpp
@@ -3,6 +3,7 @@
* LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontExt definition
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen(a)reactos.org)
+ * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
*/
#pragma once
@@ -11,7 +12,8 @@ class CFontExt :
public CComCoClass<CFontExt, &CLSID_CFontExt>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IShellFolder2,
- public IPersistFolder2
+ public IPersistFolder2,
+ public IDropTarget
{
CComHeapPtr<ITEMIDLIST> m_Folder;
@@ -51,6 +53,11 @@ public:
// *** IPersist methods ***
virtual STDMETHODIMP GetClassID(CLSID *lpClassId);
+ // *** 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);
#if 0
static HRESULT WINAPI log_stuff(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw)
@@ -79,6 +86,10 @@ public:
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
+ 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(LPCWSTR pszFontPath, LPCWSTR pszFontName);
};
diff --git a/dll/shellext/fontext/CFontMenu.cpp b/dll/shellext/fontext/CFontMenu.cpp
index eab4427202d..0a2f0e55856 100644
--- a/dll/shellext/fontext/CFontMenu.cpp
+++ b/dll/shellext/fontext/CFontMenu.cpp
@@ -9,18 +9,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(fontext);
-
-static inline PCUIDLIST_ABSOLUTE HIDA_GetPIDLFolder(CIDA const* pida)
-{
- return (PCUIDLIST_ABSOLUTE)(((LPBYTE)pida) + (pida)->aoffset[0]);
-}
-
-static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const* pida, SIZE_T i)
-{
- return (PCUIDLIST_RELATIVE)(((LPBYTE)pida) + (pida)->aoffset[i + 1]);
-}
-
static CLIPFORMAT g_cfHIDA;
+
HRESULT _GetCidlFromDataObject(IDataObject *pDataObject, CIDA** ppcida)
{
if (g_cfHIDA == NULL)
diff --git a/dll/shellext/fontext/CMakeLists.txt b/dll/shellext/fontext/CMakeLists.txt
index a5ae38822cf..2f2586b2517 100644
--- a/dll/shellext/fontext/CMakeLists.txt
+++ b/dll/shellext/fontext/CMakeLists.txt
@@ -32,7 +32,7 @@ add_library(fontext MODULE
set_module_type(fontext win32dll UNICODE)
target_link_libraries(fontext uuid wine)
-add_delay_importlibs(fontext ole32 oleaut32 shlwapi)
+add_delay_importlibs(fontext ole32 oleaut32 shlwapi gdi32)
add_importlibs(fontext shell32 advapi32 user32 msvcrt kernel32 ntdll)
add_pch(fontext precomp.h SOURCE)
add_cd_file(TARGET fontext DESTINATION reactos/system32 FOR all)
diff --git a/dll/shellext/fontext/precomp.h b/dll/shellext/fontext/precomp.h
index 28606824c1f..c17b4e53c71 100644
--- a/dll/shellext/fontext/precomp.h
+++ b/dll/shellext/fontext/precomp.h
@@ -27,6 +27,8 @@ extern LONG g_ModuleRefCnt;
#include "CFontCache.hpp"
#include "CFontExt.hpp"
+#define FONT_HIVE HKEY_LOCAL_MACHINE
+#define FONT_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
HRESULT _CEnumFonts_CreateInstance(CFontExt* zip, DWORD flags, REFIID riid, LPVOID*
ppvOut);
HRESULT _CFontMenu_CreateInstance(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
@@ -34,6 +36,30 @@ HRESULT _CFontMenu_CreateInstance(HWND hwnd, UINT cidl,
PCUITEMID_CHILD_ARRAY ap
HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl,
PCUITEMID_CHILD_ARRAY apidl,
REFIID riid, LPVOID* ppvOut);
+HRESULT _GetCidlFromDataObject(IDataObject *pDataObject, CIDA** ppcida);
+inline PCUIDLIST_ABSOLUTE HIDA_GetPIDLFolder(CIDA const* pida)
+{
+ return (PCUIDLIST_ABSOLUTE)(((LPBYTE)pida) + (pida)->aoffset[0]);
+}
+
+inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const* pida, SIZE_T i)
+{
+ return (PCUIDLIST_RELATIVE)(((LPBYTE)pida) + (pida)->aoffset[i + 1]);
+}
+
+inline BOOL IsFontDotExt(LPCWSTR pchDotExt)
+{
+ static const LPCWSTR array[] =
+ {
+ L".ttf", L".ttc", L".otf", L".otc",
L".fon", L".fnt", NULL
+ };
+ for (const LPCWSTR *pp = array; *pp; ++pp)
+ {
+ if (!_wcsicmp(*pp, pchDotExt))
+ return TRUE;
+ }
+ return FALSE;
+}
#endif /* FONTEXT_PRECOMP_H */