Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Registry namespace extension * FILE: dll/win32/shell32/extracticon.c * PURPOSE: Icon extraction * * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.org) */
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
struct IconLocation{ LPWSTR file; UINT index;};
class CExtractIcon : public CComObjectRootEx<CComMultiThreadModelNoCS>, public IDefaultExtractIconInit, public IExtractIconW, public IExtractIconA, public IPersistFile{private: UINT flags; struct IconLocation defaultIcon; struct IconLocation normalIcon; struct IconLocation openIcon; struct IconLocation shortcutIcon;public: CExtractIcon(); ~CExtractIcon();
// IDefaultExtractIconInit STDMETHOD(SetDefaultIcon)(LPCWSTR pszFile, int iIcon) override; STDMETHOD(SetFlags)(UINT uFlags) override; STDMETHOD(SetKey)(HKEY hkey) override; STDMETHOD(SetNormalIcon)(LPCWSTR pszFile, int iIcon) override; STDMETHOD(SetOpenIcon)(LPCWSTR pszFile, int iIcon) override; STDMETHOD(SetShortcutIcon)(LPCWSTR pszFile, int iIcon) override;
// IExtractIconW STDMETHOD(GetIconLocation)(UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags) override; STDMETHOD(Extract)(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) override;
// IExtractIconA STDMETHOD(GetIconLocation)(UINT uFlags, LPSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags) override; STDMETHOD(Extract)(LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) override;
// IPersist STDMETHOD(GetClassID)(CLSID *pClassID) override; STDMETHOD(IsDirty)() override;
// IPersistFile STDMETHOD(Load)(LPCOLESTR pszFileName, DWORD dwMode) override; STDMETHOD(Save)(LPCOLESTR pszFileName, BOOL fRemember) override; STDMETHOD(SaveCompleted)(LPCOLESTR pszFileName) override; STDMETHOD(GetCurFile)(LPOLESTR *ppszFileName) override;
BEGIN_COM_MAP(CExtractIcon) COM_INTERFACE_ENTRY_IID(IID_IDefaultExtractIconInit, IDefaultExtractIconInit) COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW) COM_INTERFACE_ENTRY_IID(IID_IExtractIconA, IExtractIconA) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile)END_COM_MAP()};
VOID DuplicateString( LPCWSTR Source, LPWSTR *Destination){ SIZE_T cb;
if (*Destination) CoTaskMemFree(*Destination);
cb = (wcslen(Source) + 1) * sizeof(WCHAR); *Destination = (LPWSTR)CoTaskMemAlloc(cb); if (!*Destination) return; CopyMemory(*Destination, Source, cb);}
CExtractIcon::CExtractIcon(){ flags = 0; memset(&defaultIcon, 0, sizeof(defaultIcon)); memset(&normalIcon, 0, sizeof(normalIcon)); memset(&openIcon, 0, sizeof(openIcon)); memset(&shortcutIcon, 0, sizeof(shortcutIcon));}
CExtractIcon::~CExtractIcon(){ if (defaultIcon.file) CoTaskMemFree(defaultIcon.file); if (normalIcon.file) CoTaskMemFree(normalIcon.file); if (openIcon.file) CoTaskMemFree(openIcon.file); if (shortcutIcon.file) CoTaskMemFree(shortcutIcon.file);}
HRESULT STDMETHODCALLTYPE CExtractIcon::SetDefaultIcon( LPCWSTR pszFile, int iIcon){ TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
DuplicateString(pszFile, &defaultIcon.file); if (!defaultIcon.file) return E_OUTOFMEMORY; defaultIcon.index = iIcon; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::SetFlags( UINT uFlags){ TRACE("(%p, 0x%x)\n", this, uFlags);
flags = uFlags; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::SetKey( HKEY hkey){ FIXME("(%p, %p)\n", this, hkey); UNIMPLEMENTED; return E_NOTIMPL;}
HRESULT STDMETHODCALLTYPE CExtractIcon::SetNormalIcon( LPCWSTR pszFile, int iIcon){ TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
DuplicateString(pszFile, &normalIcon.file); if (!normalIcon.file) return E_OUTOFMEMORY; normalIcon.index = iIcon; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::SetOpenIcon( LPCWSTR pszFile, int iIcon){ TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
DuplicateString(pszFile, &openIcon.file); if (!openIcon.file) return E_OUTOFMEMORY; openIcon.index = iIcon; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::SetShortcutIcon( LPCWSTR pszFile, int iIcon){ TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
DuplicateString(pszFile, &shortcutIcon.file); if (!shortcutIcon.file) return E_OUTOFMEMORY; shortcutIcon.index = iIcon; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::GetIconLocation( UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags){ const struct IconLocation *icon = NULL; SIZE_T cb;
TRACE("(%p, 0x%x, %s, 0x%x, %p, %p)\n", this, uFlags, debugstr_w(szIconFile), cchMax, piIndex, pwFlags);
if (!piIndex || !pwFlags) return E_POINTER;
if (uFlags & GIL_DEFAULTICON) icon = defaultIcon.file ? &defaultIcon : &normalIcon; else if (uFlags & GIL_FORSHORTCUT) icon = shortcutIcon.file ? &shortcutIcon : &normalIcon; else if (uFlags & GIL_OPENICON) icon = openIcon.file ? &openIcon : &normalIcon; else icon = &normalIcon;
if (!icon->file) return E_FAIL;
cb = wcslen(icon->file) + 1; if (cchMax < (UINT)cb) return E_FAIL; CopyMemory(szIconFile, icon->file, cb * sizeof(WCHAR)); *piIndex = icon->index; *pwFlags = flags; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::Extract( LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize){ TRACE("(%p, %s, %u, %p, %p, %u)\n", this, debugstr_w(pszFile), nIconIndex, phiconLarge, phiconSmall, nIconSize);
/* Nothing to do, ExtractIconW::GetIconLocation should be enough */ return S_FALSE;}
HRESULT STDMETHODCALLTYPE CExtractIcon::GetIconLocation( UINT uFlags, LPSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags){ LPWSTR szIconFileW = NULL; HRESULT hr;
if (cchMax > 0) { szIconFileW = (LPWSTR)CoTaskMemAlloc(cchMax * sizeof(WCHAR)); if (!szIconFileW) return E_OUTOFMEMORY; }
hr = GetIconLocation(uFlags, szIconFileW, cchMax, piIndex, pwFlags); if (SUCCEEDED(hr) && cchMax > 0) if (0 == WideCharToMultiByte(CP_ACP, 0, szIconFileW, cchMax, szIconFile, cchMax, NULL, NULL)) hr = E_FAIL;
if (szIconFileW) CoTaskMemFree(szIconFileW); return hr;}
HRESULT STDMETHODCALLTYPE CExtractIcon::Extract( LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize){ LPWSTR pszFileW = NULL; HRESULT hr;
if (pszFile) { int nLength;
nLength = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0); if (nLength == 0) return E_FAIL; pszFileW = (LPWSTR)CoTaskMemAlloc(nLength * sizeof(WCHAR)); if (!pszFileW) return E_OUTOFMEMORY; if (!MultiByteToWideChar(CP_ACP, 0, pszFile, nLength, pszFileW, nLength)) { CoTaskMemFree(pszFileW); return E_FAIL; } }
hr = Extract(pszFileW, nIconIndex, phiconLarge, phiconSmall, nIconSize);
if (pszFileW) CoTaskMemFree(pszFileW); return hr;}
HRESULT STDMETHODCALLTYPE CExtractIcon::GetClassID( CLSID *pClassID){ TRACE("(%p, %p)\n", this, pClassID);
if (!pClassID) return E_POINTER;
*pClassID = GUID_NULL; return S_OK;}
HRESULT STDMETHODCALLTYPE CExtractIcon::IsDirty(){ FIXME("(%p)\n", this); UNIMPLEMENTED; return E_NOTIMPL;}
HRESULT STDMETHODCALLTYPE CExtractIcon::Load( LPCOLESTR pszFileName, DWORD dwMode){ FIXME("(%p, %s, %u)\n", this, debugstr_w(pszFileName), dwMode); UNIMPLEMENTED; return E_NOTIMPL;}
HRESULT STDMETHODCALLTYPE CExtractIcon::Save( LPCOLESTR pszFileName, BOOL fRemember){ FIXME("(%p, %s, %d)\n", this, debugstr_w(pszFileName), fRemember); UNIMPLEMENTED; return E_NOTIMPL;}
HRESULT STDMETHODCALLTYPE CExtractIcon::SaveCompleted( LPCOLESTR pszFileName){ FIXME("(%p, %s)\n", this, debugstr_w(pszFileName)); UNIMPLEMENTED; return E_NOTIMPL;}
HRESULT STDMETHODCALLTYPE CExtractIcon::GetCurFile( LPOLESTR *ppszFileName){ FIXME("(%p, %p)\n", this, ppszFileName); UNIMPLEMENTED; return E_NOTIMPL;}
HRESULT WINAPI SHCreateDefaultExtractIcon(REFIID riid, void **ppv){ return ShellObjectCreator<CExtractIcon>(riid, ppv);}
/* * Partially implemented * See apitests\shell32\SHCreateFileExtractIconW.cpp for details * Currently (march 2018) our shell does not handle IExtractIconW with an invalid path, * so this (wrong) implementation actually works better for us. */EXTERN_CHRESULTWINAPISHCreateFileExtractIconW( _In_ LPCWSTR pszFile, _In_ DWORD dwFileAttributes, _In_ REFIID riid, _Outptr_ void **ppv){ SHFILEINFOW shfi; ULONG_PTR firet = SHGetFileInfoW(pszFile, dwFileAttributes, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICONLOCATION); HRESULT hr = E_FAIL; if (firet) { CComPtr<IDefaultExtractIconInit> iconInit; hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &iconInit)); if (FAILED_UNEXPECTEDLY(hr)) return hr;
hr = iconInit->SetNormalIcon(shfi.szDisplayName, shfi.iIcon); if (FAILED_UNEXPECTEDLY(hr)) return hr;
return iconInit->QueryInterface(riid, ppv); } if (FAILED_UNEXPECTEDLY(hr)) return hr;
return hr;}