windows-nt/Source/XPSP1/NT/shell/ext/occache/folder.cpp
2020-09-26 16:20:57 +08:00

354 lines
10 KiB
C++

#include "general.h"
#include "folder.h"
#include "utils.h"
#include <mluisupp.h>
#define CPP_FUNCTIONS
#include <crtfree.h>
// string displayed to represent missing data
TCHAR g_szUnknownData[64];
int CompareVersion(LPCTSTR lpszVersion1, LPCTSTR lpszVersion2);
///////////////////////////////////////////////////////////////////////////////
// IShellFolder methods
CControlFolder::CControlFolder()
{
DebugMsg(DM_TRACE,TEXT("cf - CControlFolder() called."));
m_cRef = 1;
DllAddRef();
// initialize g_szUnknownData, a string used to represent missing data
if (g_szUnknownData[0] == 0)
MLLoadString(IDS_UNKNOWNDATA, g_szUnknownData, ARRAYSIZE(g_szUnknownData));
}
CControlFolder::~CControlFolder()
{
Assert(m_cRef == 0); // should always have zero
DebugMsg(DM_TRACE, TEXT("cf - ~CControlFolder() called."));
if (m_pidl)
ILFree(m_pidl);
DllRelease();
}
STDAPI ControlFolder_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut)
{
*ppvOut = NULL; // null the out param
if (punkOuter)
return CLASS_E_NOAGGREGATION;
CControlFolder *pCFolder = new CControlFolder;
if (!pCFolder)
return E_OUTOFMEMORY;
HRESULT hr = pCFolder->QueryInterface(riid, ppvOut);
pCFolder->Release();
return hr;
}
HRESULT CControlFolder::QueryInterface(REFIID iid, void **ppv)
{
DebugMsg(DM_TRACE, TEXT("cf - QueryInterface() called."));
if ((iid == IID_IUnknown) || (iid == IID_IShellFolder))
{
*ppv = (void *)(IShellFolder*)this;
}
else if ((iid == IID_IPersistFolder) || (iid == IID_IPersist))
{
*ppv = (void *)(IPersistFolder*)this;
}
else if (iid == IID_IPersistFolder2)
{
*ppv = (void *)(IPersistFolder2*)this;
}
else if (iid == IID_IContextMenu)
{
*ppv = (void *)(IContextMenu*)this;
}
else if (iid == IID_IShellView)
{
// this is a total hack... return our view object from this folder
//
// the desktop.ini file for "Temporary Internet Files" has UICLSID={guid of this object}
// this lets us implment only ths IShellView for this folder, leaving the IShellFolder
// to the default file system. this enables operations on the pidls that are stored in
// this folder that would otherwise faile since our IShellFolder is not as complete
// as the default (this is the same thing the font folder does).
//
// to support this with defview we would either have to do a complete wrapper object
// for the view implemenation, or add this hack that hands out the view object, this
// assumes we know the order of calls that the shell makes to create this object
// and get the IShellView implementation
//
return ControlFolderView_CreateInstance(this, m_pidl, ppv);
}
else
{
*ppv = NULL; // null the out param
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG CControlFolder::AddRef()
{
return ++m_cRef;
}
ULONG CControlFolder::Release()
{
if (--m_cRef)
return m_cRef;
delete this;
return 0;
}
HRESULT CControlFolder::ParseDisplayName(
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
ULONG *pchEaten,
LPITEMIDLIST *ppidl,
ULONG *pdwAttributes)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - ParseDisplayName() called."));
*ppidl = NULL; // null the out param
return E_FAIL;
}
HRESULT CControlFolder::EnumObjects(
HWND hwndOwner,
DWORD grfFlags,
LPENUMIDLIST *ppenumIDList)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - EnumObjects() called."));
// Cannot filter on grfFlags yet - Corel Gallery expects to receive
// an empty enumerator.
return CControlFolderEnum_CreateInstance(m_pidl, grfFlags, ppenumIDList);
}
HRESULT CControlFolder::BindToObject(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
void **ppvOut)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - BindToObject() called."));
*ppvOut = NULL; // null the out param
return E_FAIL;
}
HRESULT CControlFolder::BindToStorage(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
void **ppv)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - BindToStorage() called."));
*ppv = NULL; // null the out param
return E_NOTIMPL;
}
HRESULT CControlFolder::CompareIDs(
LPARAM lParam,
LPCITEMIDLIST pidl1,
LPCITEMIDLIST pidl2)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - CompareIDs() called."));
int iRet;
LPCONTROLPIDL pcpidl1 = (LPCONTROLPIDL)pidl1;
LPCONTROLPIDL pcpidl2 = (LPCONTROLPIDL)pidl2;
LPCSTR lpszStr[2] = {NULL, NULL};
if (pcpidl1 == NULL || pcpidl2 == NULL)
return E_INVALIDARG;
switch (lParam) {
case SI_CONTROL:
iRet = lstrcmpi(
GetStringInfo(pcpidl1, SI_CONTROL),
GetStringInfo(pcpidl2, SI_CONTROL));
break;
case SI_VERSION:
lpszStr[0] = GetStringInfo(pcpidl1, SI_VERSION);
lpszStr[1] = GetStringInfo(pcpidl2, SI_VERSION);
if (lstrcmp(lpszStr[0], g_szUnknownData) == 0)
iRet = -1;
else if (lstrcmp(lpszStr[1], g_szUnknownData) == 0)
iRet = 1;
else
iRet = CompareVersion(lpszStr[0], lpszStr[1]);
break;
case SI_CREATION:
case SI_LASTACCESS:
{
FILETIME time[2];
GetTimeInfo(pcpidl1, (int)lParam, &(time[0]));
GetTimeInfo(pcpidl2, (int)lParam, &(time[1]));
iRet = CompareFileTime(&(time[0]), &(time[1]));
}
break;
case SI_STATUS:
iRet = GetStatus(pcpidl1) - GetStatus(pcpidl2);
break;
case SI_TOTALSIZE:
{
DWORD dwSize1 = GetSizeSaved((LPCONTROLPIDL)pidl1);
DWORD dwSize2 = GetSizeSaved((LPCONTROLPIDL)pidl2);
iRet = (dwSize1 == dwSize2 ? 0 : (dwSize1 > dwSize2 ? 1 : -1));
}
break;
default:
iRet = -1;
}
return ResultFromShort((SHORT)iRet);
}
HRESULT CControlFolder::CreateViewObject(
HWND hwndOwner,
REFIID riid,
void **ppvOut)
{
HRESULT hres;
DebugMsg(DM_TRACE, TEXT("cf - sf - CreateViewObject() called."));
if (riid == IID_IShellView)
{
hres = ControlFolderView_CreateInstance(this, m_pidl, ppvOut);
}
else if (riid == IID_IContextMenu)
{
hres = ControlFolder_CreateInstance(NULL, riid, ppvOut);
}
else
{
*ppvOut = NULL; // null the out param
hres = E_NOINTERFACE;
}
return hres;
}
HRESULT CControlFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST *apidl, ULONG *prgfInOut)
{
// Should we initialize this for each item in here? In other words,
// if cidl > 1, then we should initialize each entry in the prgInOut array
Assert(cidl == 1);
*prgfInOut = SFGAO_CANCOPY | SFGAO_HASPROPSHEET | SFGAO_CANMOVE | SFGAO_CANDELETE;
return NOERROR;
}
HRESULT CControlFolder::GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
LPCITEMIDLIST *apidl,
REFIID riid,
UINT *prgfInOut,
void **ppvOut)
{
HRESULT hres;
if ((riid == IID_IDataObject) ||
(riid == IID_IExtractIcon) ||
(riid == IID_IContextMenu))
{
hres = CControlItem_CreateInstance(this, cidl, apidl, riid, ppvOut);
}
else
{
*ppvOut = NULL; // null the out param
hres = E_FAIL;
}
return hres;
}
HRESULT CControlFolder::GetDisplayNameOf(
LPCITEMIDLIST pidl,
DWORD uFlags,
LPSTRRET lpName)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - GetDisplayNameOf() called."));
if (pidl)
{
lpName->uType = STRRET_CSTR;
// for the history, we'll use the title if we have one, otherwise we'll use
// the url filename.
if (uFlags & SHGDN_FORPARSING)
lstrcpyn(
lpName->cStr,
GetStringInfo((LPCONTROLPIDL)pidl, SI_LOCATION),
ARRAYSIZE(lpName->cStr));
else
lstrcpyn(
lpName->cStr,
GetStringInfo((LPCONTROLPIDL)pidl, SI_CONTROL),
ARRAYSIZE(lpName->cStr));
return NOERROR;
}
else
{
return E_INVALIDARG;
}
}
HRESULT CControlFolder::SetNameOf(
HWND hwndOwner,
LPCITEMIDLIST pidl,
LPCOLESTR lpszName,
DWORD uFlags,
LPITEMIDLIST *ppidlOut)
{
DebugMsg(DM_TRACE, TEXT("cf - sf - SetNameOf() called."));
*ppidlOut = NULL; // null the out param
return E_FAIL;
}
///////////////////////////////////////////////////////////////////////////////
// Helper functions
int CompareVersion(LPCTSTR lpszVersion1, LPCTSTR lpszVersion2)
{
LPCTSTR pszVerNum[2] = {lpszVersion1, lpszVersion2};
int nVerNum[2];
int nResult = 0;
while (nResult == 0 && *(pszVerNum[0]) != '\0' && *(pszVerNum[1]) != '\0')
{
nVerNum[0] = StrToInt(pszVerNum[0]++);
nVerNum[1] = StrToInt(pszVerNum[1]++);
nResult = ((nVerNum[0] < nVerNum[1]) ?
(-1) :
(nVerNum[0] > nVerNum[1] ? 1 : 0));
}
return nResult;
}