windows-nt/Source/XPSP1/NT/com/ole32/ole232/stdimpl/defsrv.cpp
2020-09-26 16:20:57 +08:00

586 lines
16 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: defsrv.cpp
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 10-19-95 JohannP (Johann Posch) Created
//
//----------------------------------------------------------------------------
#include <le2int.h>
#ifdef SERVER_HANDLER
#include <scode.h>
#include <objerror.h>
#include <olerem.h>
#include "defhndlr.h"
#include "defutil.h"
#include "ole1cls.h"
#ifdef _DEBUG
#include <dbgdump.h>
#endif // _DEBUG
ASSERTDATA
//+---------------------------------------------------------------------------
//
// Method: CDefObject::SrvInitialize
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 10-19-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CDefObject::SrvInitialize(void)
{
HRESULT hresult = NOERROR;
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::Initialize\n", this));
CLSID clsidsrv = CLSID_ServerHandler;
Assert (( CanUseServerHandler() ));
Assert((m_pProxyMgr != NULL));
if (CanUseClientSiteHandler())
{
hresult = CreateClientSiteHandler(m_pAppClientSite, &_pClientSiteHandler);
if (FAILED(hresult))
{
_pClientSiteHandler = NULL;
}
Assert((_pClientSiteHandler != NULL));
}
hresult = m_pProxyMgr->CreateServerWithHandler(m_clsidServer,
CLSCTX_LOCAL_SERVER, NULL,clsidsrv,
IID_IServerHandler, (void **) &_pSrvHndlr,
IID_IClientSiteHandler, _pClientSiteHandler);
if (SUCCEEDED(hresult))
{
// set up the server handler and call InitializeAndRun on it
Assert((_pSrvHndlr != NULL));
}
else
{
// try to get server without server handler object
_dwClientSiteHandler = 0;
_dwServerHandler = 0;
// release the client handler
if (_pClientSiteHandler)
{
_pClientSiteHandler->Release();
_pClientSiteHandler = NULL;
}
// Note: do not try to launch the server without handler here
// this will be done by the default handler
}
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvInitialize\n", this));
return hresult;
}
//+---------------------------------------------------------------------------
//
// Method: CDefObject::SrvRun
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 10-19-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CDefObject::SrvRun(void)
{
HRESULT hresult = NOERROR;
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvRun\n", this));
INSRVRUN InSrvRun;
OUTSRVRUN *pOutSrvRun = NULL;
BOOL fLockedContainer;
IMoniker *pmk;
memset((void*)&InSrvRun, 0, sizeof(InSrvRun));
Assert((_pSrvHndlr));
// get the Container and lock it
// NOTE: the lock state of the proxy mgr is not changed; it remembers
// the state and sets up the connection correctly.
// server is running; normally this coincides with locking the
// container, but we keep a separate flag since locking the container
// may fail.
m_flags |= DH_FORCED_RUNNING;
// Lock the container
fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
DuLockContainer(m_pAppClientSite, TRUE, &fLockedContainer );
if( fLockedContainer )
{
m_flags |= DH_LOCKED_CONTAINER;
}
else
{
m_flags &= ~DH_LOCKED_CONTAINER;
}
// PStgDelegate Load or InitNew
InSrvRun.dwInFlags = m_flags;
InSrvRun.pStg = m_pStg;
if (NULL == m_pPSDelegate)
{
InSrvRun.dwOperation |= OP_NeedPersistStorage;
}
if (NULL == m_pDataDelegate)
{
InSrvRun.dwOperation |= OP_NeedDataObject;
}
if (NULL == m_pOleDelegate)
{
InSrvRun.dwOperation |= OP_NeedOleObject;
InSrvRun.dwOperation |= OP_NeedUserClassID;
}
// Set the clientsite
if (m_pAppClientSite)
{
InSrvRun.dwOperation |= OP_GotClientSite;
}
// set the hostname
InSrvRun.pszContainerApp = (LPOLESTR)m_pHostNames;
InSrvRun.pszContainerObj = (LPOLESTR)(m_pHostNames + m_ibCntrObj);
// adivse sink
Assert((m_dwConnOle == 0L));
InSrvRun.pAS = (IAdviseSink *) &m_AdviseSink;
InSrvRun.dwConnOle = m_dwConnOle;
// Get the Moniker and call
if(m_pAppClientSite != NULL)
{
if (m_pAppClientSite->GetMoniker
(OLEGETMONIKER_ONLYIFTHERE,OLEWHICHMK_OBJREL, &pmk) == NOERROR)
{
AssertOutPtrIface(NOERROR, pmk);
InSrvRun.pMnk = pmk;
}
else
{
InSrvRun.pMnk = NULL;
}
// QI for IMsoDocumentSite
IUnknown *pMsoDS = NULL;
hresult = m_pAppClientSite->QueryInterface(
IID_IMsoDocumentSite,
(void **)&pMsoDS);
if (hresult == NOERROR)
{
// indicate we have MsoDocumentSite
InSrvRun.dwOperation |= OP_HaveMsoDocumentSite;
pMsoDS->Release();
}
}
// MAKE CALL TO SERVERHANDLER
hresult = _pSrvHndlr->RunAndInitialize(&InSrvRun, &pOutSrvRun);
if (SUCCEEDED(hresult))
{
if (InSrvRun.dwOperation & OP_NeedPersistStorage)
{
Assert(NULL != pOutSrvRun->pPStg);
m_pPSDelegate = pOutSrvRun->pPStg;
}
if (InSrvRun.dwOperation & OP_NeedDataObject)
{
Assert(NULL != pOutSrvRun->pDO);
m_pDataDelegate = pOutSrvRun->pDO;
// inform cache that we are running
Assert(NULL != m_pCOleCache);
m_pCOleCache->OnRun(m_pDataDelegate);
// Enumerate all the advises we stored while we were either not
// running or running the previous time, and send them to the
// now-running object.
Assert(NULL != m_pDataAdvCache);
m_pDataAdvCache->EnumAndAdvise(m_pDataDelegate, TRUE);
}
if (InSrvRun.dwOperation & OP_NeedOleObject)
{
Assert(NULL != pOutSrvRun->pOO);
m_pOleDelegate = pOutSrvRun->pOO;
}
if (InSrvRun.dwOperation & OP_NeedUserClassID)
{
Assert(NULL != pOutSrvRun->pUserClassID);
m_clsidUser = *(pOutSrvRun->pUserClassID);
}
m_dwConnOle = pOutSrvRun->dwOutFlag;
if (InSrvRun.pMnk != NULL)
{
InSrvRun.pMnk->Release();
}
// release the pUnkOuter for all marshald pointers
if (m_pPSDelegate && m_pUnkOuter)
{
m_pUnkOuter->Release();
}
if (m_pOleDelegate && m_pUnkOuter)
{
m_pUnkOuter->Release();
}
if (m_pDataDelegate && m_pUnkOuter)
{
m_pUnkOuter->Release();
}
}
else // Server Handler RunAndInitialize has failed... now clean up.
{
Stop();
// if for some reason we did not unlock the container by now,
// do it (e.g., app crashed or failed during InitNew).
fLockedContainer = (m_flags & DH_LOCKED_CONTAINER);
DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer );
if( fLockedContainer )
{
m_flags |= DH_LOCKED_CONTAINER;
}
else
{
m_flags &= ~DH_LOCKED_CONTAINER;
}
if (InSrvRun.pMnk != NULL)
{
InSrvRun.pMnk->Release();
}
}
if (pOutSrvRun != NULL)
{
PubMemFree(pOutSrvRun->pUserClassID); // OK to free NULL;
PubMemFree(pOutSrvRun);
}
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvRun( %lx )\n", this, hresult));
return hresult;
}
//+---------------------------------------------------------------------------
//
// Method: CDefObject::SrvRunAndDoVerb
//
// Synopsis:
//
// Arguments: [iVerb] --
// [lpmsg] --
// [pActiveSite] --
// [lindex] --
// [hwndParent] --
// [lprcPosRect] --
//
// Returns:
//
// History: 10-19-95 JohannP (Johann Posch) Created
//
// Notes: This is not implemented yet.
//
//----------------------------------------------------------------------------
HRESULT CDefObject::SrvRunAndDoVerb( LONG iVerb, LPMSG lpmsg,
LPOLECLIENTSITE pActiveSite, LONG lindex,
HWND hwndParent, const RECT * lprcPosRect)
{
HRESULT hresult = NOERROR;
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvRunAndDoVerb\n", this));
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvRunAndDoVerb\n", this));
return hresult;
}
//+---------------------------------------------------------------------------
//
// Method: CDefObject::SrvDoVerb
//
// Synopsis: 1. gathers information on the client site
// 2. calls the serverhandler with SrvDoverb with collected information
// 3. serverhandler sets up connections and calls
// OleObject::DoVerb on reall object
// 4. release objects which did not get used
//
// Arguments: [iVerb] -- OleObject DoVerb parameter
// [lpmsg] -- detto
// [pActiveSite] -- detto
// [lindex] -- detto
// [hwndParent] -- detto
// [lprcPosRect] -- detto
//
// Returns:
//
// History: 10-19-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CDefObject::SrvDoVerb( LONG iVerb, LPMSG lpmsg,
LPOLECLIENTSITE pActiveSite, LONG lindex,
HWND hwndParent, const RECT * lprcPosRect)
{
HRESULT hresult = NOERROR;
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvDoVerb\n", this));
CInSrvRun InSrvRun;
OUTSRVRUN *pOutSrvRun = NULL;
IOleContainer *pOCont = NULL;
IOleObject *pOOCont = NULL;
IOleClientSite *pOContCS;
IOleInPlaceSite *pOIPS;
// set up the DoVerb parametes
InSrvRun.dwOperation = 0;
InSrvRun.iVerb = iVerb;
InSrvRun.lpmsg = lpmsg;
InSrvRun.lindex = lindex;
InSrvRun.hwndParent = hwndParent;
InSrvRun.lprcPosRect = (RECT *)lprcPosRect;
// Step 1: set up OleClientSiteActive
if (pActiveSite)
{
// Currently this Assert goes off with LE test = deflink-1854 (bchapman Mar'96)
Assert(NULL != _pClientSiteHandler);
_pClientSiteHandler->SetClientSiteDelegate(ID_ClientSiteActive, pActiveSite);
InSrvRun.dwOperation |= OP_GotClientSiteActive;
}
// Step 2: IOleClientSite::GetContainer
// Note: this call might cause a GetUserClassID call
// to the server
hresult = m_pAppClientSite->GetContainer(&pOCont);
if (hresult == NOERROR)
{
HdlAssert((_pClientSiteHandler->_pOCont == NULL));
_pClientSiteHandler->_pOCont = pOCont;
InSrvRun.dwOperation |= OP_GotContainer;
// Step 3: QI on OleContainer for the OleObject
hresult = pOCont->QueryInterface(IID_IOleObject, (void **)&pOOCont);
if (hresult == NOERROR)
{
InSrvRun.dwOperation |= OP_GotOleObjectOfContainer;
// release OleObject of container
pOOCont->Release();
}
}
// Step 6: OI for IOleInPlaceSite
hresult = m_pAppClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&pOIPS);
if (hresult == NOERROR)
{
// set up OleInPlaceSite on the clientsitehandler
HdlAssert((_pClientSiteHandler != NULL));
// release the old OleInPlaceSite
if (_pClientSiteHandler->_pOIPS)
{
_pClientSiteHandler->_pOIPS->Release();
}
_pClientSiteHandler->_pOIPS = pOIPS;
// Step 7: IOleInPlaceSite::CanInPlaceActivate
InSrvRun.dwInPlace = pOIPS->CanInPlaceActivate();
// indicate we have OleInPlaceSite
InSrvRun.dwOperation |= OP_GotInPlaceSite;
}
// call the ServerHandler
HdlDebugOut((DEB_SERVERHANDLER, "%p In CDefObject::SrvDoVerb calling DoVerb on ServerHandler!\n",this));
hresult = _pSrvHndlr->DoVerb(&InSrvRun, &pOutSrvRun);
HdlDebugOut((DEB_SERVERHANDLER, "%p In CDefObject::SrvDoVerb return from DoVerb on ServerHandler!\n",this));
Assert(NULL != _pClientSiteHandler);
if (FAILED(hresult))
{
HdlDebugOut((DEB_ERROR, "OO::DoVerb failed !"));
goto errRtn;
}
// Release the active OleClientSite if not used by server
if ( (InSrvRun.dwOperation & OP_GotClientSiteActive)
&& !(pOutSrvRun->dwOperation & OP_GotClientSiteActive) )
{
// release the active clientsite if not used by the server app.
Assert(NULL != _pClientSiteHandler);
_pClientSiteHandler->SetClientSiteDelegate(ID_ClientSiteActive, NULL);
}
// Release OleInPlaceSite if not used by server
if ( (InSrvRun.dwOperation & OP_GotInPlaceSite)
&& !(pOutSrvRun->dwOperation & OP_GotInPlaceSite) )
{
_pClientSiteHandler->SetClientSiteDelegate(ID_InPlaceSite,NULL);
}
// Release the container if not used by server
if ( (InSrvRun.dwOperation & OP_GotContainer)
&& !(pOutSrvRun->dwOperation & OP_GotContainer) )
{
_pClientSiteHandler->SetClientSiteDelegate(ID_Container,NULL);
}
errRtn:
// delete the out parameter
if (pOutSrvRun)
{
PubMemFree(pOutSrvRun);
}
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvDoVerb\n",this));
return hresult;
}
//+---------------------------------------------------------------------------
//
// Method: CDefObject::SrvRelease
//
// Synopsis:
//
// Arguments: [void] --
//
// Returns:
//
// History: 10-19-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD CDefObject::SrvRelease(void)
{
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvRelease\n", this));
Assert((_pSrvHndlr != NULL));
DWORD dwRet = _pSrvHndlr->Release();
#if DBG==1
if (dwRet)
{
HdlDebugOut((DEB_ERROR, "Last IServerHandler::Release() return %ld\n", dwRet));
}
#endif
_pSrvHndlr = NULL;
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvRelease\n", this));
return dwRet;
}
//+---------------------------------------------------------------------------
//
// Method: CDefObject::SrvCloseAndRelease
//
// Synopsis:
//
// Arguments: [dwFlag] --
//
// Returns:
//
// History: 11-17-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CDefObject::SrvCloseAndRelease(DWORD dwFlag)
{
HRESULT hresult;
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvCloseAndRelease\n", this));
HdlAssert((_pSrvHndlr != NULL));
hresult = _pSrvHndlr->CloseAndRelease(dwFlag);
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvSrvCloseAndRelease hr:%lx\n",this,hresult));
return hresult;
}
//+---------------------------------------------------------------------------
//
// Method: CDefObject::InitializeServerHandlerOptions
//
// Synopsis:
//
// Arguments: [clsidSrv] --
//
// Returns:
//
// History: 11-17-95 JohannP (Johann Posch) Created
//
// Notes: determines server application specifics which can be used
// to make serverhandler operations more efficient
// Review: (JohannP) we would need a flag in the registery or so
//
//----------------------------------------------------------------------------
void CDefObject::InitializeServerHandlerOptions(REFCLSID clsidSrv)
{
VDATEHEAP();
HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::InitializeServerHandlerOptions\n",this));
//
// this method should retrieve server application specific informantion
//
HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::InitializeServerHandlerOptions\n",this));
}
#endif // SERVER_HANDLER