mirror of
https://github.com/reactos/reactos.git
synced 2026-05-19 17:19:49 +08:00
[FONTEXT][SHELL32][SDK] Support delete operation (#8639)
Improve usability of Fonts folder. JIRA issue: CORE-17311 - Modify PIDL design to contain name and filename. - Implement CFontExt:: ParseDisplayName to parsing name as PIDL. - Modify CDefaultContextMenu:: GetCommandString and CDefaultContextMenu:: DoCopyOrCut for DFM_GETVERBA, DFM_GETVERBW, DFM_CMD_COPY, and DFM_CMD_MOVE. - Add IDS_CONFIRM_DELETE_FONT, IDS_CANTDELETEFONT, and IDS_PROPERTIES resource strings. - Add SHMultiFileProperties prototype to <shlobj.h>.
This commit is contained in:
committed by
GitHub
parent
5213cf717c
commit
6af07a31b0
@@ -73,7 +73,7 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl, PCUITEM
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("No file found for %S\n", fontEntry->Name);
|
||||
ERR("No file found for %S\n", fontEntry->Name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,25 +42,33 @@ public:
|
||||
|
||||
while (celt)
|
||||
{
|
||||
celt--;
|
||||
|
||||
if (m_Index < g_FontCache->Size())
|
||||
{
|
||||
CStringW Name = g_FontCache->Name(m_Index);
|
||||
LPITEMIDLIST item = _ILCreate(Name);
|
||||
if (!item)
|
||||
{
|
||||
hr = Fetched ? S_FALSE : E_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
rgelt[Fetched] = item;
|
||||
m_Index++;
|
||||
Fetched++;
|
||||
}
|
||||
else
|
||||
if (m_Index >= g_FontCache->Size())
|
||||
{
|
||||
hr = S_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!g_FontCache->IsMarkDeleted(m_Index))
|
||||
{
|
||||
CStringW Name = g_FontCache->Name(m_Index), FileName = g_FontCache->File(m_Index);
|
||||
if (Name.IsEmpty() || FileName.IsEmpty())
|
||||
{
|
||||
ERR("Why is Name or FileName empty?\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a PIDL
|
||||
PITEMID_CHILD item = _ILCreate(Name, FileName);
|
||||
if (!item)
|
||||
{
|
||||
hr = Fetched ? S_FALSE : E_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
rgelt[Fetched++] = item;
|
||||
--celt;
|
||||
}
|
||||
}
|
||||
m_Index++;
|
||||
}
|
||||
|
||||
if (pceltFetched)
|
||||
@@ -70,7 +78,12 @@ public:
|
||||
|
||||
STDMETHODIMP Skip(ULONG celt) override
|
||||
{
|
||||
m_Index += celt;
|
||||
for (ULONG i = 0; i < celt && m_Index < g_FontCache->Size(); ++i)
|
||||
{
|
||||
while (m_Index < g_FontCache->Size() && g_FontCache->IsMarkDeleted(m_Index))
|
||||
++m_Index;
|
||||
++m_Index;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,9 +67,8 @@ STDMETHODIMP CFontBackgroundMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
|
||||
if (FAILED_UNEXPECTEDLY(hr) || !CheckDataObject(pDataObj))
|
||||
{
|
||||
// Show error message
|
||||
CStringW text, title;
|
||||
title.LoadStringW(IDS_REACTOS_FONTS_FOLDER);
|
||||
text.LoadStringW(IDS_INSTALL_FAILED);
|
||||
CStringW text(MAKEINTRESOURCEW(IDS_INSTALL_FAILED));
|
||||
CStringW title(MAKEINTRESOURCEW(IDS_REACTOS_FONTS_FOLDER));
|
||||
MessageBoxW(m_hwnd, text, title, MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(fontext);
|
||||
|
||||
CFontCache* g_FontCache = NULL;
|
||||
|
||||
CFontInfo::CFontInfo(LPCWSTR name)
|
||||
CFontInfo::CFontInfo(PCWSTR name, PCWSTR value)
|
||||
: m_Name(name)
|
||||
, m_File(value)
|
||||
, m_FileRead(false)
|
||||
, m_AttrsRead(false)
|
||||
, m_FileWriteTime({})
|
||||
@@ -35,7 +36,7 @@ const CStringW& CFontInfo::File()
|
||||
{
|
||||
if (!m_FileRead)
|
||||
{
|
||||
if (Valid())
|
||||
if (Valid() && m_File.IsEmpty())
|
||||
{
|
||||
// Read the filename stored in the registry.
|
||||
// This can be either a filename or a full path
|
||||
@@ -43,7 +44,7 @@ const CStringW& CFontInfo::File()
|
||||
if (key.Open(FONT_HIVE, FONT_KEY, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
CStringW Value;
|
||||
DWORD dwAllocated = 128;
|
||||
DWORD dwAllocated = MAX_PATH;
|
||||
LSTATUS Status;
|
||||
do
|
||||
{
|
||||
@@ -125,35 +126,69 @@ void CFontCache::SetFontDir(const LPCWSTR Path)
|
||||
|
||||
size_t CFontCache::Size()
|
||||
{
|
||||
if (m_Fonts.GetCount() == 0u)
|
||||
if (m_Fonts.GetSize() == 0)
|
||||
Read();
|
||||
|
||||
return m_Fonts.GetCount();
|
||||
return m_Fonts.GetSize();
|
||||
}
|
||||
|
||||
CStringW CFontCache::Name(size_t Index)
|
||||
{
|
||||
if (m_Fonts.GetCount() == 0u)
|
||||
if (m_Fonts.GetSize() == 0)
|
||||
Read();
|
||||
|
||||
if (Index >= m_Fonts.GetCount())
|
||||
return CStringW();
|
||||
if ((INT)Index >= m_Fonts.GetSize())
|
||||
return L"";
|
||||
|
||||
return m_Fonts[Index].Name();
|
||||
}
|
||||
|
||||
CStringW CFontCache::File(size_t Index)
|
||||
{
|
||||
if (m_Fonts.GetSize() == 0)
|
||||
Read();
|
||||
|
||||
if ((INT)Index >= m_Fonts.GetSize())
|
||||
return L"";
|
||||
|
||||
return m_Fonts[Index].File();
|
||||
}
|
||||
|
||||
CFontInfo* CFontCache::Find(const FontPidlEntry* fontEntry)
|
||||
{
|
||||
for (UINT n = 0; n < Size(); ++n)
|
||||
if (m_Fonts.GetSize() == 0)
|
||||
Read();
|
||||
|
||||
for (INT i = 0; i < m_Fonts.GetSize(); ++i)
|
||||
{
|
||||
if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
|
||||
if (m_Fonts[i].Name().CompareNoCase(fontEntry->Name()) == 0)
|
||||
{
|
||||
return &m_Fonts[n];
|
||||
return &m_Fonts[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL CFontCache::IsMarkDeleted(size_t Index) const
|
||||
{
|
||||
if ((INT)Index >= m_Fonts.GetSize())
|
||||
return FALSE;
|
||||
return m_Fonts[Index].IsMarkDeleted();
|
||||
}
|
||||
|
||||
// The item must exist until its visibility is removed, because the change
|
||||
// notification UI must work for existing items.
|
||||
void CFontCache::MarkDeleted(const FontPidlEntry* fontEntry)
|
||||
{
|
||||
for (INT i = 0; i < m_Fonts.GetSize(); ++i)
|
||||
{
|
||||
if (m_Fonts[i].Name().CompareNoCase(fontEntry->Name()) == 0)
|
||||
{
|
||||
m_Fonts[i].MarkDeleted();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CStringW CFontCache::Filename(CFontInfo* info, bool alwaysFullPath)
|
||||
{
|
||||
@@ -175,8 +210,14 @@ CStringW CFontCache::Filename(CFontInfo* info, bool alwaysFullPath)
|
||||
return File;
|
||||
}
|
||||
|
||||
void CFontCache::Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName)
|
||||
void CFontCache::Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName, PCWSTR Value)
|
||||
{
|
||||
CFontInfo newInfo(KeyName, Value);
|
||||
|
||||
CStringW strFontFile = g_FontCache->GetFontFilePath(newInfo.File());
|
||||
if (!PathFileExistsW(strFontFile))
|
||||
return;
|
||||
|
||||
POSITION it = fonts.GetHeadPosition();
|
||||
while (it != NULL)
|
||||
{
|
||||
@@ -184,54 +225,72 @@ void CFontCache::Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName)
|
||||
const CFontInfo& info = fonts.GetNext(it);
|
||||
if (info.Name().CompareNoCase(KeyName) >= 0)
|
||||
{
|
||||
fonts.InsertBefore(lastit, CFontInfo(KeyName));
|
||||
fonts.InsertBefore(lastit, newInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fonts.AddTail(CFontInfo(KeyName));
|
||||
|
||||
fonts.AddTail(newInfo);
|
||||
}
|
||||
|
||||
CStringW CFontCache::GetFontFilePath(const PCWSTR Path) const
|
||||
{
|
||||
if (PathIsRelativeW(Path))
|
||||
return m_FontFolderPath + Path;
|
||||
return Path;
|
||||
}
|
||||
|
||||
void CFontCache::Read()
|
||||
{
|
||||
CAtlList<CFontInfo> fonts;
|
||||
CRegKey key;
|
||||
LSTATUS error = key.Open(FONT_HIVE, FONT_KEY, KEY_READ);
|
||||
if (error != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("Can't open registry: %ld\n", error);
|
||||
return;
|
||||
}
|
||||
|
||||
CComHeapPtr<WCHAR> Name, Value;
|
||||
DWORD cchName = MAX_PATH, cchValue = MAX_PATH;
|
||||
if (!Name.Allocate(cchName) || !Value.Allocate(cchValue))
|
||||
{
|
||||
ERR("Out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Enumerate all registered font names
|
||||
if (key.Open(FONT_HIVE, FONT_KEY, KEY_READ) == ERROR_SUCCESS)
|
||||
CAtlList<CFontInfo> fonts;
|
||||
for (DWORD iItem = 0;; ++iItem)
|
||||
{
|
||||
LSTATUS Status;
|
||||
DWORD dwAllocated = 128;
|
||||
DWORD ilIndex = 0;
|
||||
CStringW KeyName;
|
||||
do
|
||||
DWORD cchName2 = cchName, cbValue = cchValue * sizeof(WCHAR);
|
||||
error = RegEnumValueW(key, iItem, Name, &cchName2, NULL, NULL,
|
||||
(PBYTE)(PWSTR)Value, &cbValue);
|
||||
if (error == ERROR_MORE_DATA)
|
||||
{
|
||||
DWORD dwSize = dwAllocated;
|
||||
PWSTR Buffer = KeyName.GetBuffer(dwSize);
|
||||
Status = RegEnumValueW(key.m_hKey, ilIndex, Buffer, &dwSize, NULL, NULL, NULL, NULL);
|
||||
KeyName.ReleaseBuffer(dwSize);
|
||||
if (Status == ERROR_SUCCESS)
|
||||
cchName += 128;
|
||||
cchValue += 128;
|
||||
if (!Name.Reallocate(cchName) || !Value.Reallocate(cchValue))
|
||||
{
|
||||
// Insert will create an ordered list
|
||||
Insert(fonts, KeyName);
|
||||
ilIndex++;
|
||||
continue;
|
||||
}
|
||||
if (Status == ERROR_NO_MORE_ITEMS)
|
||||
ERR("Out of memory\n");
|
||||
break;
|
||||
else if (Status == ERROR_MORE_DATA)
|
||||
{
|
||||
dwAllocated += 128;
|
||||
}
|
||||
} while (Status == ERROR_MORE_DATA || Status == ERROR_SUCCESS);
|
||||
--iItem;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
if (Name[0] && Value[0])
|
||||
{
|
||||
// Insert will create an ordered list (sorted)
|
||||
Insert(fonts, (PCWSTR)Name, (PCWSTR)Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Move the fonts from a list to an array (for easy indexing)
|
||||
m_Fonts.SetCount(fonts.GetCount());
|
||||
size_t Index = 0;
|
||||
m_Fonts.RemoveAll();
|
||||
POSITION it = fonts.GetHeadPosition();
|
||||
while (it != NULL)
|
||||
{
|
||||
m_Fonts[Index] = fonts.GetNext(it);
|
||||
Index++;
|
||||
}
|
||||
m_Fonts.Add(fonts.GetNext(it));
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ class CFontInfo
|
||||
private:
|
||||
CStringW m_Name;
|
||||
CStringW m_File;
|
||||
BOOL m_bMarkDeleted = FALSE;
|
||||
bool m_FileRead;
|
||||
|
||||
bool m_AttrsRead;
|
||||
LARGE_INTEGER m_FileSize;
|
||||
FILETIME m_FileWriteTime;
|
||||
@@ -22,11 +22,14 @@ private:
|
||||
void ReadAttrs();
|
||||
|
||||
public:
|
||||
CFontInfo(LPCWSTR name = L"");
|
||||
CFontInfo(PCWSTR name = L"", PCWSTR value = L"");
|
||||
|
||||
const CStringW& Name() const; // Font display name stored in the registry
|
||||
const bool Valid() const;
|
||||
|
||||
BOOL IsMarkDeleted() const { return m_bMarkDeleted; }
|
||||
void MarkDeleted() { m_bMarkDeleted = TRUE; }
|
||||
|
||||
const CStringW& File(); // Full path or file, depending on how it's stored in the registry
|
||||
const LARGE_INTEGER& FileSize();
|
||||
const FILETIME& FileWriteTime();
|
||||
@@ -36,24 +39,28 @@ public:
|
||||
class CFontCache
|
||||
{
|
||||
private:
|
||||
CAtlArray<CFontInfo> m_Fonts;
|
||||
CSimpleArray<CFontInfo> m_Fonts;
|
||||
CStringW m_FontFolderPath;
|
||||
|
||||
protected:
|
||||
CFontCache();
|
||||
|
||||
void Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName);
|
||||
void Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName, PCWSTR Value);
|
||||
|
||||
public:
|
||||
void Read();
|
||||
|
||||
void SetFontDir(const LPCWSTR Path);
|
||||
const CStringW& FontPath() const { return m_FontFolderPath; }
|
||||
CStringW GetFontFilePath(const PCWSTR Path) const;
|
||||
|
||||
size_t Size();
|
||||
CStringW Name(size_t Index); // Font display name stored in the registry
|
||||
CStringW File(size_t Index);
|
||||
|
||||
CFontInfo* Find(const FontPidlEntry* fontEntry);
|
||||
BOOL IsMarkDeleted(size_t Index) const;
|
||||
void MarkDeleted(const FontPidlEntry* fontEntry);
|
||||
CStringW Filename(CFontInfo* info, bool alwaysFullPath = false);
|
||||
|
||||
friend class CFontExtModule;
|
||||
|
||||
@@ -77,6 +77,37 @@ WCHAR* g2s(REFCLSID iid)
|
||||
return buf[idx];
|
||||
}
|
||||
|
||||
static HRESULT FONTEXT_GetAttributeString(DWORD dwAttributes, LPWSTR pszOut, UINT cchMax)
|
||||
{
|
||||
CStringW AttrLetters;
|
||||
AttrLetters.LoadString(IDS_COL_ATTR_LETTERS);
|
||||
|
||||
if (AttrLetters.GetLength() != 5)
|
||||
{
|
||||
ERR("IDS_COL_ATTR_LETTERS does not contain 5 letters!\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
UINT ich = 0;
|
||||
if ((dwAttributes & FILE_ATTRIBUTE_READONLY) && ich < cchMax)
|
||||
pszOut[ich++] = AttrLetters[0];
|
||||
if ((dwAttributes & FILE_ATTRIBUTE_HIDDEN) && ich < cchMax)
|
||||
pszOut[ich++] = AttrLetters[1];
|
||||
if ((dwAttributes & FILE_ATTRIBUTE_SYSTEM) && ich < cchMax)
|
||||
pszOut[ich++] = AttrLetters[2];
|
||||
if ((dwAttributes & FILE_ATTRIBUTE_ARCHIVE) && ich < cchMax)
|
||||
pszOut[ich++] = AttrLetters[3];
|
||||
if ((dwAttributes & FILE_ATTRIBUTE_COMPRESSED) && ich < cchMax)
|
||||
pszOut[ich++] = AttrLetters[4];
|
||||
if (ich < cchMax)
|
||||
{
|
||||
pszOut[ich] = UNICODE_NULL;
|
||||
return S_OK;
|
||||
}
|
||||
ERR("Buffer too short: %u\n", cchMax);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CFontExt::CFontExt()
|
||||
{
|
||||
InterlockedIncrement(&g_ModuleRefCnt);
|
||||
@@ -92,20 +123,18 @@ void CFontExt::SetViewWindow(HWND hwndView)
|
||||
m_hwndView = hwndView;
|
||||
}
|
||||
|
||||
HRESULT CALLBACK
|
||||
CFontExt::MenuCallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
HRESULT CFontExt::DeleteItems(IDataObject* pDataObj)
|
||||
{
|
||||
TRACE("%u, %p, %p\n", uMsg, wParam, lParam);
|
||||
switch (uMsg)
|
||||
{
|
||||
case DFM_MERGECONTEXTMENU:
|
||||
return S_OK; // Yes, I want verbs
|
||||
case DFM_INVOKECOMMAND:
|
||||
return S_FALSE; // Do it for me please
|
||||
case DFM_GETDEFSTATICID:
|
||||
return S_FALSE; // Supposedly "required for Windows 7 to pick a default"
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
HRESULT hr = DoDeleteFontFiles(m_hwndView, pDataObj);
|
||||
FAILED_UNEXPECTEDLY(hr);
|
||||
return S_OK; // Override default action
|
||||
}
|
||||
|
||||
HRESULT CFontExt::PreviewItems(IDataObject* pDataObj)
|
||||
{
|
||||
HRESULT hr = DoPreviewFontFiles(m_hwndView, pDataObj);
|
||||
FAILED_UNEXPECTEDLY(hr);
|
||||
return S_OK; // Override default action
|
||||
}
|
||||
|
||||
// *** IShellFolder2 methods ***
|
||||
@@ -179,13 +208,11 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
|
||||
auto info = g_FontCache->Find(fontEntry);
|
||||
if (info == nullptr)
|
||||
{
|
||||
ERR("Unable to query info about %S\n", fontEntry->Name);
|
||||
ERR("Unable to query info about %S\n", fontEntry->Name());
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
int ret;
|
||||
CStringA AttrLetters;
|
||||
DWORD dwAttributes;
|
||||
SYSTEMTIME time;
|
||||
switch (iColumn)
|
||||
{
|
||||
@@ -208,27 +235,13 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
|
||||
GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &psd->str.cStr[ret], MAX_PATH - ret);
|
||||
return S_OK;
|
||||
case FONTEXT_COL_ATTR:
|
||||
AttrLetters.LoadString(IDS_COL_ATTR_LETTERS);
|
||||
if (AttrLetters.GetLength() != 5)
|
||||
{
|
||||
ERR("IDS_COL_ATTR_LETTERS does not contain 5 letters!\n");
|
||||
return E_FAIL;
|
||||
WCHAR szAttr[8];
|
||||
HRESULT hr = FONTEXT_GetAttributeString(info->FileAttributes(), szAttr, _countof(szAttr));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
return SHSetStrRet(&psd->str, szAttr);
|
||||
}
|
||||
psd->str.uType = STRRET_CSTR;
|
||||
dwAttributes = info->FileAttributes();
|
||||
ret = 0;
|
||||
if (dwAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
psd->str.cStr[ret++] = AttrLetters[0];
|
||||
if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
psd->str.cStr[ret++] = AttrLetters[1];
|
||||
if (dwAttributes & FILE_ATTRIBUTE_SYSTEM)
|
||||
psd->str.cStr[ret++] = AttrLetters[2];
|
||||
if (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)
|
||||
psd->str.cStr[ret++] = AttrLetters[3];
|
||||
if (dwAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
||||
psd->str.cStr[ret++] = AttrLetters[4];
|
||||
psd->str.cStr[ret] = '\0';
|
||||
return S_OK;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -246,8 +259,53 @@ STDMETHODIMP CFontExt::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
|
||||
// *** IShellFolder2 methods ***
|
||||
STDMETHODIMP CFontExt::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
|
||||
{
|
||||
ERR("%s() UNIMPLEMENTED\n", __FUNCTION__);
|
||||
return E_NOTIMPL;
|
||||
if (!lpszDisplayName || !lpszDisplayName[0] || !ppidl)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppidl = NULL;
|
||||
if (pchEaten)
|
||||
*pchEaten = 0;
|
||||
|
||||
if (lpszDisplayName[0] == L':' && lpszDisplayName[1] == L':')
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (PathIsRelativeW(lpszDisplayName)) // Not full path?
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Load font cache
|
||||
if (g_FontCache->Size() == 0)
|
||||
g_FontCache->Read();
|
||||
|
||||
for (SIZE_T iFont = 0; iFont < g_FontCache->Size(); ++iFont)
|
||||
{
|
||||
CStringW fileName = g_FontCache->File(iFont);
|
||||
if (fileName.IsEmpty())
|
||||
continue;
|
||||
|
||||
CStringW filePath = g_FontCache->GetFontFilePath(fileName);
|
||||
if (filePath.CompareNoCase(lpszDisplayName) != 0)
|
||||
continue;
|
||||
|
||||
CStringW fontName = g_FontCache->Name(iFont);
|
||||
if (fontName.IsEmpty())
|
||||
continue;
|
||||
|
||||
// Create a PIDL
|
||||
*ppidl = _ILCreate(fontName, fileName);
|
||||
if (!*ppidl)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (pchEaten)
|
||||
*pchEaten = wcslen(lpszDisplayName);
|
||||
|
||||
if (pdwAttributes && *pdwAttributes)
|
||||
*pdwAttributes &= (SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_CANCOPY |
|
||||
SFGAO_FILESYSTEM);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); // Not found
|
||||
}
|
||||
|
||||
STDMETHODIMP CFontExt::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
|
||||
@@ -271,7 +329,6 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
|
||||
{
|
||||
const FontPidlEntry* fontEntry1 = _FontFromIL(pidl1);
|
||||
const FontPidlEntry* fontEntry2 = _FontFromIL(pidl2);
|
||||
|
||||
if (!fontEntry1 || !fontEntry2)
|
||||
return E_INVALIDARG;
|
||||
|
||||
@@ -280,7 +337,7 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
|
||||
DWORD column = lParam & 0x0000FFFF;
|
||||
if (sortMode == SHCIDS_ALLFIELDS)
|
||||
{
|
||||
result = StrCmpIW(fontEntry1->Name, fontEntry2->Name);
|
||||
result = StrCmpIW(fontEntry1->Name(), fontEntry2->Name());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -289,7 +346,7 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
|
||||
|
||||
if (!info1 || !info2)
|
||||
{
|
||||
ERR("Unable to find font %S or %S in cache!\n", fontEntry1->Name, fontEntry2->Name);
|
||||
ERR("Unable to find font %S or %S in cache!\n", fontEntry1->Name(), fontEntry2->Name());
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
@@ -298,22 +355,32 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
|
||||
case 0xffff:
|
||||
/* ROS bug? */
|
||||
case FONTEXT_COL_NAME:
|
||||
result = StrCmpIW(fontEntry1->Name, fontEntry2->Name);
|
||||
result = StrCmpIW(fontEntry1->Name(), fontEntry2->Name());
|
||||
break;
|
||||
case FONTEXT_COL_FILENAME:
|
||||
result = StrCmpIW(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;
|
||||
{
|
||||
ULONGLONG size1 = info1->FileSize().QuadPart, size2 = info2->FileSize().QuadPart;
|
||||
result = (size1 < size2) ? -1 : ((size1 > size2) ? 1 : 0);
|
||||
}
|
||||
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();
|
||||
{
|
||||
HRESULT hr;
|
||||
WCHAR szAttr1[8], szAttr2[8];
|
||||
hr = FONTEXT_GetAttributeString(info1->FileAttributes(), szAttr1, _countof(szAttr1));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
hr = FONTEXT_GetAttributeString(info2->FileAttributes(), szAttr2, _countof(szAttr2));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
result = _wcsicmp(szAttr1, szAttr2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERR("Unimplemented column %u\n", column);
|
||||
@@ -361,16 +428,11 @@ STDMETHODIMP CFontExt::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, D
|
||||
if (!rgfInOut || !cidl || !apidl)
|
||||
return E_INVALIDARG;
|
||||
|
||||
DWORD rgf = 0;
|
||||
DWORD rgf = (SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_CANCOPY | SFGAO_FILESYSTEM);
|
||||
while (cidl > 0 && *apidl)
|
||||
{
|
||||
const FontPidlEntry* fontEntry = _FontFromIL(*apidl);
|
||||
if (fontEntry)
|
||||
{
|
||||
// We don't support delete yet
|
||||
rgf |= (/*SFGAO_CANDELETE |*/ SFGAO_HASPROPSHEET | SFGAO_CANCOPY | SFGAO_FILESYSTEM);
|
||||
}
|
||||
else
|
||||
if (!fontEntry)
|
||||
{
|
||||
rgf = 0;
|
||||
break;
|
||||
@@ -380,46 +442,81 @@ STDMETHODIMP CFontExt::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, D
|
||||
cidl--;
|
||||
}
|
||||
|
||||
*rgfInOut = rgf;
|
||||
*rgfInOut &= rgf;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFontExt::CreateForegroundMenu(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, LPVOID* ppvOut)
|
||||
HRESULT CALLBACK CFontExt::MenuCallback(
|
||||
IShellFolder *psf, HWND hwnd, IDataObject *pdtobj,
|
||||
UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (cidl <= 0)
|
||||
{
|
||||
ERR("cidl: %u\n", cidl);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
const FontPidlEntry* pEntry = _FontFromIL(apidl[0]);
|
||||
if (!pEntry)
|
||||
{
|
||||
ERR("!pEntry\n");
|
||||
CFontExt* pThis = static_cast<CFontExt*>(psf);
|
||||
if (!pThis)
|
||||
return E_FAIL;
|
||||
}
|
||||
auto info = g_FontCache->Find(pEntry);
|
||||
if (!info)
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
ERR("!info\n");
|
||||
return E_FAIL;
|
||||
case DFM_MERGECONTEXTMENU:
|
||||
{
|
||||
QCMINFO* pqcminfo = (QCMINFO*)lParam;
|
||||
// Insert [Preview] menu item
|
||||
CString strPreview(MAKEINTRESOURCEW(IDS_FONT_PREVIEW));
|
||||
::InsertMenuW(pqcminfo->hmenu, 0, MF_BYPOSITION | MF_STRING,
|
||||
pqcminfo->idCmdFirst++, strPreview); // Command 0
|
||||
// Make it default
|
||||
::SetMenuDefaultItem(pqcminfo->hmenu, pqcminfo->idCmdFirst - 1, FALSE);
|
||||
return S_OK;
|
||||
}
|
||||
case DFM_GETVERBA:
|
||||
case DFM_GETVERBW:
|
||||
{
|
||||
// Replace default "open" command action
|
||||
UINT idCmd = LOWORD(wParam), cchMax = HIWORD(wParam);
|
||||
if (idCmd == 0)
|
||||
{
|
||||
if (uMsg == DFM_GETVERBA)
|
||||
lstrcpynA((PSTR)lParam, "open", cchMax);
|
||||
else
|
||||
lstrcpynW((PWSTR)lParam, L"open", cchMax);
|
||||
return S_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DFM_INVOKECOMMANDEX:
|
||||
return E_NOTIMPL;
|
||||
case DFM_INVOKECOMMAND:
|
||||
{
|
||||
if (wParam == 0)
|
||||
return pThis->PreviewItems(pdtobj);
|
||||
if (wParam == DFM_CMD_COPY)
|
||||
return S_FALSE;
|
||||
if (wParam == DFM_CMD_DELETE)
|
||||
return pThis->DeleteItems(pdtobj);
|
||||
if (wParam == DFM_CMD_PASTE)
|
||||
return S_FALSE;
|
||||
if (wParam == DFM_CMD_PROPERTIES)
|
||||
return S_FALSE;
|
||||
if (wParam == DFM_CMD_MOVE)
|
||||
{
|
||||
ERR("DFM_CMD_MOVE not supported\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
ERR("wParam: %p\n", wParam);
|
||||
return E_FAIL;
|
||||
}
|
||||
case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default
|
||||
return S_FALSE;
|
||||
case DFM_WM_INITMENUPOPUP:
|
||||
{
|
||||
HMENU hMenu = (HMENU)wParam;
|
||||
// Delete default [Open] menu item
|
||||
::DeleteMenu(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
|
||||
// Disable [Paste link] menu item
|
||||
::EnableMenuItem(hMenu, FCIDM_SHVIEW_INSERTLINK, MF_BYCOMMAND | MF_GRAYED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LPCWSTR extension = PathFindExtensionW(info->File());
|
||||
|
||||
CRegKeyHandleArray keys;
|
||||
|
||||
WCHAR wszClass[MAX_PATH];
|
||||
DWORD dwSize = sizeof(wszClass);
|
||||
if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) != ERROR_SUCCESS ||
|
||||
!*wszClass || AddClassKeyToArray(wszClass, keys, keys) != ERROR_SUCCESS)
|
||||
{
|
||||
AddClassKeyToArray(extension, keys, keys);
|
||||
|
||||
if (cidl == 1)
|
||||
AddClassKeyToArray(L"Unknown", keys, keys);
|
||||
}
|
||||
|
||||
return CDefFolderMenu_Create2(m_Folder, hwndOwner, cidl, apidl, this, MenuCallBack, keys, keys, (IContextMenu**)ppvOut);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
|
||||
@@ -428,7 +525,11 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_
|
||||
riid == IID_IContextMenu2 ||
|
||||
riid == IID_IContextMenu3)
|
||||
{
|
||||
return CreateForegroundMenu(hwndOwner, cidl, apidl, ppvOut);
|
||||
if (cidl <= 0)
|
||||
return E_FAIL;
|
||||
|
||||
return CDefFolderMenu_Create2(NULL, hwndOwner, cidl, apidl, this, MenuCallback,
|
||||
0, NULL, (IContextMenu**)ppvOut);
|
||||
}
|
||||
else if (riid == IID_IExtractIconA || riid == IID_IExtractIconW)
|
||||
{
|
||||
@@ -438,10 +539,8 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_
|
||||
if (fontEntry)
|
||||
{
|
||||
DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
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);
|
||||
CStringW strFileName = g_FontCache->GetFontFilePath(fontEntry->FileName());
|
||||
return SHCreateFileExtractIconW(strFileName, dwAttributes, riid, ppvOut);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -478,12 +577,12 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_
|
||||
|
||||
STDMETHODIMP CFontExt::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
|
||||
{
|
||||
if (!pidl)
|
||||
return E_NOTIMPL;
|
||||
if (!pidl || !strRet)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Validate that this pidl is the last one
|
||||
PCUIDLIST_RELATIVE curpidl = ILGetNext(pidl);
|
||||
if (curpidl->mkid.cb != 0)
|
||||
PCUIDLIST_RELATIVE nextPidl = ILGetNext(pidl);
|
||||
if (nextPidl && nextPidl->mkid.cb != 0)
|
||||
{
|
||||
ERR("ERROR, unhandled PIDL!\n");
|
||||
return E_FAIL;
|
||||
@@ -495,14 +594,17 @@ STDMETHODIMP CFontExt::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPS
|
||||
|
||||
if (dwFlags & SHGDN_FORPARSING)
|
||||
{
|
||||
CStringW File = g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
|
||||
if (!File.IsEmpty())
|
||||
CStringW fileName = fontEntry->FileName();
|
||||
if (!(dwFlags & SHGDN_INFOLDER))
|
||||
{
|
||||
return SHSetStrRet(strRet, File);
|
||||
CStringW fullPath = g_FontCache->GetFontFilePath(fileName);
|
||||
if (!fullPath.IsEmpty())
|
||||
return SHSetStrRet(strRet, fullPath);
|
||||
}
|
||||
return SHSetStrRet(strRet, fileName);
|
||||
}
|
||||
|
||||
return SHSetStrRet(strRet, fontEntry->Name);
|
||||
return SHSetStrRet(strRet, fontEntry->Name());
|
||||
}
|
||||
|
||||
STDMETHODIMP CFontExt::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
|
||||
@@ -546,7 +648,7 @@ STDMETHODIMP CFontExt::Initialize(LPCITEMIDLIST pidl)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
m_Folder.Attach(ILClone(pidl));
|
||||
m_Folder.Attach(ILCreateFromPathW(FontsDir));
|
||||
StringCchCatW(FontsDir, _countof(FontsDir), L"\\");
|
||||
g_FontCache->SetFontDir(FontsDir);
|
||||
|
||||
@@ -609,6 +711,7 @@ STDMETHODIMP CFontExt::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt,
|
||||
if (g_FontCache)
|
||||
g_FontCache->Read();
|
||||
|
||||
SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"fonts", SMTO_ABORTIFHUNG, 1000, NULL);
|
||||
SendMessageTimeoutW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0, SMTO_ABORTIFHUNG, 1000, NULL);
|
||||
|
||||
// Show successful message
|
||||
|
||||
@@ -19,13 +19,17 @@ class CFontExt :
|
||||
BOOL m_bDragAccepted = FALSE;
|
||||
HWND m_hwndView = nullptr;
|
||||
|
||||
static HRESULT CALLBACK MenuCallback(
|
||||
IShellFolder *psf, HWND hwnd, IDataObject *pdtobj,
|
||||
UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
HRESULT PreviewItems(IDataObject* pDataObj);
|
||||
HRESULT DeleteItems(IDataObject* pDataObj);
|
||||
|
||||
public:
|
||||
CFontExt();
|
||||
~CFontExt();
|
||||
|
||||
void SetViewWindow(HWND hwndView);
|
||||
static HRESULT CALLBACK MenuCallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
HRESULT CreateForegroundMenu(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, LPVOID* ppvOut);
|
||||
|
||||
// *** IShellFolder2 methods ***
|
||||
STDMETHODIMP GetDefaultSearchGUID(GUID *lpguid) override;
|
||||
@@ -93,6 +97,7 @@ 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_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
|
||||
//COM_INTERFACE_ENTRY_FUNC_BLIND(0, log_stuff)
|
||||
END_COM_MAP()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell_ad);
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(fontext);
|
||||
|
||||
void CFontFolderViewCB::Initialize(CFontExt* pFontExt, IShellView *psv, LPCITEMIDLIST pidlParent)
|
||||
{
|
||||
@@ -18,70 +18,29 @@ void CFontFolderViewCB::Initialize(CFontExt* pFontExt, IShellView *psv, LPCITEMI
|
||||
m_pShellView = psv;
|
||||
m_pidlParent.Attach(ILClone(pidlParent));
|
||||
if (!m_pidlParent)
|
||||
ERR("!m_pidlParent\n");
|
||||
ERR("m_pidlParent was null\n");
|
||||
}
|
||||
|
||||
HRESULT CFontFolderViewCB::TranslatePidl(LPITEMIDLIST* ppidlNew, LPCITEMIDLIST pidl)
|
||||
BOOL CFontFolderViewCB::FilterEvent(PIDLIST_ABSOLUTE* apidls, LONG lEvent) const
|
||||
{
|
||||
ATLASSERT(ppidlNew);
|
||||
lEvent &= ~SHCNE_INTERRUPT;
|
||||
|
||||
*ppidlNew = NULL;
|
||||
|
||||
WCHAR szFontFile[MAX_PATH];
|
||||
if (!SHGetPathFromIDListW(pidl, szFontFile))
|
||||
return E_FAIL;
|
||||
|
||||
CStringW strFontName;
|
||||
HRESULT hr = DoGetFontTitle(szFontFile, strFontName);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return E_FAIL;
|
||||
|
||||
LPITEMIDLIST pidlChild = _ILCreate(strFontName);
|
||||
if (!pidlChild)
|
||||
{
|
||||
ERR("!pidlChild\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*ppidlNew = ILCombine(m_pidlParent, pidlChild);
|
||||
ILFree(pidlChild);
|
||||
|
||||
return *ppidlNew ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
void CFontFolderViewCB::TranslateTwoPIDLs(PIDLIST_ABSOLUTE* pidls)
|
||||
{
|
||||
ATLASSERT(pidls);
|
||||
|
||||
HRESULT hr;
|
||||
if (pidls[0])
|
||||
{
|
||||
m_pidl0.Free();
|
||||
hr = TranslatePidl(&m_pidl0, pidls[0]);
|
||||
if (!FAILED_UNEXPECTEDLY(hr))
|
||||
pidls[0] = m_pidl0;
|
||||
}
|
||||
if (pidls[1])
|
||||
{
|
||||
m_pidl1.Free();
|
||||
hr = TranslatePidl(&m_pidl1, pidls[1]);
|
||||
if (!FAILED_UNEXPECTEDLY(hr))
|
||||
pidls[1] = m_pidl1;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CFontFolderViewCB::FilterEvent(LONG lEvent) const
|
||||
{
|
||||
switch (lEvent & ~SHCNE_INTERRUPT)
|
||||
switch (lEvent)
|
||||
{
|
||||
case SHCNE_CREATE:
|
||||
case SHCNE_DELETE:
|
||||
case SHCNE_RENAMEITEM:
|
||||
case SHCNE_UPDATEDIR:
|
||||
return FALSE; // OK
|
||||
// Refresh font cache and notify the system about the font change
|
||||
if (g_FontCache)
|
||||
g_FontCache->Read();
|
||||
break;
|
||||
case SHCNE_DELETE:
|
||||
break;
|
||||
default:
|
||||
return TRUE; // We don't want this event
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
@@ -91,19 +50,17 @@ CFontFolderViewCB::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
case SFVM_QUERYFSNOTIFY: // Registering change notification
|
||||
{
|
||||
if (!m_pShellView || !m_pFontExt)
|
||||
return E_FAIL;
|
||||
// Now, we can get the view window
|
||||
ATLASSERT(m_pShellView);
|
||||
ATLASSERT(m_pFontExt);
|
||||
m_pShellView->GetWindow(&m_hwndView);
|
||||
m_pFontExt->SetViewWindow(m_hwndView);
|
||||
return S_OK;
|
||||
}
|
||||
case SFVM_FSNOTIFY: // Change notification
|
||||
{
|
||||
if (FilterEvent((LONG)lParam))
|
||||
if (FilterEvent((PIDLIST_ABSOLUTE*)wParam, (LONG)lParam))
|
||||
return S_FALSE; // Don't process
|
||||
|
||||
TranslateTwoPIDLs((PIDLIST_ABSOLUTE*)wParam);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,23 +11,19 @@ class CFontFolderViewCB
|
||||
: public CComObjectRootEx<CComMultiThreadModelNoCS>
|
||||
, public IShellFolderViewCB
|
||||
{
|
||||
CFontExt* m_pFontExt = nullptr; // Not ref-counted!
|
||||
IShellView* m_pShellView = nullptr; // Not ref-counted!
|
||||
CFontExt* m_pFontExt = nullptr;
|
||||
CComPtr<IShellView> m_pShellView;
|
||||
HWND m_hwndView = nullptr;
|
||||
CComHeapPtr<ITEMIDLIST> m_pidlParent;
|
||||
CComHeapPtr<ITEMIDLIST> m_pidl0;
|
||||
CComHeapPtr<ITEMIDLIST> m_pidl1;
|
||||
|
||||
HRESULT TranslatePidl(LPITEMIDLIST* ppidlNew, LPCITEMIDLIST pidl);
|
||||
void TranslateTwoPIDLs(PIDLIST_ABSOLUTE* pidls);
|
||||
BOOL FilterEvent(LONG lEvent) const;
|
||||
BOOL FilterEvent(PIDLIST_ABSOLUTE* apidls, LONG lEvent) const;
|
||||
|
||||
public:
|
||||
CFontFolderViewCB() { }
|
||||
void Initialize(CFontExt* pFontExt, IShellView *psv, LPCITEMIDLIST pidlParent);
|
||||
|
||||
// IShellFolderViewCB
|
||||
STDMETHOD(MessageSFVCB)(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
|
||||
STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
|
||||
|
||||
DECLARE_NO_REGISTRY()
|
||||
DECLARE_NOT_AGGREGATABLE(CFontFolderViewCB)
|
||||
|
||||
@@ -111,14 +111,14 @@ LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys)
|
||||
if (*cKeys >= 16)
|
||||
return ERROR_MORE_DATA;
|
||||
|
||||
HKEY hkey;
|
||||
LSTATUS result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ | KEY_QUERY_VALUE, &hkey);
|
||||
if (result == ERROR_SUCCESS)
|
||||
CRegKey key;
|
||||
LSTATUS error = key.Open(HKEY_CLASSES_ROOT, szClass, KEY_READ | KEY_QUERY_VALUE);
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
array[*cKeys] = hkey;
|
||||
array[*cKeys] = key.Detach();
|
||||
*cKeys += 1;
|
||||
}
|
||||
return result;
|
||||
return error;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
@@ -436,6 +436,137 @@ HRESULT InstallFontsFromDataObject(HWND hwndView, IDataObject* pDataObj)
|
||||
return FAILED_UNEXPECTEDLY(data.hrResult) ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
HRESULT DoPreviewFontFiles(HWND hwnd, IDataObject* pDataObj)
|
||||
{
|
||||
CDataObjectHIDA cida(pDataObj);
|
||||
if (!cida || cida->cidl <= 0)
|
||||
{
|
||||
ERR("Invalid IDataObject\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
for (UINT iItem = 0; iItem < cida->cidl; ++iItem)
|
||||
{
|
||||
PCUIDLIST_RELATIVE pidlChild = HIDA_GetPIDLItem(cida, iItem);
|
||||
const FontPidlEntry* fontEntry = _FontFromIL(pidlChild);
|
||||
if (fontEntry)
|
||||
RunFontViewer(hwnd, fontEntry);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFontFiles(HWND hwnd, IDataObject* pDataObj)
|
||||
{
|
||||
CDataObjectHIDA cida(pDataObj);
|
||||
if (!cida || cida->cidl <= 0)
|
||||
{
|
||||
ERR("E_FAIL\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(cida);
|
||||
if (!pidlParent)
|
||||
{
|
||||
ERR("pidlParent is NULL\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Delete files
|
||||
for (UINT iItem = 0; iItem < cida->cidl; ++iItem)
|
||||
{
|
||||
PCUIDLIST_RELATIVE pidlChild = HIDA_GetPIDLItem(cida, iItem);
|
||||
const FontPidlEntry* pEntry = _FontFromIL(pidlChild);
|
||||
if (!pEntry)
|
||||
{
|
||||
ERR("Invalid pEntry: %p\n", pEntry);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CStringW szPath = g_FontCache->GetFontFilePath(pEntry->FileName());
|
||||
|
||||
// WINDOWS BUG: Removing once is not enough
|
||||
for (INT iTry = 0; iTry < 3; ++iTry)
|
||||
{
|
||||
if (!RemoveFontResourceW(szPath) && !RemoveFontResourceExW(szPath, FR_PRIVATE, NULL))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!DeleteFileW(szPath))
|
||||
{
|
||||
ERR("Unable to delete font file: %S: %ld\n", (PCWSTR)szPath, GetLastError());
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidl(ILCombine(pidlParent, pidlChild));
|
||||
if (pidl)
|
||||
SHChangeNotify(SHCNE_DELETE, SHCNF_IDLIST, (LPCITEMIDLIST)pidl, NULL);
|
||||
else
|
||||
ERR("Out of memory\n");
|
||||
}
|
||||
|
||||
// Delete registry values and mark the entry as deleted
|
||||
CRegKey key;
|
||||
if (key.Open(FONT_HIVE, FONT_KEY, KEY_WRITE) == ERROR_SUCCESS)
|
||||
{
|
||||
for (UINT iItem = 0; iItem < cida->cidl; ++iItem)
|
||||
{
|
||||
PCUIDLIST_RELATIVE pidlChild = HIDA_GetPIDLItem(cida, iItem);
|
||||
const FontPidlEntry* pEntry = _FontFromIL(pidlChild);
|
||||
if (pEntry)
|
||||
{
|
||||
CStringW strFontName = pEntry->Name();
|
||||
key.DeleteValue(strFontName);
|
||||
g_FontCache->MarkDeleted(pEntry);
|
||||
}
|
||||
}
|
||||
key.Close();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DoDeleteFontFiles(HWND hwnd, IDataObject* pDataObj)
|
||||
{
|
||||
CStringW title(MAKEINTRESOURCEW(IDS_REACTOS_FONTS_FOLDER));
|
||||
CStringW msg(MAKEINTRESOURCEW(IDS_CONFIRM_DELETE_FONT));
|
||||
if (MessageBoxW(hwnd, msg, title, MB_YESNOCANCEL | MB_ICONWARNING) != IDYES)
|
||||
return S_FALSE;
|
||||
|
||||
HRESULT hr = DeleteFontFiles(hwnd, pDataObj);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
msg.LoadString(IDS_CANTDELETEFONT);
|
||||
MessageBoxW(hwnd, msg, title, MB_ICONERROR);
|
||||
return hr;
|
||||
}
|
||||
|
||||
SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"fonts",
|
||||
SMTO_ABORTIFHUNG, 1000, NULL);
|
||||
SendMessageTimeoutW(HWND_BROADCAST, WM_FONTCHANGE, 0, 0, SMTO_ABORTIFHUNG, 1000, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void RunFontViewer(HWND hwnd, const FontPidlEntry* fontEntry)
|
||||
{
|
||||
CStringW Path = g_FontCache->GetFontFilePath(fontEntry->FileName());
|
||||
if (Path.IsEmpty())
|
||||
return;
|
||||
|
||||
// '/d' disables the install button
|
||||
WCHAR FontPathArg[MAX_PATH + 3];
|
||||
StringCchPrintfW(FontPathArg, _countof(FontPathArg), L"/d %s", Path.GetString());
|
||||
PathQuoteSpacesW(FontPathArg + 3);
|
||||
|
||||
SHELLEXECUTEINFOW si = { sizeof(si) };
|
||||
si.fMask = SEE_MASK_DOENVSUBST;
|
||||
si.hwnd = hwnd;
|
||||
si.lpFile = L"%SystemRoot%\\System32\\fontview.exe";
|
||||
si.lpParameters = FontPathArg;
|
||||
si.nShow = SW_SHOWNORMAL;
|
||||
ShellExecuteExW(&si);
|
||||
}
|
||||
|
||||
EXTERN_C
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
|
||||
@@ -3,33 +3,109 @@
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: pidl handling
|
||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
|
||||
* Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
LPITEMIDLIST _ILCreate(LPCWSTR lpString)
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(fontext);
|
||||
|
||||
#define FONTPIDL_MAGIC 0x7066 // 'fp'
|
||||
#define ALIGN_DWORD(size) (((size) + 3) & ~3)
|
||||
|
||||
PITEMID_CHILD _ILCreate(LPCWSTR lpName, LPCWSTR lpFileName)
|
||||
{
|
||||
// Because the FontPidlEntry contains one WCHAR, we do not need to take the null terminator into account
|
||||
size_t cbData = sizeof(FontPidlEntry) + wcslen(lpString) * sizeof(WCHAR);
|
||||
ATLASSERT(lpName);
|
||||
ATLASSERT(lpFileName);
|
||||
|
||||
if (!lpName[0] || !lpFileName[0])
|
||||
{
|
||||
ERR("Invalid parameters: lpName '%S', lpFileName '%S'\n", lpName, lpFileName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// SECURITY: Check string length
|
||||
HRESULT hr;
|
||||
size_t cbName, cbFileName;
|
||||
hr = StringCbLengthW(lpName, min(MAXWORD - 1, STRSAFE_MAX_CCH) * sizeof(WCHAR), &cbName);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return NULL;
|
||||
hr = StringCbLengthW(lpFileName, min(MAXWORD - 1, STRSAFE_MAX_CCH) * sizeof(WCHAR), &cbFileName);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return NULL;
|
||||
cbName += sizeof(UNICODE_NULL);
|
||||
cbFileName += sizeof(UNICODE_NULL);
|
||||
|
||||
size_t ibName = ALIGN_DWORD(sizeof(FontPidlEntry));
|
||||
size_t ibFileName = ALIGN_DWORD(ibName + cbName);
|
||||
size_t cbData = ibFileName + cbFileName;
|
||||
if (cbData > MAXWORD - sizeof(WORD))
|
||||
{
|
||||
ATLASSERT(FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FontPidlEntry* pidl = (FontPidlEntry*)CoTaskMemAlloc(cbData + sizeof(WORD));
|
||||
if (!pidl)
|
||||
{
|
||||
ERR("Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMemory(pidl, cbData + sizeof(WORD));
|
||||
|
||||
pidl->cb = (WORD)cbData;
|
||||
pidl->Magic = 'fp';
|
||||
wcscpy(pidl->Name, lpString);
|
||||
// Should be zero already, but make sure it is
|
||||
*(WORD*)((char*)pidl + cbData) = 0;
|
||||
pidl->Magic = FONTPIDL_MAGIC;
|
||||
pidl->ibName = (WORD)ibName;
|
||||
pidl->ibFileName = (WORD)ibFileName;
|
||||
|
||||
return (LPITEMIDLIST)pidl;
|
||||
// SECURITY: Copy strings
|
||||
hr = StringCbCopyW(pidl->Name(), cbName, lpName);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
CoTaskMemFree(pidl);
|
||||
return NULL;
|
||||
}
|
||||
hr = StringCbCopyW(pidl->FileName(), cbFileName, lpFileName);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
CoTaskMemFree(pidl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*(PWORD)((PBYTE)pidl + cbData) = UNICODE_NULL;
|
||||
|
||||
ATLASSERT(_FontFromIL((PITEMID_CHILD)pidl));
|
||||
|
||||
return (PITEMID_CHILD)pidl;
|
||||
}
|
||||
|
||||
const FontPidlEntry* _FontFromIL(LPCITEMIDLIST pidl)
|
||||
const FontPidlEntry* _FontFromIL(PCITEMID_CHILD pidl)
|
||||
{
|
||||
if (!pidl || pidl->mkid.cb < sizeof(FontPidlEntry))
|
||||
return NULL;
|
||||
|
||||
const FontPidlEntry* fontEntry = (const FontPidlEntry*)pidl;
|
||||
if (fontEntry->Magic == 'fp')
|
||||
return fontEntry;
|
||||
return NULL;
|
||||
if (fontEntry->Magic != FONTPIDL_MAGIC)
|
||||
return NULL;
|
||||
|
||||
// The function gets an arbitrary PIDL here. Security is important.
|
||||
// SECURITY: Check ibName and ibFileName
|
||||
if (fontEntry->ibName < sizeof(FontPidlEntry) || fontEntry->ibFileName < sizeof(FontPidlEntry) ||
|
||||
fontEntry->ibName >= fontEntry->cb || fontEntry->ibFileName >= fontEntry->cb ||
|
||||
fontEntry->ibName % sizeof(WCHAR) != 0 || fontEntry->ibFileName % sizeof(WCHAR) != 0)
|
||||
{
|
||||
ERR("Invalid fontEntry %p (ibName %d, ibFileName %d, cb %d)\n", fontEntry,
|
||||
fontEntry->ibName, fontEntry->ibFileName, fontEntry->cb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// SECURITY: Check null termination
|
||||
size_t cbName, cbNameMax = fontEntry->cb - fontEntry->ibName;
|
||||
if (FAILED_UNEXPECTEDLY(StringCbLengthW(fontEntry->Name(), cbNameMax, &cbName)))
|
||||
return NULL;
|
||||
size_t cbFileName, cbFileNameMax = fontEntry->cb - fontEntry->ibFileName;
|
||||
if (FAILED_UNEXPECTEDLY(StringCbLengthW(fontEntry->FileName(), cbFileNameMax, &cbFileName)))
|
||||
return NULL;
|
||||
|
||||
return fontEntry;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: pidl handling
|
||||
* COPYRIGHT: Copyright 2019 Mark Jansen <mark.jansen@reactos.org>
|
||||
* Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -12,9 +13,14 @@ struct FontPidlEntry
|
||||
{
|
||||
WORD cb;
|
||||
WORD Magic;
|
||||
WCHAR Name[1];
|
||||
WORD ibName;
|
||||
WORD ibFileName;
|
||||
LPWSTR Name() { return (LPWSTR)((PBYTE)this + ibName); }
|
||||
LPWSTR FileName() { return (LPWSTR)((PBYTE)this + ibFileName); }
|
||||
LPCWSTR Name() const { return (LPCWSTR)((PBYTE)this + ibName); }
|
||||
LPCWSTR FileName() const { return (LPCWSTR)((PBYTE)this + ibFileName); }
|
||||
};
|
||||
#include <poppack.h>
|
||||
|
||||
LPITEMIDLIST _ILCreate(LPCWSTR lpString);
|
||||
const FontPidlEntry* _FontFromIL(LPCITEMIDLIST pidl);
|
||||
PITEMID_CHILD _ILCreate(LPCWSTR lpName, LPCWSTR lpFileName);
|
||||
const FontPidlEntry* _FontFromIL(PCITEMID_CHILD pidl);
|
||||
|
||||
@@ -20,9 +20,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "ReactOS Schriftartenordner"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -15,9 +15,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "ReactOS Font Folder"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -20,9 +20,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "Cartella dei font di ReactOS"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -15,9 +15,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "Folder czcionek ReactOS"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -21,9 +21,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "Folder-ul de fonturi de ReactOS"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -15,9 +15,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "ReactOS Yazı Tipi Dizini"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -20,9 +20,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "ReactOS 字体文件夹"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -20,9 +20,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "ReactOS 字型資料夾"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -20,9 +20,11 @@ END
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_REACTOS_FONTS_FOLDER "ReactOS 字型資料夾"
|
||||
IDS_INSTALL_OK "The font files have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font files."
|
||||
IDS_INSTALL_OK "The font(s) have been installed successfully."
|
||||
IDS_INSTALL_FAILED "Failed to install the font(s)."
|
||||
IDS_CONFIRM_DELETE_FONT "Do you want to delete the font(s)?"
|
||||
IDS_PROPERTIES "P&roperties"
|
||||
IDS_CANTDELETEFONT "Failed to delete the font(s)."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <atlbase.h>
|
||||
#include <atlcom.h>
|
||||
#include <atlcoll.h>
|
||||
#include <atlsimpcoll.h>
|
||||
#include <atlstr.h>
|
||||
#include <wine/debug.h>
|
||||
#include <shellutils.h>
|
||||
@@ -82,6 +83,9 @@ HRESULT DoGetFontTitle(
|
||||
BOOL CheckDropFontFiles(HDROP hDrop);
|
||||
BOOL CheckDataObject(IDataObject *pDataObj);
|
||||
HRESULT InstallFontsFromDataObject(HWND hwndView, IDataObject* pDataObj);
|
||||
HRESULT DoPreviewFontFiles(HWND hwnd, IDataObject* pDataObj);
|
||||
HRESULT DoDeleteFontFiles(HWND hwnd, IDataObject* pDataObj);
|
||||
void RunFontViewer(HWND hwnd, const FontPidlEntry* fontEntry);
|
||||
|
||||
HRESULT
|
||||
APIENTRY
|
||||
|
||||
@@ -4,7 +4,7 @@ HKCR
|
||||
{
|
||||
ForceRemove {BD84B380-8CA2-1069-AB1D-08000948F534} = s 'Fonts'
|
||||
{
|
||||
InprocServer32 = s 'fontext.dll'
|
||||
InprocServer32 = s '%MODULE%'
|
||||
{
|
||||
val ThreadingModel = s 'Apartment'
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#define IDS_REACTOS_FONTS_FOLDER 151
|
||||
#define IDS_INSTALL_OK 152
|
||||
#define IDS_INSTALL_FAILED 153
|
||||
#define IDS_PROPERTIES 154
|
||||
#define IDS_CONFIRM_DELETE_FONT 154
|
||||
#define IDS_PROPERTIES 155
|
||||
#define IDS_CANTDELETEFONT 156
|
||||
|
||||
#define IDS_COL_NAME 301
|
||||
#define IDS_COL_FILENAME 304
|
||||
|
||||
@@ -1159,6 +1159,10 @@ HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bCo
|
||||
if (!m_cidl || !m_pDataObj)
|
||||
return E_FAIL;
|
||||
|
||||
HRESULT hr = _DoInvokeCommandCallback(lpcmi, bCopy ? DFM_CMD_COPY : DFM_CMD_MOVE);
|
||||
if (hr == S_OK)
|
||||
return hr;
|
||||
|
||||
FORMATETC formatetc;
|
||||
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
|
||||
STGMEDIUM medium = {0};
|
||||
@@ -1174,7 +1178,7 @@ HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bCo
|
||||
if (SUCCEEDED(IUnknown_QueryService(m_site, SID_SFolderView, IID_PPV_ARG(IShellFolderView, &psfv))))
|
||||
psfv->SetPoints(m_pDataObj);
|
||||
|
||||
HRESULT hr = OleSetClipboard(m_pDataObj);
|
||||
hr = OleSetClipboard(m_pDataObj);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -1775,6 +1779,15 @@ CDefaultContextMenu::GetCommandString(
|
||||
|
||||
UINT CmdId = LOWORD(idCommand);
|
||||
|
||||
if (uFlags == GCS_VERBA || uFlags == GCS_VERBW)
|
||||
{
|
||||
UINT uMsg = (uFlags == GCS_VERBA) ? DFM_GETVERBA : DFM_GETVERBW;
|
||||
WPARAM wParam = MAKEWPARAM(idCommand, uMaxNameLen);
|
||||
HRESULT hr = _DoCallback(uMsg, wParam, lpszName);
|
||||
if (hr == S_OK)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!m_DynamicEntries.IsEmpty() && CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast)
|
||||
{
|
||||
idCommand -= m_iIdSHEFirst;
|
||||
|
||||
@@ -417,6 +417,8 @@ PathMakeUniqueName(
|
||||
_In_opt_ PCWSTR pszLongPlate,
|
||||
_In_opt_ PCWSTR pszDir);
|
||||
|
||||
HRESULT WINAPI SHMultiFileProperties(_In_ IDataObject *pDataObject, _In_ DWORD dwFlags);
|
||||
|
||||
/*****************************************************************************
|
||||
* IContextMenu interface
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user