patch by Stephen Walker <sdwalker@myrealbox.com>, r=shaver, a=shaver git-svn-id: svn://10.0.0.236/trunk@173171 18797224-902f-48f8-a5cc-f745e15eee43
1421 lines
38 KiB
C++
1421 lines
38 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla 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/MPL/
|
|
*
|
|
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include <Objsafe.h>
|
|
|
|
#include "ControlSite.h"
|
|
#include "PropertyBag.h"
|
|
#include "ControlSiteIPFrame.h"
|
|
|
|
class CDefaultControlSiteSecurityPolicy : public CControlSiteSecurityPolicy
|
|
{
|
|
// Test if the specified class id implements the specified category
|
|
BOOL ClassImplementsCategory(const CLSID & clsid, const CATID &catid, BOOL &bClassExists);
|
|
public:
|
|
// Test if the class is safe to host
|
|
virtual BOOL IsClassSafeToHost(const CLSID & clsid);
|
|
// Test if the specified class is marked safe for scripting
|
|
virtual BOOL IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists);
|
|
// Test if the instantiated object is safe for scripting on the specified interface
|
|
virtual BOOL IsObjectSafeForScripting(IUnknown *pObject, const IID &iid);
|
|
};
|
|
|
|
BOOL
|
|
CDefaultControlSiteSecurityPolicy::ClassImplementsCategory(const CLSID &clsid, const CATID &catid, BOOL &bClassExists)
|
|
{
|
|
bClassExists = FALSE;
|
|
|
|
// 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 FALSE;
|
|
}
|
|
LPOLESTR szCLSID = NULL;
|
|
if (FAILED(StringFromCLSID(clsid, &szCLSID)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
USES_CONVERSION;
|
|
CRegKey keyCLSID;
|
|
LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
|
|
CoTaskMemFree(szCLSID);
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
// Class doesn't exist
|
|
return FALSE;
|
|
}
|
|
keyCLSID.Close();
|
|
|
|
// CLSID exists, so try checking what categories it implements
|
|
bClassExists = TRUE;
|
|
CComQIPtr<ICatInformation> spCatInfo;
|
|
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, (LPVOID*) &spCatInfo);
|
|
if (spCatInfo == NULL)
|
|
{
|
|
// Must fail if we can't open the category manager
|
|
return FALSE;
|
|
}
|
|
|
|
// See what categories the class implements
|
|
CComQIPtr<IEnumCATID> spEnumCATID;
|
|
if (FAILED(spCatInfo->EnumImplCategoriesOfClass(clsid, &spEnumCATID)))
|
|
{
|
|
// Can't enumerate classes in category so fail
|
|
return FALSE;
|
|
}
|
|
|
|
// Search for matching categories
|
|
BOOL bFound = FALSE;
|
|
CATID catidNext = GUID_NULL;
|
|
while (spEnumCATID->Next(1, &catidNext, NULL) == S_OK)
|
|
{
|
|
if (::IsEqualCATID(catid, catidNext))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Test if the class is safe to host
|
|
BOOL CDefaultControlSiteSecurityPolicy::IsClassSafeToHost(const CLSID & clsid)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// Test if the specified class is marked safe for scripting
|
|
BOOL CDefaultControlSiteSecurityPolicy::IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists)
|
|
{
|
|
// Test the category the object belongs to
|
|
return ClassImplementsCategory(clsid, CATID_SafeForScripting, bClassExists);
|
|
}
|
|
|
|
// Test if the instantiated object is safe for scripting on the specified interface
|
|
BOOL CDefaultControlSiteSecurityPolicy::IsObjectSafeForScripting(IUnknown *pObject, const IID &iid)
|
|
{
|
|
if (!pObject) {
|
|
return FALSE;
|
|
}
|
|
// Ask the control if its safe for scripting
|
|
CComQIPtr<IObjectSafety> spObjectSafety = pObject;
|
|
if (!spObjectSafety)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD dwSupported = 0; // Supported options (mask)
|
|
DWORD dwEnabled = 0; // Enabled options
|
|
|
|
// Assume scripting via IDispatch
|
|
if (FAILED(spObjectSafety->GetInterfaceSafetyOptions(
|
|
iid, &dwSupported, &dwEnabled)))
|
|
{
|
|
// Interface is not safe or failure.
|
|
return FALSE;
|
|
}
|
|
|
|
// Test if safe for scripting
|
|
if (!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
|
|
{
|
|
// Object says it is not set to be safe, but supports unsafe calling,
|
|
// try enabling it and asking again.
|
|
|
|
if(!(dwSupported & INTERFACESAFE_FOR_UNTRUSTED_CALLER) ||
|
|
FAILED(spObjectSafety->SetInterfaceSafetyOptions(
|
|
iid, INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER)) ||
|
|
FAILED(spObjectSafety->GetInterfaceSafetyOptions(
|
|
iid, &dwSupported, &dwEnabled)) ||
|
|
!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Constructor
|
|
CControlSite::CControlSite()
|
|
{
|
|
TRACE_METHOD(CControlSite::CControlSite);
|
|
|
|
m_hWndParent = NULL;
|
|
m_CLSID = CLSID_NULL;
|
|
m_bSetClientSiteFirst = FALSE;
|
|
m_bVisibleAtRuntime = TRUE;
|
|
memset(&m_rcObjectPos, 0, sizeof(m_rcObjectPos));
|
|
|
|
m_bInPlaceActive = FALSE;
|
|
m_bUIActive = FALSE;
|
|
m_bInPlaceLocked = FALSE;
|
|
m_bWindowless = FALSE;
|
|
m_bSupportWindowlessActivation = TRUE;
|
|
m_bSafeForScriptingObjectsOnly = FALSE;
|
|
m_pSecurityPolicy = GetDefaultControlSecurityPolicy();
|
|
|
|
// Initialise ambient properties
|
|
m_nAmbientLocale = 0;
|
|
m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
|
|
m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
|
|
m_bAmbientUserMode = true;
|
|
m_bAmbientShowHatching = true;
|
|
m_bAmbientShowGrabHandles = true;
|
|
m_bAmbientAppearance = true; // 3d
|
|
|
|
// Windowless variables
|
|
m_hDCBuffer = NULL;
|
|
m_hRgnBuffer = NULL;
|
|
m_hBMBufferOld = NULL;
|
|
m_hBMBuffer = NULL;
|
|
}
|
|
|
|
|
|
// Destructor
|
|
CControlSite::~CControlSite()
|
|
{
|
|
TRACE_METHOD(CControlSite::~CControlSite);
|
|
Detach();
|
|
}
|
|
|
|
// Create the specified control, optionally providing properties to initialise
|
|
// it with and a name.
|
|
HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
|
|
LPCWSTR szCodebase, IBindCtx *pBindContext)
|
|
{
|
|
TRACE_METHOD(CControlSite::Create);
|
|
|
|
m_CLSID = clsid;
|
|
m_ParameterList = pl;
|
|
|
|
// See if security policy will allow the control to be hosted
|
|
if (m_pSecurityPolicy && !m_pSecurityPolicy->IsClassSafeToHost(clsid))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
// See if object is script safe
|
|
BOOL checkForObjectSafety = FALSE;
|
|
if (m_pSecurityPolicy && m_bSafeForScriptingObjectsOnly)
|
|
{
|
|
BOOL bClassExists = FALSE;
|
|
BOOL bIsSafe = m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
|
|
if (!bClassExists && szCodebase)
|
|
{
|
|
// Class doesn't exist, so allow code below to fetch it
|
|
}
|
|
else if (!bIsSafe)
|
|
{
|
|
// 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
|
|
CComPtr<IUnknown> spObject;
|
|
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &spObject);
|
|
if (SUCCEEDED(hr) && checkForObjectSafety)
|
|
{
|
|
// Assume scripting via IDispatch
|
|
if (!m_pSecurityPolicy->IsObjectSafeForScripting(spObject, __uuidof(IDispatch)))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
// Drop through, success!
|
|
}
|
|
|
|
// 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;
|
|
const 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;
|
|
}
|
|
|
|
|
|
// Attach the created control to a window and activate it
|
|
HRESULT CControlSite::Attach(HWND hwndParent, const RECT &rcPos, IUnknown *pInitStream)
|
|
{
|
|
TRACE_METHOD(CControlSite::Attach);
|
|
|
|
if (hwndParent == NULL)
|
|
{
|
|
NS_ASSERTION(0, "No parent hwnd");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
m_hWndParent = hwndParent;
|
|
m_rcObjectPos = rcPos;
|
|
|
|
// Object must have been created
|
|
if (m_spObject == NULL)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
m_spIViewObject = m_spObject;
|
|
m_spIOleObject = m_spObject;
|
|
|
|
if (m_spIOleObject == NULL)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
DWORD dwMiscStatus;
|
|
m_spIOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
|
|
|
|
if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
|
|
{
|
|
m_bSetClientSiteFirst = TRUE;
|
|
}
|
|
if (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
|
|
{
|
|
m_bVisibleAtRuntime = FALSE;
|
|
}
|
|
|
|
// Some objects like to have the client site as the first thing
|
|
// to be initialised (for ambient properties and so forth)
|
|
if (m_bSetClientSiteFirst)
|
|
{
|
|
m_spIOleObject->SetClientSite(this);
|
|
}
|
|
|
|
// 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.GetSize() > 0)
|
|
{
|
|
CPropertyBagInstance::CreateInstance(&pPropertyBag);
|
|
pPropertyBag->AddRef();
|
|
for (unsigned long i = 0; i < m_ParameterList.GetSize(); i++)
|
|
{
|
|
pPropertyBag->Write(m_ParameterList.GetNameOf(i),
|
|
const_cast<VARIANT *>(m_ParameterList.GetValueOf(i)));
|
|
}
|
|
pInitStream = (IPersistPropertyBag *) pPropertyBag;
|
|
}
|
|
|
|
// Initialise the control from store if one is provided
|
|
if (pInitStream)
|
|
{
|
|
CComQIPtr<IPropertyBag, &IID_IPropertyBag> spPropertyBag = pInitStream;
|
|
CComQIPtr<IStream, &IID_IStream> spStream = pInitStream;
|
|
CComQIPtr<IPersistStream, &IID_IPersistStream> spIPersistStream = m_spIOleObject;
|
|
CComQIPtr<IPersistPropertyBag, &IID_IPersistPropertyBag> spIPersistPropertyBag = m_spIOleObject;
|
|
|
|
if (spIPersistPropertyBag && spPropertyBag)
|
|
{
|
|
spIPersistPropertyBag->Load(spPropertyBag, NULL);
|
|
}
|
|
else if (spIPersistStream && spStream)
|
|
{
|
|
spIPersistStream->Load(spStream);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Initialise the object if possible
|
|
CComQIPtr<IPersistStreamInit, &IID_IPersistStreamInit> spIPersistStreamInit = m_spIOleObject;
|
|
if (spIPersistStreamInit)
|
|
{
|
|
spIPersistStreamInit->InitNew();
|
|
}
|
|
}
|
|
|
|
m_spIOleInPlaceObject = m_spObject;
|
|
m_spIOleInPlaceObjectWindowless = m_spObject;
|
|
|
|
m_spIOleInPlaceObject->SetObjectRects(&m_rcObjectPos, &m_rcObjectPos);
|
|
|
|
// In-place activate the object
|
|
if (m_bVisibleAtRuntime)
|
|
{
|
|
DoVerb(OLEIVERB_INPLACEACTIVATE);
|
|
}
|
|
|
|
// For those objects which haven't had their client site set yet,
|
|
// it's done here.
|
|
if (!m_bSetClientSiteFirst)
|
|
{
|
|
m_spIOleObject->SetClientSite(this);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Unhook the control from the window and throw it all away
|
|
HRESULT CControlSite::Detach()
|
|
{
|
|
TRACE_METHOD(CControlSite::Detach);
|
|
|
|
if (m_spIOleInPlaceObjectWindowless)
|
|
{
|
|
m_spIOleInPlaceObjectWindowless.Release();
|
|
}
|
|
|
|
if (m_spIOleInPlaceObject)
|
|
{
|
|
m_spIOleInPlaceObject->InPlaceDeactivate();
|
|
m_spIOleInPlaceObject.Release();
|
|
}
|
|
|
|
if (m_spIOleObject)
|
|
{
|
|
m_spIOleObject->Close(OLECLOSE_NOSAVE);
|
|
m_spIOleObject->SetClientSite(NULL);
|
|
m_spIOleObject.Release();
|
|
}
|
|
|
|
m_spIViewObject.Release();
|
|
m_spObject.Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Return the IUnknown of the contained control
|
|
HRESULT CControlSite::GetControlUnknown(IUnknown **ppObject)
|
|
{
|
|
*ppObject = NULL;
|
|
if (m_spObject)
|
|
{
|
|
m_spObject->QueryInterface(IID_IUnknown, (void **) ppObject);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Subscribe to an event sink on the control
|
|
HRESULT CControlSite::Advise(IUnknown *pIUnkSink, const IID &iid, DWORD *pdwCookie)
|
|
{
|
|
if (m_spObject == NULL)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (pIUnkSink == NULL || pdwCookie == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return AtlAdvise(m_spObject, pIUnkSink, iid, pdwCookie);
|
|
}
|
|
|
|
|
|
// Unsubscribe event sink from the control
|
|
HRESULT CControlSite::Unadvise(const IID &iid, DWORD dwCookie)
|
|
{
|
|
if (m_spObject == NULL)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
return AtlUnadvise(m_spObject, iid, dwCookie);
|
|
}
|
|
|
|
|
|
// Draw the control
|
|
HRESULT CControlSite::Draw(HDC hdc)
|
|
{
|
|
TRACE_METHOD(CControlSite::Draw);
|
|
|
|
// Draw only when control is windowless or deactivated
|
|
if (m_spIViewObject)
|
|
{
|
|
if (m_bWindowless || !m_bInPlaceActive)
|
|
{
|
|
RECTL *prcBounds = (m_bWindowless) ? NULL : (RECTL *) &m_rcObjectPos;
|
|
m_spIViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, prcBounds, NULL, NULL, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Draw something to indicate no control is there
|
|
HBRUSH hbr = CreateSolidBrush(RGB(200,200,200));
|
|
FillRect(hdc, &m_rcObjectPos, hbr);
|
|
DeleteObject(hbr);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Execute the specified verb
|
|
HRESULT CControlSite::DoVerb(LONG nVerb, LPMSG lpMsg)
|
|
{
|
|
TRACE_METHOD(CControlSite::DoVerb);
|
|
|
|
if (m_spIOleObject == NULL)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return m_spIOleObject->DoVerb(nVerb, lpMsg, this, 0, m_hWndParent, &m_rcObjectPos);
|
|
}
|
|
|
|
|
|
// Set the position on the control
|
|
HRESULT CControlSite::SetPosition(const RECT &rcPos)
|
|
{
|
|
TRACE_METHOD(CControlSite::SetPosition);
|
|
m_rcObjectPos = rcPos;
|
|
if (m_spIOleInPlaceObject)
|
|
{
|
|
m_spIOleInPlaceObject->SetObjectRects(&m_rcObjectPos, &m_rcObjectPos);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CControlSite::FireAmbientPropertyChange(DISPID id)
|
|
{
|
|
if (m_spObject)
|
|
{
|
|
CComQIPtr<IOleControl> spControl = m_spObject;
|
|
if (spControl)
|
|
{
|
|
spControl->OnAmbientPropertyChange(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CControlSite::SetAmbientUserMode(BOOL bUserMode)
|
|
{
|
|
bool bNewMode = bUserMode ? true : false;
|
|
if (m_bAmbientUserMode != bNewMode)
|
|
{
|
|
m_bAmbientUserMode = bNewMode;
|
|
FireAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CControlSiteSecurityPolicy implementation
|
|
|
|
CControlSiteSecurityPolicy *CControlSite::GetDefaultControlSecurityPolicy()
|
|
{
|
|
static CDefaultControlSiteSecurityPolicy defaultControlSecurityPolicy;
|
|
return &defaultControlSecurityPolicy;
|
|
}
|
|
|
|
// Test if the class is safe to host
|
|
BOOL CControlSite::IsClassSafeToHost(const CLSID & clsid)
|
|
{
|
|
if (m_pSecurityPolicy)
|
|
return m_pSecurityPolicy->IsClassSafeToHost(clsid);
|
|
return TRUE;
|
|
}
|
|
|
|
// Test if the specified class is marked safe for scripting
|
|
BOOL CControlSite::IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists)
|
|
{
|
|
if (m_pSecurityPolicy)
|
|
return m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
|
|
return TRUE;
|
|
}
|
|
|
|
// Test if the instantiated object is safe for scripting on the specified interface
|
|
BOOL CControlSite::IsObjectSafeForScripting(IUnknown *pObject, const IID &iid)
|
|
{
|
|
if (m_pSecurityPolicy)
|
|
return m_pSecurityPolicy->IsObjectSafeForScripting(pObject, iid);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CControlSite::IsObjectSafeForScripting(const IID &iid)
|
|
{
|
|
return IsObjectSafeForScripting(m_spObject, iid);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IServiceProvider implementation
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::QueryService(REFGUID guidService, REFIID riid, void** ppv)
|
|
{
|
|
if (m_spServiceProvider)
|
|
return m_spServiceProvider->QueryService(guidService, riid, ppv);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IDispatch implementation
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetTypeInfoCount(/* [out] */ UINT __RPC_FAR *pctinfo)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetTypeInfo(/* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetIDsOfNames(/* [in] */ REFIID riid, /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames, /* [in] */ UINT cNames, /* [in] */ LCID lcid, /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::Invoke(/* [in] */ DISPID dispIdMember, /* [in] */ REFIID riid, /* [in] */ LCID lcid, /* [in] */ WORD wFlags, /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams, /* [out] */ VARIANT __RPC_FAR *pVarResult, /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo, /* [out] */ UINT __RPC_FAR *puArgErr)
|
|
{
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
{
|
|
CComVariant vResult;
|
|
|
|
switch (dispIdMember)
|
|
{
|
|
case DISPID_AMBIENT_APPEARANCE:
|
|
vResult = CComVariant(m_bAmbientAppearance);
|
|
break;
|
|
|
|
case DISPID_AMBIENT_FORECOLOR:
|
|
vResult = CComVariant((long) m_clrAmbientForeColor);
|
|
break;
|
|
|
|
case DISPID_AMBIENT_BACKCOLOR:
|
|
vResult = CComVariant((long) m_clrAmbientBackColor);
|
|
break;
|
|
|
|
case DISPID_AMBIENT_LOCALEID:
|
|
vResult = CComVariant((long) m_nAmbientLocale);
|
|
break;
|
|
|
|
case DISPID_AMBIENT_USERMODE:
|
|
vResult = CComVariant(m_bAmbientUserMode);
|
|
break;
|
|
|
|
case DISPID_AMBIENT_SHOWGRABHANDLES:
|
|
vResult = CComVariant(m_bAmbientShowGrabHandles);
|
|
break;
|
|
|
|
case DISPID_AMBIENT_SHOWHATCHING:
|
|
vResult = CComVariant(m_bAmbientShowHatching);
|
|
break;
|
|
|
|
default:
|
|
return DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
|
|
VariantCopy(pVarResult, &vResult);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IAdviseSink implementation
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnDataChange(/* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc, /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed)
|
|
{
|
|
}
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnViewChange(/* [in] */ DWORD dwAspect, /* [in] */ LONG lindex)
|
|
{
|
|
// Redraw the control
|
|
InvalidateRect(NULL, FALSE);
|
|
}
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnRename(/* [in] */ IMoniker __RPC_FAR *pmk)
|
|
{
|
|
}
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnSave(void)
|
|
{
|
|
}
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnClose(void)
|
|
{
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IAdviseSink2 implementation
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnLinkSrcChange(/* [unique][in] */ IMoniker __RPC_FAR *pmk)
|
|
{
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IAdviseSinkEx implementation
|
|
|
|
|
|
void STDMETHODCALLTYPE CControlSite::OnViewStatusChange(/* [in] */ DWORD dwViewStatus)
|
|
{
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IOleWindow implementation
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetWindow(/* [out] */ HWND __RPC_FAR *phwnd)
|
|
{
|
|
*phwnd = m_hWndParent;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::ContextSensitiveHelp(/* [in] */ BOOL fEnterMode)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IOleClientSite implementation
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::SaveObject(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetMoniker(/* [in] */ DWORD dwAssign, /* [in] */ DWORD dwWhichMoniker, /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetContainer(/* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer)
|
|
{
|
|
if (!ppContainer) return E_INVALIDARG;
|
|
*ppContainer = m_spContainer;
|
|
if (*ppContainer)
|
|
{
|
|
(*ppContainer)->AddRef();
|
|
}
|
|
return (*ppContainer) ? S_OK : E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::ShowObject(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnShowWindow(/* [in] */ BOOL fShow)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::RequestNewObjectLayout(void)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IOleInPlaceSite implementation
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::CanInPlaceActivate(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceActivate(void)
|
|
{
|
|
m_bInPlaceActive = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnUIActivate(void)
|
|
{
|
|
m_bUIActive = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetWindowContext(/* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame, /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc, /* [out] */ LPRECT lprcPosRect, /* [out] */ LPRECT lprcClipRect, /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
|
{
|
|
*lprcPosRect = m_rcObjectPos;
|
|
*lprcClipRect = m_rcObjectPos;
|
|
|
|
CControlSiteIPFrameInstance *pIPFrame = NULL;
|
|
CControlSiteIPFrameInstance::CreateInstance(&pIPFrame);
|
|
pIPFrame->AddRef();
|
|
|
|
*ppFrame = (IOleInPlaceFrame *) pIPFrame;
|
|
*ppDoc = NULL;
|
|
|
|
lpFrameInfo->fMDIApp = FALSE;
|
|
lpFrameInfo->hwndFrame = NULL;
|
|
lpFrameInfo->haccel = NULL;
|
|
lpFrameInfo->cAccelEntries = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::Scroll(/* [in] */ SIZE scrollExtant)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnUIDeactivate(/* [in] */ BOOL fUndoable)
|
|
{
|
|
m_bUIActive = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceDeactivate(void)
|
|
{
|
|
m_bInPlaceActive = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::DiscardUndoState(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::DeactivateAndUndo(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnPosRectChange(/* [in] */ LPCRECT lprcPosRect)
|
|
{
|
|
if (lprcPosRect == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
SetPosition(m_rcObjectPos);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IOleInPlaceSiteEx implementation
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceActivateEx(/* [out] */ BOOL __RPC_FAR *pfNoRedraw, /* [in] */ DWORD dwFlags)
|
|
{
|
|
m_bInPlaceActive = TRUE;
|
|
|
|
if (pfNoRedraw)
|
|
{
|
|
*pfNoRedraw = FALSE;
|
|
}
|
|
if (dwFlags & ACTIVATE_WINDOWLESS)
|
|
{
|
|
if (!m_bSupportWindowlessActivation)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
m_bWindowless = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceDeactivateEx(/* [in] */ BOOL fNoRedraw)
|
|
{
|
|
m_bInPlaceActive = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::RequestUIActivate(void)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IOleInPlaceSiteWindowless implementation
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::CanWindowlessActivate(void)
|
|
{
|
|
// Allow windowless activation?
|
|
return (m_bSupportWindowlessActivation) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetCapture(void)
|
|
{
|
|
// TODO capture the mouse for the object
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::SetCapture(/* [in] */ BOOL fCapture)
|
|
{
|
|
// TODO capture the mouse for the object
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetFocus(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::SetFocus(/* [in] */ BOOL fFocus)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetDC(/* [in] */ LPCRECT pRect, /* [in] */ DWORD grfFlags, /* [out] */ HDC __RPC_FAR *phDC)
|
|
{
|
|
if (phDC == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Can't do nested painting
|
|
if (m_hDCBuffer != NULL)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
m_rcBuffer = m_rcObjectPos;
|
|
if (pRect != NULL)
|
|
{
|
|
m_rcBuffer = *pRect;
|
|
}
|
|
|
|
m_hBMBuffer = NULL;
|
|
m_dwBufferFlags = grfFlags;
|
|
|
|
// See if the control wants a DC that is onscreen or offscreen
|
|
if (m_dwBufferFlags & OLEDC_OFFSCREEN)
|
|
{
|
|
m_hDCBuffer = CreateCompatibleDC(NULL);
|
|
if (m_hDCBuffer == NULL)
|
|
{
|
|
// Error
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
long cx = m_rcBuffer.right - m_rcBuffer.left;
|
|
long cy = m_rcBuffer.bottom - m_rcBuffer.top;
|
|
|
|
m_hBMBuffer = CreateCompatibleBitmap(m_hDCBuffer, cx, cy);
|
|
m_hBMBufferOld = (HBITMAP) SelectObject(m_hDCBuffer, m_hBMBuffer);
|
|
SetViewportOrgEx(m_hDCBuffer, m_rcBuffer.left, m_rcBuffer.top, NULL);
|
|
|
|
// TODO When OLEDC_PAINTBKGND we must draw every site behind this one
|
|
}
|
|
else
|
|
{
|
|
// TODO When OLEDC_PAINTBKGND we must draw every site behind this one
|
|
|
|
// Get the window DC
|
|
m_hDCBuffer = GetWindowDC(m_hWndParent);
|
|
if (m_hDCBuffer == NULL)
|
|
{
|
|
// Error
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Clip the control so it can't trash anywhere it isn't allowed to draw
|
|
if (!(m_dwBufferFlags & OLEDC_NODRAW))
|
|
{
|
|
m_hRgnBuffer = CreateRectRgnIndirect(&m_rcBuffer);
|
|
|
|
// TODO Clip out opaque areas of sites behind this one
|
|
|
|
SelectClipRgn(m_hDCBuffer, m_hRgnBuffer);
|
|
}
|
|
}
|
|
|
|
*phDC = m_hDCBuffer;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::ReleaseDC(/* [in] */ HDC hDC)
|
|
{
|
|
// Release the DC
|
|
if (hDC == NULL || hDC != m_hDCBuffer)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Test if the DC was offscreen or onscreen
|
|
if ((m_dwBufferFlags & OLEDC_OFFSCREEN) &&
|
|
!(m_dwBufferFlags & OLEDC_NODRAW))
|
|
{
|
|
// BitBlt the buffer into the control's object
|
|
SetViewportOrgEx(m_hDCBuffer, 0, 0, NULL);
|
|
HDC hdc = GetWindowDC(m_hWndParent);
|
|
|
|
long cx = m_rcBuffer.right - m_rcBuffer.left;
|
|
long cy = m_rcBuffer.bottom - m_rcBuffer.top;
|
|
|
|
BitBlt(hdc, m_rcBuffer.left, m_rcBuffer.top, cx, cy, m_hDCBuffer, 0, 0, SRCCOPY);
|
|
|
|
::ReleaseDC(m_hWndParent, hdc);
|
|
}
|
|
else
|
|
{
|
|
// TODO If OLEDC_PAINTBKGND is set draw the DVASPECT_CONTENT of every object above this one
|
|
}
|
|
|
|
// Clean up settings ready for next drawing
|
|
if (m_hRgnBuffer)
|
|
{
|
|
SelectClipRgn(m_hDCBuffer, NULL);
|
|
DeleteObject(m_hRgnBuffer);
|
|
m_hRgnBuffer = NULL;
|
|
}
|
|
|
|
SelectObject(m_hDCBuffer, m_hBMBufferOld);
|
|
if (m_hBMBuffer)
|
|
{
|
|
DeleteObject(m_hBMBuffer);
|
|
m_hBMBuffer = NULL;
|
|
}
|
|
|
|
// Delete the DC
|
|
if (m_dwBufferFlags & OLEDC_OFFSCREEN)
|
|
{
|
|
::DeleteDC(m_hDCBuffer);
|
|
}
|
|
else
|
|
{
|
|
::ReleaseDC(m_hWndParent, m_hDCBuffer);
|
|
}
|
|
m_hDCBuffer = NULL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::InvalidateRect(/* [in] */ LPCRECT pRect, /* [in] */ BOOL fErase)
|
|
{
|
|
// Clip the rectangle against the object's size and invalidate it
|
|
RECT rcI = { 0, 0, 0, 0 };
|
|
if (pRect == NULL)
|
|
{
|
|
rcI = m_rcObjectPos;
|
|
}
|
|
else
|
|
{
|
|
IntersectRect(&rcI, &m_rcObjectPos, pRect);
|
|
}
|
|
::InvalidateRect(m_hWndParent, &rcI, fErase);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::InvalidateRgn(/* [in] */ HRGN hRGN, /* [in] */ BOOL fErase)
|
|
{
|
|
if (hRGN == NULL)
|
|
{
|
|
::InvalidateRect(m_hWndParent, &m_rcObjectPos, fErase);
|
|
}
|
|
else
|
|
{
|
|
// Clip the region with the object's bounding area
|
|
HRGN hrgnClip = CreateRectRgnIndirect(&m_rcObjectPos);
|
|
if (CombineRgn(hrgnClip, hrgnClip, hRGN, RGN_AND) != ERROR)
|
|
{
|
|
::InvalidateRgn(m_hWndParent, hrgnClip, fErase);
|
|
}
|
|
DeleteObject(hrgnClip);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::ScrollRect(/* [in] */ INT dx, /* [in] */ INT dy, /* [in] */ LPCRECT pRectScroll, /* [in] */ LPCRECT pRectClip)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::AdjustRect(/* [out][in] */ LPRECT prc)
|
|
{
|
|
if (prc == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Clip the rectangle against the object position
|
|
RECT rcI = { 0, 0, 0, 0 };
|
|
IntersectRect(&rcI, &m_rcObjectPos, prc);
|
|
*prc = rcI;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnDefWindowMessage(/* [in] */ UINT msg, /* [in] */ WPARAM wParam, /* [in] */ LPARAM lParam, /* [out] */ LRESULT __RPC_FAR *plResult)
|
|
{
|
|
if (plResult == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Pass the message to the windowless control
|
|
if (m_bWindowless && m_spIOleInPlaceObjectWindowless)
|
|
{
|
|
return m_spIOleInPlaceObjectWindowless->OnWindowMessage(msg, wParam, lParam, plResult);
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IOleControlSite implementation
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnControlInfoChanged(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::LockInPlaceActive(/* [in] */ BOOL fLock)
|
|
{
|
|
m_bInPlaceLocked = fLock;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::GetExtendedControl(/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::TransformCoords(/* [out][in] */ POINTL __RPC_FAR *pPtlHimetric, /* [out][in] */ POINTF __RPC_FAR *pPtfContainer, /* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pPtlHimetric == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
if (pPtfContainer == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HDC hdc = ::GetDC(m_hWndParent);
|
|
::SetMapMode(hdc, MM_HIMETRIC);
|
|
POINT rgptConvert[2];
|
|
rgptConvert[0].x = 0;
|
|
rgptConvert[0].y = 0;
|
|
|
|
if (dwFlags & XFORMCOORDS_HIMETRICTOCONTAINER)
|
|
{
|
|
rgptConvert[1].x = pPtlHimetric->x;
|
|
rgptConvert[1].y = pPtlHimetric->y;
|
|
::LPtoDP(hdc, rgptConvert, 2);
|
|
if (dwFlags & XFORMCOORDS_SIZE)
|
|
{
|
|
pPtfContainer->x = (float)(rgptConvert[1].x - rgptConvert[0].x);
|
|
pPtfContainer->y = (float)(rgptConvert[0].y - rgptConvert[1].y);
|
|
}
|
|
else if (dwFlags & XFORMCOORDS_POSITION)
|
|
{
|
|
pPtfContainer->x = (float)rgptConvert[1].x;
|
|
pPtfContainer->y = (float)rgptConvert[1].y;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else if (dwFlags & XFORMCOORDS_CONTAINERTOHIMETRIC)
|
|
{
|
|
rgptConvert[1].x = (int)(pPtfContainer->x);
|
|
rgptConvert[1].y = (int)(pPtfContainer->y);
|
|
::DPtoLP(hdc, rgptConvert, 2);
|
|
if (dwFlags & XFORMCOORDS_SIZE)
|
|
{
|
|
pPtlHimetric->x = rgptConvert[1].x - rgptConvert[0].x;
|
|
pPtlHimetric->y = rgptConvert[0].y - rgptConvert[1].y;
|
|
}
|
|
else if (dwFlags & XFORMCOORDS_POSITION)
|
|
{
|
|
pPtlHimetric->x = rgptConvert[1].x;
|
|
pPtlHimetric->y = rgptConvert[1].y;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
::ReleaseDC(m_hWndParent, hdc);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::TranslateAccelerator(/* [in] */ MSG __RPC_FAR *pMsg, /* [in] */ DWORD grfModifiers)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CControlSite::OnFocus(/* [in] */ BOOL fGotFocus)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|