898 lines
19 KiB
C++
898 lines
19 KiB
C++
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// itemmenu.cpp
|
||
|
//
|
||
|
// IConextMenu for folder items.
|
||
|
//
|
||
|
// History:
|
||
|
//
|
||
|
// 3/26/97 edwardp Created.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//
|
||
|
// Includes
|
||
|
//
|
||
|
|
||
|
#include "stdinc.h"
|
||
|
#include "cdfidl.h"
|
||
|
#include "itemmenu.h"
|
||
|
#include "dll.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
#include <mluisupp.h>
|
||
|
|
||
|
// In Shdocvw: shbrowse.cpp
|
||
|
#ifndef UNIX
|
||
|
extern HRESULT CDDEAuto_Navigate(BSTR str, HWND *phwnd, long lLaunchNewWindow);
|
||
|
#else
|
||
|
extern "C" HRESULT CDDEAuto_Navigate(BSTR str, HWND *phwnd, long lLaunchNewWindow);
|
||
|
#endif /* UNIX */
|
||
|
//
|
||
|
// Constructor and destructor.
|
||
|
//
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::CContextMenu ***
|
||
|
//
|
||
|
// Constructor for IContextMenu.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
CContextMenu::CContextMenu (
|
||
|
PCDFITEMIDLIST* apcdfidl,
|
||
|
LPITEMIDLIST pidlPath,
|
||
|
UINT nCount
|
||
|
)
|
||
|
: m_cRef(1)
|
||
|
{
|
||
|
//
|
||
|
// Copy the pcdfidls.
|
||
|
//
|
||
|
|
||
|
ASSERT(apcdfidl || 0 == nCount);
|
||
|
|
||
|
ASSERT(NULL == m_apcdfidl);
|
||
|
ASSERT(NULL == m_pidlPath);
|
||
|
|
||
|
//
|
||
|
// In low memory situations pidlPath may be NULL.
|
||
|
//
|
||
|
|
||
|
if (pidlPath)
|
||
|
m_pidlPath = ILClone(pidlPath);
|
||
|
|
||
|
IMalloc* pIMalloc;
|
||
|
|
||
|
if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
|
||
|
{
|
||
|
ASSERT(pIMalloc);
|
||
|
|
||
|
m_apcdfidl = (PCDFITEMIDLIST*)pIMalloc->Alloc(
|
||
|
nCount * sizeof(PCDFITEMIDLIST));
|
||
|
|
||
|
if (m_apcdfidl)
|
||
|
{
|
||
|
for (UINT i = 0, bOutOfMem = FALSE; (i < nCount) && !bOutOfMem; i++)
|
||
|
{
|
||
|
ASSERT(CDFIDL_IsValid(apcdfidl[i]));
|
||
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)apcdfidl[i])));
|
||
|
|
||
|
m_apcdfidl[i] = (PCDFITEMIDLIST)ILClone(
|
||
|
(LPITEMIDLIST)apcdfidl[i]);
|
||
|
|
||
|
if (bOutOfMem = (NULL == m_apcdfidl[i]))
|
||
|
{
|
||
|
while (i--)
|
||
|
pIMalloc->Free(m_apcdfidl[i]);
|
||
|
|
||
|
pIMalloc->Free(m_apcdfidl);
|
||
|
m_apcdfidl = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(CDFIDL_IsValid(m_apcdfidl[i]));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pIMalloc->Release();
|
||
|
}
|
||
|
|
||
|
m_nCount = m_apcdfidl ? nCount : 0;
|
||
|
|
||
|
//
|
||
|
// Don't allow the DLL to unload.
|
||
|
//
|
||
|
|
||
|
TraceMsg(TF_OBJECTS, "+ IContextMenu");
|
||
|
|
||
|
DllAddRef();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::~CContextMenu ***
|
||
|
//
|
||
|
// Destructor.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
CContextMenu::~CContextMenu (
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
ASSERT(0 == m_cRef);
|
||
|
|
||
|
//
|
||
|
// Free the locally stored cdfidls.
|
||
|
//
|
||
|
|
||
|
if (m_apcdfidl)
|
||
|
{
|
||
|
IMalloc* pIMalloc;
|
||
|
|
||
|
if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
|
||
|
{
|
||
|
ASSERT(pIMalloc);
|
||
|
|
||
|
while (m_nCount--)
|
||
|
{
|
||
|
ASSERT(CDFIDL_IsValid(m_apcdfidl[m_nCount]));
|
||
|
ASSERT(pIMalloc->DidAlloc(m_apcdfidl[m_nCount]));
|
||
|
|
||
|
pIMalloc->Free(m_apcdfidl[m_nCount]);
|
||
|
}
|
||
|
|
||
|
ASSERT(pIMalloc->DidAlloc(m_apcdfidl));
|
||
|
|
||
|
pIMalloc->Free(m_apcdfidl);
|
||
|
|
||
|
pIMalloc->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_pidlPath)
|
||
|
ILFree(m_pidlPath);
|
||
|
|
||
|
//
|
||
|
// Matching Release for the constructor Addref.
|
||
|
//
|
||
|
|
||
|
TraceMsg(TF_OBJECTS, "- IContextMenu");
|
||
|
|
||
|
DllRelease();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IUnknown methods.
|
||
|
//
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::CContextMenu ***
|
||
|
//
|
||
|
// CExtractIcon QI.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CContextMenu::QueryInterface (
|
||
|
REFIID riid,
|
||
|
void **ppv
|
||
|
)
|
||
|
{
|
||
|
ASSERT(ppv);
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
*ppv = NULL;
|
||
|
|
||
|
if (IID_IUnknown == riid || IID_IContextMenu2 == riid)
|
||
|
{
|
||
|
*ppv = (IContextMenu2*)this;
|
||
|
}
|
||
|
else if (IID_IContextMenu == riid)
|
||
|
{
|
||
|
*ppv = (IContextMenu*)this;
|
||
|
}
|
||
|
|
||
|
if (*ppv)
|
||
|
{
|
||
|
((IUnknown*)*ppv)->AddRef();
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::AddRef ***
|
||
|
//
|
||
|
// CContextMenu AddRef.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
CContextMenu::AddRef (
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
ASSERT(m_cRef != 0);
|
||
|
ASSERT(m_cRef < (ULONG)-1);
|
||
|
|
||
|
return ++m_cRef;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::Release ***
|
||
|
//
|
||
|
// CContextMenu Release.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP_(ULONG)
|
||
|
CContextMenu::Release (
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
ASSERT (m_cRef != 0);
|
||
|
|
||
|
ULONG cRef = --m_cRef;
|
||
|
|
||
|
if (0 == cRef)
|
||
|
delete this;
|
||
|
|
||
|
return cRef;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IContextMenu methods.
|
||
|
//
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::QueryContextMenu ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
// Adds menu items to the given item's context menu.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [In Out] hmenu - A handle to the menu. New items are inserted into
|
||
|
// this menu
|
||
|
// [In] indexMenu - Zero-based position at which to insert the first
|
||
|
// menu item.
|
||
|
// [In] idCmdFirst - Minimum value that can be used for a new menu item
|
||
|
// identifier.
|
||
|
// [In] idCmdLast - Maximum value the can be used for a menu item id.
|
||
|
// [In] uFlags - CMF_DEFAULTONLY, CMF_EXPLORE, CMF_NORMAL or
|
||
|
// CMF_VERBSONLY.
|
||
|
//
|
||
|
// Return:
|
||
|
// On success the scode contains the the menu identifier offset of the last
|
||
|
// menu item added plus one.
|
||
|
//
|
||
|
// Comments:
|
||
|
// CMF_DEFAULTONLY flag indicates the user double-clicked on the item. In
|
||
|
// this case no menu is displayed. The shell is simply querying for the ID
|
||
|
// of the default action.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CContextMenu::QueryContextMenu(
|
||
|
HMENU hmenu,
|
||
|
UINT indexMenu,
|
||
|
UINT idCmdFirst,
|
||
|
UINT idCmdLast,
|
||
|
UINT uFlags
|
||
|
)
|
||
|
{
|
||
|
ASSERT(hmenu);
|
||
|
ASSERT(idCmdFirst < idCmdLast);
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (CMF_DEFAULTONLY & uFlags)
|
||
|
{
|
||
|
ASSERT(idCmdFirst + IDM_OPEN < idCmdLast);
|
||
|
|
||
|
InsertMenu(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst + IDM_OPEN,
|
||
|
TEXT(""));
|
||
|
|
||
|
SetMenuDefaultItem(hmenu, idCmdFirst + IDM_OPEN, FALSE);
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(idCmdFirst + IDM_PROPERTIES < idCmdLast);
|
||
|
|
||
|
HMENU hmenuParent = LoadMenu(MLGetHinst(),
|
||
|
MAKEINTRESOURCE(IDM_CONTEXTMENU));
|
||
|
|
||
|
if (hmenuParent)
|
||
|
{
|
||
|
HMENU hmenuContext = GetSubMenu(hmenuParent, 0);
|
||
|
|
||
|
if (hmenuContext)
|
||
|
{
|
||
|
ULONG idNew = Shell_MergeMenus(hmenu, hmenuContext, indexMenu,
|
||
|
idCmdFirst, idCmdLast,
|
||
|
MM_ADDSEPARATOR |
|
||
|
MM_SUBMENUSHAVEIDS);
|
||
|
|
||
|
SetMenuDefaultItem(hmenu, idCmdFirst + IDM_OPEN, FALSE);
|
||
|
|
||
|
hr = 0x000ffff & idNew;
|
||
|
|
||
|
DestroyMenu(hmenuContext);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
|
||
|
DestroyMenu(hmenuParent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::InvokeCommand ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
// Carries out the command for the given menu item id.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [In] lpici - Structure containing the verb, hwnd, menu id, etc.
|
||
|
//
|
||
|
// Return:
|
||
|
// S_OK if the command was successful.
|
||
|
// E_FAIL otherwise.
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CContextMenu::InvokeCommand(
|
||
|
LPCMINVOKECOMMANDINFO lpici
|
||
|
)
|
||
|
{
|
||
|
ASSERT(lpici);
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (HIWORD(lpici->lpVerb))
|
||
|
{
|
||
|
hr = E_NOTIMPL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WORD wCmd = LOWORD(lpici->lpVerb);
|
||
|
|
||
|
switch(wCmd)
|
||
|
{
|
||
|
case IDM_OPEN:
|
||
|
hr = DoOpen(lpici->hwnd, lpici->nShow);
|
||
|
break;
|
||
|
|
||
|
case IDM_PROPERTIES:
|
||
|
hr = DoProperties(lpici->hwnd);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = E_NOTIMPL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::GetCommandString ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
//
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
//
|
||
|
// Return:
|
||
|
//
|
||
|
//
|
||
|
// Comments:
|
||
|
// note -- return an ANSI command string
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CContextMenu::GetCommandString(
|
||
|
UINT_PTR idCommand,
|
||
|
UINT uFlags,
|
||
|
UINT *pwReserved,
|
||
|
LPSTR pszName,
|
||
|
UINT cchMax
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
if ((uFlags == GCS_VERB) && (idCommand == IDM_OPEN))
|
||
|
{
|
||
|
StrCpyN((LPTSTR)pszName, TEXT("open"), cchMax);
|
||
|
hr = NOERROR;
|
||
|
}
|
||
|
#ifdef UNICODE
|
||
|
else if ((uFlags == GCS_VERBA) && (idCommand == IDM_OPEN))
|
||
|
{
|
||
|
StrCpyNA(pszName, "open", cchMax);
|
||
|
hr = NOERROR;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// IContextMenu2 methods.
|
||
|
//
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::HandleMenuMsg ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
//
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
//
|
||
|
// Return:
|
||
|
//
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
STDMETHODIMP
|
||
|
CContextMenu::HandleMenuMsg(
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Helper functions.
|
||
|
//
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::DoOpen ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
// Command handler for IDM_OPEN.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [In] hwnd - Parent window. Used for dialogs etc.
|
||
|
// [In] nShow - ShowFlag use in ShowWindow command.
|
||
|
//
|
||
|
// Return:
|
||
|
// S_OK if the command executed.
|
||
|
// E_FAIL if the command iddn't execute.
|
||
|
// E_OUTOFMEMORY if there wasn't enough memory to execute the command.
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CContextMenu::DoOpen(
|
||
|
HWND hwnd,
|
||
|
int nShow
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (m_apcdfidl)
|
||
|
{
|
||
|
ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
|
||
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
|
||
|
|
||
|
if (CDFIDL_IsFolder(m_apcdfidl[0]))
|
||
|
{
|
||
|
hr = DoOpenFolder(hwnd, nShow);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = DoOpenStory(hwnd, nShow);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::DoOpenFolder ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
// Open command for folders.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [In] hwnd - Parent window. Used for dialogs etc.
|
||
|
// [In] nShow - ShowFlag use in ShowWindow command.
|
||
|
//
|
||
|
// Return:
|
||
|
// S_OK if the command executed.
|
||
|
// E_FAIL if the command iddn't execute.
|
||
|
// E_OUTOFMEMORY if there wasn't enough memory to execute the command.
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CContextMenu::DoOpenFolder(
|
||
|
HWND hwnd,
|
||
|
int nShow
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (m_pidlPath)
|
||
|
{
|
||
|
ASSERT(m_apcdfidl);
|
||
|
ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
|
||
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
|
||
|
|
||
|
LPITEMIDLIST pidlFull = ILCombine(m_pidlPath,
|
||
|
(LPITEMIDLIST)m_apcdfidl[0]);
|
||
|
|
||
|
if (pidlFull)
|
||
|
{
|
||
|
SHELLEXECUTEINFO ei = {0};
|
||
|
|
||
|
ei.cbSize = sizeof(SHELLEXECUTEINFO);
|
||
|
ei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
|
||
|
ei.hwnd = hwnd;
|
||
|
ei.lpVerb = TEXT("Open");
|
||
|
ei.nShow = nShow;
|
||
|
ei.lpIDList = (LPVOID)pidlFull;
|
||
|
ei.lpClass = TEXT("Folder");
|
||
|
|
||
|
hr = ShellExecuteEx(&ei) ? S_OK : E_FAIL;
|
||
|
|
||
|
ILFree(pidlFull);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::DoOpenStory ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
// Open command for stories (internet links).
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [In] hwnd - Parent window. Used for dialogs etc.
|
||
|
// [In] nShow - ShowFlag use in ShowWindow command.
|
||
|
//
|
||
|
// Return:
|
||
|
// S_OK if ShellExecuteEx succeeded.
|
||
|
// E_FAIL if ShellExecuteEx didn't succeed.
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CContextMenu::DoOpenStory(
|
||
|
HWND hwnd,
|
||
|
int nShow
|
||
|
)
|
||
|
{
|
||
|
ASSERT(m_apcdfidl);
|
||
|
ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
|
||
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
LPTSTR pszURL = CDFIDL_GetURL(m_apcdfidl[0]);
|
||
|
|
||
|
if (PathIsURL(pszURL))
|
||
|
{
|
||
|
|
||
|
WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
|
||
|
HWND hwndTemp = (HWND)-1;
|
||
|
BSTR bstrURL;
|
||
|
|
||
|
SHTCharToUnicode(pszURL, wszURL, ARRAYSIZE(wszURL));
|
||
|
bstrURL = SysAllocString(wszURL);
|
||
|
if (bstrURL)
|
||
|
{
|
||
|
hr = CDDEAuto_Navigate(bstrURL, &hwndTemp, 0);
|
||
|
SysFreeString(bstrURL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** CContextMenu::DoProperties ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
// Command handler for IDM_PROPERTIES.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [In] hwnd - Parent window. Used for dialogs etc.
|
||
|
//
|
||
|
// Return:
|
||
|
// S_OK if the command executed.
|
||
|
// E_FAIL if the command iddn't execute.
|
||
|
// E_OUTOFMEMORY if there wasn't enough memory to execute the command.
|
||
|
//
|
||
|
// Comments:
|
||
|
// Uses the property pages of the InternetShortcut object.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
CContextMenu::DoProperties(
|
||
|
HWND hwnd
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (m_apcdfidl)
|
||
|
{
|
||
|
ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
|
||
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
|
||
|
|
||
|
IShellPropSheetExt* pIShellPropSheetExt;
|
||
|
|
||
|
hr = QueryInternetShortcut(m_apcdfidl[0], IID_IShellPropSheetExt,
|
||
|
(void**)&pIShellPropSheetExt);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
ASSERT(pIShellPropSheetExt);
|
||
|
|
||
|
PROPSHEETHEADER psh = {0};
|
||
|
HPROPSHEETPAGE ahpage[MAX_PROP_PAGES];
|
||
|
|
||
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
||
|
psh.dwFlags = PSH_NOAPPLYNOW;
|
||
|
psh.hwndParent = hwnd;
|
||
|
psh.hInstance = MLGetHinst();
|
||
|
psh.pszCaption = CDFIDL_GetName(m_apcdfidl[0]);
|
||
|
psh.phpage = ahpage;
|
||
|
|
||
|
hr = pIShellPropSheetExt->AddPages(AddPages_Callback, (LPARAM)&psh);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// Property sheets are currently disabled. This is the only
|
||
|
// API called in comctl32.dll so remove it to avoid a
|
||
|
//dependency.
|
||
|
|
||
|
//hr = (-1 == PropertySheet(&psh)) ? E_FAIL : S_OK;
|
||
|
}
|
||
|
|
||
|
pIShellPropSheetExt->Release();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** AddPages_Callback ***
|
||
|
//
|
||
|
//
|
||
|
// Description:
|
||
|
//
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
//
|
||
|
// Return:
|
||
|
//
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
BOOL CALLBACK
|
||
|
AddPages_Callback(
|
||
|
HPROPSHEETPAGE hpage,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
ASSERT(hpage);
|
||
|
ASSERT(lParam);
|
||
|
|
||
|
BOOL bRet;
|
||
|
PROPSHEETHEADER* ppsh = (PROPSHEETHEADER*)lParam;
|
||
|
|
||
|
if (ppsh->nPages < MAX_PROP_PAGES)
|
||
|
{
|
||
|
ppsh->phpage[ppsh->nPages++] = hpage;
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bRet = FALSE;
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
HRESULT CALLBACK
|
||
|
MenuCallBack(
|
||
|
IShellFolder* pIShellFolder,
|
||
|
HWND hwndOwner,
|
||
|
LPDATAOBJECT pdtobj,
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
||
|
//
|
||
|
// *** 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
|
||
|
CContextMenu::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);
|
||
|
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();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
|
||
|
ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
|
||
|
|
||
|
return hr;
|
||
|
}
|