//+---------------------------------------------------------------------------- // // File: ctr.cpp // // Module: CMDIAL32.DLL // // Synopsis: Implements the Ole Container object for the future splash // Animation control. // // Copyright (c) 1998-1999 Microsoft Corporation // // Author: nickball Created 02/10/98 // //+---------------------------------------------------------------------------- #include "cmmaster.h" /* #define STRICT */ // macros used to reduce verbiage in RECT handling. #define WIDTH(r) (r.right - r.left) #define HEIGHT(r) (r.bottom - r.top) // max size for LoadString. // string constants const WCHAR g_awchHostName[] = L"ICM FS OC Container"; //+--------------------------------------------------------------------------- // // Function: LinkToOle32 // // Synopsis: Initializes the specified Ole32Linkage by linking to the DLL // specified in pszOle32 and retrieving the proc address for the // functions that we need to call // // Arguments: pOle32Link - ptr to Ole32LinkagStruct // pszOl32 - ptr DLL name string // // Returns: TRUE if SUCCESS // FALSE otherwise. // // History: nickball Created 8/14/97 // //---------------------------------------------------------------------------- BOOL LinkToOle32( Ole32LinkageStruct *pOle32Link, LPCSTR pszOle32) { MYDBGASSERT(pOle32Link); MYDBGASSERT(pszOle32); LPCSTR apszOle32[] = { "OleInitialize", "OleUninitialize", "OleSetContainedObject", "CoCreateInstance", NULL }; MYDBGASSERT(sizeof(pOle32Link->apvPfnOle32)/sizeof(pOle32Link->apvPfnOle32[0])==sizeof(apszOle32)/sizeof(apszOle32[0])); ZeroMemory(pOle32Link, sizeof(Ole32LinkageStruct)); return (LinkToDll(&pOle32Link->hInstOle32, pszOle32, apszOle32, pOle32Link->apvPfnOle32)); } //+--------------------------------------------------------------------------- // // Function: UnlinkFromOle32 // // Synopsis: The reverse of LinkToOle32(). // // Arguments: pOle32Link - ptr to Ole32LinkagStruct // // Returns: Nothing // // History: nickball Created 8/14/97 // //---------------------------------------------------------------------------- void UnlinkFromOle32(Ole32LinkageStruct *pOle32Link) { MYDBGASSERT(pOle32Link); if (pOle32Link->hInstOle32) { FreeLibrary(pOle32Link->hInstOle32); } ZeroMemory(pOle32Link, sizeof(Ole32LinkageStruct)); } VOID CleanupCtr(LPICMOCCtr pCtr) { if (pCtr) { pCtr->ShutDown(); pCtr->Release(); } } // move (translate) the rectangle by (dx, dy) inline VOID MoveRect(LPRECT prc, int dx, int dy) { prc->left += dx; prc->right += dx; prc->top += dy; prc->bottom += dy; } const ULONG MAX_STATUS_TEXT = MAX_PATH; //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::CDynamicOleAut // // Synopsis: ctor for the Dynamic OleAut class // // Arguments: None // //---------------------------------------------------------------------------- CDynamicOleAut::CDynamicOleAut() { // // Setup OLEAUT32 linkage // LPCSTR apszOleAut[] = { "VariantClear", "VariantCopy", "VariantInit", "VariantChangeType", "SysAllocString", "SysFreeString", NULL }; MYDBGASSERT(sizeof(m_OleAutLink.apvPfnOleAut)/sizeof(m_OleAutLink.apvPfnOleAut[0]) == sizeof(apszOleAut)/sizeof(apszOleAut[0])); ZeroMemory(&m_OleAutLink, sizeof(m_OleAutLink)); // // Do the link, but make it obvious if it fails // if (!LinkToDll(&m_OleAutLink.hInstOleAut, "OLEAUT32.DLL", apszOleAut, m_OleAutLink.apvPfnOleAut)) { if (m_OleAutLink.hInstOleAut) { FreeLibrary(m_OleAutLink.hInstOleAut); } ZeroMemory(&m_OleAutLink, sizeof(m_OleAutLink)); } MYDBGASSERT(m_OleAutLink.hInstOleAut); } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::~CDynamicOleAut // // Synopsis: dtor for the Dynamic OleAut class // // Arguments: None // //---------------------------------------------------------------------------- CDynamicOleAut::~CDynamicOleAut() { if (m_OleAutLink.hInstOleAut) { FreeLibrary(m_OleAutLink.hInstOleAut); } } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::DynVariantClear // // Synopsis: Wrapper for VariantClear in OLEAUT32.DLL // // Arguments: See OLEAUT32.DLL documentation // //---------------------------------------------------------------------------- HRESULT CDynamicOleAut::DynVariantClear(VARIANTARG FAR* pVar) { if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnVariantClear) { return E_FAIL; } return m_OleAutLink.pfnVariantClear(pVar); } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::DynVariantCopy // // Synopsis: Wrapper for VariantCopy in OLEAUT32.DLL // // Arguments: See OLEAUT32.DLL documentation // //---------------------------------------------------------------------------- HRESULT CDynamicOleAut::DynVariantCopy( VARIANTARG FAR* pVar1, VARIANTARG FAR* pVar2) { if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnVariantCopy) { return E_FAIL; } return m_OleAutLink.pfnVariantCopy(pVar1, pVar2); } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::DynVariantInit // // Synopsis: Wrapper for VariantInit in OLEAUT32.DLL // // Arguments: See OLEAUT32.DLL documentation // //---------------------------------------------------------------------------- VOID CDynamicOleAut::DynVariantInit(VARIANTARG FAR* pVar) { if (m_OleAutLink.hInstOleAut && m_OleAutLink.pfnVariantInit) { m_OleAutLink.pfnVariantInit(pVar); } } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::DynVariantChangeType // // Synopsis: Wrapper for VariantChangeType in OLEAUT32.DLL // // Arguments: See OLEAUT32.DLL documentation // //---------------------------------------------------------------------------- HRESULT CDynamicOleAut::DynVariantChangeType( VARIANTARG FAR* pVar1, VARIANTARG FAR* pVar2, unsigned short wFlags, VARTYPE vt) { if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnVariantChangeType) { return E_FAIL; } return m_OleAutLink.pfnVariantChangeType(pVar1, pVar2, wFlags, vt); } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::DynSysAllocString // // Synopsis: Wrapper for SysAllocString in OLEAUT32.DLL // // Arguments: See OLEAUT32.DLL documentation // //---------------------------------------------------------------------------- BSTR CDynamicOleAut::DynSysAllocString(OLECHAR FAR* sz) { if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnSysAllocString) { return NULL; } return m_OleAutLink.pfnSysAllocString(sz); } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::DynSysFreeString // // Synopsis: Wrapper for SysFreeString in OLEAUT32.DLL // // Arguments: See OLEAUT32.DLL documentation // //---------------------------------------------------------------------------- VOID CDynamicOleAut::DynSysFreeString(BSTR bstr) { if (m_OleAutLink.hInstOleAut && m_OleAutLink.pfnSysFreeString) { m_OleAutLink.pfnSysFreeString(bstr); } } //+-------------------------------------------------------------------------- // // Member: CDynamicOleAut::Initialized // // Synopsis: Simple query to report if linkage is valid // // Arguments: None // //---------------------------------------------------------------------------- BOOL CDynamicOleAut::Initialized() { return (NULL != m_OleAutLink.hInstOleAut); } //+-------------------------------------------------------------------------- // // Member: CICMOCCtr::CICMOCCtr // // Synopsis: ctor for the OLE Controls container class. // // Arguments: [hWnd] -- hWnd for the main browser // //---------------------------------------------------------------------------- #pragma warning(disable:4355) // this used in initialization list CICMOCCtr::CICMOCCtr(const HWND hWndMainDlg, const HWND hWndFrame) : m_hWndMainDlg(hWndMainDlg), m_hWndFrame(hWndFrame), m_CS(this), m_AS(this), m_IPF(this), m_IPS(this), m_OCtr(this), m_PB(this), m_pActiveObj(0), m_Ref(1), m_pUnk(0), m_pOC(0), m_pVO(0), m_pOO(0), m_pIPO(0), m_pDisp(0), m_state(OS_PASSIVE), m_dwMiscStatus(0), m_fModelessEnabled(TRUE) { ::memset(&m_rcToolSpace, 0, sizeof m_rcToolSpace); InitPixelsPerInch(); // initialize the HIMETRIC routines // init all the state mappings to -1 for (INT i = PS_Interactive; i < PS_Last; i++) { m_alStateMappings[i] = -1; } } #pragma warning(default:4355) CICMOCCtr::~CICMOCCtr(VOID) { } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::HasLinkage // // Synopsis: Initialize - verify that we have a link to OLEAUT32.DLL // //---------------------------------------------------------------------------- BOOL CICMOCCtr::Initialized(VOID) { return m_DOA.Initialized(); } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::ShutDown // // Synopsis: cleanup all the OLE stuff. // //---------------------------------------------------------------------------- VOID CICMOCCtr::ShutDown(VOID) { if (m_pOC) m_pOC->Release(); if (m_pIPO) { MYDBGASSERT(m_state == OS_UIACTIVE || m_state == OS_INPLACE); if (m_state == OS_UIACTIVE) { m_pIPO->UIDeactivate(); // m_state = OS_INPLACE; // for documentation purposes if (m_pActiveObj) { m_pActiveObj->Release(); m_pActiveObj = 0; } } m_pIPO->InPlaceDeactivate(); // m_state = OS_RUNNING; } if (m_pVO) { // kill the advisory connection m_pVO->SetAdvise(DVASPECT_CONTENT, 0, 0); m_pVO->Release(); } if (m_pOO) { m_pOO->Close(OLECLOSE_NOSAVE); m_pOO->SetClientSite(0); m_pOO->Release(); } if (m_pDisp) m_pDisp->Release(); if (m_pUnk) m_pUnk->Release(); MYDBGASSERT(!m_pActiveObj); m_pDisp = 0; m_pOC = 0; m_pIPO = 0; m_pActiveObj = 0; m_pVO = 0; m_pOO = 0; m_pUnk = 0; m_state = OS_PASSIVE; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::AddRef // // Synopsis: bump refcount up on container. Note that all the // interfaces handed out delegate to this one. // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CICMOCCtr::AddRef(VOID) { return ++m_Ref; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::Release // // Synopsis: decrement the refcount on container, and delete when it // hits 0 - note that all the interfaces handed out delegate // to this one. // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CICMOCCtr::Release(VOID) { ULONG ulRC = --m_Ref; if (!ulRC) { delete this; } return ulRC; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::QueryInterface // // Synopsis: this is where we hand out all the interfaces. All the // interfaces delegate back to this. // // Arguments: [riid] -- IID of interface desired. // [ppv] -- interface returned. // // Returns: HRESULT // //---------------------------------------------------------------------------- STDMETHODIMP CICMOCCtr::QueryInterface(REFIID riid, LPVOID FAR * ppv) { *ppv = 0; LPUNKNOWN pUnk; if (::IsEqualIID(riid, IID_IOleClientSite)) pUnk = &m_CS; else if (::IsEqualIID(riid, IID_IAdviseSink)) pUnk = &m_AS; else if (::IsEqualIID(riid, IID_IUnknown)) pUnk = this; else if (::IsEqualIID(riid, IID_IOleInPlaceFrame) || ::IsEqualIID(riid, IID_IOleInPlaceUIWindow)) pUnk = &m_IPF; else if (::IsEqualIID(riid, IID_IOleInPlaceSite)) pUnk = &m_IPS; else if (::IsEqualIID(riid, IID_IPropertyBag)) pUnk = &m_PB; else return E_NOINTERFACE; pUnk->AddRef(); *ppv = pUnk; return S_OK; } extern "C" CLSID const CLSID_FS = { 0xD27CDB6E, 0xAE6D, 0x11CF, { 0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }; //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::CreateFSOC // // Synopsis: Creates an instance of the Future Splash OC, embedding it in // our container. QIs for all the relevant pointers and // transitions the control to the UIActive state. // // Arguments: pOle32Link - ptr to Ole32LinkageStruct containing funtion // pointers to dynamically linked OLE32 DLL // //---------------------------------------------------------------------------- HRESULT CICMOCCtr::CreateFSOC(Ole32LinkageStruct *pOle32Link) { MYDBGASSERT(pOle32Link); HRESULT hr = -1; RECT rc; LPPERSISTPROPERTYBAG pPPB = 0; // GetFrameWindow() also asserts that hwnd ::IsWindow() MYDBGASSERT(GetFrameWindow()); // // Use dyna-linked CoCreateInstance to create the OC // if (pOle32Link->hInstOle32 && pOle32Link->pfnCoCreateInstance) { hr = pOle32Link->pfnCoCreateInstance( CLSID_FS, 0, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID *) &m_pUnk); } else { hr = E_FAIL; } if (hr) goto Cleanup; m_state = OS_RUNNING; // get the View object - although we rarely draw the OC thru this. // since we immediately transition it to the UIActive state, it // usually draws itself through its own wndproc. hr = m_pUnk->QueryInterface(IID_IViewObject, (LPVOID FAR *) &m_pVO); if (hr) goto Cleanup; // get the IOleObject pointer - the main interface through which // we handle the basic OLE object state transition stuff // for the Future Splash OC hr = m_pUnk->QueryInterface(IID_IOleObject, (LPVOID FAR *) &m_pOO); if (hr) goto Cleanup; // get status bits on the OC - we're not currently doing anything // with them. hr = m_pOO->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus); if (hr) goto Cleanup; // set our client site into the oleobject hr = m_pOO->SetClientSite(&m_CS); if (hr) goto Cleanup; hr = m_pUnk->QueryInterface(IID_IPersistPropertyBag, (LPVOID *) &pPPB); if (hr) goto Cleanup; hr = pPPB->Load(&m_PB, 0); if (hr) goto Cleanup; // set our advise sink into the view object, so we // get notifications that we need to redraw. hr = m_pVO->SetAdvise(DVASPECT_CONTENT, 0, &m_AS); if (hr) goto Cleanup; // // Use dyna-linked OleSetContainedObject // if (pOle32Link->hInstOle32 && pOle32Link->pfnOleSetContainedObject) { // standard OLE protocol stuff. hr = pOle32Link->pfnOleSetContainedObject(m_pUnk, TRUE); } else { hr = E_FAIL; } if (hr) goto Cleanup; // ditto hr = m_pOO->SetHostNames(g_awchHostName, 0); if (hr) goto Cleanup; // get the IDispatch for the control. This is for late-bound // access to the properties and methods. hr = m_pUnk->QueryInterface(IID_IDispatch, (LPVOID FAR *) &m_pDisp); if (hr) goto Cleanup; // get the IOleControl interface; although we use it for very little. hr = m_pUnk->QueryInterface(IID_IOleControl, (LPVOID FAR *) &m_pOC); if (hr) goto Cleanup; // transition the control to the inplace-active state - it will have // an hWnd after it returns from DoVerb, and will begin drawing // itself. _GetDoVerbRect(&rc); // get rect for firing verbs. hr = m_pOO->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, &m_CS, 0, GetMainWindow(), &rc); if (hr) goto Cleanup; // go ahead and UI activate it. This will cause it to QI for our // IOleInPlaceFrame and call SetActiveObject, which we will store // in m_pActiveObj hr = m_pOO->DoVerb(OLEIVERB_UIACTIVATE, 0, &m_CS, 0, GetMainWindow(), &rc); if (hr) goto Cleanup; Cleanup: if (pPPB) pPPB->Release(); return hr; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::_AdjustForTools // // Synopsis: adjusts the rect passed in for any toolspace claimed by the // FS OC. Currently, the FS OC always just // passed in a rect with four zeros in it - but if it ever // does decide to do this, we're ready :). // // Arguments: [prc] -- the rect we want to reduce by the BORDERWIDTHS // stored in m_rcToolSpace. // //---------------------------------------------------------------------------- VOID CICMOCCtr::_AdjustForTools(LPRECT prc) { prc->left += m_rcToolSpace.left; prc->top += m_rcToolSpace.top; prc->bottom -= m_rcToolSpace.bottom; prc->right -= m_rcToolSpace.right; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::GetSize // // Synopsis: returns the size, in pixels, of the FS OC. // // Arguments: [prc] -- returned size. // //---------------------------------------------------------------------------- HRESULT CICMOCCtr::GetSize(LPRECT prc) { MYDBGASSERT(m_pOO); HRESULT hr; // if we're inplace active, just ask the frame window. if (m_state >= OS_INPLACE) { MYDBGASSERT(m_pIPO); ::GetClientRect(GetFrameWindow(), prc); hr = S_OK; } else // not inplace active - probably this is never hit. { SIZEL sizel; hr = m_pOO->GetExtent(DVASPECT_CONTENT, &sizel); if (!hr) { prc->left = 0; prc->top = 0; prc->right = ::HPixFromHimetric(sizel.cx); prc->bottom = ::VPixFromHimetric(sizel.cy); } } // adjust the borders for any tools that a UIActive object // wants to place there. if (!hr) _AdjustForTools(prc); return hr; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::DoLayout // // Synopsis: manages the vertical layout of things - // sizes the OC container itself. // // Arguments: [cxMain] -- width // [cyMain] -- height // //---------------------------------------------------------------------------- VOID CICMOCCtr::DoLayout(INT cxMain, INT cyMain) { RECT rc; MYDBGASSERT(m_hWndFrame && ::IsWindow(m_hWndFrame)); ::GetClientRect(m_hWndFrame, &rc); SetSize(&rc, TRUE); } HRESULT CICMOCCtr::_SetExtent(LPRECT prc) { SIZEL sizel; HRESULT hr; sizel.cx = ::HimetricFromHPix(prc->right - prc->left); sizel.cy = ::HimetricFromVPix(prc->bottom - prc->top); MYDBGASSERT(m_pOO); hr = m_pOO->SetExtent(DVASPECT_CONTENT, &sizel); if (hr) goto cleanup; hr = m_pOO->GetExtent(DVASPECT_CONTENT, &sizel); if (hr) goto cleanup; prc->right = ::HPixFromHimetric(sizel.cx); prc->bottom = ::VPixFromHimetric(sizel.cy); cleanup: return hr; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::SetSize // // Synopsis: sets the size of the FS OC space (the HTML area) // // Effects: if fMoveFrameWindow is TRUE, then it moves the whole // framewindow around, otherwise, it just readjusts how much // of the framewindow space is used by the OC itself. // In reality, what happens is that the OC calls us to // set some border space (although at this writing it still // is setting BORDERWIDTHS of 0,0,0,0), we allow that // much space, then call IOleInPlaceObject->SetObjectRects // to resize the object to whatever's left. // Otherwise, if the object is not yet active, we just // call IOleObject::SetExtent(). // // Arguments: [prc] -- size to set object to // [fMoveFrameWindow] -- is the hwnd size changing, or just // the object within? // // //---------------------------------------------------------------------------- HRESULT CICMOCCtr::SetSize(LPRECT prc, BOOL fMoveFrameWindow) { HRESULT hr; RECT rcClient; RECT rcExtent; // get client coords. rcClient = *prc; ::MoveRect(&rcClient, -rcClient.left, -rcClient.top); if (fMoveFrameWindow) { ::SetWindowPos( GetFrameWindow(), 0, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, SWP_NOZORDER | SWP_NOACTIVATE); if (m_pActiveObj) m_pActiveObj->ResizeBorder(&rcClient, &m_IPF, TRUE); } // subtract off any tools the client has around . _AdjustForTools(&rcClient); rcExtent = rcClient; hr = _SetExtent(&rcExtent); if (hr) goto cleanup; // now we need to call SetObjectRects if (m_pIPO && m_state >= OS_INPLACE) hr = m_pIPO->SetObjectRects(&rcExtent, &rcClient); cleanup: return hr; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::Paint // // Synopsis: Paint with no parameters // //---------------------------------------------------------------------------- VOID CICMOCCtr::Paint(VOID) { PAINTSTRUCT ps; RECT rc; // we don't need to call IViewObject if the object is activated. // it's got an hWnd and is receiving paint messages of its own. if (m_state < OS_INPLACE) { if (!GetSize(&rc)) { ::BeginPaint(GetFrameWindow(), &ps); Paint(ps.hdc, &rc); ::EndPaint(GetFrameWindow(), &ps); } } } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::Paint // // Synopsis: paint with the hdc and rect passed in. Uses // IViewObject::Draw() // // Arguments: [hDC] -- dc to draw to - can be container's or // even print dc (never is a print dc in // our scenario - // [lpr] -- rect for painting. // //---------------------------------------------------------------------------- VOID CICMOCCtr::Paint(HDC hDC, LPRECT lpr) { // adjust the borders in to allow for any tools the OC // wanted to insert - so far it never does. _AdjustForTools(lpr); // have to use a RECTL instead of RECT - remnant of the // OLE 16 bit days. RECTL rcl = {lpr->left, lpr->top, lpr->right, lpr->bottom}; if (m_pVO) m_pVO->Draw(DVASPECT_CONTENT, -1, 0, 0, 0, hDC, &rcl, 0, 0, 0); } VOID CICMOCCtr::MapStateToFrame(ProgState ps) { // if the statemappings are -1, they are unitialized, don't use them. LONG lFrame = m_alStateMappings[ps]; if (-1 != lFrame) SetFrame(lFrame); // ignore error - nothing we can do. } HRESULT CICMOCCtr::SetFrame(LONG lFrame) { HRESULT hr; OLECHAR * pFrameNum = OLESTR("FrameNum"); OLECHAR * pPlay = OLESTR("Play"); DISPPARAMS dp = {0, 0, 0, 0}; DISPID dispidPut = DISPID_PROPERTYPUT; VARIANTARG var; EXCEPINFO ei; DISPID id; UINT uArgErr; m_DOA.DynVariantInit(&var); V_VT(&var) = VT_I4; V_I4(&var) = lFrame; dp.cArgs = 1; dp.rgvarg = &var; dp.cNamedArgs = 1; dp.rgdispidNamedArgs = &dispidPut; hr = m_pDisp->GetIDsOfNames( IID_NULL, &pFrameNum, 1, LOCALE_SYSTEM_DEFAULT, &id); if (hr) goto Cleanup; hr = m_pDisp->Invoke( id, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, 0, &ei, &uArgErr); if (hr) goto Cleanup; hr = m_pDisp->GetIDsOfNames( IID_NULL, &pPlay, 1, LOCALE_SYSTEM_DEFAULT, &id); if (hr) goto Cleanup; ::memset(&dp, 0, sizeof dp); hr = m_pDisp->Invoke( id, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dp, 0, &ei, &uArgErr); if (hr) goto Cleanup; Cleanup: return hr; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::OnActivateApp // // Synopsis: all WM_ACTIVATE messages (forwarded from // main browser hWnd wndproc) must call // IOleInPlaceActiveObject::OnFrameWindowActivate(), // per the OLE compound document spec. // // Arguments: [wParam] -- whatever the WM_ACTIVATE msg passed // [lParam] -- ditto // // Returns: 0 - to say we handled the message. // //---------------------------------------------------------------------------- LRESULT CICMOCCtr::OnActivateApp(WPARAM wParam, LPARAM lParam) { if (m_pActiveObj) m_pActiveObj->OnFrameWindowActivate((BOOL)wParam); return 0; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::SetFocus // // Synopsis: transfers focus from framewindow to the current // in-place active object. Per OLE Compound Document spec. // //---------------------------------------------------------------------------- LRESULT CICMOCCtr::SetFocus(VOID) { HWND hWnd = NULL; LPOLEINPLACEACTIVEOBJECT pAO = GetIPAObject(); if (pAO) { if (!pAO->GetWindow(&hWnd)) { if (hWnd && !::IsWindow(hWnd)) hWnd = NULL; } } // if no inplaceactive object, set focus to frame window. if (!hWnd) hWnd = GetFrameWindow(); ::SetFocus(hWnd); return 0; } //+--------------------------------------------------------------------------- // // Class: CAdviseSink implementations // // Purpose: to implement IAdviseSink for CICMOCCtr // // Notes: we don't do much with this interface - it's required // for contractual reasons only. // //---------------------------------------------------------------------------- STDMETHODIMP CAdviseSink::QueryInterface(REFIID riid, LPVOID FAR * ppv) { return m_pCtr->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CAdviseSink::AddRef(VOID) { return m_pCtr->AddRef(); } STDMETHODIMP_(ULONG) CAdviseSink::Release(VOID) { return m_pCtr->Release(); } CAdviseSink::CAdviseSink(LPICMOCCtr pCtr) : m_pCtr(pCtr) { } STDMETHODIMP_(VOID) CAdviseSink::OnDataChange(LPFORMATETC pFEIn, LPSTGMEDIUM pSTM) { return; } //+--------------------------------------------------------------------------- // // Member: CAdviseSink::OnViewChange // // Synopsis: IAdviseSink::OnViewChange() - we do get called with this // occasionally, but it appears that we're better off just // letting the control's wndproc paint it. // Calling this was causing extra flicker. // //---------------------------------------------------------------------------- STDMETHODIMP_(VOID) CAdviseSink::OnViewChange(DWORD dwAspect, LONG lIndex) { return; } STDMETHODIMP_(VOID) CAdviseSink::OnRename(LPMONIKER pmk) { } STDMETHODIMP_(VOID) CAdviseSink::OnSave(VOID) { } STDMETHODIMP_(VOID) CAdviseSink::OnClose(VOID) { } //+--------------------------------------------------------------------------- // // Class: COleClientSite () // // Purpose: our implementation of IOleClientSite // // Interface: COleClientSite -- ctor // QueryInterface -- gimme an interface! // AddRef -- bump up refcount // Release -- bump down refcount // SaveObject -- returns E_FAIL // GetMoniker -- E_NOTIMPL // GetContainer -- returns our COleContainer impl // ShowObject -- just say OK // OnShowWindow -- just say OK // RequestNewObjectLayout -- E_NOTIMPL // // Notes: probably the most important thing our IOleClientSite // implementation does is hand off our IOleContainer // implementation when GetContainer() is called. // //---------------------------------------------------------------------------- COleClientSite::COleClientSite(LPICMOCCtr pCtr) : m_pCtr(pCtr) { } STDMETHODIMP COleClientSite::QueryInterface(REFIID riid, LPVOID FAR * ppv) { return m_pCtr->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) COleClientSite::AddRef(VOID) { return m_pCtr->AddRef(); } STDMETHODIMP_(ULONG) COleClientSite::Release(VOID) { return m_pCtr->Release(); } //+--------------------------------------------------------------------------- // // Member: COleClientSite::SaveObject // // Synopsis: not implemented - makes no sense in this scenario. // //---------------------------------------------------------------------------- STDMETHODIMP COleClientSite::SaveObject(VOID) { return E_FAIL; } //+--------------------------------------------------------------------------- // // Member: COleClientSite::GetMoniker // // Synopsis: Not yet implemented; never will be implemented. // //---------------------------------------------------------------------------- STDMETHODIMP COleClientSite::GetMoniker(DWORD dwAssign, DWORD dwWhich, LPMONIKER FAR * ppmk) { *ppmk = 0; return E_NOTIMPL; } //+--------------------------------------------------------------------------- // // Member: COleClientSite::GetContainer // // Synopsis: returns our implementation of IOleContainer. For some // reason, unless we do this, frames don't work. Note that // our IOleContainer implementation is stubbed out with // E_NOTIMPL (it seems kind of odd to implement this for // a container with one embedding). But it turns out the // FS OC has a bug in it's error handling - it // QIs for IOleContainer, then QIs from that for // IQueryService. In truth, we'll hand out our implementation // of IQueryService, from any interface - we're easy :). // We *want* to provide every service the OC asks for. // Anyway, when it can't get IOleContainer, the OC's failure // path seems to be constructed in such a way that frames // don't work thereafter. // // Arguments: [ppCtr] -- returned IOleContainer // // Returns: S_OK. Never fails. // //---------------------------------------------------------------------------- STDMETHODIMP COleClientSite::GetContainer(LPOLECONTAINER FAR * ppCtr) { *ppCtr = &m_pCtr->m_OCtr; (*ppCtr)->AddRef(); return S_OK; } //+--------------------------------------------------------------------------- // // Member: COleClientSite::ShowObject // // Synopsis: IOleClientSite::ShowObject implementation. To quote the docs: // "Tells the container to position the object so it is visible // to the user. This method ensures that the container itself // is visible and not minimized." // // In short, we ignore it. We're not going to un-minimize // the container on the embeddings' whim :). // //---------------------------------------------------------------------------- STDMETHODIMP COleClientSite::ShowObject(VOID) { return S_OK; } //+--------------------------------------------------------------------------- // // Member: COleClientSite::OnShowWindow // // Synopsis: fine with us, return S_OK. // //---------------------------------------------------------------------------- STDMETHODIMP COleClientSite::OnShowWindow(BOOL bShow) { return S_OK; } //+--------------------------------------------------------------------------- // // Member: COleClientSite::RequestNewObjectLayout // // Synopsis: not being called by WebBrower OC, so do not implement. // //---------------------------------------------------------------------------- STDMETHODIMP COleClientSite::RequestNewObjectLayout(VOID) { return E_NOTIMPL; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::CInPlaceFrame // // Synopsis: inits m_pCtr - pointer to MSNOCCtr // //---------------------------------------------------------------------------- CInPlaceFrame::CInPlaceFrame(LPICMOCCtr pCtr) : m_pCtr(pCtr) { } STDMETHODIMP CInPlaceFrame::QueryInterface(REFIID riid, LPVOID FAR * ppv) { return m_pCtr->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CInPlaceFrame::AddRef(VOID) { return m_pCtr->AddRef(); } STDMETHODIMP_(ULONG) CInPlaceFrame::Release(VOID) { return m_pCtr->Release(); } // IOleWindow stuff //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::GetWindow // // Synopsis: returns frame window // // Arguments: [phwnd] -- place to return window // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::GetWindow(HWND * phwnd) { MYDBGASSERT(phwnd); // this can never fail if we've gotten this far. *phwnd = m_pCtr->GetFrameWindow(); MYDBGASSERT(*phwnd); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::ContextSensitiveHelp // // Synopsis: This is not implemented by design - this is for // the SHift+F1 context sensitive help mode and Esc // to exit. Esc is already being used in the main // accelerator table to mean 'stop browsing' to be // like IE3. We do not do help this way. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; } // IOleInPlaceUIWindow stuff //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::GetBorder // // Synopsis: IOleInPlaceFrame::GetBorder() - let's us restrict where // the server can put tools. We don't care, they can put // them anywhere. // // Arguments: [lprectBorder] -- return border info in here. // // Returns: S_OK always with entire frame client rect - // we place no restrictions. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::GetBorder(LPRECT lprectBorder) { // we have no restrictions about where the server can put tools. ::GetClientRect(m_pCtr->GetFrameWindow(), lprectBorder); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::RequestBorderSpace // // Synopsis: IOleInPlaceFrame::RequestBorderSpace() // inplace object actually requests border space - if // we can satisfy the request, we return S_OK, otherwise // INPLACE_E_NOTOOLSPACE. It doesn't actually use the // borderspace until it calls // IOleInPlaceFrame::SetBorderSpace(). This is used for // negotiation. // // Arguments: [pborderwidths] -- structure (actually a RECT) that is // interpreted differently from a RECT. // The left.top.bottom.right members // represent space on each of our four // borders the server would like to use. // // Returns: HRESULT // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) { RECT rc; RECT rcBorder; if (!pborderwidths) return S_OK; // they're telling us no toolspace necessary. rcBorder = *pborderwidths; if (GetBorder(&rc)) return INPLACE_E_NOTOOLSPACE; if (rcBorder.left + rcBorder.right > WIDTH(rc) || rcBorder.top + rcBorder.bottom > HEIGHT(rc)) return INPLACE_E_NOTOOLSPACE; return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::SetBorderSpace // // Synopsis: Sets border space for tools - for some reason, the // FS OC always calls this with a pborderwidths // consisting of four zeros - it never actually uses any // border space (sigh). Well, the code is here for this // to work. We do a SetSize() to relayout stuff when // it does this. // // Arguments: [pborderwidths] -- space the OC wants to use. // // Returns: HRESULT // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::SetBorderSpace(LPCBORDERWIDTHS pborderwidths) { RECT rc; if (!pborderwidths) { ::memset(&m_pCtr->m_rcToolSpace, 0, sizeof m_pCtr->m_rcToolSpace); return S_OK; } if (RequestBorderSpace(pborderwidths)) return OLE_E_INVALIDRECT; // we get the entire client space to pass to setSize(). ::GetClientRect(m_pCtr->GetFrameWindow(), &rc); m_pCtr->m_rcToolSpace = *pborderwidths; return m_pCtr->SetSize(&rc, FALSE); } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::SetActiveObject // // Synopsis: IOleInPlaceFrame::SetActiveObject(). The server calls // this normally whenever it transitions to the UIActive // state. There can only be one UIActive object at a time. // This UIACtive object is represented by its // IOleInPlaceActiveObject implementation. We call this // object's implementation of TranslateAccelerator() right // in the main message loop to give the current embedding // first shot at keyboard messages. // // Normally, this is only called when the container transitions // an object to UIActive by calling // IOleObject::DoVerb(OLEIVERB_UIACTIVE) for the object, // transitioning all the other objects (we don't have any :)) // to OS_INPLACE (if they're OLEMISC_ACTIVATEWHENVISIBLE is set) // or even just OS_RUNNING. // // Effects: sets a new active object in m_pActiveObj. Releases the // old one, if any. // // Arguments: [pActiveObject] -- new active object // [pszObjName] -- name of object - we don't use this. // // Returns: S_OK always. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::SetActiveObject( IOleInPlaceActiveObject * pActiveObject, LPCOLESTR pszObjName) { // reset the toolspace rect in case the last inplacactive object // forgot to. m_pCtr->_ResetToolSpace(); // if it was already set, save it so we can release // it. We don't want to release it before we addref // the new one in case they're the same thing. LPOLEINPLACEACTIVEOBJECT pOld = m_pCtr->m_pActiveObj; m_pCtr->m_pActiveObj = pActiveObject; if (pActiveObject) { MYDBGASSERT(OS_UIACTIVE == m_pCtr->GetState()); m_pCtr->m_pActiveObj->AddRef(); } if (pOld) pOld->Release(); return S_OK; } // IOleInPlaceFrame stuff //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::InsertMenus // // Synopsis: OC calling us when it wants to do menu negotiation // It calls us with a blank hmenu that we're supposed to // add items to and fille out the OLEMENUGROUPWIDTHS // structure to let it know what we did. // We're not adding items to it currently. // // Arguments: [hmenuShared] -- menu to append to // [pMGW] -- OLEMENUGROUPWIDTHS struct to fill out. // // Returns: S_OK // // // Note: OC doesn't call this. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS pMGW) { // we're not inserting anything of our own to this menu. pMGW->width[0] = 0; // 'File' menu pMGW->width[2] = 0; // 'View' menu pMGW->width[4] = 0; // 'Window' menu pMGW->width[5] = 0; // 'Help' menu return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::SetMenu // // Synopsis: This is the OC calling the container asking us to // set the shared menu in its frame. We're supposed to // use the HOLEMENU object passed in and the // hWndActiveObject to call OleSetMenuDescriptor() so // that OLE can do message filtering and route WM_COMMAND // messages. // // // Arguments: [hmenuShared] -- shared menu. // [holemenu] -- ole menu descriptor thingy // [hwndActiveObject] -- hwnd of server who's merging menus // // Returns: HRESULT // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) { // we're not doing any menu negotiation return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::RemoveMenus // // Synopsis: IOleInPlaceFrame::RemoveMenus(), this is where the // server gives us a chance to remove all our items from // the hMenu. We're not adding any, so we don't remove any. // // Arguments: [hmenuShared] -- menu to clean up. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::RemoveMenus(HMENU hmenuShared) { // we aren't adding anything to this thing anyway. return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::SetStatusText // // Synopsis: called by the FS OC to put text in our status // text area. // // Returns: HRESULT // // Arguments: [pszStatusText] -- text to display // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::SetStatusText(LPCOLESTR pszStatusText) { return m_pCtr->_DisplayStatusText(pszStatusText); } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::_DisplayStatusText // // Synopsis: helper that displays status text. // // Arguments: [pszStatusText] -- text to display // // // Returns: S_OK or HRESULT_FROM_WIN32(::GetLastError()); // //---------------------------------------------------------------------------- HRESULT CICMOCCtr::_DisplayStatusText(LPCOLESTR pszStatusText) { CHAR ach[MAX_STATUS_TEXT]; if (::WideCharToMultiByte( CP_ACP, 0, pszStatusText, -1, ach, NElems(ach), 0, 0)) { // put the status text somewhere. return S_OK; } else { return HRESULT_FROM_WIN32(::GetLastError()); } } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::EnableModeless // // Synopsis: this is called by the embedding to let us know it's // putting up a modal dialog box - we should 'grey' out // any of our modeless dialogs. It delegates to // CICMOCCtr::EnableModeless() // // Arguments: [fEnable] -- enable or disable. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::EnableModeless(BOOL fEnable) { return m_pCtr->EnableModeless(fEnable); } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::EnableModeless // // Synopsis: delegated to from CInPlaceFrame::EnableModeless(). // always returns S_OK - we don't have any modeless // dialogs (yet). // // Arguments: [fEnable] -- enable or disable. // // Returns: S_OK // //---------------------------------------------------------------------------- HRESULT CICMOCCtr::EnableModeless(BOOL fEnable) { m_fModelessEnabled = fEnable; // in case anyone wants to know. return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceFrame::TranslateAccelerator // // Synopsis: The current active object's // IOleInPlaceActiveObject::TranslateAccelerator() is being // called at the top of our main message loop. If it // does *not* want to handle a message, it will call // this method of ours to pass the keyboard message back to // us. We call ::TranslateAccelerator on the global main // haccel, and, if it's handled (by returning TRUE - 1), // we indicate it's handled by returning S_OK (0 :). // On the other hand, if it's *not* handled, we return // S_FALSE. // // Arguments: [lpmsg] -- keyboard msg to handle // [wID] -- command identifier value - per spec. // // Returns: HRESULT // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceFrame::TranslateAccelerator(LPMSG lpmsg, WORD wID) { // note this should never be called - only local servers // (out of process) should call this by using // OleTranslateAccelerator(). return m_pCtr->_TransAccelerator(lpmsg, wID); } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::_TransAccelerator // // Synopsis: handle accelerator messages coming from // either IOleInplaceFrame::TranslateAccelerator, or // IOleControlSite::TranslateAccelerator. // // Effects: forwards them to the main accelerator table. // // Arguments: [lpmsg] -- keyboard msg. // [wID] -- per spec. // // Returns: S_OK if we handled it, S_FALSE otherwise. // //---------------------------------------------------------------------------- HRESULT CICMOCCtr::_TransAccelerator(LPMSG lpmsg, WORD wID) { // the docs suggest that this method might need to return E_INVALIDARG. // anyway, this is defensive. If the FS OC // calls us with an 0 ptr, we just return error if (!lpmsg) return E_INVALIDARG; // forward the keystroke to the main accelerator table, if you have one. // if you handle it, say S_OK. #if 0 // this sample has no main accelerator table. if (::TranslateAccelerator(GetMainWindow(),GetMainAccel(), lpmsg)) { return S_OK; // we handled it } else #endif { return S_FALSE; // we didn't. } } //+--------------------------------------------------------------------------- // // Class: CInPlaceSite () // // Purpose: IOleInPlaceSite implementation. // // Interface: CInPlaceSite -- ctor // QueryInterface -- get a new interface // AddRef -- bump ref count // Release -- decrement ref count // GetWindow -- returns frame window // ContextSensitiveHelp -- not implemented by design // CanInPlaceActivate -- returns S_OK. // OnInPlaceActivate -- caches IOleInPlaceObject ptr // OnUIActivate -- returns S_OK - sets state // GetWindowContext -- returns IOleInPlaceFrame, // IOleInPlaceUIWindow, // PosRect and ClipRect // Scroll -- not implemented ever // OnUIDeactivate -- kills objmenu // OnInPlaceDeactivate -- releases cached IOleInPlaceObject // DiscardUndoState -- returns S_OK // DeactivateAndUndo -- deactivates in place active object // OnPosRectChange -- never implemented. // //---------------------------------------------------------------------------- CInPlaceSite::CInPlaceSite(LPICMOCCtr pCtr) : m_pCtr(pCtr) { } STDMETHODIMP CInPlaceSite::QueryInterface(REFIID riid, LPVOID FAR * ppv) { return m_pCtr->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CInPlaceSite::AddRef(VOID) { return m_pCtr->AddRef(); } STDMETHODIMP_(ULONG) CInPlaceSite::Release(VOID) { return m_pCtr->Release(); } CPropertyBag::CPropertyBag(LPICMOCCtr pCtr) : m_pCtr(pCtr) { } CPropertyBag::~CPropertyBag(VOID) { for (INT i = 0; i < m_aryBagProps.Size(); i++) { m_pCtr->m_DOA.DynSysFreeString(m_aryBagProps[i].bstrName); m_pCtr->m_DOA.DynVariantClear(&m_aryBagProps[i].varValue); } } STDMETHODIMP CPropertyBag::QueryInterface(REFIID riid, LPVOID FAR * ppv) { return m_pCtr->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CPropertyBag::AddRef(VOID) { return m_pCtr->AddRef(); } STDMETHODIMP_(ULONG) CPropertyBag::Release(VOID) { return m_pCtr->Release(); } static LONG LongFromValue(LPTSTR sz) { if (CmIsDigit(sz)) return CmAtol(sz); return -1; } HRESULT CPropertyBag::AddPropertyToBag(LPTSTR szName, LPTSTR szValue) { BagProp bp; HRESULT hr; LONG lValue; LPWSTR pawch; //WCHAR awch[INTERNET_MAX_URL_LENGTH] = {0}; // initialize so error cleanup can work properly. bp.bstrName = 0; m_pCtr->m_DOA.DynVariantInit(&bp.varValue); if (!(pawch = (LPWSTR)CmMalloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR)))) { goto MemoryError; } //if (-1 == ::mbstowcs(awch, szName, NElems(awch))) #ifndef UNICODE if (!MultiByteToWideChar(CP_ACP, 0, szName, -1, pawch, INTERNET_MAX_URL_LENGTH)) // NElems(awch))) { hr = E_FAIL; goto Error; } #else lstrcpyU(pawch, szName); #endif bp.bstrName = m_pCtr->m_DOA.DynSysAllocString(pawch); if (!bp.bstrName) goto MemoryError; // see if it's a VT_I4. lValue = ::LongFromValue(szValue); // it's a VT_BSTR - probably most common case if (-1 == lValue) { //if (-1 == ::mbstowcs(awch, szValue, NElems(awch))) #ifndef UNICODE if (!MultiByteToWideChar(CP_ACP, 0, szValue, -1, pawch, INTERNET_MAX_URL_LENGTH)) // NElems(awch))) { hr = E_FAIL; goto Error; } #else lstrcpyU(pawch, szValue); #endif V_VT(&bp.varValue) = VT_BSTR; V_BSTR(&bp.varValue) = m_pCtr->m_DOA.DynSysAllocString(pawch); if (!V_BSTR(&bp.varValue)) goto MemoryError; } else // it's a VT_I4 { V_VT(&bp.varValue) = VT_I4; V_I4(&bp.varValue) = lValue; } hr = m_aryBagProps.AppendIndirect(&bp); if (hr) goto Error; Cleanup: if (pawch) { CmFree(pawch); } return hr; MemoryError: hr = E_OUTOFMEMORY; Error: if (bp.bstrName) m_pCtr->m_DOA.DynSysFreeString(bp.bstrName); if (pawch) { CmFree(pawch); } m_pCtr->m_DOA.DynVariantClear(&bp.varValue); goto Cleanup; } STDMETHODIMP CPropertyBag::Read(LPCOLESTR pszName, LPVARIANT pVar, LPERRORLOG pErrorLog) { for (INT i = 0; i < m_aryBagProps.Size(); i++) { if (!::lstrcmpiU(m_aryBagProps[i].bstrName, pszName)) { if (V_VT(pVar) == V_VT(&m_aryBagProps[i].varValue)) { return m_pCtr->m_DOA.DynVariantCopy(pVar, &m_aryBagProps[i].varValue); } else { return m_pCtr->m_DOA.DynVariantChangeType( pVar, &m_aryBagProps[i].varValue, 0, V_VT(pVar)); } } } return E_INVALIDARG; // we don't have the property. } // IOleWindow stuff //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::GetWindow // // Synopsis: returns frame window. // // Arguments: [phwnd] -- return window *here* // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::GetWindow(HWND * phwnd) { // just reuse the CInPlaceFrame impl return m_pCtr->m_IPF.GetWindow(phwnd); } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::ContextSensitiveHelp // // Synopsis: This is not implemented by design - this is for // the SHift+F1 context sensitive help mode and Esc // to exit. Esc is already being used in the main // accelerator table to mean 'stop browsing' to be // like IE3. We do not do help this way. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; } // IOleInPlaceSite stuff //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::CanInPlaceActivate // // Synopsis: just say yes. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::CanInPlaceActivate(VOID) { return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::OnInPlaceActivate // // Synopsis: caches the IOleInPlaceObject pointer. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::OnInPlaceActivate(VOID) { HRESULT hr = m_pCtr->m_pOO->QueryInterface( IID_IOleInPlaceObject, (LPVOID *) &m_pCtr->m_pIPO); if (!hr) m_pCtr->SetState(OS_INPLACE); return hr; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::OnUIActivate // // Synopsis: just sets state bit // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::OnUIActivate(VOID) { m_pCtr->SetState(OS_UIACTIVE); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::GetWindowContext // // Synopsis: returns a bunch of interfaces and positioning interface // the inplace-active object needs to do its thang. // // Arguments: [ppFrame] -- return our IOleInPlaceFrame implementation // [ppDoc] -- return our IOleInPlaceUIWindow impl. // [prcPosRect] -- position info // [prcClipRect] -- clip info - same as pos info for this case // [pFrameInfo] -- return 0 - inproc object doesn't use this. // // Notes: note that ppFrame and ppDoc are really just the same // object because we're an SDI app. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::GetWindowContext( IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT prcPosRect, LPRECT prcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo) { // get the frame HRESULT hr = m_pCtr->QueryInterface( IID_IOleInPlaceFrame, (LPVOID *)ppFrame); MYDBGASSERT(!hr); // return the frame again :) - this is all per-spec. hr = m_pCtr->QueryInterface( IID_IOleInPlaceUIWindow, (LPVOID *) ppDoc); MYDBGASSERT(!hr); // get the clip and pos rect - same for this application. HWND hWnd = m_pCtr->GetMainWindow(); MYDBGASSERT(hWnd); HWND hWndFrame = m_pCtr->GetFrameWindow(); ::GetClientRect(hWndFrame, prcPosRect); // // NTRAID - #148143 // Apparently the W9x implementation is different, so MapWindowPoints for // the clipping and position rect only on 9X. Also, make sure that the // origin is NULL to keep post 2.0 versions of future splash happy on 9X. // if (OS_W9X) { ::MapWindowPoints(hWndFrame, hWnd, (LPPOINT)prcPosRect, 2); prcPosRect->top = 0; prcPosRect->left = 0; } *prcClipRect = *prcPosRect; // // OLYMPUS - #156880 // Clipping handled differently by future splash versions > 2.0 // so don't re-map the rect points, just use the client rect so we // work with all splash versions - nickball // //::MapWindowPoints(hWndFrame, hWnd, (LPPOINT)prcClipRect, 2); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::Scroll // // Synopsis: never implement this for FS OC. This has // nothing to do with the scrollbars you see on the HTML. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::Scroll(SIZE scrollExtent) { return E_NOTIMPL; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::OnUIDeactivate // // Synopsis: set state bits // // Arguments: [fUndoable] -- not used // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::OnUIDeactivate(BOOL fUndoable) { m_pCtr->SetState(OS_INPLACE); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::OnInPlaceDeactivate // // Synopsis: releases the IOleInPlaceObject pointer we were // caching for the object, and sets state to OS_RUNNING. // Also fires the OLEIVERB_DISCARDUNDOSTATE at the control // to tell it to release any undo state it's holding onto. // I very much doubt the FS OC has any undo state, // but, this is the protocol. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::OnInPlaceDeactivate(VOID) { RECT rc; if (m_pCtr->m_pIPO) { m_pCtr->m_pIPO->Release(); m_pCtr->SetState(OS_RUNNING); m_pCtr->m_pIPO = 0; } if (m_pCtr->m_pOO) { m_pCtr->_GetDoVerbRect(&rc); // get rect for firing verbs. m_pCtr->m_pOO->DoVerb( OLEIVERB_DISCARDUNDOSTATE, 0, &m_pCtr->m_CS, 0, m_pCtr->GetFrameWindow(), 0); } return S_OK; } //+--------------------------------------------------------------------------- // // Member: CICMOCCtr::_GetDoVerbRect // // Synopsis: whenever firing DoVerb(), we need a rect for the object // that describes the area for the object in parent client coords. // // Arguments: [prc] -- rect returned. // //---------------------------------------------------------------------------- VOID CICMOCCtr::_GetDoVerbRect(LPRECT prc) { ::GetClientRect(GetFrameWindow(), prc); ::MapWindowPoints(GetFrameWindow(), GetMainWindow(), (LPPOINT)prc, 2); } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::DiscardUndoState // // Synopsis: just say OK - we don't hold any undo state for // object. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::DiscardUndoState(VOID) { return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::DeactivateAndUndo // // Synopsis: absolutely minimum implementation of deactivateandundo. // just calls IOleInPlaceObject::InPlaceDeactivate(). // // Returns: S_OK always. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::DeactivateAndUndo(VOID) { if (m_pCtr->m_pIPO) m_pCtr->m_pIPO->InPlaceDeactivate(); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CInPlaceSite::OnPosRectChange // // Synopsis: never implement this. // //---------------------------------------------------------------------------- STDMETHODIMP CInPlaceSite::OnPosRectChange(LPCRECT lprcPosRect) { return E_NOTIMPL; } //+--------------------------------------------------------------------------- // // Class: COleContainer () // // Purpose: our implementation of IOleContainer. does nothing. // //---------------------------------------------------------------------------- STDMETHODIMP COleContainer::QueryInterface(REFIID riid, LPVOID FAR * ppv) { return m_pCtr->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) COleContainer::AddRef(VOID) { return m_pCtr->AddRef(); } STDMETHODIMP_(ULONG) COleContainer::Release(VOID) { return m_pCtr->Release(); } COleContainer::COleContainer(LPICMOCCtr pCtr) : m_pCtr(pCtr) { } STDMETHODIMP COleContainer::EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum) { MYDBGASSERT(FALSE); // never called return E_NOTIMPL; } STDMETHODIMP COleContainer::LockContainer(BOOL fLock) { MYDBGASSERT(FALSE); // never called return S_OK; } STDMETHODIMP COleContainer::ParseDisplayName( IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) { return E_NOTIMPL; }