https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c214c0496477a9f3e7aa65c063cbf0cdf66f175a

commit c214c0496477a9f3e7aa65c063cbf0cdf66f175a
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Tue Nov 12 20:26:56 2019 +0900
Commit:     GitHub <[email protected]>
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 ([email protected])
+ *              Copyright 2019 Katayama Hirofumi MZ 
([email protected])
  */
 
 #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 ([email protected])
+ *              Copyright 2019 Katayama Hirofumi MZ 
([email protected])
  */
 
 #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 */

Reply via email to