|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// Chanmenu.cpp
//
// IConextMenu for folder items.
//
// History:
//
// 6/12/97 edwardp Created.
//
////////////////////////////////////////////////////////////////////////////////
//
// Includes
//
#include "stdinc.h"
#include "cdfidl.h"
#include "xmlutil.h"
#include "chanmenu.h"
#include "dll.h"
#include "persist.h"
#include "resource.h"
#include "chanapi.h"
#include "chanmgrp.h"
#include "chanmgri.h"
#define _SHDOCVW_
#include <shdocvw.h>
#include <mluisupp.h>
//
// Constructor and destructor.
//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// *** CContextMenu::CContextMenu ***
//
// Constructor for IContextMenu.
//
////////////////////////////////////////////////////////////////////////////////
CChannelMenu::CChannelMenu ( void ) : m_cRef(1) { TraceMsg(TF_OBJECTS, "+ IContextMenu (root)");
DllAddRef();
ASSERT(NULL == m_pSubscriptionMgr); ASSERT(NULL == m_bstrURL); ASSERT(NULL == m_bstrName);
return; }
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// *** CContextMenu::~CContextMenu ***
//
// Destructor.
//
////////////////////////////////////////////////////////////////////////////////
CChannelMenu::~CChannelMenu ( void ) { ASSERT(0 == m_cRef);
if (NULL != m_bstrURL) SysFreeString(m_bstrURL);
if (NULL != m_bstrName) SysFreeString(m_bstrName); if (NULL != m_pSubscriptionMgr) m_pSubscriptionMgr->Release(); //
// Matching Release for the constructor Addref.
//
TraceMsg(TF_OBJECTS, "- IContextMenu (root)");
DllRelease();
return; }
//
// IUnknown methods.
//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// *** CContextMenu::CContextMenu ***
//
// CExtractIcon QI.
//
////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CChannelMenu::QueryInterface ( REFIID riid, void **ppv ) { ASSERT(ppv);
HRESULT hr;
*ppv = NULL;
if (IID_IUnknown == riid || IID_IContextMenu == riid) { *ppv = (IContextMenu*)this; } else if (IID_IShellExtInit == riid) { *ppv = (IShellExtInit*)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) CChannelMenu::AddRef ( void ) { ASSERT(m_cRef != 0); ASSERT(m_cRef < (ULONG)-1);
return ++m_cRef; }
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// *** CContextMenu::Release ***
//
// CContextMenu Release.
//
////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CChannelMenu::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 CChannelMenu::QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags ) { HRESULT hr = S_OK; BOOL fSubscribed; HMENU hChannelMenu, hChannelSubMenu; ASSERT(hmenu); ASSERT(idCmdFirst < idCmdLast);
if (!(CMF_DEFAULTONLY & uFlags)) { if (NULL != m_pSubscriptionMgr) { ASSERT(idCmdFirst + IDM_SUBSCRIBE < idCmdLast);
#ifndef UNIX
if (CanSubscribe(m_bstrURL)) { m_pSubscriptionMgr->IsSubscribed(m_bstrURL, &fSubscribed); if (fSubscribed) { hChannelMenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(IDM_SUBSCRIBEDMENU));
if (SHRestricted2W(REST_NoRemovingSubscriptions, m_bstrURL, 0)) { EnableMenuItem(hChannelMenu, IDM_SUBSCRIBE, MF_BYCOMMAND | MF_GRAYED); } if (SHRestricted2W(REST_NoManualUpdates, m_bstrURL, 0)) { EnableMenuItem(hChannelMenu, IDM_UPDATESUBSCRIPTION, MF_BYCOMMAND | MF_GRAYED); } } else { int idMenu = !SHRestricted2W(REST_NoAddingSubscriptions, m_bstrURL, 0) ? IDM_UNSUBSCRIBEDMENU : IDM_NOSUBSCRIBEMENU; hChannelMenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(idMenu)); } } else #endif /* !UNIX */
{ hChannelMenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(IDM_NOSUBSCRIBEMENU)); }
if (NULL != hChannelMenu) { hChannelSubMenu = GetSubMenu(hChannelMenu, 0);
if (NULL != hChannelSubMenu) { hr = Shell_MergeMenus(hmenu, hChannelSubMenu, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR) - idCmdFirst; } else { hr = E_FAIL; } DestroyMenu(hChannelMenu); } else { hr = E_FAIL; } }
RemoveMenuItems(hmenu); }
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 CChannelMenu::InvokeCommand( LPCMINVOKECOMMANDINFO lpici ) { HRESULT hr = S_OK; ASSERT(lpici);
if (HIWORD(lpici->lpVerb) == 0) { switch (LOWORD(lpici->lpVerb)) { case IDM_UPDATESUBSCRIPTION: ASSERT(NULL != m_pSubscriptionMgr); m_pSubscriptionMgr->UpdateSubscription(m_bstrURL); break; case IDM_SUBSCRIBE: ASSERT(NULL != m_pSubscriptionMgr); ASSERT( sizeof(SUBSCRIPTIONINFO) == m_si.cbSize);
hr = Subscribe(lpici->hwnd); break; case IDM_UNSUBSCRIBE: ASSERT(NULL != m_pSubscriptionMgr); m_pSubscriptionMgr->DeleteSubscription(m_bstrURL, lpici->hwnd); break;
case IDM_EDITSUBSCRIPTION: ASSERT(NULL != m_pSubscriptionMgr); m_pSubscriptionMgr->ShowSubscriptionProperties(m_bstrURL, lpici->hwnd); break;
case IDM_REFRESHCHANNEL: Refresh(lpici->hwnd); break;
case IDM_VIEWSOURCE: ViewSource(lpici->hwnd); break; } }
return hr; }
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// *** CContextMenu::GetCommandString ***
//
//
// Description:
//
//
// Parameters:
//
//
// Return:
//
//
// Comments:
//
//
////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CChannelMenu::GetCommandString( UINT_PTR idCommand, UINT uFLags, UINT *pwReserved, LPSTR pszName, UINT cchMax ) { return E_NOTIMPL; }
//
//
//
STDMETHODIMP CChannelMenu::Initialize( LPCITEMIDLIST pidl, LPDATAOBJECT pdobj, HKEY hkey ) { HRESULT hr; STGMEDIUM stgmed; FORMATETC fmtetc = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
ASSERT(pdobj); hr = pdobj->GetData(&fmtetc, &stgmed);
if (SUCCEEDED(hr)) { if (DragQueryFile((HDROP)stgmed.hGlobal, 0, m_szPath, ARRAYSIZE(m_szPath))) { m_tt.cbTriggerSize = sizeof(TASK_TRIGGER); m_si.cbSize = sizeof(SUBSCRIPTIONINFO); m_si.fUpdateFlags |= SUBSINFO_SCHEDULE; m_si.schedule = SUBSSCHED_AUTO; m_si.pTrigger = &m_tt;
hr = GetNameAndURLAndSubscriptionInfo(m_szPath, &m_bstrName, &m_bstrURL, &m_si);
ASSERT((SUCCEEDED(hr) && m_bstrName && m_bstrURL) || FAILED(hr)); } else { hr = E_FAIL; }
ReleaseStgMedium(&stgmed);
if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&m_pSubscriptionMgr); } } // Return S_OK even if things didn't go as planned so that
// RemoveMenus will get called.
return S_OK; }
//
// Helper functions
//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// *** Name ***
//
//
// Description:
//
//
// Parameters:
//
//
// Return:
//
//
// Comments:
//
//
////////////////////////////////////////////////////////////////////////////////
void CChannelMenu::RemoveMenuItems( HMENU hmenu ) { TCHAR aszRemove[4][62] = {{0}, {0}, {0}, {0}};
MLLoadString(IDS_SHARING, aszRemove[0], ARRAYSIZE(aszRemove[0])); MLLoadString(IDS_RENAME, aszRemove[1], ARRAYSIZE(aszRemove[1])); MLLoadString(IDS_SENDTO, aszRemove[2], ARRAYSIZE(aszRemove[2]));
if (SHRestricted2W(REST_NoEditingChannels, NULL, 0)) MLLoadString(IDS_PROPERTIES, aszRemove[3], ARRAYSIZE(aszRemove[3]));
TCHAR szBuffer[62]; MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_TYPE;
for (int i = GetMenuItemCount(hmenu) - 1; i >= 0; i--) { mii.dwTypeData = szBuffer; mii.cch = ARRAYSIZE(szBuffer);
if (GetMenuItemInfo(hmenu, i, TRUE, &mii) && mii.cch) { for (int j = 0; j < ARRAYSIZE(aszRemove); j++) { if (StrEql(aszRemove[j], mii.dwTypeData)) { DeleteMenu(hmenu, i, MF_BYPOSITION); break; } } } }
return; }
void CChannelMenu::Refresh(HWND hwnd) { IXMLDocument* pIXMLDocument;
DLL_ForcePreloadDlls(PRELOAD_MSXML); HRESULT hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDocument, (void**)&pIXMLDocument);
if (SUCCEEDED(hr)) { ASSERT(pIXMLDocument);
if (DownloadCdfUI(hwnd, m_bstrURL, pIXMLDocument)) { UpdateImage(m_szPath); SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSH, (void*)m_szPath, NULL); }
pIXMLDocument->Release(); } }
static TCHAR c_szFileProtocol[] = TEXT("file:"); static TCHAR c_szCDFExtension[] = TEXT(".cdf"); static TCHAR c_szShellEdit[] = TEXT("\\shell\\edit\\command"); static TCHAR c_szEditVerb[] = TEXT("edit"); static TCHAR c_szChannelFile[] = TEXT("ChannelFile"); static TCHAR c_szChannelFileEdit[] = TEXT("ChannelFile\\shell\\edit\\command"); static TCHAR c_szNotepad[] = TEXT("notepad.exe");
void CChannelMenu::ViewSource(HWND hwnd) { TCHAR szProgId[64] = TEXT(""); TCHAR szBuf[INTERNET_MAX_URL_LENGTH]; TCHAR szFile[MAX_PATH + 2]; // Leave room for quotes
DWORD cch, ccb, dwType; SHELLEXECUTEINFO sei; BOOL fFoundProg = FALSE; HRESULT hr = S_OK;
TraceMsg(TF_OBJECTS, "+ IContextMenu ViewSource %ls", m_bstrURL);
if (SHUnicodeToTChar(m_bstrURL, szBuf, ARRAYSIZE(szBuf))) { if (SUCCEEDED(URLGetLocalFileName(szBuf, szFile, ARRAYSIZE(szFile), NULL))) { if (StrCmpNI(szFile, c_szFileProtocol, 5) == 0) { ASSERT(ARRAYSIZE(szFile) < ARRAYSIZE(szBuf)); StrCpyN(szBuf, szFile, ARRAYSIZE(szBuf)); cch = ARRAYSIZE(szFile) - 2; hr = PathCreateFromUrl(szBuf, szFile, &cch, 0); }
if (SUCCEEDED(hr)) { PathQuoteSpaces(szFile);
//
// We don't just call ShellExec with edit verb since
// who knows what the file extension will be.
//
cch = ARRAYSIZE(szProgId); if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, c_szCDFExtension, NULL, &dwType, szProgId, &cch) ) { ASSERT(ARRAYSIZE(szProgId) < ARRAYSIZE(szBuf)); StrCpyN(szBuf, szProgId, ARRAYSIZE(szBuf)); ASSERT(ARRAYSIZE(szProgId) + ARRAYSIZE(c_szShellEdit) < ARRAYSIZE(szBuf)); StrCatBuff(szBuf, c_szShellEdit, ARRAYSIZE(szBuf)); ccb = sizeof(szBuf); if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, szBuf, NULL, &dwType, szBuf, &ccb) ) { //
// Getting here means they have an edit verb for CDF files
//
fFoundProg = TRUE; } }
//
// If we haven't found a class key yet and the CDF ProgID
// isn't ours, then fall back to our edit verb.
//
if (!fFoundProg && StrCmpI(szProgId, c_szChannelFile)) { ccb = sizeof(szBuf); if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, c_szChannelFileEdit, NULL, &dwType, szBuf, &ccb) ) { fFoundProg = TRUE; ASSERT(ARRAYSIZE(c_szChannelFile) < ARRAYSIZE(szProgId)); StrCpyN(szProgId, c_szChannelFile, ARRAYSIZE(szProgId)); } }
ZeroMemory(&sei, sizeof(sei)); sei.cbSize = sizeof(sei); sei.hwnd = hwnd; sei.nShow = SW_SHOW; if (fFoundProg) { sei.fMask = SEE_MASK_CLASSNAME; sei.lpVerb = c_szEditVerb; sei.lpFile = szFile; sei.lpClass = szProgId; TraceMsg(TF_OBJECTS, "IContextMenu ViewSource progid=%s file=%s", szProgId, szFile); } else { sei.lpFile = c_szNotepad; sei.lpParameters = szFile; TraceMsg(TF_OBJECTS, "IContextMenu ViewSource Notepad file=%s", szFile); }
#ifndef UNIX
ShellExecuteEx(&sei); #else
unixInvokeEditor(szFile); #endif /* UNIX */
} } else { CDFMessageBox(hwnd, IDS_ERROR_NO_CACHE_ENTRY, IDS_ERROR_DLG_TITLE, MB_OK | MB_ICONEXCLAMATION, szBuf); } } else { TraceMsg(TF_OBJECTS, "IContextMenu ViewSource couldn't convert to TSTR"); } TraceMsg(TF_OBJECTS, "- IContextMenu ViewSource"); }
HRESULT CChannelMenu::Subscribe(HWND hwnd) { HRESULT hr = S_OK;
CChannelMgr *pChannelMgr = new CChannelMgr;
if (pChannelMgr) { hr = pChannelMgr->AddAndSubscribeEx2(hwnd, m_bstrURL, m_pSubscriptionMgr, TRUE); pChannelMgr->Release();
if (SUCCEEDED(hr) && (NULL != m_pSubscriptionMgr)) { hr = m_pSubscriptionMgr->UpdateSubscription(m_bstrURL); } } else { hr = E_OUTOFMEMORY; }
return hr; }
|