mirror of https://github.com/lianthony/NT4.0
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.
773 lines
25 KiB
773 lines
25 KiB
//+-------------------------------------------------------------------
|
|
//
|
|
// File: coapi.cxx
|
|
//
|
|
// Contents: Public COM remote subsystem APIs
|
|
//
|
|
// Functions: CoGetStandardMarshal - returns IMarshal for given interface
|
|
// CoGetMarshalSizeMax - returns max size buffer needed
|
|
// CoMarshalInterface - marshals an interface
|
|
// CoUnmarshalInterface - unmarshals an interface
|
|
// CoReleaseMarshalData - releases data from marshaled interface
|
|
// CoLockObjectExternal - keep object alive or releases it
|
|
// CoDisconnectObject - kills sessions held by remote clients
|
|
// CoIsHandlerConnected - try to determine if handler connected
|
|
//
|
|
// History: 23-Nov-92 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to identity object
|
|
// 05-Jul-94 BruceMa Check for end of stream
|
|
// 20-Feb-95 Rickhi Major changes for DCOM
|
|
//
|
|
//--------------------------------------------------------------------
|
|
#include <ole2int.h>
|
|
#include <olerem.h>
|
|
#include <marshal.hxx> // CStdMarshal
|
|
#include <stdid.hxx> // CStdIdentity, IDTable APIs
|
|
#include <service.hxx> // SASIZE
|
|
|
|
|
|
// static unmarshaler
|
|
IMarshal *gpStdMarshal = NULL;
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoGetStandardMarshal, public
|
|
//
|
|
// Synopsis: Returns an instance of the standard IMarshal for the
|
|
// specifed object.
|
|
//
|
|
// Algorithm: lookup or create a CStdIdentity (and CStdMarshal) for
|
|
// the object.
|
|
//
|
|
// History: 23-Nov-92 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to identity object
|
|
// 20-Feb-95 Rickhi Switched to CStdMarshal
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk, DWORD dwDestCtx,
|
|
void *pvDestCtx, DWORD mshlflags, IMarshal **ppMarshal)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoGetStandardMarshal");
|
|
ComDebOut((DEB_MARSHAL,
|
|
"CoGetStandardMarshal riid:%I pUnk:%x dwDest:%x pvDest:%x flags:%x\n",
|
|
&riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
|
|
|
|
// validate the input parameters
|
|
if (ppMarshal == NULL ||
|
|
dwDestCtx > MSHCTX_INPROC || pvDestCtx != NULL ||
|
|
(mshlflags & ~MSHLFLAGS_ALL))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppMarshal = NULL;
|
|
|
|
HRESULT hr = InitChannelIfNecessary();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (pUnk == NULL)
|
|
{
|
|
// this is the unmarshal side. any instance will do so we return
|
|
// the static one. Calling UnmarshalInterface will return the real
|
|
// proxy.
|
|
|
|
hr = GetStaticUnMarshaler(ppMarshal);
|
|
}
|
|
else
|
|
{
|
|
// this is the marshal side. We put a strong reference on the StdId
|
|
// so that the ID does not get disconnected when the last external
|
|
// Release occurs.
|
|
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,&pUnk);
|
|
|
|
DWORD dwFlags = IDLF_CREATE | IDLF_STRONG;
|
|
if (mshlflags & MSHLFLAGS_NOPING)
|
|
{
|
|
// requesting NOPING, so set the IDL flags accordingly
|
|
dwFlags |= IDLF_NOPING;
|
|
}
|
|
|
|
CStdIdentity *pStdId;
|
|
hr = LookupIDFromUnk(pUnk, dwFlags, &pStdId);
|
|
*ppMarshal = (IMarshal *)pStdId;
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL, "CoGetStandardMarshal: pIM:%x hr:%x\n",
|
|
*ppMarshal, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoGetMarshalSizeMax, public
|
|
//
|
|
// synopsis: returns max size needed to marshal the specified interface.
|
|
//
|
|
// History: 23-Nov-92 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to static marshaler
|
|
// 20-Feb-95 Rickhi Return correct sizes once again.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
|
|
DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoGetMarshalSizeMax");
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,&pUnk);
|
|
ComDebOut((DEB_MARSHAL,
|
|
"CoGetMarshalSizeMax: riid:%I pUnk:%x dwDest:%x pvDest:%x flags:%x\n",
|
|
&riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
|
|
|
|
// validate the input parameters
|
|
if (pulSize == NULL || pUnk == NULL ||
|
|
dwDestCtx > MSHCTX_INPROC || pvDestCtx != NULL ||
|
|
(mshlflags & ~MSHLFLAGS_ALL))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*pulSize = 0;
|
|
|
|
HRESULT hr = InitChannelIfNecessary();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
IMarshal *pIM;
|
|
hr = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// object supports custom marshalling, ask it how much space it needs
|
|
hr = pIM->GetMarshalSizeMax(riid, (void *)pUnk, dwDestCtx,
|
|
pvDestCtx, mshlflags, pulSize);
|
|
pIM->Release();
|
|
|
|
// add in the size of the stuff CoMarshalInterface will write
|
|
*pulSize += sizeof(OBJREF);
|
|
}
|
|
else
|
|
{
|
|
// uses standard marshalling, we know the max size already.
|
|
*pulSize = sizeof(OBJREF) + SASIZE(gpsaLocalResolver->wNumEntries);
|
|
hr = S_OK;
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL, "CoGetMarshalSizeMax: pUnk:%x size:%x hr:%x\n",
|
|
pUnk, *pulSize, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoMarshalInterface, public
|
|
//
|
|
// Synopsis: marshals the specified interface into the given stream
|
|
//
|
|
// History: 23-Nov-92 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to identity object and
|
|
// new marshaling format
|
|
// 20-Feb-95 Rickhi switched to newer marshal format
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoMarshalInterface(IStream *pStm, REFIID riid, IUnknown *pUnk,
|
|
DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoMarshalInterface");
|
|
ComDebOut((DEB_MARSHAL,
|
|
"CoMarshalInterface: pStm:%x riid:%I pUnk:%x dwDest:%x pvDest:%x flags:%x\n",
|
|
pStm, &riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
|
|
|
|
// validate the input parameters
|
|
if (pStm == NULL || pUnk == NULL ||
|
|
dwDestCtx > MSHCTX_INPROC || pvDestCtx != NULL ||
|
|
(mshlflags & ~MSHLFLAGS_ALL))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = InitChannelIfNecessary();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,(IUnknown **)&pUnk);
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
|
|
|
|
|
|
// determine whether to do custom or standard marshaling
|
|
IMarshal *pIM;
|
|
hr = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// object supports custom marshaling, use it. we package the
|
|
// custom data inside an OBJREF.
|
|
Win4Assert(pIM);
|
|
|
|
OBJREF objref;
|
|
objref.signature = OBJREF_SIGNATURE;
|
|
objref.flags = OBJREF_CUSTOM;
|
|
objref.iid = riid;
|
|
|
|
// get the clsid for unmarshaling
|
|
hr = pIM->GetUnmarshalClass(riid, pUnk, dwDestCtx, pvDestCtx,
|
|
mshlflags, &ORCST(objref).clsid);
|
|
|
|
if (SUCCEEDED(hr) &&
|
|
!IsEqualCLSID(CLSID_StdMarshal, ORCST(objref).clsid))
|
|
{
|
|
// get the size of data to marshal
|
|
hr = pIM->GetMarshalSizeMax(riid, (void *)pUnk, dwDestCtx,
|
|
pvDestCtx, mshlflags,
|
|
&ORCST(objref).size);
|
|
|
|
// currently we dont write any extensions into the custom
|
|
// objref. The provision is there so we can do it in the
|
|
// future, for example, if the unmarshaler does not have the
|
|
// unmarshal class code available we could to provide a callback
|
|
// mechanism by putting the OXID, and saResAddr in there.
|
|
ORCST(objref).cbExtension = 0;
|
|
|
|
// write the objref header info into the stream
|
|
ULONG cbToWrite = (BYTE *)(&ORCST(objref).pData) - (BYTE *)&objref;
|
|
hr = pStm->Write(&objref, cbToWrite, NULL);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// tell the marshaler to write the rest of the data
|
|
hr = pIM->MarshalInterface(pStm, riid, pUnk, dwDestCtx,
|
|
pvDestCtx, mshlflags);
|
|
}
|
|
|
|
pIM->Release();
|
|
}
|
|
else
|
|
{
|
|
// use standard marshaling - find or create a standard marshaler
|
|
// note this may include handler marshaling.
|
|
|
|
// HACKALERT:
|
|
// Figure out what flags to pass. If marshaling TABLEWEAK, don't
|
|
// add then remove a strong connection, since many objects have a
|
|
// bogus implementation of IExternalConnection that shuts down the
|
|
// object when the last strong count goes to zero regardless of the
|
|
// fLastReleaseCloses flag.
|
|
|
|
DWORD dwFlags = IDLF_CREATE;
|
|
if (!(mshlflags & MSHLFLAGS_TABLEWEAK))
|
|
{
|
|
dwFlags |= IDLF_STRONG;
|
|
}
|
|
|
|
CStdIdentity *pStdId;
|
|
hr = LookupIDFromUnk(pUnk, dwFlags, &pStdId);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pStdId->MarshalInterface(pStm, riid, pUnk, dwDestCtx,
|
|
pvDestCtx, mshlflags);
|
|
|
|
if (!(mshlflags & MSHLFLAGS_TABLEWEAK))
|
|
{
|
|
// If marshaling succeeded, removing the last strong connection
|
|
// should keep the object alive. If marshaling failed,
|
|
// removing the last strong connection should shut it down.
|
|
|
|
BOOL fKeepAlive = (SUCCEEDED(hr)) ? TRUE : FALSE;
|
|
pStdId->DecStrongCnt(fKeepAlive);
|
|
}
|
|
else
|
|
{
|
|
pStdId->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL,"CoMarshalInterface: pUnk:%x hr:%x\n",pUnk,hr));
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoUnmarshalInterface, public
|
|
//
|
|
// Synopsis: Unmarshals a marshaled interface pointer from the stream.
|
|
//
|
|
// Notes: when a controlling unknown is supplied, it is assumed that
|
|
// the HANDLER for the class has done a CreateInstance and wants
|
|
// to aggregate just the proxymanager, ie. we dont want to
|
|
// instantiate a new class handler (the default unmarshalling
|
|
// behaviour).
|
|
//
|
|
// History: 23-Nov-92 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to static marshaler and
|
|
// new marshaling format
|
|
// 20-Feb-95 Rickhi switched to newer marshal format
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoUnmarshalInterface(IStream *pStm,
|
|
REFIID riid,
|
|
void **ppv)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoUnmarshalInterface");
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
|
|
ComDebOut((DEB_MARSHAL,
|
|
"CoUnmarshalInterface: pStm:%x riid:%I\n", pStm, &riid));
|
|
|
|
// validate the input parameters
|
|
if (pStm == NULL || ppv == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppv = NULL;
|
|
|
|
HRESULT hr = InitChannelIfNecessary();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// read the objref from the stream.
|
|
OBJREF objref;
|
|
hr = ReadObjRef(pStm, objref);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (objref.flags & OBJREF_CUSTOM)
|
|
{
|
|
// uses custom marshaling, create an instance and ask that guy
|
|
// to do the unmarshaling. special case createinstance for the
|
|
// freethreaded marshaler.
|
|
|
|
IMarshal *pIM;
|
|
|
|
if (IsEqualCLSID(CLSID_InProcFreeMarshaler, ORCST(objref).clsid))
|
|
{
|
|
hr = GetInProcFreeMarshaler(&pIM);
|
|
}
|
|
else
|
|
{
|
|
hr = CoCreateInstance(ORCST(objref).clsid, NULL, CLSCTX_INPROC,
|
|
IID_IMarshal, (void **)&pIM);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIM->UnmarshalInterface(pStm, objref.iid, ppv);
|
|
pIM->Release();
|
|
}
|
|
else
|
|
{
|
|
// seek past the custom marshalers data so we leave the
|
|
// stream at the correct position.
|
|
|
|
LARGE_INTEGER libMove;
|
|
libMove.LowPart = ORCST(objref).size;
|
|
libMove.HighPart = 0;
|
|
pStm->Seek(libMove, STREAM_SEEK_CUR, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// uses standard marshaling, call API to find or create the
|
|
// instance of CStdMarshal for the oid inside the objref, and
|
|
// ask that instance to unmarshal the interface. This covers
|
|
// handler unmarshaling also.
|
|
|
|
hr = UnmarshalObjRef(objref, ppv);
|
|
}
|
|
|
|
// free the objref we read above
|
|
FreeObjRef(objref);
|
|
|
|
if (!InlineIsEqualGUID(riid, GUID_NULL) &&
|
|
!InlineIsEqualGUID(riid, objref.iid) && SUCCEEDED(hr))
|
|
{
|
|
// the interface iid requested was different than the one that
|
|
// was marshaled (and was not GUID_NULL), so go get the requested
|
|
// one and release the marshaled one. GUID_NULL is used by the Ndr
|
|
// unmarshaling engine and means return whatever interface was
|
|
// marshaled.
|
|
|
|
IUnknown *pUnk = (IUnknown *)*ppv;
|
|
|
|
#ifdef WX86OLE
|
|
if (gcwx86.IsN2XProxy(pUnk))
|
|
{
|
|
// Tell wx86 thunk layer to thunk as IUnknown
|
|
gcwx86.SetStubInvokeFlag((BOOL)1);
|
|
}
|
|
#endif
|
|
|
|
hr = pUnk->QueryInterface(riid, ppv);
|
|
pUnk->Release();
|
|
}
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL, "CoUnmarshalInterface: pUnk:%x hr:%x\n",
|
|
*ppv, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoReleaseMarshalData, public
|
|
//
|
|
// Synopsis: release the reference created by CoMarshalInterface
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 23-Nov-92 Rickhi
|
|
// 11-Dec-93 CraigWi Switched to static marshaler and
|
|
// new marshaling format
|
|
// 20-Feb-95 Rickhi switched to newer marshal format
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoReleaseMarshalData(IStream *pStm)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoReleaseMarshalData");
|
|
ComDebOut((DEB_MARSHAL, "CoReleaseMarshalData pStm:%x\n", pStm));
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **) &pStm);
|
|
|
|
// validate the input parameters
|
|
if (pStm == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = InitChannelIfNecessary();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// read the objref from the stream.
|
|
OBJREF objref;
|
|
hr = ReadObjRef(pStm, objref);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (objref.flags & OBJREF_CUSTOM)
|
|
{
|
|
// object uses custom marshaling. create an instance of
|
|
// the unmarshaling code and ask it to release the marshaled
|
|
// data.
|
|
|
|
IMarshal *pIM;
|
|
|
|
if (IsEqualCLSID(CLSID_InProcFreeMarshaler, ORCST(objref).clsid))
|
|
{
|
|
hr = GetInProcFreeMarshaler(&pIM);
|
|
}
|
|
else
|
|
{
|
|
hr = CoCreateInstance(ORCST(objref).clsid, NULL, CLSCTX_INPROC,
|
|
IID_IMarshal, (void **)&pIM);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIM->ReleaseMarshalData(pStm);
|
|
pIM->Release();
|
|
}
|
|
else
|
|
{
|
|
// seek past the custom marshalers data so we leave the
|
|
// stream at the correct position.
|
|
|
|
LARGE_INTEGER libMove;
|
|
libMove.LowPart = ORCST(objref).size;
|
|
libMove.HighPart = 0;
|
|
pStm->Seek(libMove, STREAM_SEEK_CUR, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// uses standard marshaling, find or create the instance of
|
|
// CStdMarshal for the oid inside the objref, and ask that
|
|
// instance to unmarshal the interface.
|
|
|
|
CStdMarshal *pStdMshl;
|
|
hr = FindStdMarshal(objref, &pStdMshl);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pStdMshl->ReleaseMarshalObjRef(objref);
|
|
pStdMshl->Release();
|
|
}
|
|
else if (hr == CO_E_OBJNOTCONNECTED)
|
|
{
|
|
// it was for this process but the object is already dead
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
// free the objref we read above
|
|
FreeObjRef(objref);
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL, "CoReleaseMarshalData hr:%x\n", hr));
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoDisconnectObject, public
|
|
//
|
|
// synopsis: disconnects all clients of an object by marking their
|
|
// connections as terminted abnormaly.
|
|
//
|
|
// History: 04-Oct-93 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to identity object
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoDisconnectObject(IUnknown *pUnk, DWORD dwReserved)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoDisconnectObject");
|
|
ComDebOut((DEB_MARSHAL, "CoDisconnectObject pUnk:%x dwRes:%x\n",
|
|
pUnk, dwReserved));
|
|
|
|
// validate the input parameters
|
|
if (pUnk == NULL || dwReserved != 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!IsValidInterface(pUnk))
|
|
return E_INVALIDARG;
|
|
|
|
if (!IsApartmentInitialized())
|
|
{
|
|
return CO_E_NOTINITIALIZED;
|
|
}
|
|
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,&pUnk);
|
|
|
|
IMarshal *pIM = NULL;
|
|
HRESULT hr = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// object does not support IMarshal directly. Find its standard
|
|
// marshaler if there is one, otherwise return an error.
|
|
|
|
CStdIdentity *pStdId;
|
|
hr = LookupIDFromUnk(pUnk, 0, &pStdId);
|
|
pIM = (IMarshal *)pStdId;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIM->DisconnectObject(dwReserved);
|
|
pIM->Release();
|
|
}
|
|
else
|
|
{
|
|
// could not get std marshal, must be disconnected already
|
|
return S_OK;
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL,"CoDisconnectObject pIM:%x hr:%x\n", pIM, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoLockObjectExternal, public
|
|
//
|
|
// synopsis: adds/revokes a strong reference count to/from the
|
|
// identity for the given object.
|
|
//
|
|
// parameters: [punkObject] - IUnknown of the object
|
|
// [fLock] - lock/unlock the object
|
|
// [fLastUR] - last unlock releases.
|
|
//
|
|
// History: 23-Nov-92 Rickhi Created
|
|
// 11-Dec-93 CraigWi Switched to identity object
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoLockObjectExternal(IUnknown *pUnk, BOOL fLock, BOOL fLastUR)
|
|
{
|
|
TRACECALL(TRACE_MARSHAL, "CoLockObjectExternal");
|
|
ComDebOut((DEB_MARSHAL,
|
|
"CoLockObjectExternal pUnk:%x fLock:%x fLastUR:%x\n", pUnk, fLock, fLastUR));
|
|
|
|
if (!IsValidInterface(pUnk))
|
|
return E_INVALIDARG;
|
|
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnk);
|
|
|
|
HRESULT hr = InitChannelIfNecessary();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CStdIdentity *pStdID;
|
|
hr = LookupIDFromUnk(pUnk, (fLock) ? IDLF_CREATE : 0, &pStdID);
|
|
|
|
switch (hr)
|
|
{
|
|
case S_OK:
|
|
|
|
// REF COUNTING: inc or dec external ref count
|
|
hr = pStdID->LockObjectExternal(fLock, fLastUR);
|
|
pStdID->Release();
|
|
break;
|
|
|
|
case CO_E_OBJNOTREG:
|
|
// unlock when not registered; 16bit code returned NOERROR;
|
|
// disconnected handler goes to S_OK case above.
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case E_OUTOFMEMORY:
|
|
break;
|
|
|
|
default:
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
ComDebOut((DEB_MARSHAL,
|
|
"CoLockObjectExternal pStdID:%x hr:%x\n", pStdID, hr));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoIsHandlerConnected, public
|
|
//
|
|
// Synopsis: Returns whether or not handler is connected to remote
|
|
//
|
|
// Algorithm: QueryInterface to IProxyManager. If this is supported,
|
|
// then this is a handler. We ask the handler
|
|
// for its opinion otherwise we simply return TRUE.
|
|
//
|
|
// History: 04-Oct-93 Rickhi Created
|
|
//
|
|
// Notes: The answer of this routine may be wrong by the time
|
|
// the routine returns. This is correct behavior as
|
|
// this routine is primilary to cleanup state associated
|
|
// with connections.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk)
|
|
{
|
|
// validate input parameters
|
|
if (!IsValidInterface(pUnk))
|
|
return FALSE;
|
|
|
|
// Assume it is connected
|
|
BOOL fResult = TRUE;
|
|
|
|
// Handler should support IProxyManager
|
|
IProxyManager *pPM;
|
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnk);
|
|
if (SUCCEEDED(pUnk->QueryInterface(IID_IProxyManager, (void **)&pPM)))
|
|
{
|
|
// We have something that thinks its is an Ole handler so we ask
|
|
fResult = pPM->IsConnected();
|
|
pPM->Release();
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: GetStaticUnMarshaler, private
|
|
//
|
|
// Synopsis: Returns the static instance of the CStdMarshal.
|
|
//
|
|
// History: 20-Feb-95 Rickhi Created.
|
|
//
|
|
// Notes: The standard marshaler must be able to resolve identity, that
|
|
// is two proxies for the same object must never be created in
|
|
// the same apartment. Given that, it makes sense to let the
|
|
// standard guy do the unmarshaling. Since we dont know the
|
|
// identity of the object upfront, and any instance will do, we
|
|
// use a static instance to handle unmarshal.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
INTERNAL GetStaticUnMarshaler(IMarshal **ppIM)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
LOCK
|
|
if (gpStdMarshal == NULL)
|
|
{
|
|
// the global instance has not been created yet, so go make it now.
|
|
hr = CreateIdentityHandler(NULL, 0, IID_IMarshal,
|
|
(void **)&gpStdMarshal);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// dont let anybody but us delete this thing.
|
|
((CStdIdentity *)gpStdMarshal)->SetLockedInMemory();
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
*ppIM = gpStdMarshal;
|
|
if (gpStdMarshal)
|
|
{
|
|
gpStdMarshal->AddRef();
|
|
}
|
|
UNLOCK;
|
|
return hr;
|
|
}
|
|
|
|
#ifdef WX86OLE
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoGetIIDFromMarshaledInterface, public
|
|
//
|
|
// Synopsis: Returns the IID embedded inside a marshaled interface
|
|
// pointer. Needed by the x86 thunking code.
|
|
//
|
|
// History: 16-Apr-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDAPI CoGetIIDFromMarshaledInterface(IStream *pStm, IID *piid)
|
|
{
|
|
ULARGE_INTEGER ulSeekEnd;
|
|
LARGE_INTEGER lSeekStart, lSeekEnd;
|
|
LISet32(lSeekStart, 0);
|
|
|
|
// remember the current position
|
|
HRESULT hr = pStm->Seek(lSeekStart, STREAM_SEEK_CUR, &ulSeekEnd);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// read the first part of the objref which contains the IID
|
|
// also check to ensure the objref is at least partially sane
|
|
|
|
OBJREF objref;
|
|
hr = StRead(pStm, &objref, 2*sizeof(ULONG) + sizeof(IID));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if ((objref.signature != OBJREF_SIGNATURE) ||
|
|
(objref.flags & OBJREF_RSRVD_MBZ) ||
|
|
(objref.flags == 0))
|
|
{
|
|
// the objref signature is bad, or one of the reserved
|
|
// bits in the flags is set, or none of the required bits
|
|
// in the flags is set. the objref cant be interpreted so
|
|
// fail the call.
|
|
|
|
Win4Assert(!"Invalid Objref Flags");
|
|
return RPC_E_INVALID_OBJREF;
|
|
}
|
|
|
|
// extract the IID
|
|
*piid = objref.iid;
|
|
}
|
|
|
|
// put the seek pointer back to the original location
|
|
lSeekEnd.LowPart = ulSeekEnd.LowPart;
|
|
lSeekEnd.HighPart = (LONG)ulSeekEnd.HighPart;
|
|
hr = pStm->Seek(lSeekEnd, STREAM_SEEK_SET, NULL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
#endif
|