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

commit 91e63ee0b5a28f5a0e56f4c56b701888d12692f3
Author:     Mark Jansen <[email protected]>
AuthorDate: Thu Jul 15 22:45:19 2021 +0200
Commit:     Mark Jansen <[email protected]>
CommitDate: Fri Jul 23 22:10:30 2021 +0200

    [FONTEXT] Cache attributes, handle sorting
---
 dll/shellext/fontext/CDataObject.cpp |  36 ++--------
 dll/shellext/fontext/CEnumFonts.cpp  |   2 +-
 dll/shellext/fontext/CFontCache.cpp  |  86 ++++++++++++++++++++----
 dll/shellext/fontext/CFontCache.hpp  |  24 +++++--
 dll/shellext/fontext/CFontExt.cpp    | 125 +++++++++++++++++++++++++----------
 dll/shellext/fontext/CFontExt.hpp    |   4 +-
 dll/shellext/fontext/CFontMenu.cpp   |  15 ++++-
 dll/shellext/fontext/fontext.cpp     |   2 +-
 dll/shellext/fontext/fontpidl.cpp    |   2 +-
 dll/shellext/fontext/fontpidl.hpp    |   4 +-
 sdk/include/reactos/shellutils.h     |  65 ++++++++++++++++++
 11 files changed, 268 insertions(+), 97 deletions(-)

diff --git a/dll/shellext/fontext/CDataObject.cpp 
b/dll/shellext/fontext/CDataObject.cpp
index f6851f19985..bff70910043 100644
--- a/dll/shellext/fontext/CDataObject.cpp
+++ b/dll/shellext/fontext/CDataObject.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     CFontMenu implementation
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019-2021 Mark Jansen <[email protected]>
  */
 
 #include "precomp.h"
@@ -58,7 +58,7 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, 
UINT cidl, PCUITEM
         const FontPidlEntry* fontEntry = _FontFromIL(apidl[n]);
         if (fontEntry)
         {
-            CStringW File = g_FontCache->Filename(fontEntry, true);
+            CStringW File = 
g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
             if (!File.IsEmpty())
             {
                 // Now append the path (+ nullterminator) to the buffer
@@ -94,36 +94,8 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE 
folder, UINT cidl, PCUITEM
     pDrop->pt.x = pDrop->pt.y = 0;
     pDrop-> fNC = NULL;
 
-    // Prepare the format descriptors
-    STGMEDIUM medium = {0};
-    medium.tymed = TYMED_HGLOBAL;
-
-    // Copy the data to an HGLOBAL
-    medium.hGlobal = GlobalAlloc(GHND, offset);
-    if (medium.hGlobal)
-    {
-        LPVOID blob = GlobalLock(medium.hGlobal);
-        if (blob)
-        {
-            CopyMemory(blob, (BYTE*)data, offset);
-            GlobalUnlock(medium.hGlobal);
-
-            CComPtr<IDataObject> spDataObject(*(IDataObject**)ppvOut);
-            if (spDataObject)
-            {
-                FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, 
TYMED_HGLOBAL };
-                hr = spDataObject->SetData(&etc, &medium, TRUE);
-            }
-        }
-        else
-        {
-            ERR("Unable to lock the hGlobal?!\n");
-        }
-    }
-    else
-    {
-        ERR("Unable to allocate %u bytes for the hGlobal\n", offset);
-    }
+    hr = DataObject_SetData(*(IDataObject**)ppvOut, CF_HDROP, data, offset);
+    FAILED_UNEXPECTEDLY(hr);
 
     return hr;
 }
diff --git a/dll/shellext/fontext/CEnumFonts.cpp 
b/dll/shellext/fontext/CEnumFonts.cpp
index 7e197187cdf..1b81a09318b 100644
--- a/dll/shellext/fontext/CEnumFonts.cpp
+++ b/dll/shellext/fontext/CEnumFonts.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     CEnumFonts implementation
- * COPYRIGHT:   Copyright 2019 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019 Mark Jansen <[email protected]>
  */
 
 #include "precomp.h"
diff --git a/dll/shellext/fontext/CFontCache.cpp 
b/dll/shellext/fontext/CFontCache.cpp
index 218be7bb638..53a7a5a6aec 100644
--- a/dll/shellext/fontext/CFontCache.cpp
+++ b/dll/shellext/fontext/CFontCache.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     font list cache handling
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019-2021 Mark Jansen <[email protected]>
  */
 
 #include "precomp.h"
@@ -14,7 +14,11 @@ CFontCache* g_FontCache = NULL;
 CFontInfo::CFontInfo(LPCWSTR name)
     : m_Name(name)
     , m_FileRead(false)
+    , m_AttrsRead(false)
+    , m_FileWriteTime({})
+    , m_dwFileAttributes(0)
 {
+    m_FileSize.QuadPart = 0;
 }
 
 const CStringW& CFontInfo::Name() const
@@ -62,7 +66,52 @@ const CStringW& CFontInfo::File()
     return m_File;
 }
 
+void CFontInfo::ReadAttrs()
+{
+    CStringW File = g_FontCache->Filename(this, true);
+
+    m_AttrsRead = true;
+
+    WIN32_FIND_DATAW findFileData;
+    HANDLE hFile = FindFirstFileW(File, &findFileData);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+
+        // File write time
+        FileTimeToLocalFileTime(&findFileData.ftLastWriteTime, 
&m_FileWriteTime);
+
+        // File size
+        m_FileSize.HighPart = findFileData.nFileSizeHigh;
+        m_FileSize.LowPart = findFileData.nFileSizeLow;
+
+        m_dwFileAttributes = findFileData.dwFileAttributes;
+        FindClose(hFile);
+    }
+}
+
+const LARGE_INTEGER& CFontInfo::FileSize()
+{
+    if (!m_AttrsRead)
+        ReadAttrs();
+
+    return m_FileSize;
+}
+
+const FILETIME& CFontInfo::FileWriteTime()
+{
+    if (!m_AttrsRead)
+        ReadAttrs();
+
+    return m_FileWriteTime;
+}
+
+DWORD CFontInfo::FileAttributes()
+{
+    if (!m_AttrsRead)
+        ReadAttrs();
 
+    return m_dwFileAttributes;
+}
 
 CFontCache::CFontCache()
 {
@@ -93,30 +142,39 @@ CStringW CFontCache::Name(size_t Index)
     return m_Fonts[Index].Name();
 }
 
-CStringW CFontCache::Filename(const FontPidlEntry* fontEntry, bool 
alwaysFullPath)
+CFontInfo* CFontCache::Find(const FontPidlEntry* fontEntry)
 {
-    CStringW File;
-
     if (fontEntry->Index < m_Fonts.GetCount())
     {
-        CFontInfo& info = m_Fonts[fontEntry->Index];
-
-        if (info.Name().CompareNoCase(fontEntry->Name) == 0)
-            File = info.File();
+        if (m_Fonts[fontEntry->Index].Name().CompareNoCase(fontEntry->Name) == 
0)
+            return &m_Fonts[fontEntry->Index];
     }
 
-    for (UINT n = 0; File.IsEmpty() && n < Size(); ++n)
+    for (UINT n = 0; n < Size(); ++n)
     {
         if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
-            File = m_Fonts[n].File();
+        {
+            return &m_Fonts[n];
+        }
     }
+    return nullptr;
+}
 
-    if (!File.IsEmpty() && alwaysFullPath)
+
+CStringW CFontCache::Filename(CFontInfo* info, bool alwaysFullPath)
+{
+    CStringW File;
+    if (info)
     {
-        // Ensure this is a full path
-        if (PathIsRelativeW(File))
+        File = info->File();
+
+        if (!File.IsEmpty() && alwaysFullPath)
         {
-            File = m_FontFolderPath + File;
+            // Ensure this is a full path
+            if (PathIsRelativeW(File))
+            {
+                File = m_FontFolderPath + File;
+            }
         }
     }
 
diff --git a/dll/shellext/fontext/CFontCache.hpp 
b/dll/shellext/fontext/CFontCache.hpp
index 9454660a653..e047e6b4b1d 100644
--- a/dll/shellext/fontext/CFontCache.hpp
+++ b/dll/shellext/fontext/CFontCache.hpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     font list cache handling
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019-2021 Mark Jansen <[email protected]>
  */
 
 #pragma once
@@ -14,12 +14,24 @@ private:
     CStringW m_Name;
     CStringW m_File;
     bool m_FileRead;
+
+    bool m_AttrsRead;
+    LARGE_INTEGER m_FileSize;
+    FILETIME m_FileWriteTime;
+    DWORD m_dwFileAttributes;
+
+    void ReadAttrs();
+
 public:
     CFontInfo(LPCWSTR name = L"");
 
-    const CStringW& Name() const;
-    const CStringW& File();
+    const CStringW& Name() const;   // Font display name stored in the registry
     const bool Valid() const;
+
+    const CStringW& File();         // Full path or file, depending on how 
it's stored in the registry
+    const LARGE_INTEGER& FileSize();
+    const FILETIME& FileWriteTime();
+    DWORD FileAttributes();
 };
 
 
@@ -40,8 +52,10 @@ public:
     const CStringW& FontPath() const { return m_FontFolderPath; }
 
     size_t Size();
-    CStringW Name(size_t Index);
-    CStringW Filename(const FontPidlEntry* fontEntry, bool alwaysFullPath = 
false);
+    CStringW Name(size_t Index);    // Font display name stored in the registry
+
+    CFontInfo* Find(const FontPidlEntry* fontEntry);
+    CStringW Filename(CFontInfo* info, bool alwaysFullPath = false);
 
     friend class CFontExtModule;
 };
diff --git a/dll/shellext/fontext/CFontExt.cpp 
b/dll/shellext/fontext/CFontExt.cpp
index 03d03f420b1..b2681055cd2 100644
--- a/dll/shellext/fontext/CFontExt.cpp
+++ b/dll/shellext/fontext/CFontExt.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     CFontExt implementation
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019-2021 Mark Jansen <[email protected]>
  *              Copyright 2019 Katayama Hirofumi MZ 
([email protected])
  */
 
@@ -11,6 +11,9 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(fontext);
 
+#ifndef SHCIDS_ALLFIELDS
+#define SHCIDS_ALLFIELDS 0x80000000L
+#endif
 
 struct FolderViewColumns
 {
@@ -20,6 +23,15 @@ struct FolderViewColumns
     int fmt;
 };
 
+enum font_columns
+{
+    FONTEXT_COL_NAME,
+    FONTEXT_COL_FILENAME,
+    FONTEXT_COL_SIZE,
+    FONTEXT_COL_MODIFIED,
+    FONTEXT_COL_ATTR,
+};
+
 static FolderViewColumns g_ColumnDefs[] =
 {
     { IDS_COL_NAME,      SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT,   25, 
LVCFMT_LEFT },
@@ -140,7 +152,7 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, 
UINT iColumn, SHELLDET
     }
 
     // Name, ReactOS specific?
-    if (iColumn == 0)
+    if (iColumn == FONTEXT_COL_NAME)
         return GetDisplayNameOf(pidl, 0, &psd->str);
 
     const FontPidlEntry* fontEntry = _FontFromIL(pidl);
@@ -151,41 +163,28 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, 
UINT iColumn, SHELLDET
     }
 
     // If we got here, we are in details view!
-    // Let's see if we got info about this file that we can re-use
-    if (m_LastDetailsFontName != fontEntry->Name)
+    auto info = g_FontCache->Find(fontEntry);
+    if (info == nullptr)
     {
-        CStringW File = g_FontCache->Filename(fontEntry, true);
-        HANDLE hFile = FindFirstFileW(File, &m_LastDetailsFileData);
-        if (hFile == INVALID_HANDLE_VALUE)
-        {
-            m_LastDetailsFontName.Empty();
-            ERR("Unable to query info about %S\n", File.GetString());
-            return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-        }
-        FindClose(hFile);
-        m_LastDetailsFontName = fontEntry->Name;
+        ERR("Unable to query info about %S\n", fontEntry->Name);
+        return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
     }
 
-    // Most code borrowed from CFSFolder::GetDetailsOf
-    FILETIME lft;
-    SYSTEMTIME time;
     int ret;
-    LARGE_INTEGER FileSize;
     CStringA AttrLetters;
+    DWORD dwAttributes;
+    SYSTEMTIME time;
     switch (iColumn)
     {
-    case 1: // Filename
-        return SHSetStrRet(&psd->str, m_LastDetailsFileData.cFileName);
-    case 2: // Size
+    case FONTEXT_COL_FILENAME:
+        return SHSetStrRet(&psd->str, PathFindFileNameW(info->File()));
+    case FONTEXT_COL_SIZE:
         psd->str.uType = STRRET_CSTR;
-        FileSize.HighPart = m_LastDetailsFileData.nFileSizeHigh;
-        FileSize.LowPart = m_LastDetailsFileData.nFileSizeLow;
-        StrFormatKBSizeA(FileSize.QuadPart, psd->str.cStr, MAX_PATH);
+        StrFormatKBSizeA(info->FileSize().QuadPart, psd->str.cStr, MAX_PATH);
         return S_OK;
-    case 3: // Modified
-        FileTimeToLocalFileTime(&m_LastDetailsFileData.ftLastWriteTime, &lft);
-        FileTimeToSystemTime (&lft, &time);
+    case FONTEXT_COL_MODIFIED:
         psd->str.uType = STRRET_CSTR;
+        FileTimeToSystemTime(&info->FileWriteTime(), &time);
         ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, 
psd->str.cStr, MAX_PATH);
         if (ret < 1)
         {
@@ -195,7 +194,7 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, 
UINT iColumn, SHELLDET
         psd->str.cStr[ret-1] = ' ';
         GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, 
&psd->str.cStr[ret], MAX_PATH - ret);
         return S_OK;
-    case 4: // Attributes
+    case FONTEXT_COL_ATTR:
         AttrLetters.LoadString(IDS_COL_ATTR_LETTERS);
         if (AttrLetters.GetLength() != 5)
         {
@@ -203,16 +202,17 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, 
UINT iColumn, SHELLDET
             return E_FAIL;
         }
         psd->str.uType = STRRET_CSTR;
+        dwAttributes = info->FileAttributes();
         ret = 0;
-        if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+        if (dwAttributes & FILE_ATTRIBUTE_READONLY)
             psd->str.cStr[ret++] = AttrLetters[0];
-        if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
+        if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
             psd->str.cStr[ret++] = AttrLetters[1];
-        if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
+        if (dwAttributes & FILE_ATTRIBUTE_SYSTEM)
             psd->str.cStr[ret++] = AttrLetters[2];
-        if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
+        if (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)
             psd->str.cStr[ret++] = AttrLetters[3];
-        if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
+        if (dwAttributes & FILE_ATTRIBUTE_COMPRESSED)
             psd->str.cStr[ret++] = AttrLetters[4];
         psd->str.cStr[ret] = '\0';
         return S_OK;
@@ -262,7 +262,53 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, 
PCUIDLIST_RELATIVE pidl1, PCUID
     if (!fontEntry1 || !fontEntry2)
         return E_INVALIDARG;
 
-    int result = (int)fontEntry1->Index - (int)fontEntry2->Index;
+    int result;
+    DWORD sortMode = lParam & 0xFFFF0000;
+    DWORD column = lParam & 0x0000FFFF;
+    if (sortMode == SHCIDS_ALLFIELDS)
+    {
+        UNIMPLEMENTED;
+        result = (int)fontEntry1->Index - (int)fontEntry2->Index;
+    }
+    else
+    {
+        auto info1 = g_FontCache->Find(fontEntry1);
+        auto info2 = g_FontCache->Find(fontEntry2);
+
+        if (!info1 || !info2)
+        {
+            ERR("Unable to find font %S or %S in cache!\n", fontEntry1->Name, 
fontEntry2->Name);
+            return E_INVALIDARG;
+        }
+
+        switch (column)
+        {
+        case 0xffff:
+            /* ROS bug? */
+        case FONTEXT_COL_NAME:
+            // These items are already ordered by name
+            result = (int)fontEntry1->Index - (int)fontEntry2->Index;
+            break;
+        case FONTEXT_COL_FILENAME:
+            result = wcsicmp(PathFindFileNameW(info1->File()), 
PathFindFileNameW(info2->File()));
+            break;
+        case FONTEXT_COL_SIZE:
+            result = (int)info1->FileSize().HighPart - 
info2->FileSize().HighPart;
+            if (result == 0)
+                result = (int)info1->FileSize().LowPart - 
info2->FileSize().LowPart;
+            break;
+        case FONTEXT_COL_MODIFIED:
+            result = CompareFileTime(&info1->FileWriteTime(), 
&info2->FileWriteTime());
+            break;
+        case FONTEXT_COL_ATTR:
+            // FIXME: how to compare attributes?
+            result = (int)info1->FileAttributes() - info2->FileAttributes();
+            break;
+        default:
+            ERR("Unimplemented column %u\n", column);
+            return E_INVALIDARG;
+        }
+    }
 
     return MAKE_COMPARE_HRESULT(result);
 }
@@ -341,7 +387,7 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT 
cidl, PCUITEMID_CHILD_
             if (fontEntry)
             {
                 DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL;
-                CStringW File = g_FontCache->Filename(fontEntry);
+                CStringW File = 
g_FontCache->Filename(g_FontCache->Find(fontEntry));
                 // Just create a default icon extractor based on the filename
                 // We might want to create a preview with the font to get 
really fancy one day.
                 return SHCreateFileExtractIconW(File, dwAttributes, riid, 
ppvOut);
@@ -385,6 +431,15 @@ STDMETHODIMP CFontExt::GetDisplayNameOf(PCUITEMID_CHILD 
pidl, DWORD dwFlags, LPS
     if (!fontEntry)
         return E_FAIL;
 
+    if (dwFlags == SHGDN_FORPARSING)
+    {
+        CStringW File = g_FontCache->Filename(g_FontCache->Find(fontEntry), 
true);
+        if (!File.IsEmpty())
+        {
+            return SHSetStrRet(strRet, File);
+        }
+    }
+
     return SHSetStrRet(strRet, fontEntry->Name);
 }
 
diff --git a/dll/shellext/fontext/CFontExt.hpp 
b/dll/shellext/fontext/CFontExt.hpp
index ba868628957..a3e5431c90f 100644
--- a/dll/shellext/fontext/CFontExt.hpp
+++ b/dll/shellext/fontext/CFontExt.hpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     CFontExt definition
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019,2020 Mark Jansen <[email protected]>
  *              Copyright 2019 Katayama Hirofumi MZ 
([email protected])
  */
 
@@ -16,8 +16,6 @@ class CFontExt :
     public IDropTarget
 {
     CComHeapPtr<ITEMIDLIST> m_Folder;
-    CStringW m_LastDetailsFontName;
-    WIN32_FIND_DATAW m_LastDetailsFileData;
 
 public:
 
diff --git a/dll/shellext/fontext/CFontMenu.cpp 
b/dll/shellext/fontext/CFontMenu.cpp
index 05b968e27d3..62464a099ee 100644
--- a/dll/shellext/fontext/CFontMenu.cpp
+++ b/dll/shellext/fontext/CFontMenu.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     CFontMenu implementation
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019,2020 Mark Jansen <[email protected]>
  */
 
 #include "precomp.h"
@@ -69,7 +69,7 @@ static void RunFontViewer(HWND hwnd, const FontPidlEntry* 
fontEntry)
     WCHAR FontViewerPath[MAX_PATH] = L"%SystemRoot%\\System32\\fontview.exe";
     WCHAR FontPathArg[MAX_PATH + 3];
 
-    CStringW Path = g_FontCache->Filename(fontEntry, true);
+    CStringW Path = g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
     if (!Path.IsEmpty())
     {
         // '/d' disables the install button
@@ -108,7 +108,7 @@ static HRESULT CALLBACK FontFolderMenuCallback(IShellFolder 
*psf, HWND hwnd, IDa
         return S_OK;
     }
     case DFM_INVOKECOMMAND:
-        // Preview is the only item we can handle
+        // Preview is the only item we handle
         if (wParam == 0)
         {
             CComHeapPtr<CIDA> cida;
@@ -123,6 +123,15 @@ static HRESULT CALLBACK 
FontFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDa
             }
             return S_OK;
         }
+        else if (wParam == DFM_CMD_PROPERTIES)
+        {
+            ERR("Default properties handling!\n");
+            return S_FALSE;
+        }
+        else
+        {
+            ERR("Unhandled DFM_INVOKECOMMAND(wParam=0x%x)\n", wParam);
+        }
         return S_FALSE;
 
     case DFM_INVOKECOMMANDEX:
diff --git a/dll/shellext/fontext/fontext.cpp b/dll/shellext/fontext/fontext.cpp
index d3659199e2d..0b68e40a7cb 100644
--- a/dll/shellext/fontext/fontext.cpp
+++ b/dll/shellext/fontext/fontext.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     Shell extension entry point
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019,2020 Mark Jansen <[email protected]>
  */
 
 #include "precomp.h"
diff --git a/dll/shellext/fontext/fontpidl.cpp 
b/dll/shellext/fontext/fontpidl.cpp
index 38bb7814c84..6354e848bf2 100644
--- a/dll/shellext/fontext/fontpidl.cpp
+++ b/dll/shellext/fontext/fontpidl.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     pidl handling
- * COPYRIGHT:   Copyright 2019,2020 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019,2020 Mark Jansen <[email protected]>
  */
 
 #include "precomp.h"
diff --git a/dll/shellext/fontext/fontpidl.hpp 
b/dll/shellext/fontext/fontpidl.hpp
index f5ef556ddff..1546f646f78 100644
--- a/dll/shellext/fontext/fontpidl.hpp
+++ b/dll/shellext/fontext/fontpidl.hpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Font Shell Extension
  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     pidl handling
- * COPYRIGHT:   Copyright 2019 Mark Jansen ([email protected])
+ * COPYRIGHT:   Copyright 2019 Mark Jansen <[email protected]>
  */
 
 #pragma once
@@ -12,7 +12,7 @@ struct FontPidlEntry
 {
     WORD cb;
     WORD Magic;
-    ULONG Index;        // Informative only
+    ULONG Index;        // Informative only, used for sorting
 
     WCHAR Name[1];
 };
diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h
index 82f2f708eee..c4e4026fd14 100644
--- a/sdk/include/reactos/shellutils.h
+++ b/sdk/include/reactos/shellutils.h
@@ -546,4 +546,69 @@ static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA 
const* pida, SIZE_T i)
 }
 
 
+#ifdef __cplusplus
+
+inline
+HRESULT DataObject_GetData(IDataObject* pDataObject, CLIPFORMAT clipformat, 
PVOID pBuffer, SIZE_T dwBufferSize)
+{
+    FORMATETC fmt = { clipformat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+    STGMEDIUM medium = { TYMED_NULL };
+
+    HRESULT hr = pDataObject->GetData(&fmt, &medium);
+    if (SUCCEEDED(hr))
+    {
+        LPVOID blob = GlobalLock(medium.hGlobal);
+        if (blob)
+        {
+            SIZE_T size = GlobalSize(medium.hGlobal);
+            if (size <= dwBufferSize)
+            {
+                CopyMemory(pBuffer, blob, size);
+                hr = S_OK;
+            }
+            else
+            {
+                hr = E_OUTOFMEMORY;
+            }
+            GlobalUnlock(medium.hGlobal);
+        }
+        else
+        {
+            hr = STG_E_INVALIDHANDLE;
+        }
+
+        ReleaseStgMedium(&medium);
+    }
+    return hr;
+}
+
+inline
+HRESULT DataObject_SetData(IDataObject* pDataObject, CLIPFORMAT clipformat, 
PVOID pBuffer, SIZE_T dwBufferSize)
+{
+    STGMEDIUM medium = { TYMED_HGLOBAL };
+
+    medium.hGlobal = GlobalAlloc(GHND, dwBufferSize);
+    if (!medium.hGlobal)
+        return E_OUTOFMEMORY;
+
+    HRESULT hr = E_UNEXPECTED;
+    LPVOID blob = GlobalLock(medium.hGlobal);
+    if (blob)
+    {
+        CopyMemory(blob, pBuffer, dwBufferSize);
+        GlobalUnlock(medium.hGlobal);
+
+        FORMATETC etc = { clipformat, NULL, DVASPECT_CONTENT, -1, 
TYMED_HGLOBAL };
+        hr = pDataObject->SetData(&etc, &medium, TRUE);
+    }
+
+    if (FAILED(hr))
+        GlobalFree(medium.hGlobal);
+
+    return hr;
+}
+
+#endif
+
+
 #endif /* __ROS_SHELL_UTILS_H */

Reply via email to