[SHELLEXT][FONTEXT] An attempt to implement IDropTarget (#2019)

CORE-12861
This commit is contained in:
Katayama Hirofumi MZ 2019-11-12 20:26:56 +09:00 committed by GitHub
parent d037003511
commit c214c04964
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 211 additions and 19 deletions

View file

@ -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)

View file

@ -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@reactos.org)
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@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;
}

View file

@ -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@reactos.org)
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@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);
};

View file

@ -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)

View file

@ -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)

View file

@ -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 */