Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2301 lines
62 KiB

//+----------------------------------------------------------------------------
//
// 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;
}