|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// 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; }
|