You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
6.4 KiB
262 lines
6.4 KiB
#include "shellprv.h"
|
|
#include <sfview.h>
|
|
#include "defviewp.h"
|
|
|
|
int CGenList::Add(LPVOID pv, int nInsert)
|
|
{
|
|
if (!_hList)
|
|
{
|
|
_hList = DSA_Create(_cbItem, 8);
|
|
if (!_hList)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
return DSA_InsertItem(_hList, nInsert, pv);
|
|
}
|
|
|
|
|
|
int CViewsList::Add(const SFVVIEWSDATA*pView, int nInsert, BOOL bCopy)
|
|
{
|
|
if (bCopy)
|
|
{
|
|
pView = CopyData(pView);
|
|
if (!pView)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int iIndex = CGenList::Add((LPVOID)(&pView), nInsert);
|
|
|
|
if (bCopy && iIndex<0)
|
|
{
|
|
SHFree((LPVOID)pView);
|
|
}
|
|
|
|
return iIndex;
|
|
}
|
|
|
|
|
|
void CViewsList::Empty()
|
|
{
|
|
_bGotDef = FALSE;
|
|
|
|
for (int i=GetItemCount()-1; i>=0; --i)
|
|
{
|
|
SFVVIEWSDATA *sfvData = GetPtr(i);
|
|
|
|
ASSERT(sfvData);
|
|
if (sfvData->dwFlags & SFVF_CUSTOMIZEDVIEW)
|
|
{
|
|
CUSTOMVIEWSDATA *pCustomPtr = sfvData->pCustomData;
|
|
if (pCustomPtr)
|
|
{
|
|
if (pCustomPtr->lpDataBlock)
|
|
SHFree(pCustomPtr->lpDataBlock);
|
|
SHFree(pCustomPtr);
|
|
}
|
|
}
|
|
SHFree(sfvData);
|
|
}
|
|
|
|
CGenList::Empty();
|
|
}
|
|
|
|
|
|
SFVVIEWSDATA* CViewsList::CopyData(const SFVVIEWSDATA* pData)
|
|
{
|
|
SFVVIEWSDATA* pCopy = (SFVVIEWSDATA*)SHAlloc(sizeof(SFVVIEWSDATA));
|
|
if (pCopy)
|
|
{
|
|
memcpy(pCopy, pData, sizeof(SFVVIEWSDATA));
|
|
if ((pData->dwFlags & SFVF_CUSTOMIZEDVIEW) && pData->pCustomData)
|
|
{
|
|
CUSTOMVIEWSDATA *pCustomData = (CUSTOMVIEWSDATA *)SHAlloc(sizeof(CUSTOMVIEWSDATA));
|
|
if (pCustomData)
|
|
{
|
|
memcpy(pCustomData, pData->pCustomData, sizeof(CUSTOMVIEWSDATA));
|
|
pCopy->pCustomData = pCustomData;
|
|
|
|
if (pCustomData->lpDataBlock)
|
|
{
|
|
// NOTE: DataBlock size is in WCHARs
|
|
LPWSTR lpDataBlock = (LPWSTR)SHAlloc(pCustomData->cchSizeOfBlock * sizeof(WCHAR));
|
|
if (lpDataBlock)
|
|
{
|
|
// NOTE: DataBlock size is in WCHARs
|
|
memcpy(lpDataBlock, pCustomData->lpDataBlock, pCustomData->cchSizeOfBlock * sizeof(WCHAR));
|
|
pCustomData->lpDataBlock = lpDataBlock;
|
|
}
|
|
else
|
|
{
|
|
SHFree(pCustomData);
|
|
goto Failed;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Failed:
|
|
SHFree(pCopy);
|
|
pCopy = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pCopy;
|
|
}
|
|
|
|
|
|
int CViewsList::NextUnique(int nLast)
|
|
{
|
|
for (int nNext = nLast + 1; ; ++nNext)
|
|
{
|
|
SFVVIEWSDATA* pItem = GetPtr(nNext);
|
|
if (!pItem)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (int nPrev=nNext-1; nPrev>=0; --nPrev)
|
|
{
|
|
SFVVIEWSDATA*pPrev = GetPtr(nPrev);
|
|
if (pItem->idView == pPrev->idView)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (nPrev < 0)
|
|
{
|
|
return nNext;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
void CCallback::_GetExtViews(BOOL bForce)
|
|
{
|
|
CDefView* pView = IToClass(CDefView, _cCallback, this);
|
|
|
|
IEnumSFVViews *pev = NULL;
|
|
|
|
if (bForce)
|
|
{
|
|
_bGotViews = FALSE;
|
|
}
|
|
|
|
if (_bGotViews)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_lViews.Empty();
|
|
|
|
SHELLVIEWID vid = VID_LargeIcons;
|
|
if (FAILED(pView->CallCB(SFVM_GETVIEWS, (WPARAM)&vid, (LPARAM)&pev)) ||
|
|
!pev)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_lViews.SetDef(&vid);
|
|
|
|
SFVVIEWSDATA *pData;
|
|
ULONG uFetched;
|
|
|
|
while ((pev->Next(1, &pData, &uFetched) == S_OK) && (uFetched == 1))
|
|
{
|
|
// The list comes to us in general to specific order, but we want
|
|
// to search it in specific->general order. Inverting the list
|
|
// is easiest here, even though it causes a bunch of memcpy calls.
|
|
//
|
|
_lViews.Prepend(pData, FALSE);
|
|
}
|
|
|
|
ATOMICRELEASE(pev);
|
|
|
|
_bGotViews = TRUE;
|
|
}
|
|
|
|
|
|
HRESULT CCallback::TryLegacyGetViews(SFVM_WEBVIEW_TEMPLATE_DATA* pvit)
|
|
{
|
|
CDefView* pView = IToClass(CDefView, _cCallback, this);
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CLSID clsid;
|
|
HRESULT hr2 = IUnknown_GetClassID(pView->_pshf, &clsid);
|
|
if (FAILED(hr2) || !(SHGetObjectCompatFlags(NULL, &clsid) & OBJCOMPATF_NOLEGACYWEBVIEW))
|
|
{
|
|
_GetExtViews(FALSE);
|
|
if (_bGotViews)
|
|
{
|
|
SFVVIEWSDATA* pItem;
|
|
GetViewIdFromGUID(&VID_WebView, &pItem);
|
|
if (pItem)
|
|
{
|
|
hr = StringCchCopyW(pvit->szWebView, ARRAYSIZE(pvit->szWebView), pItem->wszMoniker);
|
|
}
|
|
}
|
|
else if (SUCCEEDED(hr2))
|
|
{
|
|
// check for PersistMoniker under isf's coclass (Web Folders used this in W2K to get .htt Web View)
|
|
WCHAR szCLSID[GUIDSTR_MAX];
|
|
if (SHStringFromGUID(clsid, szCLSID, ARRAYSIZE(szCLSID)))
|
|
{
|
|
WCHAR wszSubKey[MAX_PATH];
|
|
hr = StringCchPrintf(wszSubKey, ARRAYSIZE(wszSubKey), L"CLSID\\%s\\shellex\\ExtShellFolderViews\\{5984FFE0-28D4-11CF-AE66-08002B2E1262}", szCLSID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DWORD cbSize = sizeof(pvit->szWebView);
|
|
hr = ResultFromWin32(SHRegGetValueW(HKEY_CLASSES_ROOT, wszSubKey, L"PersistMoniker", SRRF_RT_REG_SZ, NULL, pvit->szWebView, &cbSize));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCallback::OnRefreshLegacy(void* pv, BOOL fPrePost)
|
|
{
|
|
// If we're using the SFVM_GETVIEWS layer, invalidate it
|
|
if (_bGotViews)
|
|
{
|
|
_lViews.Empty();
|
|
_bGotViews = FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
int CCallback::GetViewIdFromGUID(SHELLVIEWID const *pvid, SFVVIEWSDATA** ppItem)
|
|
{
|
|
int iView = -1;
|
|
for (UINT uView=0; uView<MAX_EXT_VIEWS; ++uView)
|
|
{
|
|
iView = _lViews.NextUnique(iView);
|
|
|
|
SFVVIEWSDATA* pItem = _lViews.GetPtr(iView);
|
|
if (!pItem)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (*pvid == pItem->idView)
|
|
{
|
|
if (ppItem)
|
|
*ppItem = pItem;
|
|
|
|
return (int)uView;
|
|
}
|
|
}
|
|
|
|
if (ppItem)
|
|
*ppItem = NULL;
|
|
return -1;
|
|
}
|
|
|