1014 lines
26 KiB
C++
1014 lines
26 KiB
C++
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// folder.cpp
|
|
//
|
|
// IShellFolder for the cdfview class.
|
|
//
|
|
// History:
|
|
//
|
|
// 3/16/97 edwardp Created.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "stdinc.h"
|
|
#include "resource.h"
|
|
#include "cdfidl.h"
|
|
#include "xmlutil.h"
|
|
#include "persist.h"
|
|
#include "cdfview.h"
|
|
#include "enum.h"
|
|
#include "view.h"
|
|
#include "exticon.h"
|
|
#include "itemmenu.h"
|
|
#include "tooltip.h"
|
|
|
|
|
|
|
|
//
|
|
// IShellFolder methods.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::ParseDisplayName ***
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::ParseDisplayName(
|
|
HWND hwndOwner,
|
|
LPBC pbcReserved,
|
|
LPOLESTR lpszDisplayName,
|
|
ULONG* pchEaten,
|
|
LPITEMIDLIST* ppidl,
|
|
ULONG* pdwAttributes
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::EnumObjects ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns an enumerator for this folder.
|
|
//
|
|
// Parameters:
|
|
// [In] hwndOwner - Handle of the owner window. Ignored.
|
|
// [In] grfFlags - A combination of Folders, NonFolders and Include
|
|
// Hidden.
|
|
// [Out] ppenumIdList - A pointer to receive the IEnumIDList interface.
|
|
//
|
|
// Return:
|
|
// S_OK if the enumrator was created and returned.
|
|
// E_OUTOFMEMORY if the enumerator couldn't be created.
|
|
//
|
|
// Comments:
|
|
// The caller must Release() the returned enumerator.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::EnumObjects(
|
|
HWND hwndOwner,
|
|
DWORD grfFlags,
|
|
LPENUMIDLIST* ppIEnumIDList
|
|
)
|
|
{
|
|
ASSERT(ppIEnumIDList);
|
|
|
|
TraceMsg(TF_CDFENUM, "<IN> EnumObjects tid:0x%x", GetCurrentThreadId());
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_bCdfParsed)
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "IShellFolder EnumObjects(%s) %s",
|
|
hwndOwner ? TEXT("HWND") : TEXT("NULL"),
|
|
PathFindFileName(m_szPath));
|
|
hr = ParseCdfFolder(NULL, PARSE_LOCAL);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppIEnumIDList = (IEnumIDList*) new CCdfEnum(m_pIXMLElementCollection,
|
|
grfFlags, m_pcdfidl);
|
|
|
|
hr = *ppIEnumIDList ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
*ppIEnumIDList = NULL;
|
|
}
|
|
|
|
|
|
ASSERT((SUCCEEDED(hr) && *ppIEnumIDList) ||
|
|
(FAILED(hr) && NULL == *ppIEnumIDList));
|
|
|
|
TraceMsg(TF_CDFENUM, "<OUT> EnumObjects tid:0x%x", GetCurrentThreadId());
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::BindToObject ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Creates an IShellFolder for a given subfolder.
|
|
//
|
|
// Parameters:
|
|
// [In] pidl - Pointer to the id list of the subfolder.
|
|
// [] pdcReserved - Not used.
|
|
// [In] riid - The requested interface.
|
|
// [Out] ppvOut - A pointer to receive the returned interface.
|
|
//
|
|
// Return:
|
|
// S_OK if the request folder is created and the interface returned.
|
|
// E_OUTOFMEMORY if there isn't enough memory to create the folder.
|
|
// E_NOINTERFACE if the requested interface isn't supported.
|
|
//
|
|
// Comments:
|
|
// This function is generaly called on a member of the current folder
|
|
// to create a subfolder.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::BindToObject(
|
|
LPCITEMIDLIST pidl,
|
|
LPBC pbcReserved,
|
|
REFIID riid,
|
|
LPVOID* ppvOut
|
|
)
|
|
{
|
|
ASSERT(ppvOut);
|
|
|
|
//
|
|
// REVIEW: Hack to get around shell pidls. Bug in shell!
|
|
//
|
|
|
|
#if 1 //Hack
|
|
while(!ILIsEmpty(pidl) && !CDFIDL_IsValidId((PCDFITEMID)&pidl->mkid))
|
|
pidl = _ILNext(pidl);
|
|
|
|
if (ILIsEmpty(pidl))
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_bCdfParsed)
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "IShellFolder BindToObject (Hack) %s",
|
|
PathFindFileName(m_szPath));
|
|
hr = ParseCdfFolder(NULL, PARSE_LOCAL);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AddRef();
|
|
*ppvOut = (void**)(IShellFolder*)this;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
#endif //Hack
|
|
|
|
ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl));
|
|
|
|
//
|
|
// REVIEW: nsc.cpp calls this function with non-folder pidls.
|
|
// Currently remove the ASSERT and replace it with a check. nsc
|
|
// shouldn't make this call with non-folder pidls.
|
|
//
|
|
|
|
//ASSERT(CDFIDL_IsFolderId((PCDFITEMID)&pidl->mkid));
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppvOut = NULL;
|
|
|
|
if (CDFIDL_IsFolderId((PCDFITEMID)&pidl->mkid))
|
|
{
|
|
if (!m_bCdfParsed)
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "IShellFolder BindToObject %s",
|
|
PathFindFileName(m_szPath));
|
|
hr = ParseCdfFolder(NULL, PARSE_LOCAL);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
|
|
(PCDFITEMIDLIST)pidl));
|
|
|
|
CCdfView* pCCdfView = (CCdfView*)new CCdfView((PCDFITEMIDLIST)pidl,
|
|
m_pidlPath,
|
|
m_pIXMLElementCollection);
|
|
|
|
if (pCCdfView)
|
|
{
|
|
if (ILIsEmpty(_ILNext(pidl)))
|
|
{
|
|
hr = pCCdfView->QueryInterface(riid, ppvOut);
|
|
}
|
|
else
|
|
{
|
|
hr = pCCdfView->BindToObject(_ILNext(pidl), pbcReserved, riid,
|
|
ppvOut);
|
|
}
|
|
|
|
pCCdfView->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
|
|
ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::BindToStorage ***
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::BindToStorage(
|
|
LPCITEMIDLIST pidl,
|
|
LPBC pbcReserved,
|
|
REFIID riid,
|
|
LPVOID* ppvObj
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::CompareIDs ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Determines the relative ordering of two objects given their id lists.
|
|
//
|
|
// Parameters:
|
|
// [In] lParam - Value specifying the type of comparison to perform.
|
|
// Currently ignored. Always sort by name.
|
|
// [In] pidl1 - The id list of the first item to compare.
|
|
// [In] pidl2 - The id list of the second item to compare.
|
|
//
|
|
// Return:
|
|
// The SCODE of the HRESULT (low word) is <0 if pidl1 comes before pidl2,
|
|
// =0 if pidl1 is the same as pidl2 and >0 if pidl1 comes after pidl2.
|
|
//
|
|
// Comments:
|
|
// Shell expects this function to never fail.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::CompareIDs(
|
|
LPARAM lParam,
|
|
LPCITEMIDLIST pidl1,
|
|
LPCITEMIDLIST pidl2
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl1));
|
|
ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl2));
|
|
|
|
SHORT sRes = CDFIDL_Compare((PCDFITEMIDLIST)pidl1,(PCDFITEMIDLIST)pidl2);
|
|
|
|
return 0x0000ffff & sRes;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::CreateViewObject ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Creates a com object for the current folder implementing the specified
|
|
// interface
|
|
//
|
|
// Parameters:
|
|
// [In] hwndOwner - Owner window. Ignored.
|
|
// [In] riid - The interface to create.
|
|
// [Out] ppvOut - A pointer that receives the new object.
|
|
//
|
|
// Return:
|
|
// S_OK if the requested object was successfully created.
|
|
// E_NOINTERFACE if the object is not suppported.
|
|
// E_OUTOFMEMORY if the pidl couldn't be cloned.
|
|
// The return value from SHCreateShellFolderViewEx otherwise.
|
|
//
|
|
// Comments:
|
|
// It is important to remember that the COM object created by
|
|
// CreateViewObject must be a different object than the shell folder object.
|
|
// The Explorer may call CreateViewObject more than once to create more than
|
|
// one view object and expects them to behave as independent objects. A new
|
|
// view object must be created for each call.
|
|
//
|
|
// Request for IShellView return a default Shell implementation.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::CreateViewObject(
|
|
HWND hwndOwner,
|
|
REFIID riid,
|
|
LPVOID* ppvOut
|
|
)
|
|
{
|
|
ASSERT(ppvOut);
|
|
|
|
//
|
|
// This function is called when the cdf hasn't been parsed. m_pcdfidl is
|
|
// likely NULL in this case. This doesn't appear to be a problem so the
|
|
// ASSERT has been commented out.
|
|
//
|
|
|
|
// ASSERT(m_bCdfParsed);
|
|
|
|
HRESULT hr;
|
|
|
|
if (IID_IShellView == riid)
|
|
{
|
|
hr = CreateDefaultShellView((IShellFolder*)this,
|
|
(LPITEMIDLIST)m_pidlPath,
|
|
(IShellView**)ppvOut);
|
|
}
|
|
else
|
|
{
|
|
*ppvOut = NULL;
|
|
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::GetAttributesOf ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the common attributes of the given id lists.
|
|
//
|
|
// Parameters:
|
|
// [In] cidl - The number of id lists passed in.
|
|
// [In] apidl - An array of id list pointers.
|
|
// [Out] pfAttributesOut - Address to receive the common attributes. These
|
|
// attributes are defined with the SFGAO_ prefix.
|
|
// For example SFGAO_FOLDER and SFGAO_CANDELETE.
|
|
//
|
|
// Return:
|
|
// S_OK if the attributes of the given id lists could be determined.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// The attributes of the given id lists are AND'ed to obtain the common
|
|
// members.
|
|
//
|
|
// Shell calls this on the root folder with cidl set to zero to get the
|
|
// attributes of the root folder. It also doesn't bother to check the
|
|
// return value so make sure the attributes are set correctly for this
|
|
// case.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::GetAttributesOf(
|
|
UINT cidl,
|
|
LPCITEMIDLIST* apidl,
|
|
ULONG* pfAttributesOut
|
|
)
|
|
{
|
|
ASSERT(apidl || cidl == 0);
|
|
ASSERT(pfAttributesOut);
|
|
|
|
ULONG fAttributeFilter = *pfAttributesOut;
|
|
|
|
if (!m_bCdfParsed)
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "IShellFolder GetAttributesOf %s",
|
|
PathFindFileName(m_szPath));
|
|
ParseCdfFolder(NULL, PARSE_LOCAL);
|
|
}
|
|
|
|
if (m_pIXMLElementCollection)
|
|
{
|
|
if (cidl)
|
|
{
|
|
|
|
*pfAttributesOut = (ULONG)-1;
|
|
|
|
while(cidl-- && *pfAttributesOut)
|
|
{
|
|
ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)apidl[cidl]));
|
|
ASSERT(ILIsEmpty(_ILNext(apidl[cidl])));
|
|
ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
|
|
(PCDFITEMIDLIST)apidl[cidl]));
|
|
|
|
//
|
|
// CDFIDL_GetAttributes returns zero on failure.
|
|
//
|
|
|
|
*pfAttributesOut &= CDFIDL_GetAttributes(
|
|
m_pIXMLElementCollection,
|
|
(PCDFITEMIDLIST)apidl[cidl],
|
|
fAttributeFilter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Return this folder's attributes.
|
|
//
|
|
|
|
*pfAttributesOut = SFGAO_FOLDER;
|
|
|
|
if (XML_ContainsFolder(m_pIXMLElementCollection))
|
|
*pfAttributesOut |= SFGAO_HASSUBFOLDER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// m_pIXMLElementCollection == NULL in low memory situations.
|
|
//
|
|
|
|
*pfAttributesOut = 0;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::GetUIObjectOf ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Creates a COM object implemeneting the requested interface for the
|
|
// specidied id lists.
|
|
//
|
|
// Parameters:
|
|
// [In] hwndOwner - The owner window.
|
|
// [In] cidl - The number of idlist passed in.
|
|
// [In] apild - An array of id list pointers.
|
|
// [In] riid - The requested interface. Can be IExtractIcon,
|
|
// IContextMenu, IDataObject or IDropTarget.
|
|
// [] prgfInOut - Not used.
|
|
// [Out] ppvOut - The pointer to receive the requested COM object.
|
|
//
|
|
// Return:
|
|
// S_OK if the interface was created.
|
|
// E_OUTOFMEMORY if the COM object couldn't be created.
|
|
// E_NOINTERFACE if the requested interface isn't supported.
|
|
// E_FAIL if cidl is zero.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::GetUIObjectOf(
|
|
HWND hwndOwner,
|
|
UINT cidl,
|
|
LPCITEMIDLIST* apidl,
|
|
REFIID riid,
|
|
UINT* prgfInOut,
|
|
LPVOID * ppvOut
|
|
)
|
|
{
|
|
ASSERT(apidl || 0 == cidl);
|
|
ASSERT(ppvOut);
|
|
|
|
// ASSERT(m_bCdfParsed); Called when cdf is not parsed.
|
|
|
|
#ifdef DEBUG
|
|
for(UINT i = 0; i < cidl; i++)
|
|
{
|
|
ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)apidl[i]));
|
|
ASSERT(ILIsEmpty(_ILNext(apidl[i])));
|
|
ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
|
|
(PCDFITEMIDLIST)apidl[i]));
|
|
}
|
|
#endif // DEBUG
|
|
|
|
HRESULT hr;
|
|
|
|
*ppvOut = NULL;
|
|
|
|
if (cidl)
|
|
{
|
|
if (IID_IExtractIcon == riid
|
|
#ifdef UNICODE
|
|
|| IID_IExtractIconA == riid
|
|
#endif
|
|
)
|
|
{
|
|
ASSERT(1 == cidl);
|
|
|
|
if (!m_bCdfParsed)
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "IShellFolder IExtractIcon %s",
|
|
PathFindFileName(m_szPath));
|
|
ParseCdfFolder(NULL, PARSE_LOCAL);
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
CExtractIcon *pxi = new CExtractIcon((PCDFITEMIDLIST)apidl[0],
|
|
m_pIXMLElementCollection);
|
|
|
|
if (riid == IID_IExtractIconW)
|
|
*ppvOut = (IExtractIconW *)pxi;
|
|
else
|
|
*ppvOut = (IExtractIconA *)pxi;
|
|
#else
|
|
*ppvOut = (IExtractIcon*)new CExtractIcon((PCDFITEMIDLIST)apidl[0],
|
|
m_pIXMLElementCollection);
|
|
#endif
|
|
hr = *ppvOut ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
else if (IID_IContextMenu == riid)
|
|
{
|
|
|
|
#if USE_DEFAULT_MENU_HANDLER
|
|
|
|
hr = CDefFolderMenu_Create((LPITEMIDLIST)m_pcdfidl, hwndOwner, cidl,
|
|
apidl, (IShellFolder*)this, MenuCallBack,
|
|
NULL, NULL, (IContextMenu**)ppvOut);
|
|
#else // USE_DEFAULT_MENU_HANDLER
|
|
|
|
*ppvOut = (IContextMenu*)new CContextMenu((PCDFITEMIDLIST*)apidl,
|
|
m_pidlPath, cidl);
|
|
|
|
hr = *ppvOut ? S_OK : E_OUTOFMEMORY;
|
|
|
|
#endif // USE_DEFAULT_MENU_HANDLER
|
|
|
|
}
|
|
else if (IID_IQueryInfo == riid)
|
|
{
|
|
ASSERT(1 == cidl);
|
|
|
|
if (!m_bCdfParsed)
|
|
{
|
|
TraceMsg(TF_CDFPARSE, "IShellFolder IQueryInfo %s",
|
|
PathFindFileName(m_szPath));
|
|
ParseCdfFolder(NULL, PARSE_LOCAL);
|
|
}
|
|
|
|
*ppvOut = (IQueryInfo*)new CQueryInfo((PCDFITEMIDLIST)apidl[0],
|
|
m_pIXMLElementCollection);
|
|
|
|
hr = *ppvOut ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
else if (IID_IShellLink == riid || IID_IDataObject == riid
|
|
#ifdef UNICODE
|
|
|| IID_IShellLinkA == riid
|
|
#endif
|
|
)
|
|
{
|
|
ASSERT(1 == cidl); // IDataObject should handle cidl > 1!
|
|
|
|
hr = QueryInternetShortcut((PCDFITEMIDLIST)apidl[0], riid, ppvOut);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0); // Is this ever called with cidl == 0?
|
|
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::GetDisplayNameOf ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the diaply name for the specified Id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pidl - A pointer to the id list.
|
|
// [In] uFlags - SHGDN_NORMAL, SHGN_INFOLDER or SHGDN_FORPARSING.
|
|
// [Out] lpName - A pointer to a STRRET structure that receives the name.
|
|
//
|
|
// Return:
|
|
// S_OK if the name can be determined.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// This may be called on the root element in which case the pidl is a shell
|
|
// id list and not a cdf id list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::GetDisplayNameOf(
|
|
LPCITEMIDLIST pidl,
|
|
DWORD uFlags,
|
|
LPSTRRET lpName
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl));
|
|
ASSERT(ILIsEmpty(_ILNext(pidl)));
|
|
ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
|
|
(PCDFITEMIDLIST)pidl));
|
|
ASSERT(lpName);
|
|
|
|
return CDFIDL_GetDisplayName((PCDFITEMIDLIST)pidl, lpName);
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::SetNameOf ***
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
// Return:
|
|
//
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::SetNameOf(
|
|
HWND hwndOwner,
|
|
LPCITEMIDLIST pidl,
|
|
LPCOLESTR lpszName,
|
|
DWORD uFlags,
|
|
LPITEMIDLIST* ppidlOut
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//
|
|
// IPersistFolder method,
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::Initialize ***
|
|
//
|
|
//
|
|
// Description:
|
|
// This function is called with the fully qualified id list (location) of
|
|
// the selected cdf file.
|
|
//
|
|
// Parameters:
|
|
// [In] pidl - The pidl of the selected cdf file. This pidl conatins the
|
|
// full path to the CDF.
|
|
//
|
|
// Return:
|
|
// S_OK if content for the cdf file could be created.
|
|
// E_OUTOFMEMORY otherwise.
|
|
//
|
|
// Comments:
|
|
// This function can be called more than once for a given folder. When a
|
|
// CDFView is being instantiated from a desktop.ini file the shell calls
|
|
// Initialize once before it calls GetUIObjectOf asking for IDropTarget.
|
|
// After the GetUIObjectOf call the folder is Released. It then calls
|
|
// Initialize again on a new folder. This time it keeps the folder and it
|
|
// ends up being displayed.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CCdfView::Initialize(
|
|
LPCITEMIDLIST pidl
|
|
)
|
|
{
|
|
ASSERT(pidl);
|
|
|
|
HRESULT hr;
|
|
|
|
ASSERT(NULL == m_pidlPath);
|
|
|
|
m_pidlPath = ILClone(pidl);
|
|
|
|
if (m_pidlPath)
|
|
{
|
|
hr = CPersist::Initialize(pidl);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Helper functions.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::ParseCdf ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Parses the cdf file associated with this folder.
|
|
//
|
|
// Parameters:
|
|
// [In] hwndOwner - The parent window of any dialogs that need to be
|
|
// displayed.
|
|
// [In] dwFParseType - PARSE_LOCAL, PARSE_NET and PARSE_REPARSE.
|
|
//
|
|
// Return:
|
|
// S_OK if the cdf file was found and successfully parsed.
|
|
// E_FAIL otherwise.
|
|
//
|
|
// Comments:
|
|
// Uses the m_pidlRoot that was set during IPersistFolder::Initialize.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CCdfView::ParseCdfFolder(
|
|
HWND hwndOwner,
|
|
DWORD dwParseFlags
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Parse the file and get the first channel element.
|
|
//
|
|
|
|
IXMLDocument* pIXMLDocument = NULL;
|
|
|
|
hr = CPersist::ParseCdf(hwndOwner, &pIXMLDocument, dwParseFlags);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLDocument);
|
|
|
|
IXMLElement* pIXMLElement;
|
|
LONG nIndex;
|
|
|
|
hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIXMLElement);
|
|
//ASSERT(NULL == m_pcdfidl); Can be non-NULL on a reparse.
|
|
|
|
if (m_pcdfidl)
|
|
CDFIDL_Free(m_pcdfidl);
|
|
|
|
if (m_pIXMLElementCollection)
|
|
m_pIXMLElementCollection->Release();
|
|
|
|
m_pcdfidl = CDFIDL_CreateFromXMLElement(pIXMLElement, nIndex);
|
|
|
|
HRESULT hr2 = pIXMLElement->get_children(&m_pIXMLElementCollection);
|
|
if(!m_pIXMLElementCollection)
|
|
{
|
|
ASSERT(hr2 != S_OK);
|
|
hr = E_FAIL;
|
|
}
|
|
ASSERT((S_OK == hr2 && m_pIXMLElementCollection) ||
|
|
(S_OK != hr2 && NULL == m_pIXMLElementCollection));
|
|
|
|
pIXMLElement->Release();
|
|
}
|
|
}
|
|
if (pIXMLDocument)
|
|
pIXMLDocument->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::QueryInternetShortcut ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Sets up an internet shorcut object for the given URL.
|
|
//
|
|
// Parameters:
|
|
// [In] pszURL - The URL.
|
|
// [In] riid - The requested interface on the shortcut object.
|
|
// [Out] ppvOut - A pointer that receives the interface.
|
|
//
|
|
// Return:
|
|
// S_OK if the object is created and the interface is found.
|
|
// A COM error code otherwise.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
QueryInternetShortcut(
|
|
LPCTSTR pszURL,
|
|
REFIID riid,
|
|
void** ppvOut
|
|
)
|
|
{
|
|
ASSERT(pszURL);
|
|
ASSERT(ppvOut);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
|
|
|
|
if (SHTCharToUnicode(pszURL, wszURL, ARRAYSIZE(wszURL)))
|
|
{
|
|
BSTR bstrURL = SysAllocString(wszURL);
|
|
|
|
if (bstrURL)
|
|
{
|
|
CDFITEM cdfi;
|
|
|
|
cdfi.nIndex = 1;
|
|
cdfi.cdfItemType = CDF_Folder;
|
|
cdfi.bstrName = bstrURL;
|
|
cdfi.bstrURL = bstrURL;
|
|
|
|
PCDFITEMIDLIST pcdfidl = CDFIDL_Create(&cdfi);
|
|
|
|
if (pcdfidl)
|
|
{
|
|
hr = QueryInternetShortcut(pcdfidl, riid, ppvOut);
|
|
|
|
CDFIDL_Free(pcdfidl);
|
|
}
|
|
|
|
SysFreeString(bstrURL);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CCdfView::QueryInternetShortcut ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Sets up an internet shorcut object for the given pidl.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - The shortcut object is created for the URL stored in this
|
|
// cdf item id list.
|
|
// [In] riid - The requested interface on the shortcut object.
|
|
// [Out] ppvOut - A pointer that receives the interface.
|
|
//
|
|
// Return:
|
|
// S_OK if the object is created and the interface is found.
|
|
// A COM error code otherwise.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
QueryInternetShortcut(
|
|
PCDFITEMIDLIST pcdfidl,
|
|
REFIID riid,
|
|
void** ppvOut
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
|
|
ASSERT(ppvOut);
|
|
|
|
HRESULT hr;
|
|
|
|
*ppvOut = NULL;
|
|
|
|
//
|
|
// Only create a shell link object if the CDF contains an URL
|
|
//
|
|
if (*(CDFIDL_GetURL(pcdfidl)) != 0)
|
|
{
|
|
IShellLinkA * pIShellLink;
|
|
|
|
hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IShellLinkA, (void**)&pIShellLink);
|
|
|
|
|
|
BOOL bCoInit = FALSE;
|
|
|
|
if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
|
|
SUCCEEDED(CoInitialize(NULL)))
|
|
{
|
|
bCoInit = TRUE;
|
|
hr = CoCreateInstance(CLSID_InternetShortcut, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IShellLinkA,
|
|
(void**)&pIShellLink);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIShellLink);
|
|
|
|
#ifdef UNICODE
|
|
CHAR szUrlA[INTERNET_MAX_URL_LENGTH];
|
|
|
|
SHTCharToAnsi(CDFIDL_GetURL(pcdfidl), szUrlA, ARRAYSIZE(szUrlA));
|
|
hr = pIShellLink->SetPath(szUrlA);
|
|
#else
|
|
hr = pIShellLink->SetPath(CDFIDL_GetURL(pcdfidl));
|
|
#endif
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// The description ends up being the file name created.
|
|
//
|
|
|
|
TCHAR szPath[MAX_PATH];
|
|
#ifdef UNICODE
|
|
CHAR szPathA[MAX_PATH];
|
|
#endif
|
|
|
|
StrCpyN(szPath, CDFIDL_GetName(pcdfidl), ARRAYSIZE(szPath) - 5);
|
|
StrCat(szPath, TEXT(".url"));
|
|
#ifdef UNICODE
|
|
SHTCharToAnsi(szPath, szPathA, ARRAYSIZE(szPathA));
|
|
pIShellLink->SetDescription(szPathA);
|
|
#else
|
|
pIShellLink->SetDescription(szPath);
|
|
#endif
|
|
|
|
hr = pIShellLink->QueryInterface(riid, ppvOut);
|
|
}
|
|
|
|
pIShellLink->Release();
|
|
}
|
|
|
|
if (bCoInit)
|
|
CoUninitialize();
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
|
|
|
|
return hr;
|
|
}
|