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

604 lines
16 KiB
C++

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
//
// oleobj.cpp
//
// IOleObject Implementation. IOleObject is required for for downloading
// cdf files from within the browser.
//
// History:
//
// 6/18/97 edwardp Created.
//
////////////////////////////////////////////////////////////////////////////////
//
// Includes
//
#include "stdinc.h"
#include "cdfidl.h"
#include "xmlutil.h"
#include "chanapi.h"
#include "chanenum.h"
#include "persist.h"
#include "resource.h"
#include <shguidp.h>
#include <htiface.h> // IID_ITargetEmbedding
#define _SHDOCVW_
#include <shdocvw.h>
#include <mluisupp.h>
STDMETHODIMP CPersist::SetClientSite(IOleClientSite *pIOleClientSite)
{
#ifdef IMP_CLIENTSITE
if (NULL != m_pOleClientSite)
m_pOleClientSite->Release();
m_pOleClientSite = pIOleClientSite;
if (m_pOleClientSite)
m_pOleClientSite->AddRef();
#endif
if (pIOleClientSite && NULL == m_pIWebBrowser2)
{
IOleWindow *pIOleWindow;
HRESULT hr = pIOleClientSite->QueryInterface(IID_IOleWindow,
(void**)&pIOleWindow);
if (SUCCEEDED(hr))
{
ASSERT(NULL != pIOleWindow);
pIOleWindow->GetWindow(&m_hwnd);
pIOleWindow->Release();
}
IServiceProvider* pIServiceProvider;
hr = pIOleClientSite->QueryInterface(IID_IServiceProvider,
(void**)&pIServiceProvider);
if (SUCCEEDED(hr))
{
ASSERT(pIServiceProvider);
IServiceProvider* pIServiceProvider2;
hr = pIServiceProvider->QueryService(SID_STopLevelBrowser,
IID_IServiceProvider,
(void**)&pIServiceProvider2);
if (SUCCEEDED(hr))
{
ASSERT(pIServiceProvider2);
hr = pIServiceProvider2->QueryService(SID_SWebBrowserApp,
IID_IWebBrowser2,
(void**)&m_pIWebBrowser2);
//
// REVIEW: Determine if the current browser is IE
//
// New check if the browser is IE. IE will fail on a QI of
// IWebBrowserApp for ITargetEmbedding. Anyone else hosting
// the browser OC must support this interface.
//
IWebBrowserApp* pIWebBrowserApp;
hr = m_pIWebBrowser2->QueryInterface(IID_IWebBrowserApp,
(void**)&pIWebBrowserApp);
if (SUCCEEDED(hr))
{
ASSERT(pIWebBrowserApp);
ITargetEmbedding* pITargetEmbedding;
hr = pIWebBrowserApp->QueryInterface(IID_ITargetEmbedding,
(void**)&pITargetEmbedding);
if (SUCCEEDED(hr))
{
ASSERT(pITargetEmbedding);
//
// This isn't IE. So release m_IWebBrowser2. IE
// will be CoCreated later if m_IWebBrowser2 == NULL.
//
m_pIWebBrowser2->Release();
m_pIWebBrowser2 = NULL;
pITargetEmbedding->Release();
}
pIWebBrowserApp->Release();
}
pIServiceProvider2->Release();
}
pIServiceProvider->Release();
}
}
return S_OK;
}
STDMETHODIMP CPersist::GetClientSite(IOleClientSite **ppClientSite)
{
#ifdef IMP_CLIENTSITE
ASSERT(ppClientSite);
if (NULL != m_pOleClientSite)
{
*ppClientSite = m_pOleClientSite;
return S_OK;
}
else
return E_UNEXPECTED;
#else
return E_NOTIMPL;
#endif
}
STDMETHODIMP CPersist::SetHostNames(LPCOLESTR szContainerApp,
LPCOLESTR szContainerObj)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::Close(DWORD dwSaveOption)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::SetMoniker(DWORD dwWhichMoniker, IMoniker *pmk)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,
IMoniker **ppmk)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::InitFromData(IDataObject *pDataObject, BOOL fCreation,
DWORD dwReserved)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::GetClipboardData(DWORD dwReserved,IDataObject **ppDataObject)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
{
HRESULT hr;
if (OLEIVERB_PRIMARY == iVerb)
{
ASSERT(m_pIXMLDocument);
XMLDOCTYPE xdt = XML_GetDocType(m_pIXMLDocument);
switch(xdt)
{
case DOC_CHANNEL:
case DOC_SOFTWAREUPDATE:
// Admins can disallow adding channels and limit
// the number of installed channels.
if (1 /*(dwFlags & STC_CHANNEL)*/ &&
!SHRestricted2W(REST_NoAddingChannels, m_polestrURL, 0) &&
(!SHRestricted2W(REST_MaxChannelCount, NULL, 0) ||
(CountChannels() < SHRestricted2W(REST_MaxChannelCount, NULL, 0))))
{
XML_DownloadLogo(m_pIXMLDocument);
//
// In case the SELF tag is different than the URL get the
// subscribed URL from SubscriptionHelper.
//
BSTR bstrSubscribedURL = NULL;
if (SubscriptionHelper(m_pIXMLDocument, m_hwnd,
SUBSTYPE_CHANNEL,
SUBSACTION_ADDADDITIONALCOMPONENTS,
m_polestrURL, xdt, &bstrSubscribedURL))
{
TCHAR szSubscribedURL[INTERNET_MAX_URL_LENGTH];
if (bstrSubscribedURL &&
SHUnicodeToTChar(bstrSubscribedURL, szSubscribedURL,
ARRAYSIZE(szSubscribedURL)))
{
FILETIME ftLastMod;
URLGetLastModTime(szSubscribedURL, &ftLastMod);
Cache_AddItem(szSubscribedURL, m_pIXMLDocument,
PARSE_NET, ftLastMod, g_dwCacheCount);
}
OpenChannel(bstrSubscribedURL);
hr = S_OK;
}
else
{
hr = S_FALSE;
}
if (bstrSubscribedURL)
SysFreeString(bstrSubscribedURL);
}
else
{
hr = E_ACCESSDENIED;
}
break;
case DOC_DESKTOPCOMPONENT:
#ifndef UNIX
if (m_hwnd && WhichPlatform() != PLATFORM_INTEGRATED)
#else
if (0)
#endif /* UNIX */
{
TCHAR szText[MAX_PATH];
TCHAR szTitle[MAX_PATH];
MLLoadString(IDS_BROWSERONLY_DLG_TEXT, szText,
ARRAYSIZE(szText));
MLLoadString(IDS_BROWSERONLY_DLG_TITLE, szTitle,
ARRAYSIZE(szTitle));
MessageBox(m_hwnd, szText, szTitle, MB_OK);
}
else if (1 /*dwFlags & STC_DESKTOPCOMPONENT*/)
{
COMPONENT Info;
hr = XML_GetDesktopComponentInfo(m_pIXMLDocument, &Info);
if(SUCCEEDED(hr))
{
if(!Info.wszSubscribedURL[0])
{
if(m_polestrURL)
{
StrCpyNW(Info.wszSubscribedURL, m_polestrURL, ARRAYSIZE(Info.wszSubscribedURL));
}
else
{
TraceMsg(TF_GENERAL, "CPersist::DoVerb : COMPONENT::wszSubscribedURL is not set.");
hr = S_FALSE;
}
}
#ifndef UNIX
/* No Active Desktop on Unix */
if (SUCCEEDED(hr))
{
IActiveDesktop* pIActiveDesktop;
hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,
IID_IActiveDesktop, (void**)&pIActiveDesktop);
if (SUCCEEDED(hr))
{
ASSERT(pIActiveDesktop);
hr = pIActiveDesktop->AddDesktopItemWithUI(m_hwnd, &Info, DTI_ADDUI_DISPSUBWIZARD);
// Note: Do not call pIActiveDesktop->ApplyChanges() here. AddDesktopItemWithUI() itself creates
// one instance of ActiveDesktop object, adds the component and calls ApplyChanges() for us.
// Calling ApplyChanges() again here causes the second instance US to overwrite with stale data.
// Bug #404153. Fixed by Sankar. 29th May 2001.
pIActiveDesktop->Release();
}
else
{
TraceMsg(TF_GENERAL, "CPersist::DoVerb : CoCreateInstance for CLSID_ActiveDesktop failed.");
}
}
#endif /* !UNIX */
}
if(SUCCEEDED(hr))
{
hr = S_OK;
}
else
{
hr = S_FALSE;
}
}
else
{
hr = E_ACCESSDENIED;
}
break;
case DOC_UNKNOWN:
default:
hr = E_FAIL;
break;
}
}
else
{
hr = E_NOTIMPL;
}
return hr;
}
STDMETHODIMP CPersist::EnumVerbs(IEnumOLEVERB **ppEnumOleVerb)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::Update(void)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::IsUpToDate(void)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::GetUserClassID(CLSID *pClsid)
{
return E_FAIL;
}
STDMETHODIMP CPersist::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::GetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::Unadvise(DWORD dwConnection)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::EnumAdvise(IEnumSTATDATA **ppenumAdvise)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
{
return E_NOTIMPL;
}
STDMETHODIMP CPersist::SetColorScheme(LOGPALETTE *pLogpal)
{
return E_NOTIMPL;
}
//
// Helper functions.
//
HRESULT
CPersist::OpenChannel(
LPCWSTR pszSubscribedURL
)
{
ASSERT(m_pIXMLDocument);
HRESULT hr;
if (NULL == m_pIWebBrowser2)
{
hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
CLSCTX_LOCAL_SERVER,
IID_IWebBrowser2,
(void**)&m_pIWebBrowser2);
if (FAILED(hr))
{
return hr;
}
}
//m_pIWebBrowser2->put_TheaterMode(-1); Moved to worker window
//m_pIWebBrowser2->put_Visible(-1);
//ShowChannelPane(m_pIWebBrowser2);
IXMLElement* pIXMLElement;
LONG nIndex;
hr = XML_GetFirstChannelElement(m_pIXMLDocument,
&pIXMLElement, &nIndex);
if (SUCCEEDED(hr))
{
ASSERT(pIXMLElement);
BSTR bstrURL = XML_GetAttribute(pIXMLElement, XML_HREF);
if (bstrURL)
{
VARIANT vNull = {0};
VARIANT vFlags = {0};
//
// check for null string
//
if (*bstrURL != 0)
{
HWND hwnd = CreateNavigationWorkerWindow(m_hwnd,
m_pIWebBrowser2);
if (hwnd)
{
LPOLESTR pszPath = Channel_GetChannelPanePath(
pszSubscribedURL);
if (pszPath)
PostMessage(hwnd, WM_NAVIGATE_PANE, 0, (LPARAM)pszPath);
PostMessage(hwnd, WM_NAVIGATE, 0, (LPARAM)bstrURL);
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
else
{
SysFreeString(bstrURL);
}
}
else
{
SysFreeString(bstrURL);
}
}
pIXMLElement->Release();
}
return hr;
}
HWND
CPersist::CreateNavigationWorkerWindow(
HWND hwndParent,
IWebBrowser2* pIWebBrowser2
)
{
ASSERT(pIWebBrowser2);
HWND hwnd;
static BOOL fRegistered = FALSE;
if (!fRegistered) {
WNDCLASS wc = {0};
wc.lpfnWndProc = NavigateWndProc;
wc.cbWndExtra = SIZEOF(IWebBrowser2*);
wc.hInstance = g_hinst;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wc.lpszClassName = TEXT("NavigationWorker");
fRegistered = (BOOL)RegisterClass(&wc);
}
hwnd = CreateWindow(TEXT("NavigationWorker"), NULL, WS_CHILD, 0, 0, 0, 0,
hwndParent, (HMENU)0xED, g_hinst, NULL);
if (hwnd) {
ASSERT(sizeof(IWebBrowser2*) == sizeof(LONG));
pIWebBrowser2->AddRef();
SetWindowLongPtr(hwnd, 0, (LRESULT)pIWebBrowser2);
}
return hwnd;
}
LRESULT
CALLBACK
NavigateWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
LRESULT lRet = 0;
IWebBrowser2* pIWebBrowser2;
switch (msg)
{
case WM_NAVIGATE:
ASSERT(lParam);
pIWebBrowser2 = (IWebBrowser2*)GetWindowLongPtr(hwnd, 0);
if (pIWebBrowser2)
{
//pIWebBrowser2->put_TheaterMode(-1);
pIWebBrowser2->put_Visible(-1);
VARIANT varNull = {0};
VARIANT varURL;
varURL.vt = VT_BSTR;
varURL.bstrVal = (BSTR)lParam;
pIWebBrowser2->Navigate2(&varURL, &varNull, &varNull, &varNull,
&varNull);
}
SysFreeString((BSTR)lParam);
break;
case WM_NAVIGATE_PANE:
ASSERT(lParam);
pIWebBrowser2 = (IWebBrowser2*)GetWindowLongPtr(hwnd, 0);
if (pIWebBrowser2)
{
if (SUCCEEDED(ShowChannelPane(pIWebBrowser2)))
NavigateChannelPane(pIWebBrowser2, (LPWSTR)lParam);
}
CoTaskMemFree((LPOLESTR)lParam);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
pIWebBrowser2 = (IWebBrowser2*)GetWindowLongPtr(hwnd, 0);
if (pIWebBrowser2)
{
SetWindowLongPtr(hwnd, 0, 0);
pIWebBrowser2->Release();
}
// Fall through
default:
lRet = DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
return lRet;
}