239 lines
6.8 KiB
C
239 lines
6.8 KiB
C
#include "shellprv.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
// CDefExtIcon Class definition
|
|
|
|
typedef struct
|
|
{
|
|
IExtractIcon xi;
|
|
#ifdef UNICODE
|
|
IExtractIconA xiA;
|
|
#endif
|
|
LONG cRef;
|
|
int iIcon;
|
|
int iIconOpen;
|
|
UINT uFlags; // GIL_SIMULATEDOC/PERINSTANCE/PERCLASS
|
|
TCHAR achModule[1];
|
|
} CDefExtIcon;
|
|
|
|
STDMETHODIMP CDefExtIcon_QueryInterface(IExtractIcon *pxi, REFIID riid, void **ppvObj);
|
|
STDMETHODIMP_(ULONG) CDefExtIcon_AddRef(IExtractIcon *pxi);
|
|
STDMETHODIMP_(ULONG) CDefExtIcon_Release(IExtractIcon *pxi);
|
|
|
|
|
|
STDAPI SHCreateDefExtIcon(LPCTSTR pszModule, int iIcon, int iIconOpen, UINT uFlags, REFIID riid, void **ppvOut)
|
|
{
|
|
return SHCreateDefExtIconKey(NULL, pszModule, iIcon, iIconOpen, uFlags, riid, ppvOut);
|
|
}
|
|
|
|
extern IExtractIconVtbl c_CDefExtIconVtbl; // forward
|
|
#ifdef UNICODE
|
|
extern IExtractIconAVtbl c_CDefExtIconAVtbl; // forward
|
|
#endif
|
|
|
|
STDAPI SHCreateDefExtIconKey(HKEY hkey, LPCTSTR pszModule, int iIcon, int iIconOpen, UINT uFlags, REFIID riid, void **pxiOut)
|
|
{
|
|
HRESULT hresSuccess = NOERROR;
|
|
HRESULT hres = E_OUTOFMEMORY; // assume error;
|
|
CDefExtIcon *pdxi;
|
|
TCHAR szModule[MAX_PATH];
|
|
DWORD cb = SIZEOF(szModule);
|
|
|
|
if (hkey)
|
|
{
|
|
if (SHRegQueryValue(hkey, c_szDefaultIcon, szModule, &cb) == ERROR_SUCCESS && szModule[0])
|
|
{
|
|
iIcon = PathParseIconLocation(szModule);
|
|
iIconOpen = iIcon;
|
|
pszModule = szModule;
|
|
}
|
|
else
|
|
hresSuccess = S_FALSE;
|
|
}
|
|
|
|
if (pszModule == NULL)
|
|
{
|
|
// REVIEW: We should be able to make it faster!
|
|
GetModuleFileName(HINST_THISDLL, szModule, ARRAYSIZE(szModule));
|
|
pszModule = szModule;
|
|
}
|
|
|
|
pdxi = (void*)LocalAlloc(LPTR, SIZEOF(CDefExtIcon) + (lstrlen(pszModule) * SIZEOF(TCHAR)));
|
|
if (pdxi)
|
|
{
|
|
pdxi->xi.lpVtbl = &c_CDefExtIconVtbl;
|
|
#ifdef UNICODE
|
|
pdxi->xiA.lpVtbl = &c_CDefExtIconAVtbl;
|
|
#endif
|
|
pdxi->cRef = 1;
|
|
pdxi->iIcon = iIcon;
|
|
pdxi->iIconOpen = iIconOpen;
|
|
pdxi->uFlags = uFlags;
|
|
lstrcpy(pdxi->achModule, pszModule);
|
|
|
|
if (SUCCEEDED(CDefExtIcon_QueryInterface(&pdxi->xi, riid, pxiOut)))
|
|
hres = hresSuccess;
|
|
CDefExtIcon_Release(&pdxi->xi);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
STDMETHODIMP CDefExtIcon_QueryInterface(IExtractIcon *pxi, REFIID riid, void **ppvObj)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xi, pxi);
|
|
if (IsEqualIID(riid, &IID_IExtractIcon) || IsEqualIID(riid, &IID_IUnknown))
|
|
{
|
|
*ppvObj = pxi;
|
|
}
|
|
#ifdef UNICODE
|
|
else if (IsEqualIID(riid, &IID_IExtractIconA))
|
|
{
|
|
*ppvObj = &this->xiA;
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
CDefExtIcon_AddRef(&this->xi);
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDefExtIcon_AddRef(IExtractIcon *pxi)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xi, pxi);
|
|
return InterlockedIncrement(&this->cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDefExtIcon_Release(IExtractIcon *pxi)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xi, pxi);
|
|
if (InterlockedDecrement(&this->cRef))
|
|
return this->cRef;
|
|
|
|
LocalFree((HLOCAL)this);
|
|
return 0;
|
|
}
|
|
|
|
STDMETHODIMP CDefExtIcon_GetIconLocation(IExtractIcon *pxi, UINT uFlags,
|
|
LPTSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xi, pxi);
|
|
HRESULT hres = S_FALSE;
|
|
int iIcon = (uFlags & GIL_OPENICON) ? this->iIconOpen : this->iIcon;
|
|
if (iIcon != (UINT)-1)
|
|
{
|
|
lstrcpyn(szIconFile, this->achModule, cchMax);
|
|
*piIndex = iIcon;
|
|
*pwFlags = this->uFlags;
|
|
hres = NOERROR;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
STDMETHODIMP CDefExtIcon_Extract(IExtractIcon *pxi, LPCTSTR pszFile, UINT nIconIndex,
|
|
HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xi, pxi);
|
|
|
|
if (this->uFlags & GIL_NOTFILENAME)
|
|
{
|
|
|
|
// "*" as the file name means iIndex is already a system
|
|
// icon index, we are done.
|
|
|
|
// defview never calls us in this case, but external people will.
|
|
|
|
if (pszFile[0] == TEXT('*') && pszFile[1] == 0)
|
|
{
|
|
DebugMsg(DM_TRACE, TEXT("DefExtIcon::Extract handling '*' for backup"));
|
|
|
|
if (g_himlIcons == NULL)
|
|
{
|
|
FileIconInit( FALSE );
|
|
}
|
|
|
|
if (phiconLarge)
|
|
*phiconLarge = ImageList_GetIcon(g_himlIcons, nIconIndex, 0);
|
|
|
|
if (phiconSmall)
|
|
*phiconSmall = ImageList_GetIcon(g_himlIconsSmall, nIconIndex, 0);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// this is the case where nIconIndex is a unique id for the
|
|
// file. always get the first icon.
|
|
|
|
nIconIndex = 0;
|
|
}
|
|
|
|
return SHDefExtractIcon(pszFile, nIconIndex, this->uFlags,
|
|
phiconLarge, phiconSmall, nIconSize);
|
|
}
|
|
|
|
IExtractIconVtbl c_CDefExtIconVtbl = {
|
|
CDefExtIcon_QueryInterface, CDefExtIcon_AddRef, CDefExtIcon_Release,
|
|
CDefExtIcon_GetIconLocation,
|
|
CDefExtIcon_Extract,
|
|
};
|
|
|
|
|
|
#ifdef UNICODE
|
|
|
|
STDMETHODIMP CDefExtIconA_QueryInterface(LPEXTRACTICONA pxiA, REFIID riid, void **ppvObj)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xiA, pxiA);
|
|
return CDefExtIcon_QueryInterface(&this->xi, riid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDefExtIconA_AddRef(LPEXTRACTICONA pxiA)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xiA, pxiA);
|
|
return CDefExtIcon_AddRef(&this->xi);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDefExtIconA_Release(LPEXTRACTICONA pxiA)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xiA, pxiA);
|
|
return CDefExtIcon_Release(&this->xi);
|
|
}
|
|
|
|
STDMETHODIMP CDefExtIconA_GetIconLocation(LPEXTRACTICONA pxiA,
|
|
UINT uFlags, LPSTR pszIconFile, UINT cchMax,
|
|
int *piIndex, UINT *pwFlags)
|
|
{
|
|
WCHAR wsz[MAX_PATH];
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xiA, pxiA);
|
|
HRESULT hres = CDefExtIcon_GetIconLocation(&this->xi, uFlags,
|
|
wsz, ARRAYSIZE(wsz), piIndex, pwFlags);
|
|
if (SUCCEEDED(hres) && hres != S_FALSE)
|
|
{
|
|
// We don't want to copy the icon file name on the S_FALSE case
|
|
SHUnicodeToAnsi(wsz, pszIconFile, cchMax);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
STDMETHODIMP CDefExtIconA_Extract(LPEXTRACTICONA pxiA,
|
|
LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge,
|
|
HICON *phiconSmall, UINT nIconSize)
|
|
{
|
|
CDefExtIcon *this = IToClass(CDefExtIcon, xiA, pxiA);
|
|
WCHAR wsz[MAX_PATH];
|
|
|
|
SHAnsiToUnicode(pszFile, wsz, ARRAYSIZE(wsz));
|
|
return CDefExtIcon_Extract(&this->xi, wsz,nIconIndex, phiconLarge, phiconSmall, nIconSize);
|
|
}
|
|
|
|
IExtractIconAVtbl c_CDefExtIconAVtbl = {
|
|
CDefExtIconA_QueryInterface, CDefExtIconA_AddRef, CDefExtIconA_Release,
|
|
CDefExtIconA_GetIconLocation,
|
|
CDefExtIconA_Extract,
|
|
};
|
|
|
|
#endif // UNICODE
|