Rewrite PropertyList to remove STL, fix various issues in ControlSite and add control download & install. b=178542 r=peterl@netscape.com sr=rpotts@netscape.com

This commit is contained in:
locka%iol.ie 2002-11-07 23:06:08 +00:00
Родитель 78c3b02115
Коммит 21ba9b4939
5 изменённых файлов: 315 добавлений и 127 удалений

Просмотреть файл

@ -39,8 +39,9 @@
#include "StdAfx.h"
#include "ControlSite.h"
#include <Objsafe.h>
#include "ControlSite.h"
std::list<CControlSite *> CControlSite::m_cControlList;
@ -93,6 +94,34 @@ CControlSite::~CControlSite()
// Helper method checks whether a class implements a particular category
HRESULT CControlSite::ClassImplementsCategory(const CLSID &clsid, const CATID &catid)
{
// Test if there is a CLSID entry. If there isn't then obviously
// the object doesn't exist and therefore doesn't implement any category.
// In this situation, the function returns REGDB_E_CLASSNOTREG.
CRegKey key;
if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) != ERROR_SUCCESS)
{
// Must fail if we can't even open this!
return E_FAIL;
}
LPOLESTR szCLSID = NULL;
if (FAILED(StringFromCLSID(clsid, &szCLSID)))
{
return E_FAIL;
}
USES_CONVERSION;
CRegKey keyCLSID;
LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
CoTaskMemFree(szCLSID);
if (lResult != ERROR_SUCCESS)
{
// Class doesn't exist
return REGDB_E_CLASSNOTREG;
}
keyCLSID.Close();
// CLSID exists, so try checking what categories it implements
CIPtr(ICatInformation) spCatInfo;
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, (LPVOID*) &spCatInfo);
if (spCatInfo == NULL)
@ -136,7 +165,8 @@ static const CATID CATID_SafeForScripting =
// Create the specified control, optionally providing properties to initialise
// it with and a name.
HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl)
HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
LPCWSTR szCodebase, IBindCtx *pBindContext)
{
NG_TRACE_METHOD(CControlSite::Create);
@ -144,20 +174,167 @@ HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl)
m_ParameterList = pl;
// See if object is script safe
if (m_bSafeForScriptingObjectsOnly &&
ClassImplementsCategory(clsid, CATID_SafeForScripting) != S_OK)
BOOL checkForObjectSafety = FALSE;
if (m_bSafeForScriptingObjectsOnly)
{
return E_FAIL;
HRESULT hrClass = ClassImplementsCategory(clsid, CATID_SafeForScripting);
if (hrClass == REGDB_E_CLASSNOTREG && szCodebase)
{
// Class doesn't exist, so allow code below to fetch it
}
else if (FAILED(hrClass))
{
// The class is not flagged as safe for scripting, so
// we'll have to create it to ask it if its safe.
checkForObjectSafety = TRUE;
}
}
// Create the object
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &m_spObject);
if (FAILED(hr))
CComPtr<IUnknown> spObject;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &spObject);
if (SUCCEEDED(hr) && checkForObjectSafety)
{
return E_FAIL;
// The control was created but it didn't check out as safe so
// it must be asked if its safe for scripting.
CComQIPtr<IObjectSafety> spObjectSafety = spObject;
if (!spObjectSafety)
{
return E_FAIL;
}
DWORD dwSupported = 0; // Supported options (mask)
DWORD dwEnabled = 0; // Enabled options
// Assume scripting via IDispatch
if (FAILED(spObjectSafety->GetInterfaceSafetyOptions(
__uuidof(IDispatch), &dwSupported, &dwEnabled)))
{
// Interface is not safe or failure.
return E_FAIL;
}
// Test if safe for scripting
if (!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
{
return E_FAIL;
}
// Drop through, success!
}
return S_OK;
// Do we need to download the control?
if (FAILED(hr) && szCodebase)
{
wchar_t *szURL = NULL;
// Test if the code base ends in #version=a,b,c,d
DWORD dwFileVersionMS = 0xffffffff;
DWORD dwFileVersionLS = 0xffffffff;
wchar_t *szHash = wcsrchr(szCodebase, wchar_t('#'));
if (szHash)
{
if (wcsnicmp(szHash, L"#version=", 9) == 0)
{
int a, b, c, d;
if (swscanf(szHash + 9, L"%d,%d,%d,%d", &a, &b, &c, &d) == 4)
{
dwFileVersionMS = MAKELONG(b,a);
dwFileVersionLS = MAKELONG(d,c);
}
}
szURL = _wcsdup(szCodebase);
// Terminate at the hash mark
if (szURL)
szURL[szHash - szCodebase] = wchar_t('\0');
}
else
{
szURL = _wcsdup(szCodebase);
}
if (!szURL)
return E_OUTOFMEMORY;
CComPtr<IBindCtx> spBindContext;
CComPtr<IBindStatusCallback> spBindStatusCallback;
CComPtr<IBindStatusCallback> spOldBSC;
// Create our own bind context or use the one provided?
BOOL useInternalBSC = FALSE;
if (!pBindContext)
{
useInternalBSC = TRUE;
hr = CreateBindCtx(0, &spBindContext);
if (FAILED(hr))
{
free(szURL);
return hr;
}
spBindStatusCallback = dynamic_cast<IBindStatusCallback *>(this);
hr = RegisterBindStatusCallback(spBindContext, spBindStatusCallback, &spOldBSC, 0);
if (FAILED(hr))
{
free(szURL);
return hr;
}
}
else
{
spBindContext = pBindContext;
}
hr = CoGetClassObjectFromURL(clsid, szURL, dwFileVersionMS, dwFileVersionLS,
NULL, spBindContext, CLSCTX_ALL, NULL, IID_IUnknown, (void **) &m_spObject);
free(szURL);
// Handle the internal binding synchronously so the object exists
// or an error code is available when the method returns.
if (useInternalBSC)
{
if (MK_S_ASYNCHRONOUS == hr)
{
m_bBindingInProgress = TRUE;
m_hrBindResult = E_FAIL;
// Spin around waiting for binding to complete
HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
while (m_bBindingInProgress)
{
MSG msg;
// Process pending messages
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!::GetMessage(&msg, NULL, 0, 0))
{
m_bBindingInProgress = FALSE;
break;
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
if (!m_bBindingInProgress)
break;
// Sleep for a bit or the next msg to appear
::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS);
}
::CloseHandle(hFakeEvent);
// Set the result
hr = m_hrBindResult;
}
// Destroy the bind status callback & context
if (spBindStatusCallback)
{
RevokeBindStatusCallback(spBindContext, spBindStatusCallback);
spBindContext.Release();
}
}
}
if (spObject)
m_spObject = spObject;
return hr;
}
@ -178,7 +355,6 @@ HRESULT CControlSite::Attach(HWND hwndParent, const RECT &rcPos, IUnknown *pInit
// Object must have been created
if (m_spObject == NULL)
{
NG_ASSERT(0);
return E_UNEXPECTED;
}
@ -212,13 +388,14 @@ HRESULT CControlSite::Attach(HWND hwndParent, const RECT &rcPos, IUnknown *pInit
// If there is a parameter list for the object and no init stream then
// create one here.
CPropertyBagInstance *pPropertyBag = NULL;
if (pInitStream == NULL && m_ParameterList.size() >= 1)
if (pInitStream == NULL && m_ParameterList.GetSize() > 0)
{
CPropertyBagInstance::CreateInstance(&pPropertyBag);
pPropertyBag->AddRef();
for (PropertyList::const_iterator i = m_ParameterList.begin(); i != m_ParameterList.end(); i++)
for (unsigned long i = 0; i < m_ParameterList.GetSize(); i++)
{
pPropertyBag->Write((*i).szName, (VARIANT *) &(*i).vValue);
pPropertyBag->Write(m_ParameterList.GetNameOf(i),
const_cast<VARIANT *>(m_ParameterList.GetValueOf(i)));
}
pInitStream = (IPersistPropertyBag *) pPropertyBag;
}
@ -584,7 +761,13 @@ HRESULT STDMETHODCALLTYPE CControlSite::GetMoniker(/* [in] */ DWORD dwAssign, /*
HRESULT STDMETHODCALLTYPE CControlSite::GetContainer(/* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer)
{
return E_NOINTERFACE;
if (!ppContainer) return E_INVALIDARG;
*ppContainer = m_spContainer;
if (*ppContainer)
{
(*ppContainer)->AddRef();
}
return (*ppContainer) ? S_OK : E_NOINTERFACE;
}
@ -1074,3 +1257,75 @@ HRESULT STDMETHODCALLTYPE CControlSite::ShowPropertyFrame(void)
return E_NOTIMPL;
}
///////////////////////////////////////////////////////////////////////////////
// IBindStatusCallback implementation
HRESULT STDMETHODCALLTYPE CControlSite::OnStartBinding(DWORD dwReserved,
IBinding __RPC_FAR *pib)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CControlSite::GetPriority(LONG __RPC_FAR *pnPriority)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CControlSite::OnLowResource(DWORD reserved)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CControlSite::OnProgress(ULONG ulProgress,
ULONG ulProgressMax,
ULONG ulStatusCode,
LPCWSTR szStatusText)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CControlSite::OnStopBinding(HRESULT hresult, LPCWSTR szError)
{
m_bBindingInProgress = FALSE;
m_hrBindResult = hresult;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CControlSite::GetBindInfo(DWORD __RPC_FAR *pgrfBINDF,
BINDINFO __RPC_FAR *pbindInfo)
{
*pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
pbindInfo->cbSize = sizeof(BINDINFO);
pbindInfo->szExtraInfo = NULL;
memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
pbindInfo->grfBindInfoF = 0;
pbindInfo->dwBindVerb = 0;
pbindInfo->szCustomVerb = NULL;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CControlSite::OnDataAvailable(DWORD grfBSCF,
DWORD dwSize,
FORMATETC __RPC_FAR *pformatetc,
STGMEDIUM __RPC_FAR *pstgmed)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CControlSite::OnObjectAvailable(REFIID riid,
IUnknown __RPC_FAR *punk)
{
return S_OK;
}
// IWindowForBindingUI
HRESULT STDMETHODCALLTYPE CControlSite::GetWindow(
/* [in] */ REFGUID rguidReason,
/* [out] */ HWND *phwnd)
{
*phwnd = NULL;
return S_OK;
}

Просмотреть файл

@ -20,8 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Adam Lock <adamlock@netscape.com>
*
* Adam Lock <adamlock@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -57,7 +57,9 @@
COM_INTERFACE_ENTRY_IID(IID_IAdviseSink2, IAdviseSinkEx) \
COM_INTERFACE_ENTRY_IID(IID_IAdviseSinkEx, IAdviseSinkEx) \
COM_INTERFACE_ENTRY(IOleCommandTarget) \
COM_INTERFACE_ENTRY(IServiceProvider)
COM_INTERFACE_ENTRY(IServiceProvider) \
COM_INTERFACE_ENTRY(IBindStatusCallback) \
COM_INTERFACE_ENTRY(IWindowForBindingUI)
//
// Class for hosting an ActiveX control
@ -89,7 +91,9 @@ class CControlSite : public CComObjectRootEx<CComSingleThreadModel>,
public IAdviseSinkEx,
public IDispatch,
public IServiceProvider,
public IOleCommandTargetImpl<CControlSite>
public IOleCommandTargetImpl<CControlSite>,
public IBindStatusCallback,
public IWindowForBindingUI
{
public:
// Site management values
@ -113,6 +117,10 @@ public:
unsigned m_bWindowless:1;
// Flag indicating if only safely scriptable controls are allowed
unsigned m_bSafeForScriptingObjectsOnly:1;
// Pointer to an externally registered service provider
CComPtr<IServiceProvider> m_spServiceProvider;
// Pointer to the OLE container
CComPtr<IOleContainer> m_spContainer;
protected:
// Pointers to object interfaces
@ -126,13 +134,17 @@ protected:
CComQIPtr<IOleInPlaceObject, &IID_IOleInPlaceObject> m_spIOleInPlaceObject;
// Pointer to object's IOleInPlaceObjectWindowless interface
CComQIPtr<IOleInPlaceObjectWindowless, &IID_IOleInPlaceObjectWindowless> m_spIOleInPlaceObjectWindowless;
// Pointer to an externally registered service provider
CComPtr<IServiceProvider> m_spServiceProvider;
// CLSID of the control
CLSID m_clsid;
// Parameter list
PropertyList m_ParameterList;
// Binding variables
// Flag indicating whether binding is in progress
unsigned m_bBindingInProgress;
// Result from the binding operation
HRESULT m_hrBindResult;
// Double buffer drawing variables used for windowless controls
// Area of buffer
RECT m_rcBuffer;
@ -195,7 +207,8 @@ END_OLECOMMAND_TABLE()
// Object creation and management functions
// Creates and initialises an object
virtual HRESULT Create(REFCLSID clsid, PropertyList &pl = PropertyList());
virtual HRESULT Create(REFCLSID clsid, PropertyList &pl = PropertyList(),
LPCWSTR szCodebase = NULL, IBindCtx *pBindContext = NULL);
// Attaches the object to the site
virtual HRESULT Attach(HWND hwndParent, const RECT &rcPos, IUnknown *pInitStream = NULL);
// Detaches the object from the site
@ -217,6 +230,10 @@ END_OLECOMMAND_TABLE()
{
m_spServiceProvider = pSP;
}
virtual void SetContainer(IOleContainer *pContainer)
{
m_spContainer = pContainer;
}
// Methods to set ambient properties
virtual void SetAmbientUserMode(BOOL bUser);
@ -316,6 +333,19 @@ END_OLECOMMAND_TABLE()
virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(/* [in] */ MSG __RPC_FAR *pMsg, /* [in] */ DWORD grfModifiers);
virtual HRESULT STDMETHODCALLTYPE OnFocus(/* [in] */ BOOL fGotFocus);
virtual HRESULT STDMETHODCALLTYPE ShowPropertyFrame( void);
// IBindStatusCallback
virtual HRESULT STDMETHODCALLTYPE OnStartBinding(/* [in] */ DWORD dwReserved, /* [in] */ IBinding __RPC_FAR *pib);
virtual HRESULT STDMETHODCALLTYPE GetPriority(/* [out] */ LONG __RPC_FAR *pnPriority);
virtual HRESULT STDMETHODCALLTYPE OnLowResource(/* [in] */ DWORD reserved);
virtual HRESULT STDMETHODCALLTYPE OnProgress(/* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR szStatusText);
virtual HRESULT STDMETHODCALLTYPE OnStopBinding(/* [in] */ HRESULT hresult, /* [unique][in] */ LPCWSTR szError);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetBindInfo( /* [out] */ DWORD __RPC_FAR *grfBINDF, /* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE OnDataAvailable(/* [in] */ DWORD grfBSCF, /* [in] */ DWORD dwSize, /* [in] */ FORMATETC __RPC_FAR *pformatetc, /* [in] */ STGMEDIUM __RPC_FAR *pstgmed);
virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(/* [in] */ REFIID riid, /* [iid_is][in] */ IUnknown __RPC_FAR *punk);
// IWindowForBindingUI
virtual HRESULT STDMETHODCALLTYPE GetWindow(/* [in] */ REFGUID rguidReason, /* [out] */ HWND *phwnd);
};
typedef CComObject<CControlSite> CControlSiteInstance;

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Adam Lock <adamlock@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
@ -2484,23 +2485,9 @@ HRESULT STDMETHODCALLTYPE CMozillaBrowser::PutProperty(BSTR szProperty, VARIANT
{
RETURN_E_INVALIDARG();
}
PropertyList::iterator i;
for (i = mPropertyList.begin(); i != mPropertyList.end(); i++)
{
// Is the property already in the list?
if (wcscmp((*i).szName, szProperty) == 0)
{
// Copy the new value
(*i).vValue = CComVariant(vtValue);
return S_OK;
}
}
Property p;
p.szName = CComBSTR(szProperty);
p.vValue = vtValue;
mPropertyList.AddOrReplaceNamedProperty(szProperty, vtValue);
mPropertyList.push_back(p);
return S_OK;
}
@ -2524,14 +2511,12 @@ HRESULT STDMETHODCALLTYPE CMozillaBrowser::GetProperty(BSTR Property, VARIANT __
}
VariantInit(pvtValue);
PropertyList::iterator i;
for (i = mPropertyList.begin(); i != mPropertyList.end(); i++)
for (unsigned long i = 0; i < mPropertyList.GetSize(); i++)
{
// Is the property already in the list?
if (wcscmp((*i).szName, Property) == 0)
if (wcsicmp(mPropertyList.GetNameOf(i), Property) == 0)
{
// Copy the new value
VariantCopy(pvtValue, &(*i).vValue);
VariantCopy(pvtValue, const_cast<VARIANT *>(mPropertyList.GetValueOf(i)));
return S_OK;
}
}

Просмотреть файл

@ -67,14 +67,12 @@ HRESULT STDMETHODCALLTYPE CPropertyBag::Read(/* [in] */ LPCOLESTR pszPropName, /
}
VariantInit(pVar);
PropertyList::iterator i;
for (i = m_PropertyList.begin(); i != m_PropertyList.end(); i++)
for (unsigned long i = 0; i < m_PropertyList.GetSize(); i++)
{
// Is the property already in the list?
if (wcsicmp((*i).szName, pszPropName) == 0)
if (wcsicmp(m_PropertyList.GetNameOf(i), pszPropName) == 0)
{
// Copy the new value
VariantCopy(pVar, &(*i).vValue);
VariantCopy(pVar, const_cast<VARIANT *>(m_PropertyList.GetValueOf(i)));
return S_OK;
}
}
@ -94,23 +92,9 @@ HRESULT STDMETHODCALLTYPE CPropertyBag::Write(/* [in] */ LPCOLESTR pszPropName,
return E_INVALIDARG;
}
PropertyList::iterator i;
for (i = m_PropertyList.begin(); i != m_PropertyList.end(); i++)
{
// Is the property already in the list?
if (wcsicmp((*i).szName, pszPropName) == 0)
{
// Copy the new value
(*i).vValue = CComVariant(*pVar);
return S_OK;
}
}
CComBSTR bstrName(pszPropName);
m_PropertyList.AddOrReplaceNamedProperty(bstrName, *pVar);
Property p;
p.szName = CComBSTR(pszPropName);
p.vValue = *pVar;
m_PropertyList.push_back(p);
return S_OK;
}

Просмотреть файл

@ -1,66 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Adam Lock <adamlock@netscape.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef PROPERTYLIST_H
#define PROPERTYLIST_H
// Property is a name,variant pair held by the browser. In IE, properties
// offer a primitive way for DHTML elements to talk back and forth with
// the host app.
struct Property
{
CComBSTR szName;
CComVariant vValue;
};
// A list of properties
typedef std::vector<Property> PropertyList;
// DEVNOTE: These operators are required since the unpatched VC++ 5.0
// generates code even for unreferenced template methods in
// the file <vector> and will give compiler errors without
// them. Service Pack 1 and above fixes this problem
int operator <(const Property&, const Property&);
int operator ==(const Property&, const Property&);
#endif