[FONTEXT] Cache attributes, handle sorting

This commit is contained in:
Mark Jansen 2021-07-15 22:45:19 +02:00
parent cb9b538725
commit 91e63ee0b5
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
11 changed files with 271 additions and 100 deletions

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontMenu implementation * PURPOSE: CFontMenu implementation
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "precomp.h" #include "precomp.h"
@ -58,7 +58,7 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl, PCUITEM
const FontPidlEntry* fontEntry = _FontFromIL(apidl[n]); const FontPidlEntry* fontEntry = _FontFromIL(apidl[n]);
if (fontEntry) if (fontEntry)
{ {
CStringW File = g_FontCache->Filename(fontEntry, true); CStringW File = g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
if (!File.IsEmpty()) if (!File.IsEmpty())
{ {
// Now append the path (+ nullterminator) to the buffer // 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->pt.x = pDrop->pt.y = 0;
pDrop-> fNC = NULL; pDrop-> fNC = NULL;
// Prepare the format descriptors hr = DataObject_SetData(*(IDataObject**)ppvOut, CF_HDROP, data, offset);
STGMEDIUM medium = {0}; FAILED_UNEXPECTEDLY(hr);
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);
}
return hr; return hr;
} }

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CEnumFonts implementation * PURPOSE: CEnumFonts implementation
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "precomp.h" #include "precomp.h"

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: font list cache handling * PURPOSE: font list cache handling
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "precomp.h" #include "precomp.h"
@ -14,7 +14,11 @@ CFontCache* g_FontCache = NULL;
CFontInfo::CFontInfo(LPCWSTR name) CFontInfo::CFontInfo(LPCWSTR name)
: m_Name(name) : m_Name(name)
, m_FileRead(false) , m_FileRead(false)
, m_AttrsRead(false)
, m_FileWriteTime({})
, m_dwFileAttributes(0)
{ {
m_FileSize.QuadPart = 0;
} }
const CStringW& CFontInfo::Name() const const CStringW& CFontInfo::Name() const
@ -62,7 +66,52 @@ const CStringW& CFontInfo::File()
return m_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() CFontCache::CFontCache()
{ {
@ -93,23 +142,31 @@ CStringW CFontCache::Name(size_t Index)
return m_Fonts[Index].Name(); 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()) if (fontEntry->Index < m_Fonts.GetCount())
{ {
CFontInfo& info = m_Fonts[fontEntry->Index]; if (m_Fonts[fontEntry->Index].Name().CompareNoCase(fontEntry->Name) == 0)
return &m_Fonts[fontEntry->Index];
if (info.Name().CompareNoCase(fontEntry->Name) == 0)
File = info.File();
} }
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) if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
File = m_Fonts[n].File(); {
return &m_Fonts[n];
} }
}
return nullptr;
}
CStringW CFontCache::Filename(CFontInfo* info, bool alwaysFullPath)
{
CStringW File;
if (info)
{
File = info->File();
if (!File.IsEmpty() && alwaysFullPath) if (!File.IsEmpty() && alwaysFullPath)
{ {
@ -119,6 +176,7 @@ CStringW CFontCache::Filename(const FontPidlEntry* fontEntry, bool alwaysFullPat
File = m_FontFolderPath + File; File = m_FontFolderPath + File;
} }
} }
}
return File; return File;
} }

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: font list cache handling * PURPOSE: font list cache handling
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
*/ */
#pragma once #pragma once
@ -14,12 +14,24 @@ private:
CStringW m_Name; CStringW m_Name;
CStringW m_File; CStringW m_File;
bool m_FileRead; bool m_FileRead;
bool m_AttrsRead;
LARGE_INTEGER m_FileSize;
FILETIME m_FileWriteTime;
DWORD m_dwFileAttributes;
void ReadAttrs();
public: public:
CFontInfo(LPCWSTR name = L""); CFontInfo(LPCWSTR name = L"");
const CStringW& Name() const; const CStringW& Name() const; // Font display name stored in the registry
const CStringW& File();
const bool Valid() const; 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; } const CStringW& FontPath() const { return m_FontFolderPath; }
size_t Size(); size_t Size();
CStringW Name(size_t Index); CStringW Name(size_t Index); // Font display name stored in the registry
CStringW Filename(const FontPidlEntry* fontEntry, bool alwaysFullPath = false);
CFontInfo* Find(const FontPidlEntry* fontEntry);
CStringW Filename(CFontInfo* info, bool alwaysFullPath = false);
friend class CFontExtModule; friend class CFontExtModule;
}; };

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontExt implementation * PURPOSE: CFontExt implementation
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
@ -11,6 +11,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(fontext); WINE_DEFAULT_DEBUG_CHANNEL(fontext);
#ifndef SHCIDS_ALLFIELDS
#define SHCIDS_ALLFIELDS 0x80000000L
#endif
struct FolderViewColumns struct FolderViewColumns
{ {
@ -20,6 +23,15 @@ struct FolderViewColumns
int fmt; int fmt;
}; };
enum font_columns
{
FONTEXT_COL_NAME,
FONTEXT_COL_FILENAME,
FONTEXT_COL_SIZE,
FONTEXT_COL_MODIFIED,
FONTEXT_COL_ATTR,
};
static FolderViewColumns g_ColumnDefs[] = static FolderViewColumns g_ColumnDefs[] =
{ {
{ IDS_COL_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 25, LVCFMT_LEFT }, { 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? // Name, ReactOS specific?
if (iColumn == 0) if (iColumn == FONTEXT_COL_NAME)
return GetDisplayNameOf(pidl, 0, &psd->str); return GetDisplayNameOf(pidl, 0, &psd->str);
const FontPidlEntry* fontEntry = _FontFromIL(pidl); 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! // If we got here, we are in details view!
// Let's see if we got info about this file that we can re-use auto info = g_FontCache->Find(fontEntry);
if (m_LastDetailsFontName != fontEntry->Name) if (info == nullptr)
{ {
CStringW File = g_FontCache->Filename(fontEntry, true); ERR("Unable to query info about %S\n", fontEntry->Name);
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); return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
} }
FindClose(hFile);
m_LastDetailsFontName = fontEntry->Name;
}
// Most code borrowed from CFSFolder::GetDetailsOf
FILETIME lft;
SYSTEMTIME time;
int ret; int ret;
LARGE_INTEGER FileSize;
CStringA AttrLetters; CStringA AttrLetters;
DWORD dwAttributes;
SYSTEMTIME time;
switch (iColumn) switch (iColumn)
{ {
case 1: // Filename case FONTEXT_COL_FILENAME:
return SHSetStrRet(&psd->str, m_LastDetailsFileData.cFileName); return SHSetStrRet(&psd->str, PathFindFileNameW(info->File()));
case 2: // Size case FONTEXT_COL_SIZE:
psd->str.uType = STRRET_CSTR; psd->str.uType = STRRET_CSTR;
FileSize.HighPart = m_LastDetailsFileData.nFileSizeHigh; StrFormatKBSizeA(info->FileSize().QuadPart, psd->str.cStr, MAX_PATH);
FileSize.LowPart = m_LastDetailsFileData.nFileSizeLow;
StrFormatKBSizeA(FileSize.QuadPart, psd->str.cStr, MAX_PATH);
return S_OK; return S_OK;
case 3: // Modified case FONTEXT_COL_MODIFIED:
FileTimeToLocalFileTime(&m_LastDetailsFileData.ftLastWriteTime, &lft);
FileTimeToSystemTime (&lft, &time);
psd->str.uType = STRRET_CSTR; psd->str.uType = STRRET_CSTR;
FileTimeToSystemTime(&info->FileWriteTime(), &time);
ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, psd->str.cStr, MAX_PATH); ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, psd->str.cStr, MAX_PATH);
if (ret < 1) if (ret < 1)
{ {
@ -195,7 +194,7 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
psd->str.cStr[ret-1] = ' '; psd->str.cStr[ret-1] = ' ';
GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &psd->str.cStr[ret], MAX_PATH - ret); GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &psd->str.cStr[ret], MAX_PATH - ret);
return S_OK; return S_OK;
case 4: // Attributes case FONTEXT_COL_ATTR:
AttrLetters.LoadString(IDS_COL_ATTR_LETTERS); AttrLetters.LoadString(IDS_COL_ATTR_LETTERS);
if (AttrLetters.GetLength() != 5) if (AttrLetters.GetLength() != 5)
{ {
@ -203,16 +202,17 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
return E_FAIL; return E_FAIL;
} }
psd->str.uType = STRRET_CSTR; psd->str.uType = STRRET_CSTR;
dwAttributes = info->FileAttributes();
ret = 0; ret = 0;
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) if (dwAttributes & FILE_ATTRIBUTE_READONLY)
psd->str.cStr[ret++] = AttrLetters[0]; psd->str.cStr[ret++] = AttrLetters[0];
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
psd->str.cStr[ret++] = AttrLetters[1]; psd->str.cStr[ret++] = AttrLetters[1];
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) if (dwAttributes & FILE_ATTRIBUTE_SYSTEM)
psd->str.cStr[ret++] = AttrLetters[2]; psd->str.cStr[ret++] = AttrLetters[2];
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) if (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)
psd->str.cStr[ret++] = AttrLetters[3]; 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++] = AttrLetters[4];
psd->str.cStr[ret] = '\0'; psd->str.cStr[ret] = '\0';
return S_OK; return S_OK;
@ -262,7 +262,53 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
if (!fontEntry1 || !fontEntry2) if (!fontEntry1 || !fontEntry2)
return E_INVALIDARG; 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); return MAKE_COMPARE_HRESULT(result);
} }
@ -341,7 +387,7 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_
if (fontEntry) if (fontEntry)
{ {
DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL; 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 // 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. // We might want to create a preview with the font to get really fancy one day.
return SHCreateFileExtractIconW(File, dwAttributes, riid, ppvOut); return SHCreateFileExtractIconW(File, dwAttributes, riid, ppvOut);
@ -385,6 +431,15 @@ STDMETHODIMP CFontExt::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPS
if (!fontEntry) if (!fontEntry)
return E_FAIL; 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); return SHSetStrRet(strRet, fontEntry->Name);
} }

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontExt definition * PURPOSE: CFontExt definition
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
@ -16,8 +16,6 @@ class CFontExt :
public IDropTarget public IDropTarget
{ {
CComHeapPtr<ITEMIDLIST> m_Folder; CComHeapPtr<ITEMIDLIST> m_Folder;
CStringW m_LastDetailsFontName;
WIN32_FIND_DATAW m_LastDetailsFileData;
public: public:

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: CFontMenu implementation * PURPOSE: CFontMenu implementation
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "precomp.h" #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 FontViewerPath[MAX_PATH] = L"%SystemRoot%\\System32\\fontview.exe";
WCHAR FontPathArg[MAX_PATH + 3]; 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()) if (!Path.IsEmpty())
{ {
// '/d' disables the install button // '/d' disables the install button
@ -108,7 +108,7 @@ static HRESULT CALLBACK FontFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDa
return S_OK; return S_OK;
} }
case DFM_INVOKECOMMAND: case DFM_INVOKECOMMAND:
// Preview is the only item we can handle // Preview is the only item we handle
if (wParam == 0) if (wParam == 0)
{ {
CComHeapPtr<CIDA> cida; CComHeapPtr<CIDA> cida;
@ -123,6 +123,15 @@ static HRESULT CALLBACK FontFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDa
} }
return S_OK; 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; return S_FALSE;
case DFM_INVOKECOMMANDEX: case DFM_INVOKECOMMANDEX:

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Shell extension entry point * PURPOSE: Shell extension entry point
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "precomp.h" #include "precomp.h"

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: pidl handling * PURPOSE: pidl handling
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
*/ */
#include "precomp.h" #include "precomp.h"

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Font Shell Extension * PROJECT: ReactOS Font Shell Extension
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: pidl handling * PURPOSE: pidl handling
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) * COPYRIGHT: Copyright 2019 Mark Jansen <mark.jansen@reactos.org>
*/ */
#pragma once #pragma once
@ -12,7 +12,7 @@ struct FontPidlEntry
{ {
WORD cb; WORD cb;
WORD Magic; WORD Magic;
ULONG Index; // Informative only ULONG Index; // Informative only, used for sorting
WCHAR Name[1]; WCHAR Name[1];
}; };

View file

@ -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 */ #endif /* __ROS_SHELL_UTILS_H */