Back to index

lightning-sunbird  0.9+nobinonly
ControlSite.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Adam Lock <adamlock@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "StdAfx.h"
00040 
00041 #include <Objsafe.h>
00042 
00043 #include "ControlSite.h"
00044 #include "PropertyBag.h"
00045 #include "ControlSiteIPFrame.h"
00046 
00047 class CDefaultControlSiteSecurityPolicy : public CControlSiteSecurityPolicy
00048 {
00049     // Test if the specified class id implements the specified category
00050     BOOL ClassImplementsCategory(const CLSID & clsid, const CATID &catid, BOOL &bClassExists);
00051 public:
00052     // Test if the class is safe to host
00053     virtual BOOL IsClassSafeToHost(const CLSID & clsid);
00054     // Test if the specified class is marked safe for scripting
00055     virtual BOOL IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists);
00056     // Test if the instantiated object is safe for scripting on the specified interface
00057     virtual BOOL IsObjectSafeForScripting(IUnknown *pObject, const IID &iid);
00058 };
00059 
00060 BOOL
00061 CDefaultControlSiteSecurityPolicy::ClassImplementsCategory(const CLSID &clsid, const CATID &catid, BOOL &bClassExists)
00062 {
00063     bClassExists = FALSE;
00064 
00065     // Test if there is a CLSID entry. If there isn't then obviously
00066     // the object doesn't exist and therefore doesn't implement any category.
00067     // In this situation, the function returns REGDB_E_CLASSNOTREG.
00068 
00069     CRegKey key;
00070     if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) != ERROR_SUCCESS)
00071     {
00072         // Must fail if we can't even open this!
00073         return FALSE;
00074     }
00075     LPOLESTR szCLSID = NULL;
00076     if (FAILED(StringFromCLSID(clsid, &szCLSID)))
00077     {
00078         return FALSE;
00079     }
00080     USES_CONVERSION;
00081     CRegKey keyCLSID;
00082     LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
00083     CoTaskMemFree(szCLSID);
00084     if (lResult != ERROR_SUCCESS)
00085     {
00086         // Class doesn't exist
00087         return FALSE;
00088     }
00089     keyCLSID.Close();
00090 
00091     // CLSID exists, so try checking what categories it implements
00092     bClassExists = TRUE;
00093     CComQIPtr<ICatInformation> spCatInfo;
00094     HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, (LPVOID*) &spCatInfo);
00095     if (spCatInfo == NULL)
00096     {
00097         // Must fail if we can't open the category manager
00098         return FALSE;
00099     }
00100     
00101     // See what categories the class implements
00102     CComQIPtr<IEnumCATID> spEnumCATID;
00103     if (FAILED(spCatInfo->EnumImplCategoriesOfClass(clsid, &spEnumCATID)))
00104     {
00105         // Can't enumerate classes in category so fail
00106         return FALSE;
00107     }
00108 
00109     // Search for matching categories
00110     BOOL bFound = FALSE;
00111     CATID catidNext = GUID_NULL;
00112     while (spEnumCATID->Next(1, &catidNext, NULL) == S_OK)
00113     {
00114         if (::IsEqualCATID(catid, catidNext))
00115         {
00116             return TRUE;
00117         }
00118     }
00119     return FALSE;
00120 }
00121 
00122 // Test if the class is safe to host
00123 BOOL CDefaultControlSiteSecurityPolicy::IsClassSafeToHost(const CLSID & clsid)
00124 {
00125     return TRUE;
00126 }
00127 
00128 // Test if the specified class is marked safe for scripting
00129 BOOL CDefaultControlSiteSecurityPolicy::IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists)
00130 {
00131     // Test the category the object belongs to
00132     return ClassImplementsCategory(clsid, CATID_SafeForScripting, bClassExists);
00133 }
00134 
00135 // Test if the instantiated object is safe for scripting on the specified interface
00136 BOOL CDefaultControlSiteSecurityPolicy::IsObjectSafeForScripting(IUnknown *pObject, const IID &iid)
00137 {
00138     if (!pObject) {
00139         return FALSE;
00140     }
00141     // Ask the control if its safe for scripting
00142     CComQIPtr<IObjectSafety> spObjectSafety = pObject;
00143     if (!spObjectSafety)
00144     {
00145         return FALSE;
00146     }
00147 
00148     DWORD dwSupported = 0; // Supported options (mask)
00149     DWORD dwEnabled = 0; // Enabled options
00150 
00151     // Assume scripting via IDispatch
00152     if (FAILED(spObjectSafety->GetInterfaceSafetyOptions(
00153             iid, &dwSupported, &dwEnabled)))
00154     {
00155         // Interface is not safe or failure.
00156         return FALSE;
00157     }
00158 
00159     // Test if safe for scripting
00160     if (!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
00161     {
00162         // Object says it is not set to be safe, but supports unsafe calling,
00163         // try enabling it and asking again.
00164 
00165         if(!(dwSupported & INTERFACESAFE_FOR_UNTRUSTED_CALLER) ||
00166             FAILED(spObjectSafety->SetInterfaceSafetyOptions(
00167                iid, INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER)) ||
00168             FAILED(spObjectSafety->GetInterfaceSafetyOptions(
00169                 iid, &dwSupported, &dwEnabled)) ||
00170             !(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
00171         {
00172             return FALSE;
00173         }
00174     }
00175 
00176     return TRUE;
00177 }
00178 
00180 
00181 // Constructor
00182 CControlSite::CControlSite()
00183 {
00184     TRACE_METHOD(CControlSite::CControlSite);
00185 
00186     m_hWndParent = NULL;
00187     m_CLSID = CLSID_NULL;
00188     m_bSetClientSiteFirst = FALSE;
00189     m_bVisibleAtRuntime = TRUE;
00190     memset(&m_rcObjectPos, 0, sizeof(m_rcObjectPos));
00191 
00192     m_bInPlaceActive = FALSE;
00193     m_bUIActive = FALSE;
00194     m_bInPlaceLocked = FALSE;
00195     m_bWindowless = FALSE;
00196     m_bSupportWindowlessActivation = TRUE;
00197     m_bSafeForScriptingObjectsOnly = FALSE;
00198     m_pSecurityPolicy = GetDefaultControlSecurityPolicy();
00199 
00200     // Initialise ambient properties
00201     m_nAmbientLocale = 0;
00202     m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
00203     m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
00204     m_bAmbientUserMode = true;
00205     m_bAmbientShowHatching = true;
00206     m_bAmbientShowGrabHandles = true;
00207     m_bAmbientAppearance = true; // 3d
00208 
00209     // Windowless variables
00210     m_hDCBuffer = NULL;
00211     m_hRgnBuffer = NULL;
00212     m_hBMBufferOld = NULL;
00213     m_hBMBuffer = NULL;
00214 }
00215 
00216 
00217 // Destructor
00218 CControlSite::~CControlSite()
00219 {
00220     TRACE_METHOD(CControlSite::~CControlSite);
00221     Detach();
00222 }
00223 
00224 // Create the specified control, optionally providing properties to initialise
00225 // it with and a name.
00226 HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
00227     LPCWSTR szCodebase, IBindCtx *pBindContext)
00228 {
00229     TRACE_METHOD(CControlSite::Create);
00230 
00231     m_CLSID = clsid;
00232     m_ParameterList = pl;
00233 
00234     // See if security policy will allow the control to be hosted
00235     if (m_pSecurityPolicy && !m_pSecurityPolicy->IsClassSafeToHost(clsid))
00236     {
00237         return E_FAIL;
00238     }
00239 
00240     // See if object is script safe
00241     BOOL checkForObjectSafety = FALSE;
00242     if (m_pSecurityPolicy && m_bSafeForScriptingObjectsOnly)
00243     {
00244         BOOL bClassExists = FALSE;
00245         BOOL bIsSafe = m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
00246         if (!bClassExists && szCodebase)
00247         {
00248             // Class doesn't exist, so allow code below to fetch it
00249         }
00250         else if (!bIsSafe)
00251         {
00252             // The class is not flagged as safe for scripting, so
00253             // we'll have to create it to ask it if its safe.
00254             checkForObjectSafety = TRUE;
00255         }
00256     }
00257 
00258     // Create the object
00259     CComPtr<IUnknown> spObject;
00260     HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &spObject);
00261     if (SUCCEEDED(hr) && checkForObjectSafety)
00262     {
00263         // Assume scripting via IDispatch
00264         if (!m_pSecurityPolicy->IsObjectSafeForScripting(spObject, __uuidof(IDispatch)))
00265         {
00266             return E_FAIL;
00267         }
00268         // Drop through, success!
00269     }
00270 
00271     // Do we need to download the control?
00272     if (FAILED(hr) && szCodebase)
00273     {
00274         wchar_t *szURL = NULL;
00275 
00276         // Test if the code base ends in #version=a,b,c,d
00277         DWORD dwFileVersionMS = 0xffffffff;
00278         DWORD dwFileVersionLS = 0xffffffff;
00279         const wchar_t *szHash = wcsrchr(szCodebase, wchar_t('#'));
00280         if (szHash)
00281         {
00282             if (wcsnicmp(szHash, L"#version=", 9) == 0)
00283             {
00284                 int a, b, c, d;
00285                 if (swscanf(szHash + 9, L"%d,%d,%d,%d", &a, &b, &c, &d) == 4)
00286                 {
00287                     dwFileVersionMS = MAKELONG(b,a);
00288                     dwFileVersionLS = MAKELONG(d,c);
00289                 }
00290             }
00291             szURL = _wcsdup(szCodebase);
00292             // Terminate at the hash mark
00293             if (szURL)
00294                 szURL[szHash - szCodebase] = wchar_t('\0');
00295         }
00296         else
00297         {
00298             szURL = _wcsdup(szCodebase);
00299         }
00300         if (!szURL)
00301             return E_OUTOFMEMORY;
00302 
00303         CComPtr<IBindCtx> spBindContext; 
00304         CComPtr<IBindStatusCallback> spBindStatusCallback;
00305         CComPtr<IBindStatusCallback> spOldBSC;
00306 
00307         // Create our own bind context or use the one provided?
00308         BOOL useInternalBSC = FALSE;
00309         if (!pBindContext)
00310         {
00311             useInternalBSC = TRUE;
00312             hr = CreateBindCtx(0, &spBindContext);
00313             if (FAILED(hr))
00314             {
00315                 free(szURL);
00316                 return hr;
00317             }
00318             spBindStatusCallback = dynamic_cast<IBindStatusCallback *>(this);
00319             hr = RegisterBindStatusCallback(spBindContext, spBindStatusCallback, &spOldBSC, 0);
00320             if (FAILED(hr))
00321             {
00322                 free(szURL);
00323                 return hr;
00324             }
00325         }
00326         else
00327         {
00328             spBindContext = pBindContext;
00329         }
00330 
00331         hr = CoGetClassObjectFromURL(clsid, szURL, dwFileVersionMS, dwFileVersionLS,
00332             NULL, spBindContext, CLSCTX_ALL, NULL, IID_IUnknown, (void **) &m_spObject);
00333         
00334         free(szURL);
00335         
00336         // Handle the internal binding synchronously so the object exists
00337         // or an error code is available when the method returns.
00338         if (useInternalBSC)
00339         {
00340             if (MK_S_ASYNCHRONOUS == hr)
00341             {
00342                 m_bBindingInProgress = TRUE;
00343                 m_hrBindResult = E_FAIL;
00344 
00345                 // Spin around waiting for binding to complete
00346                 HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00347                 while (m_bBindingInProgress)
00348                 {
00349                     MSG msg;
00350                     // Process pending messages
00351                     while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
00352                     {
00353                         if (!::GetMessage(&msg, NULL, 0, 0))
00354                         {
00355                             m_bBindingInProgress = FALSE;
00356                             break;
00357                         }
00358                         ::TranslateMessage(&msg);
00359                         ::DispatchMessage(&msg);
00360                     }
00361                     if (!m_bBindingInProgress)
00362                         break;
00363                     // Sleep for a bit or the next msg to appear
00364                     ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS);
00365                 }
00366                 ::CloseHandle(hFakeEvent);
00367 
00368                 // Set the result
00369                 hr = m_hrBindResult;
00370             }
00371 
00372             // Destroy the bind status callback & context
00373             if (spBindStatusCallback)
00374             {
00375                 RevokeBindStatusCallback(spBindContext, spBindStatusCallback);
00376                 spBindContext.Release();
00377             }
00378         }
00379     }
00380 
00381     if (spObject)
00382         m_spObject = spObject;
00383 
00384     return hr;
00385 }
00386 
00387 
00388 // Attach the created control to a window and activate it
00389 HRESULT CControlSite::Attach(HWND hwndParent, const RECT &rcPos, IUnknown *pInitStream)
00390 {
00391     TRACE_METHOD(CControlSite::Attach);
00392 
00393     if (hwndParent == NULL)
00394     {
00395         NS_ASSERTION(0, "No parent hwnd");
00396         return E_INVALIDARG;
00397     }
00398 
00399     m_hWndParent = hwndParent;
00400     m_rcObjectPos = rcPos;
00401 
00402     // Object must have been created
00403     if (m_spObject == NULL)
00404     {
00405         return E_UNEXPECTED;
00406     }
00407 
00408     m_spIViewObject = m_spObject;
00409     m_spIOleObject = m_spObject;
00410     
00411     if (m_spIOleObject == NULL)
00412     {
00413         return E_FAIL;
00414     }
00415     
00416     DWORD dwMiscStatus;
00417     m_spIOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
00418 
00419     if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
00420     {
00421         m_bSetClientSiteFirst = TRUE;
00422     }
00423     if (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
00424     {
00425         m_bVisibleAtRuntime = FALSE;
00426     }
00427 
00428     // Some objects like to have the client site as the first thing
00429     // to be initialised (for ambient properties and so forth)
00430     if (m_bSetClientSiteFirst)
00431     {
00432         m_spIOleObject->SetClientSite(this);
00433     }
00434 
00435     // If there is a parameter list for the object and no init stream then
00436     // create one here.
00437     CPropertyBagInstance *pPropertyBag = NULL;
00438     if (pInitStream == NULL && m_ParameterList.GetSize() > 0)
00439     {
00440         CPropertyBagInstance::CreateInstance(&pPropertyBag);
00441         pPropertyBag->AddRef();
00442         for (unsigned long i = 0; i < m_ParameterList.GetSize(); i++)
00443         {
00444             pPropertyBag->Write(m_ParameterList.GetNameOf(i),
00445                 const_cast<VARIANT *>(m_ParameterList.GetValueOf(i)));
00446         }
00447         pInitStream = (IPersistPropertyBag *) pPropertyBag;
00448     }
00449 
00450     // Initialise the control from store if one is provided
00451     if (pInitStream)
00452     {
00453         CComQIPtr<IPropertyBag, &IID_IPropertyBag> spPropertyBag = pInitStream;
00454         CComQIPtr<IStream, &IID_IStream> spStream = pInitStream;
00455         CComQIPtr<IPersistStream, &IID_IPersistStream> spIPersistStream = m_spIOleObject;
00456         CComQIPtr<IPersistPropertyBag, &IID_IPersistPropertyBag> spIPersistPropertyBag = m_spIOleObject;
00457 
00458         if (spIPersistPropertyBag && spPropertyBag)
00459         {
00460             spIPersistPropertyBag->Load(spPropertyBag, NULL);
00461         }
00462         else if (spIPersistStream && spStream)
00463         {
00464             spIPersistStream->Load(spStream);
00465         }
00466     }
00467     else
00468     {
00469         // Initialise the object if possible
00470         CComQIPtr<IPersistStreamInit, &IID_IPersistStreamInit> spIPersistStreamInit = m_spIOleObject;
00471         if (spIPersistStreamInit)
00472         {
00473             spIPersistStreamInit->InitNew();
00474         }
00475     }
00476 
00477     m_spIOleInPlaceObject = m_spObject;
00478     m_spIOleInPlaceObjectWindowless = m_spObject;
00479 
00480     m_spIOleInPlaceObject->SetObjectRects(&m_rcObjectPos, &m_rcObjectPos);
00481 
00482     // In-place activate the object
00483     if (m_bVisibleAtRuntime)
00484     {
00485         DoVerb(OLEIVERB_INPLACEACTIVATE);
00486     }
00487 
00488     // For those objects which haven't had their client site set yet,
00489     // it's done here.
00490     if (!m_bSetClientSiteFirst)
00491     {
00492         m_spIOleObject->SetClientSite(this);
00493     }
00494 
00495     return S_OK;
00496 }
00497 
00498 
00499 // Unhook the control from the window and throw it all away
00500 HRESULT CControlSite::Detach()
00501 {
00502     TRACE_METHOD(CControlSite::Detach);
00503 
00504     if (m_spIOleInPlaceObjectWindowless)
00505     {
00506         m_spIOleInPlaceObjectWindowless.Release();
00507     }
00508 
00509     if (m_spIOleInPlaceObject)
00510     {
00511         m_spIOleInPlaceObject->InPlaceDeactivate();
00512         m_spIOleInPlaceObject.Release();
00513     }
00514 
00515     if (m_spIOleObject)
00516     {
00517         m_spIOleObject->Close(OLECLOSE_NOSAVE);
00518         m_spIOleObject->SetClientSite(NULL);
00519         m_spIOleObject.Release();
00520     }
00521 
00522     m_spIViewObject.Release();
00523     m_spObject.Release();
00524     
00525     return S_OK;
00526 }
00527 
00528 
00529 // Return the IUnknown of the contained control
00530 HRESULT CControlSite::GetControlUnknown(IUnknown **ppObject)
00531 {
00532     *ppObject = NULL;
00533     if (m_spObject)
00534     {
00535         m_spObject->QueryInterface(IID_IUnknown, (void **) ppObject);
00536     }
00537     return S_OK;
00538 }
00539 
00540 
00541 // Subscribe to an event sink on the control
00542 HRESULT CControlSite::Advise(IUnknown *pIUnkSink, const IID &iid, DWORD *pdwCookie)
00543 {
00544     if (m_spObject == NULL)
00545     {
00546         return E_UNEXPECTED;
00547     }
00548 
00549     if (pIUnkSink == NULL || pdwCookie == NULL)
00550     {
00551         return E_INVALIDARG;
00552     }
00553 
00554     return AtlAdvise(m_spObject, pIUnkSink, iid, pdwCookie);
00555 }
00556 
00557 
00558 // Unsubscribe event sink from the control
00559 HRESULT CControlSite::Unadvise(const IID &iid, DWORD dwCookie)
00560 {
00561     if (m_spObject == NULL)
00562     {
00563         return E_UNEXPECTED;
00564     }
00565 
00566     return AtlUnadvise(m_spObject, iid, dwCookie);
00567 }
00568 
00569 
00570 // Draw the control
00571 HRESULT CControlSite::Draw(HDC hdc)
00572 {
00573     TRACE_METHOD(CControlSite::Draw);
00574 
00575     // Draw only when control is windowless or deactivated
00576     if (m_spIViewObject)
00577     {
00578         if (m_bWindowless || !m_bInPlaceActive)
00579         {
00580             RECTL *prcBounds = (m_bWindowless) ? NULL : (RECTL *) &m_rcObjectPos;
00581             m_spIViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, prcBounds, NULL, NULL, 0);
00582         }
00583     }
00584     else
00585     {
00586         // Draw something to indicate no control is there
00587         HBRUSH hbr = CreateSolidBrush(RGB(200,200,200));
00588         FillRect(hdc, &m_rcObjectPos, hbr);
00589         DeleteObject(hbr);
00590     }
00591 
00592     return S_OK;
00593 }
00594 
00595 
00596 // Execute the specified verb
00597 HRESULT CControlSite::DoVerb(LONG nVerb, LPMSG lpMsg)
00598 {
00599     TRACE_METHOD(CControlSite::DoVerb);
00600 
00601     if (m_spIOleObject == NULL)
00602     {
00603         return E_FAIL;
00604     }
00605 
00606     return m_spIOleObject->DoVerb(nVerb, lpMsg, this, 0, m_hWndParent, &m_rcObjectPos);
00607 }
00608 
00609 
00610 // Set the position on the control
00611 HRESULT CControlSite::SetPosition(const RECT &rcPos)
00612 {
00613     TRACE_METHOD(CControlSite::SetPosition);
00614     m_rcObjectPos = rcPos;
00615     if (m_spIOleInPlaceObject)
00616     {
00617         m_spIOleInPlaceObject->SetObjectRects(&m_rcObjectPos, &m_rcObjectPos);
00618     }
00619     return S_OK;
00620 }
00621 
00622 
00623 void CControlSite::FireAmbientPropertyChange(DISPID id)
00624 {
00625     if (m_spObject)
00626     {
00627         CComQIPtr<IOleControl> spControl = m_spObject;
00628         if (spControl)
00629         {
00630             spControl->OnAmbientPropertyChange(id);
00631         }
00632     }
00633 }
00634 
00635 
00636 void CControlSite::SetAmbientUserMode(BOOL bUserMode)
00637 {
00638     bool bNewMode = bUserMode ? true : false;
00639     if (m_bAmbientUserMode != bNewMode)
00640     {
00641         m_bAmbientUserMode = bNewMode;
00642         FireAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
00643     }
00644 }
00645 
00647 // CControlSiteSecurityPolicy implementation
00648 
00649 CControlSiteSecurityPolicy *CControlSite::GetDefaultControlSecurityPolicy()
00650 {
00651     static CDefaultControlSiteSecurityPolicy defaultControlSecurityPolicy;
00652     return &defaultControlSecurityPolicy;
00653 }
00654 
00655 // Test if the class is safe to host
00656 BOOL CControlSite::IsClassSafeToHost(const CLSID & clsid)
00657 {
00658     if (m_pSecurityPolicy)
00659         return m_pSecurityPolicy->IsClassSafeToHost(clsid);
00660     return TRUE;
00661 }
00662 
00663 // Test if the specified class is marked safe for scripting
00664 BOOL CControlSite::IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists)
00665 {
00666     if (m_pSecurityPolicy)
00667         return m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
00668     return TRUE;
00669 }
00670 
00671 // Test if the instantiated object is safe for scripting on the specified interface
00672 BOOL CControlSite::IsObjectSafeForScripting(IUnknown *pObject, const IID &iid)
00673 {
00674     if (m_pSecurityPolicy)
00675         return m_pSecurityPolicy->IsObjectSafeForScripting(pObject, iid);
00676     return TRUE;
00677 }
00678 
00679 BOOL CControlSite::IsObjectSafeForScripting(const IID &iid)
00680 {
00681     return IsObjectSafeForScripting(m_spObject, iid);
00682 }
00683 
00685 // IServiceProvider implementation
00686 
00687 HRESULT STDMETHODCALLTYPE CControlSite::QueryService(REFGUID guidService, REFIID riid, void** ppv)
00688 {
00689     if (m_spServiceProvider)
00690         return m_spServiceProvider->QueryService(guidService, riid, ppv);
00691     return E_NOINTERFACE;
00692 }
00693 
00694 
00696 // IDispatch implementation
00697 
00698 
00699 HRESULT STDMETHODCALLTYPE CControlSite::GetTypeInfoCount(/* [out] */ UINT __RPC_FAR *pctinfo)
00700 {
00701     return E_NOTIMPL;
00702 }
00703 
00704 
00705 HRESULT STDMETHODCALLTYPE CControlSite::GetTypeInfo(/* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
00706 {
00707     return E_NOTIMPL;
00708 }
00709 
00710 
00711 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)
00712 {
00713     return E_NOTIMPL;
00714 }
00715 
00716 
00717 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)
00718 {
00719     if (wFlags & DISPATCH_PROPERTYGET)
00720     {
00721         CComVariant vResult;
00722 
00723         switch (dispIdMember)
00724         {
00725         case DISPID_AMBIENT_APPEARANCE:
00726             vResult = CComVariant(m_bAmbientAppearance);
00727             break;
00728 
00729         case DISPID_AMBIENT_FORECOLOR:
00730             vResult = CComVariant((long) m_clrAmbientForeColor);
00731             break;
00732 
00733         case DISPID_AMBIENT_BACKCOLOR:
00734             vResult = CComVariant((long) m_clrAmbientBackColor);
00735             break;
00736 
00737         case DISPID_AMBIENT_LOCALEID:
00738             vResult = CComVariant((long) m_nAmbientLocale);
00739             break;
00740 
00741         case DISPID_AMBIENT_USERMODE:
00742             vResult = CComVariant(m_bAmbientUserMode);
00743             break;
00744         
00745         case DISPID_AMBIENT_SHOWGRABHANDLES:
00746             vResult = CComVariant(m_bAmbientShowGrabHandles);
00747             break;
00748         
00749         case DISPID_AMBIENT_SHOWHATCHING:
00750             vResult = CComVariant(m_bAmbientShowHatching);
00751             break;
00752 
00753         default:
00754             return DISP_E_MEMBERNOTFOUND;
00755         }
00756 
00757         VariantCopy(pVarResult, &vResult);
00758         return S_OK;
00759     }
00760 
00761     return E_FAIL;
00762 }
00763 
00764 
00766 // IAdviseSink implementation
00767 
00768 
00769 void STDMETHODCALLTYPE CControlSite::OnDataChange(/* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc, /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed)
00770 {
00771 }
00772 
00773 
00774 void STDMETHODCALLTYPE CControlSite::OnViewChange(/* [in] */ DWORD dwAspect, /* [in] */ LONG lindex)
00775 {
00776     // Redraw the control
00777     InvalidateRect(NULL, FALSE);
00778 }
00779 
00780 
00781 void STDMETHODCALLTYPE CControlSite::OnRename(/* [in] */ IMoniker __RPC_FAR *pmk)
00782 {
00783 }
00784 
00785 
00786 void STDMETHODCALLTYPE CControlSite::OnSave(void)
00787 {
00788 }
00789 
00790 
00791 void STDMETHODCALLTYPE CControlSite::OnClose(void)
00792 {
00793 }
00794 
00795 
00797 // IAdviseSink2 implementation
00798 
00799 
00800 void STDMETHODCALLTYPE CControlSite::OnLinkSrcChange(/* [unique][in] */ IMoniker __RPC_FAR *pmk)
00801 {
00802 }
00803 
00804 
00806 // IAdviseSinkEx implementation
00807 
00808 
00809 void STDMETHODCALLTYPE CControlSite::OnViewStatusChange(/* [in] */ DWORD dwViewStatus)
00810 {
00811 }
00812 
00813 
00815 // IOleWindow implementation
00816 
00817 HRESULT STDMETHODCALLTYPE CControlSite::GetWindow(/* [out] */ HWND __RPC_FAR *phwnd)
00818 {
00819     *phwnd = m_hWndParent;
00820     return S_OK;
00821 }
00822 
00823 
00824 HRESULT STDMETHODCALLTYPE CControlSite::ContextSensitiveHelp(/* [in] */ BOOL fEnterMode)
00825 {
00826     return S_OK;
00827 }
00828 
00829 
00831 // IOleClientSite implementation
00832 
00833 
00834 HRESULT STDMETHODCALLTYPE CControlSite::SaveObject(void)
00835 {
00836     return S_OK;
00837 }
00838 
00839 
00840 HRESULT STDMETHODCALLTYPE CControlSite::GetMoniker(/* [in] */ DWORD dwAssign, /* [in] */ DWORD dwWhichMoniker, /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk)
00841 {
00842     return E_NOTIMPL;
00843 }
00844 
00845 
00846 HRESULT STDMETHODCALLTYPE CControlSite::GetContainer(/* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer)
00847 {
00848     if (!ppContainer) return E_INVALIDARG;
00849     *ppContainer = m_spContainer;
00850     if (*ppContainer)
00851     {
00852         (*ppContainer)->AddRef();
00853     }
00854     return (*ppContainer) ? S_OK : E_NOINTERFACE;
00855 }
00856 
00857 
00858 HRESULT STDMETHODCALLTYPE CControlSite::ShowObject(void)
00859 {
00860     return S_OK;
00861 }
00862 
00863 
00864 HRESULT STDMETHODCALLTYPE CControlSite::OnShowWindow(/* [in] */ BOOL fShow)
00865 {
00866     return S_OK;
00867 }
00868 
00869 
00870 HRESULT STDMETHODCALLTYPE CControlSite::RequestNewObjectLayout(void)
00871 {
00872     return E_NOTIMPL;
00873 }
00874 
00875 
00877 // IOleInPlaceSite implementation
00878 
00879 
00880 HRESULT STDMETHODCALLTYPE CControlSite::CanInPlaceActivate(void)
00881 {
00882     return S_OK;
00883 }
00884 
00885 
00886 HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceActivate(void)
00887 {
00888     m_bInPlaceActive = TRUE;
00889     return S_OK;
00890 }
00891 
00892 
00893 HRESULT STDMETHODCALLTYPE CControlSite::OnUIActivate(void)
00894 {
00895     m_bUIActive = TRUE;
00896     return S_OK;
00897 }
00898 
00899 
00900 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)
00901 {
00902     *lprcPosRect = m_rcObjectPos;
00903     *lprcClipRect = m_rcObjectPos;
00904 
00905     CControlSiteIPFrameInstance *pIPFrame = NULL;
00906     CControlSiteIPFrameInstance::CreateInstance(&pIPFrame);
00907     pIPFrame->AddRef();
00908 
00909     *ppFrame = (IOleInPlaceFrame *) pIPFrame;
00910     *ppDoc = NULL;
00911 
00912     lpFrameInfo->fMDIApp = FALSE;
00913     lpFrameInfo->hwndFrame = NULL;
00914     lpFrameInfo->haccel = NULL;
00915     lpFrameInfo->cAccelEntries = 0;
00916 
00917     return S_OK;
00918 }
00919 
00920 
00921 HRESULT STDMETHODCALLTYPE CControlSite::Scroll(/* [in] */ SIZE scrollExtant)
00922 {
00923     return S_OK;
00924 }
00925 
00926 
00927 HRESULT STDMETHODCALLTYPE CControlSite::OnUIDeactivate(/* [in] */ BOOL fUndoable)
00928 {
00929     m_bUIActive = FALSE;
00930     return S_OK;
00931 }
00932 
00933 
00934 HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceDeactivate(void)
00935 {
00936     m_bInPlaceActive = FALSE;
00937     return S_OK;
00938 }
00939 
00940 
00941 HRESULT STDMETHODCALLTYPE CControlSite::DiscardUndoState(void)
00942 {
00943     return S_OK;
00944 }
00945 
00946 
00947 HRESULT STDMETHODCALLTYPE CControlSite::DeactivateAndUndo(void)
00948 {
00949     return S_OK;
00950 }
00951 
00952 
00953 HRESULT STDMETHODCALLTYPE CControlSite::OnPosRectChange(/* [in] */ LPCRECT lprcPosRect)
00954 {
00955     if (lprcPosRect == NULL)
00956     {
00957         return E_INVALIDARG;
00958     }
00959     SetPosition(m_rcObjectPos);
00960     return S_OK;
00961 }
00962 
00963 
00965 // IOleInPlaceSiteEx implementation
00966 
00967 
00968 HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceActivateEx(/* [out] */ BOOL __RPC_FAR *pfNoRedraw, /* [in] */ DWORD dwFlags)
00969 {
00970     m_bInPlaceActive = TRUE;
00971 
00972     if (pfNoRedraw)
00973     {
00974         *pfNoRedraw = FALSE;
00975     }
00976     if (dwFlags & ACTIVATE_WINDOWLESS)
00977     {
00978         if (!m_bSupportWindowlessActivation)
00979         {
00980             return E_INVALIDARG;
00981         }
00982         m_bWindowless = TRUE;
00983     }
00984     return S_OK;
00985 }
00986 
00987 
00988 HRESULT STDMETHODCALLTYPE CControlSite::OnInPlaceDeactivateEx(/* [in] */ BOOL fNoRedraw)
00989 {
00990     m_bInPlaceActive = FALSE;
00991     return S_OK;
00992 }
00993 
00994 
00995 HRESULT STDMETHODCALLTYPE CControlSite::RequestUIActivate(void)
00996 {
00997     return S_FALSE;
00998 }
00999 
01000 
01002 // IOleInPlaceSiteWindowless implementation
01003 
01004 
01005 HRESULT STDMETHODCALLTYPE CControlSite::CanWindowlessActivate(void)
01006 {
01007     // Allow windowless activation?
01008     return (m_bSupportWindowlessActivation) ? S_OK : S_FALSE;
01009 }
01010 
01011 
01012 HRESULT STDMETHODCALLTYPE CControlSite::GetCapture(void)
01013 {
01014     // TODO capture the mouse for the object
01015     return S_FALSE;
01016 }
01017 
01018 
01019 HRESULT STDMETHODCALLTYPE CControlSite::SetCapture(/* [in] */ BOOL fCapture)
01020 {
01021     // TODO capture the mouse for the object
01022     return S_FALSE;
01023 }
01024 
01025 
01026 HRESULT STDMETHODCALLTYPE CControlSite::GetFocus(void)
01027 {
01028     return S_OK;
01029 }
01030 
01031 
01032 HRESULT STDMETHODCALLTYPE CControlSite::SetFocus(/* [in] */ BOOL fFocus)
01033 {
01034     return S_OK;
01035 }
01036 
01037 
01038 HRESULT STDMETHODCALLTYPE CControlSite::GetDC(/* [in] */ LPCRECT pRect, /* [in] */ DWORD grfFlags, /* [out] */ HDC __RPC_FAR *phDC)
01039 {
01040     if (phDC == NULL)
01041     {
01042         return E_INVALIDARG;
01043     }
01044 
01045     // Can't do nested painting
01046     if (m_hDCBuffer != NULL)
01047     {
01048         return E_UNEXPECTED;
01049     }
01050 
01051     m_rcBuffer = m_rcObjectPos;
01052     if (pRect != NULL)
01053     {
01054         m_rcBuffer = *pRect;
01055     }
01056 
01057     m_hBMBuffer = NULL;
01058     m_dwBufferFlags = grfFlags;
01059 
01060     // See if the control wants a DC that is onscreen or offscreen
01061     if (m_dwBufferFlags & OLEDC_OFFSCREEN)
01062     {
01063         m_hDCBuffer = CreateCompatibleDC(NULL);
01064         if (m_hDCBuffer == NULL)
01065         {
01066             // Error
01067             return E_OUTOFMEMORY;
01068         }
01069 
01070         long cx = m_rcBuffer.right - m_rcBuffer.left;
01071         long cy = m_rcBuffer.bottom - m_rcBuffer.top;
01072 
01073         m_hBMBuffer = CreateCompatibleBitmap(m_hDCBuffer, cx, cy);
01074         m_hBMBufferOld = (HBITMAP) SelectObject(m_hDCBuffer, m_hBMBuffer);
01075         SetViewportOrgEx(m_hDCBuffer, m_rcBuffer.left, m_rcBuffer.top, NULL);
01076 
01077         // TODO When OLEDC_PAINTBKGND we must draw every site behind this one
01078     }
01079     else
01080     {
01081         // TODO When OLEDC_PAINTBKGND we must draw every site behind this one
01082 
01083         // Get the window DC
01084         m_hDCBuffer = GetWindowDC(m_hWndParent);
01085         if (m_hDCBuffer == NULL)
01086         {
01087             // Error
01088             return E_OUTOFMEMORY;
01089         }
01090 
01091         // Clip the control so it can't trash anywhere it isn't allowed to draw
01092         if (!(m_dwBufferFlags & OLEDC_NODRAW))
01093         {
01094             m_hRgnBuffer = CreateRectRgnIndirect(&m_rcBuffer);
01095 
01096             // TODO Clip out opaque areas of sites behind this one
01097 
01098             SelectClipRgn(m_hDCBuffer, m_hRgnBuffer);
01099         }
01100     }
01101 
01102     *phDC = m_hDCBuffer;
01103 
01104     return S_OK;
01105 }
01106 
01107 
01108 HRESULT STDMETHODCALLTYPE CControlSite::ReleaseDC(/* [in] */ HDC hDC)
01109 {
01110     // Release the DC
01111     if (hDC == NULL || hDC != m_hDCBuffer)
01112     {
01113         return E_INVALIDARG;
01114     }
01115 
01116     // Test if the DC was offscreen or onscreen
01117     if ((m_dwBufferFlags & OLEDC_OFFSCREEN) &&
01118         !(m_dwBufferFlags & OLEDC_NODRAW))
01119     {
01120         // BitBlt the buffer into the control's object
01121         SetViewportOrgEx(m_hDCBuffer, 0, 0, NULL);
01122         HDC hdc = GetWindowDC(m_hWndParent);
01123 
01124         long cx = m_rcBuffer.right - m_rcBuffer.left;
01125         long cy = m_rcBuffer.bottom - m_rcBuffer.top;
01126 
01127         BitBlt(hdc, m_rcBuffer.left, m_rcBuffer.top, cx, cy, m_hDCBuffer, 0, 0, SRCCOPY);
01128         
01129         ::ReleaseDC(m_hWndParent, hdc);
01130     }
01131     else
01132     {
01133         // TODO If OLEDC_PAINTBKGND is set draw the DVASPECT_CONTENT of every object above this one
01134     }
01135 
01136     // Clean up settings ready for next drawing
01137     if (m_hRgnBuffer)
01138     {
01139         SelectClipRgn(m_hDCBuffer, NULL);
01140         DeleteObject(m_hRgnBuffer);
01141         m_hRgnBuffer = NULL;
01142     }
01143     
01144     SelectObject(m_hDCBuffer, m_hBMBufferOld);
01145     if (m_hBMBuffer)
01146     {
01147         DeleteObject(m_hBMBuffer);
01148         m_hBMBuffer = NULL;
01149     }
01150 
01151     // Delete the DC
01152     if (m_dwBufferFlags & OLEDC_OFFSCREEN)
01153     {
01154         ::DeleteDC(m_hDCBuffer);
01155     }
01156     else
01157     {
01158         ::ReleaseDC(m_hWndParent, m_hDCBuffer);
01159     }
01160     m_hDCBuffer = NULL;
01161 
01162     return S_OK;
01163 }
01164 
01165 
01166 HRESULT STDMETHODCALLTYPE CControlSite::InvalidateRect(/* [in] */ LPCRECT pRect, /* [in] */ BOOL fErase)
01167 {
01168     // Clip the rectangle against the object's size and invalidate it
01169     RECT rcI = { 0, 0, 0, 0 };
01170     if (pRect == NULL)
01171     {
01172         rcI = m_rcObjectPos;
01173     }
01174     else
01175     {
01176         IntersectRect(&rcI, &m_rcObjectPos, pRect);
01177     }
01178     ::InvalidateRect(m_hWndParent, &rcI, fErase);
01179 
01180     return S_OK;
01181 }
01182 
01183 HRESULT STDMETHODCALLTYPE CControlSite::InvalidateRgn(/* [in] */ HRGN hRGN, /* [in] */ BOOL fErase)
01184 {
01185     if (hRGN == NULL)
01186     {
01187         ::InvalidateRect(m_hWndParent, &m_rcObjectPos, fErase);
01188     }
01189     else
01190     {
01191         // Clip the region with the object's bounding area
01192         HRGN hrgnClip = CreateRectRgnIndirect(&m_rcObjectPos);
01193         if (CombineRgn(hrgnClip, hrgnClip, hRGN, RGN_AND) != ERROR)
01194         {
01195             ::InvalidateRgn(m_hWndParent, hrgnClip, fErase);
01196         }
01197         DeleteObject(hrgnClip);
01198     }
01199 
01200     return S_OK;
01201 }
01202 
01203 HRESULT STDMETHODCALLTYPE CControlSite::ScrollRect(/* [in] */ INT dx, /* [in] */ INT dy, /* [in] */ LPCRECT pRectScroll, /* [in] */ LPCRECT pRectClip)
01204 {
01205     return S_OK;
01206 }
01207 
01208 HRESULT STDMETHODCALLTYPE CControlSite::AdjustRect(/* [out][in] */ LPRECT prc)
01209 {
01210     if (prc == NULL)
01211     {
01212         return E_INVALIDARG;
01213     }
01214 
01215     // Clip the rectangle against the object position
01216     RECT rcI = { 0, 0, 0, 0 };
01217     IntersectRect(&rcI, &m_rcObjectPos, prc);
01218     *prc = rcI;
01219     return S_OK;
01220 }
01221 
01222 HRESULT STDMETHODCALLTYPE CControlSite::OnDefWindowMessage(/* [in] */ UINT msg, /* [in] */ WPARAM wParam, /* [in] */ LPARAM lParam, /* [out] */ LRESULT __RPC_FAR *plResult)
01223 {
01224     if (plResult == NULL)
01225     {
01226         return E_INVALIDARG;
01227     }
01228     
01229     // Pass the message to the windowless control
01230     if (m_bWindowless && m_spIOleInPlaceObjectWindowless)
01231     {
01232         return m_spIOleInPlaceObjectWindowless->OnWindowMessage(msg, wParam, lParam, plResult);
01233     }
01234 
01235     return S_FALSE;
01236 }
01237 
01238 
01240 // IOleControlSite implementation
01241 
01242 
01243 HRESULT STDMETHODCALLTYPE CControlSite::OnControlInfoChanged(void)
01244 {
01245     return S_OK;
01246 }
01247 
01248 
01249 HRESULT STDMETHODCALLTYPE CControlSite::LockInPlaceActive(/* [in] */ BOOL fLock)
01250 {
01251     m_bInPlaceLocked = fLock;
01252     return S_OK;
01253 }
01254 
01255 
01256 HRESULT STDMETHODCALLTYPE CControlSite::GetExtendedControl(/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp)
01257 {
01258     return E_NOTIMPL;
01259 }
01260 
01261 
01262 HRESULT STDMETHODCALLTYPE CControlSite::TransformCoords(/* [out][in] */ POINTL __RPC_FAR *pPtlHimetric, /* [out][in] */ POINTF __RPC_FAR *pPtfContainer, /* [in] */ DWORD dwFlags)
01263 {
01264     HRESULT hr = S_OK;
01265 
01266     if (pPtlHimetric == NULL)
01267     {
01268         return E_INVALIDARG;
01269     }
01270     if (pPtfContainer == NULL)
01271     {
01272         return E_INVALIDARG;
01273     }
01274 
01275     HDC hdc = ::GetDC(m_hWndParent);
01276     ::SetMapMode(hdc, MM_HIMETRIC);
01277     POINT rgptConvert[2];
01278     rgptConvert[0].x = 0;
01279     rgptConvert[0].y = 0;
01280 
01281     if (dwFlags & XFORMCOORDS_HIMETRICTOCONTAINER)
01282     {
01283         rgptConvert[1].x = pPtlHimetric->x;
01284         rgptConvert[1].y = pPtlHimetric->y;
01285         ::LPtoDP(hdc, rgptConvert, 2);
01286         if (dwFlags & XFORMCOORDS_SIZE)
01287         {
01288             pPtfContainer->x = (float)(rgptConvert[1].x - rgptConvert[0].x);
01289             pPtfContainer->y = (float)(rgptConvert[0].y - rgptConvert[1].y);
01290         }
01291         else if (dwFlags & XFORMCOORDS_POSITION)
01292         {
01293             pPtfContainer->x = (float)rgptConvert[1].x;
01294             pPtfContainer->y = (float)rgptConvert[1].y;
01295         }
01296         else
01297         {
01298             hr = E_INVALIDARG;
01299         }
01300     }
01301     else if (dwFlags & XFORMCOORDS_CONTAINERTOHIMETRIC)
01302     {
01303         rgptConvert[1].x = (int)(pPtfContainer->x);
01304         rgptConvert[1].y = (int)(pPtfContainer->y);
01305         ::DPtoLP(hdc, rgptConvert, 2);
01306         if (dwFlags & XFORMCOORDS_SIZE)
01307         {
01308             pPtlHimetric->x = rgptConvert[1].x - rgptConvert[0].x;
01309             pPtlHimetric->y = rgptConvert[0].y - rgptConvert[1].y;
01310         }
01311         else if (dwFlags & XFORMCOORDS_POSITION)
01312         {
01313             pPtlHimetric->x = rgptConvert[1].x;
01314             pPtlHimetric->y = rgptConvert[1].y;
01315         }
01316         else
01317         {
01318             hr = E_INVALIDARG;
01319         }
01320     }
01321     else
01322     {
01323         hr = E_INVALIDARG;
01324     }
01325 
01326     ::ReleaseDC(m_hWndParent, hdc);
01327 
01328     return hr;
01329 }
01330 
01331 
01332 HRESULT STDMETHODCALLTYPE CControlSite::TranslateAccelerator(/* [in] */ MSG __RPC_FAR *pMsg, /* [in] */ DWORD grfModifiers)
01333 {
01334     return E_NOTIMPL;
01335 }
01336 
01337 
01338 HRESULT STDMETHODCALLTYPE CControlSite::OnFocus(/* [in] */ BOOL fGotFocus)
01339 {
01340     return S_OK;
01341 }
01342 
01343 
01344 HRESULT STDMETHODCALLTYPE CControlSite::ShowPropertyFrame(void)
01345 {
01346     return E_NOTIMPL;
01347 }
01348 
01350 // IBindStatusCallback implementation
01351 
01352 HRESULT STDMETHODCALLTYPE CControlSite::OnStartBinding(DWORD dwReserved, 
01353                                                        IBinding __RPC_FAR *pib)
01354 {
01355     return S_OK;
01356 }
01357 
01358 HRESULT STDMETHODCALLTYPE CControlSite::GetPriority(LONG __RPC_FAR *pnPriority)
01359 {
01360     return S_OK;
01361 }
01362     
01363 HRESULT STDMETHODCALLTYPE CControlSite::OnLowResource(DWORD reserved)
01364 {
01365     return S_OK;
01366 }
01367     
01368 HRESULT STDMETHODCALLTYPE CControlSite::OnProgress(ULONG ulProgress, 
01369                                         ULONG ulProgressMax, 
01370                                         ULONG ulStatusCode, 
01371                                         LPCWSTR szStatusText)
01372 {
01373     return S_OK;
01374 }
01375 
01376 HRESULT STDMETHODCALLTYPE CControlSite::OnStopBinding(HRESULT hresult, LPCWSTR szError)
01377 {
01378     m_bBindingInProgress = FALSE;
01379     m_hrBindResult = hresult;
01380     return S_OK;
01381 }
01382     
01383 HRESULT STDMETHODCALLTYPE CControlSite::GetBindInfo(DWORD __RPC_FAR *pgrfBINDF, 
01384                                                     BINDINFO __RPC_FAR *pbindInfo)
01385 {
01386     *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
01387                  BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
01388     pbindInfo->cbSize = sizeof(BINDINFO);
01389     pbindInfo->szExtraInfo = NULL;
01390     memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
01391     pbindInfo->grfBindInfoF = 0;
01392     pbindInfo->dwBindVerb = 0;
01393     pbindInfo->szCustomVerb = NULL;
01394     return S_OK;
01395 }
01396     
01397 HRESULT STDMETHODCALLTYPE CControlSite::OnDataAvailable(DWORD grfBSCF, 
01398                                                         DWORD dwSize, 
01399                                                         FORMATETC __RPC_FAR *pformatetc, 
01400                                                         STGMEDIUM __RPC_FAR *pstgmed)
01401 {
01402     return E_NOTIMPL;
01403 }
01404   
01405 HRESULT STDMETHODCALLTYPE CControlSite::OnObjectAvailable(REFIID riid, 
01406                                                           IUnknown __RPC_FAR *punk)
01407 {
01408     return S_OK;
01409 }
01410 
01411 // IWindowForBindingUI
01412 HRESULT STDMETHODCALLTYPE CControlSite::GetWindow(
01413     /* [in] */ REFGUID rguidReason,
01414     /* [out] */ HWND *phwnd)
01415 {
01416     *phwnd = NULL;
01417     return S_OK;
01418 }
01419 
01420