919 lines
27 KiB
C++
919 lines
27 KiB
C++
|
//+-------------------------------------------------------------------
|
||
|
//
|
||
|
// File: sichnl.cxx
|
||
|
//
|
||
|
// Contents: stub implementation for remoting IChannelService
|
||
|
//
|
||
|
// Classes: none
|
||
|
//
|
||
|
// Functions: ICS_GetObjectHdl - get object handle
|
||
|
// ICS_ReleaseObject - release object
|
||
|
// POBJCTX_Rundown - rundown on dropped connections
|
||
|
//
|
||
|
// History: 23-Nov-92 Rickhi Created
|
||
|
// 31-Dec-93 ErikGav Chicago port
|
||
|
// 19 Jul 94 CraigWi Added support for ASYNC calls
|
||
|
//
|
||
|
//--------------------------------------------------------------------
|
||
|
|
||
|
#include <ole2int.h>
|
||
|
|
||
|
#include <olerem.h>
|
||
|
#include <channelb.hxx> // CRpcChannelBuffer
|
||
|
#include <ichnl.h> // midl generated interface definitions
|
||
|
#include <objact.hxx> // gdllcacheInprocSrv
|
||
|
#include <sichnl.hxx>
|
||
|
|
||
|
#include "callmain.hxx" // for access to callcat of outgoing call
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ThreadGetChannelId
|
||
|
//
|
||
|
// Synopsis: Creates a channel for the specified remote handler and
|
||
|
// service object.
|
||
|
//
|
||
|
// Arguments: rh - remote handler to call
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 30 Nov 93 AlexMit Created
|
||
|
// 12 May 94 CraigWi Removed middle man case
|
||
|
//
|
||
|
// Notes: This must run on the server thread because the RH release
|
||
|
// can cause the object to be released (if the context handle
|
||
|
// ran down during the call).
|
||
|
//
|
||
|
// REF COUNTING:
|
||
|
//
|
||
|
// We always increment the marshal count (i.e., set it to 1) because
|
||
|
// then clients don't have to make a separate call to get it incremented.
|
||
|
//
|
||
|
// In all normal cases we already did the AddConnection; in the middle man
|
||
|
// case, this was done during marshaling by calling over to the server. This
|
||
|
// was important to ensure the object stays alive in the face of other
|
||
|
// disconnects. In the table case we always need the AddConnection since the
|
||
|
// marshal just did AddConnection for the marshal itself.
|
||
|
//
|
||
|
// CODEWORK: when we precompute the channel, this routine would only be used
|
||
|
// for the table case (since we would need to get the right channel created).
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT ThreadGetChannelId( STHREADCALLINFO *call )
|
||
|
{
|
||
|
SGetChannelId *params = (SGetChannelId *) call;
|
||
|
IStdIdentity *pStdId = NULL;
|
||
|
IMarshal *pIM = NULL;
|
||
|
IRemoteHdlr *pRH = NULL;
|
||
|
CRpcChannelBuffer *pChannel = NULL;
|
||
|
CChannelControl *controller;
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
BOOL fAddedConnection = FALSE;
|
||
|
|
||
|
// See if the client (the app that made this call) died before we got
|
||
|
// here.
|
||
|
if (!params->service->IsConnected())
|
||
|
{
|
||
|
// It doesn't matter what is returned since the caller is dead.
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
// See if the channel has already been created. The client can attempt
|
||
|
// to unmarshal the same channel twice when it yields to get the
|
||
|
// the channel id.
|
||
|
params->channel_id = ChannelList.LookupIdByOid( params->object_id,
|
||
|
params->service,
|
||
|
params->dwClientTID );
|
||
|
if (params->channel_id != BAD_CHANNEL_ID)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
BEGIN_BLOCK
|
||
|
|
||
|
// Find the remote handler. Since the identity holds the remote
|
||
|
// handler alive, it can not be released till the remote handler has
|
||
|
// been released.
|
||
|
|
||
|
hr = LookupIDFromID(params->object_id, TRUE, &pStdId);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
EXIT_BLOCK;
|
||
|
}
|
||
|
|
||
|
if ((pIM = pStdId->GetStdRemMarshal()) == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
EXIT_BLOCK;
|
||
|
}
|
||
|
|
||
|
hr = pIM->QueryInterface(IID_IRemoteHdlr, (void **) &pRH);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
EXIT_BLOCK;
|
||
|
}
|
||
|
|
||
|
if ((params->flags & HDLRFLAGS_TABLE) != MSHLFLAGS_NORMAL)
|
||
|
{
|
||
|
// this is always strong since we are adding the
|
||
|
// connection that is normally added at marshal time
|
||
|
// Note: we count on the fact this only updates the
|
||
|
// identity object and makes no call to the channel.
|
||
|
hr = pStdId->AddConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
EXIT_BLOCK;
|
||
|
}
|
||
|
|
||
|
fAddedConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
// Create the channel.
|
||
|
GetLocalChannelControl(controller);
|
||
|
|
||
|
pChannel = new CRpcChannelBuffer(pRH, params->service,
|
||
|
params->dwClientTID, controller, server_cs);
|
||
|
|
||
|
if (pChannel == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
EXIT_BLOCK;
|
||
|
}
|
||
|
|
||
|
// Add the channel to the list; AddRefs the channel ptr
|
||
|
params->channel_id = ChannelList.Add(pChannel);
|
||
|
|
||
|
if (params->channel_id == BAD_CHANNEL_ID)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
EXIT_BLOCK;
|
||
|
}
|
||
|
|
||
|
|
||
|
// do this after the above add connection because the
|
||
|
// TransferMarshalConnection may convert it to a
|
||
|
// weak count if this is the container connection.
|
||
|
pChannel->TransferMarshalConnection();
|
||
|
|
||
|
// now that the channel is in a consistent state, we can test it
|
||
|
pChannel->AssertValid(FALSE, TRUE);
|
||
|
|
||
|
// If we made it to here, we succeeded
|
||
|
hr = S_OK;
|
||
|
|
||
|
END_BLOCK;
|
||
|
|
||
|
if (pChannel != NULL)
|
||
|
{
|
||
|
pChannel->Release();
|
||
|
}
|
||
|
|
||
|
if (pRH != NULL)
|
||
|
{
|
||
|
pRH->Release();
|
||
|
}
|
||
|
|
||
|
if (pIM != NULL)
|
||
|
{
|
||
|
pIM->Release();
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
params->channel_id = BAD_CHANNEL_ID;
|
||
|
|
||
|
if (fAddedConnection)
|
||
|
{
|
||
|
// Note: we don't say last release closes because this
|
||
|
// might be marshal table weak and we don't want to
|
||
|
// remove it just because of a transitory out of memory.
|
||
|
pStdId->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0,
|
||
|
FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pStdId != NULL)
|
||
|
{
|
||
|
pStdId->Release();
|
||
|
}
|
||
|
|
||
|
CairoleDebugOut((DEB_MARSHAL,
|
||
|
"ICS_GetChannelId pSRV=%x pRH=%x pChannel=%x ChannelID=%x\n",
|
||
|
params->service, pRH, pChannel, params->channel_id));
|
||
|
|
||
|
Win4Assert( (hr == S_OK && params->channel_id != BAD_CHANNEL_ID) ||
|
||
|
(hr != S_OK && params->channel_id == BAD_CHANNEL_ID) );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SReleaseChannel::MakeAsyncCopy
|
||
|
//
|
||
|
// Synopsis: Does the copy operation for async release
|
||
|
//
|
||
|
// Arguments: [thread] -- NULL ; indicates that we are to allocate a new one
|
||
|
//
|
||
|
// History: 26-June-94 CraigWi Created
|
||
|
// 12-July-94 CraigWi Made into method on SReleaseChannel
|
||
|
//
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
STHREADCALLINFO *SReleaseChannel::MakeAsyncCopy(STHREADCALLINFO *thread)
|
||
|
{
|
||
|
Win4Assert(thread == NULL);
|
||
|
|
||
|
// allocate unconstructed packet
|
||
|
SReleaseChannel *prelchan = (SReleaseChannel *)PrivMemAlloc(sizeof(SReleaseChannel));
|
||
|
|
||
|
if (prelchan == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
prelchan->SReleaseChannel::SReleaseChannel(init_vtable);
|
||
|
|
||
|
// call base class to initialize its part of the instance
|
||
|
if (STHREADCALLINFO::MakeAsyncCopy(prelchan) == NULL)
|
||
|
{
|
||
|
PrivMemFree(prelchan);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// NOTE: we transfer the responsiblity of releasing the channel
|
||
|
// to the copy and thus do not AddRef.
|
||
|
|
||
|
prelchan->count = count;
|
||
|
prelchan->async = async;
|
||
|
prelchan->channel_id = channel_id;
|
||
|
|
||
|
// NULL out this pointer so the destroy function can tell the difference
|
||
|
// between the client side (where cancel is called) and the server side
|
||
|
// (where async is called).
|
||
|
prelchan->service = NULL;
|
||
|
|
||
|
return prelchan;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ThreadReleaseChannel
|
||
|
//
|
||
|
// Synopsis: Decrements strong count. Called on the correct thread for
|
||
|
// the server
|
||
|
//
|
||
|
// Arguments: params - remote handler to call and count
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 8 Nov 93 AlexMit Created
|
||
|
//
|
||
|
// Notes: This must run on the server thread because the RH release
|
||
|
// may call release on the server object.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT ThreadReleaseChannel( STHREADCALLINFO *call )
|
||
|
{
|
||
|
SReleaseChannel *params = (SReleaseChannel *) call;
|
||
|
|
||
|
// lookup, AddRef, and remove the channel from the channel list.
|
||
|
CRpcChannelBuffer *pChnl = ChannelList.Lookup(params->channel_id, TRUE, TRUE);
|
||
|
|
||
|
if (pChnl)
|
||
|
{
|
||
|
#if DBG==1
|
||
|
pChnl->DebugCheckMarshalCnt( params->count );
|
||
|
#endif
|
||
|
// do a disconnect here since there may be other uses of the
|
||
|
// channel pending. the channel has already been removed from the
|
||
|
// channel list
|
||
|
pChnl->DisconnectObject(0);
|
||
|
|
||
|
// This release of the channel will make it go away since it has already
|
||
|
// been removed from the channel list which released it.
|
||
|
pChnl->Release();
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CairoleDebugOut((DEB_MARSHAL, "ThreadReleaseChannel pChnl not found\n"));
|
||
|
return E_HANDLE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ThreadDoChannelOperation
|
||
|
//
|
||
|
// Synopsis: Does channel operation. Called on the correct thread for
|
||
|
// the server.
|
||
|
//
|
||
|
// Arguments: params - object id to release
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 12 May 94 CraigWi Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT ThreadDoChannelOperation( STHREADCALLINFO *call )
|
||
|
{
|
||
|
SDoChannelOperation *params = (SDoChannelOperation *) call;
|
||
|
IRemoteHdlr *pRH;
|
||
|
BOOL bDoesSupport = FALSE;
|
||
|
HRESULT result = S_OK;
|
||
|
|
||
|
|
||
|
// find the channel and AddRef it
|
||
|
CRpcChannelBuffer *pChnl = ChannelList.Lookup(params->channel_id, FALSE, TRUE);
|
||
|
|
||
|
if (pChnl == NULL)
|
||
|
{
|
||
|
CairoleDebugOut((DEB_WARN, "ThreadDoChannelOp pChnl not found\n"));
|
||
|
return E_HANDLE;
|
||
|
}
|
||
|
|
||
|
if (pChnl->IsConnected() != S_OK)
|
||
|
{
|
||
|
pChnl->Release();
|
||
|
return CO_E_OBJNOTCONNECTED;
|
||
|
}
|
||
|
|
||
|
#if DBG == 1
|
||
|
// BUGBUG: To enable this debug check we would have to pass the parameters here.
|
||
|
// if (params->chop & CHOPFLAG_CHECK_OID_ENDPOINT_APT)
|
||
|
// pChnl->DebugCheckOIDEndPointApt(params->guid, params->pEndPoint, params->hapt);
|
||
|
#endif
|
||
|
|
||
|
pRH = pChnl->GetRH();
|
||
|
|
||
|
switch (params->chop & CHOP_OPERATION)
|
||
|
{
|
||
|
case CHOP_TRANSFER_MARSHALCONNECTION:
|
||
|
// REF COUNTING
|
||
|
// This transfers responsibility for a single strong connection
|
||
|
// (that is added during marshaling) to the server channel.
|
||
|
|
||
|
// CODEWORK: when we precompute channel, this call would no longer be
|
||
|
// necessary since the marshal did the increment in the normal case
|
||
|
// and the table marshal doesn't change the count (either locally
|
||
|
// or remotely).
|
||
|
|
||
|
result = pChnl->TransferMarshalConnection();
|
||
|
break;
|
||
|
|
||
|
case CHOP_ADD_MARSHALCONNECTION:
|
||
|
// REF COUNTING
|
||
|
// marshaling on client; simulate what marshaling on server does
|
||
|
result = pRH->AddConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0);
|
||
|
break;
|
||
|
|
||
|
case CHOP_REMOVE_MARSHALCONNECTION:
|
||
|
// REF COUNTING
|
||
|
// marshaling on client; undo above
|
||
|
// fLastReleaseClose == FALSE on purpose; ignore errors; see imchnl.cxx.
|
||
|
pRH->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE,0,FALSE);
|
||
|
break;
|
||
|
|
||
|
case CHOP_LOCK_CONNECTION:
|
||
|
pChnl->LockConnection();
|
||
|
break;
|
||
|
|
||
|
case CHOP_UNLOCK_CONNECTION:
|
||
|
pChnl->UnlockConnection(params->chop&CHOPFLAG_LASTUNLOCKCLOSES);
|
||
|
break;
|
||
|
|
||
|
case CHOP_DOESSUPPORTIID:
|
||
|
bDoesSupport = pRH->DoesSupportIID(params->guid);
|
||
|
|
||
|
if (!bDoesSupport)
|
||
|
result = E_NOINTERFACE;
|
||
|
// else S_OK set above
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Win4Assert(!"Bad chop in DoChannelOperation");
|
||
|
result = E_UNEXPECTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// this balances the lookup done above
|
||
|
pChnl->Release();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_GetContextHdl
|
||
|
//
|
||
|
// Synopsis: server side of RPC GetObjectHdl function. generates
|
||
|
// a context handle for the object.
|
||
|
//
|
||
|
// Arguments: [hRpcBind] - Rpc bind handle
|
||
|
// [ChannelID] - channel (and hence object) identifier
|
||
|
// [dwflags] - marshal flags
|
||
|
// [ppObjCtx] - object context handle to return
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 23-Nov-92 Rickhi Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_GetContextHdl(
|
||
|
handle_t hRpcBind, // rpc handle call was made on
|
||
|
SEndPoint *caller_bindings,// string bindings of caller
|
||
|
PPOBJCTX ppObjCtx, // returned ctx hdl
|
||
|
error_status_t *perrstat) // RPC error status
|
||
|
{
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*perrstat = 0;
|
||
|
HRESULT hr;
|
||
|
|
||
|
CairoleDebugOut((DEB_ENDPNT, "ICS_GetContextHdl SEp:%p\n", caller_bindings));
|
||
|
|
||
|
// Find or create a service object.
|
||
|
CRpcService *pService = FindSRVFromEP(caller_bindings, TRUE);
|
||
|
CairoleDebugOut((DEB_ENDPNT, "ICS_GetContextHdl RpcService:%p\n", pService));
|
||
|
|
||
|
if (pService)
|
||
|
{
|
||
|
// here we give the AddRef on the service object away with the context
|
||
|
// handle; the only way this is released is via the rundown.
|
||
|
|
||
|
*ppObjCtx = pService;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppObjCtx = NULL;
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
CairoleDebugOut((DEB_MARSHAL, "ICS_GetContextHdl pSRV:%x hr:%x\n", pService, hr));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_ReleaseContextHdl
|
||
|
//
|
||
|
// Synopsis: Releases a context handle.
|
||
|
//
|
||
|
// Arguments: [ppObjCtx] - object context handle to return
|
||
|
//
|
||
|
// Returns: S_OK
|
||
|
//
|
||
|
// History: 2 Aug 94 AlexMit Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_ReleaseContextHdl(
|
||
|
PPOBJCTX ppObjCtx, // released ctx hdl
|
||
|
error_status_t *perrstat) // RPC error status
|
||
|
{
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*perrstat = 0;
|
||
|
*ppObjCtx = NULL;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_GetChannelId
|
||
|
//
|
||
|
// Synopsis: server side of RPC GetChannelId function. Creates
|
||
|
// channel and returns channel id.
|
||
|
//
|
||
|
// Arguments: see comments below
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 27 Nov 93 AlexMit Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_GetChannelId(
|
||
|
PPOBJCTX ppObjCtx, // context handle
|
||
|
SEndPoint *caller_bindings, // string bindings of caller
|
||
|
OID ObjectId, // object id
|
||
|
DWORD dwFlags, // marshal flags
|
||
|
HAPT server_apt, // server apartment
|
||
|
GUID logical_thread, // logical thread of caller
|
||
|
DWORD dwClientTID, // callers thread id
|
||
|
DWORD *dwChannelId, // channel id
|
||
|
error_status_t *prpcstat) // RPC error status
|
||
|
{
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*prpcstat = 0;
|
||
|
*dwChannelId = BAD_CHANNEL_ID;
|
||
|
|
||
|
// Make sure this service object exists. Leave it on the list if found.
|
||
|
CRpcService *pSrv = FindSRVFromContext(*ppObjCtx, FALSE);
|
||
|
|
||
|
// If the service object doesn't exists, create it.
|
||
|
if (pSrv == NULL)
|
||
|
{
|
||
|
CairoleDebugOut((DEB_CHANNEL,
|
||
|
"ICS_GetChannelId Service Object not found *ppObjCtx=%x\n",
|
||
|
*ppObjCtx));
|
||
|
pSrv = FindSRVFromEP(caller_bindings, TRUE);
|
||
|
*ppObjCtx = pSrv;
|
||
|
|
||
|
// Add a reference count for the pointer held by the context handle.
|
||
|
if (pSrv != NULL)
|
||
|
pSrv->AddRef();
|
||
|
}
|
||
|
|
||
|
if (pSrv)
|
||
|
{
|
||
|
SGetChannelId params(
|
||
|
ThreadGetChannelId,
|
||
|
CALLCAT_INTERNALINPUTSYNC,
|
||
|
logical_thread);
|
||
|
|
||
|
// Get to the server thread to make this call.
|
||
|
params.service = pSrv; // transfer addref; release in dtor
|
||
|
params.object_id = ObjectId;
|
||
|
params.flags = dwFlags;
|
||
|
params.dwClientTID = dwClientTID;
|
||
|
params.channel_id = BAD_CHANNEL_ID;
|
||
|
HRESULT result = CChannelControl::GetToCOMThread(server_apt, ¶ms);
|
||
|
|
||
|
// fill in the return parameters
|
||
|
*dwChannelId = params.channel_id;
|
||
|
|
||
|
Win4Assert( (result == S_OK && *dwChannelId != BAD_CHANNEL_ID) ||
|
||
|
(result != S_OK && *dwChannelId == BAD_CHANNEL_ID) );
|
||
|
return result;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_ReleaseChannel
|
||
|
//
|
||
|
// Synopsis: server side of RPC ReleaseChannelHdl function. releases the
|
||
|
// object and frees the context handle for the interface.
|
||
|
//
|
||
|
// Arguments: [hRpcBind] - rpc handle call was made on
|
||
|
// [ChannelID] - channel to do the release on
|
||
|
// [ulMarshalCnt] - count of references to Release
|
||
|
// [logical_thread] - logical thread id
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 23-Nov-92 Rickhi Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_ReleaseChannel(
|
||
|
handle_t hRpcBind, // rpc handle call was made on
|
||
|
DWORD ChannelID, // id for channel to release
|
||
|
ULONG ulMarshalCnt, // count to release
|
||
|
BOOL fAsync, // TRUE -> async (returns immediately)
|
||
|
GUID logical_thread, // logical thread id of caller
|
||
|
error_status_t *perrstat) // RPC error status
|
||
|
{
|
||
|
CairoleDebugOut((DEB_CHANNEL, "ICS_ReleaseChannel for ChannelID=%x\n", ChannelID));
|
||
|
|
||
|
HRESULT hr = E_HANDLE;
|
||
|
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*perrstat = 0;
|
||
|
|
||
|
// look for the channel id in the channel list, and return the
|
||
|
// channel controller AddRef'd. if not there, return an error.
|
||
|
|
||
|
CChannelControl *pChanCtrl = ChannelList.LookupControl(ChannelID);
|
||
|
|
||
|
if (pChanCtrl)
|
||
|
{
|
||
|
CairoleDebugOut((DEB_MARSHAL | DEB_CHANNEL,
|
||
|
"ICS_ReleaseChannel ChannelID=%x\n", ChannelID ));
|
||
|
|
||
|
|
||
|
SReleaseChannel params(
|
||
|
ThreadReleaseChannel,
|
||
|
fAsync ? CALLCAT_ASYNC : CALLCAT_INTERNALSYNC,
|
||
|
logical_thread);
|
||
|
|
||
|
params.channel_id = ChannelID;
|
||
|
params.count = ulMarshalCnt;
|
||
|
params.service = NULL;
|
||
|
|
||
|
hr = pChanCtrl->GetToCOMThread( ¶ms );
|
||
|
pChanCtrl->Release();
|
||
|
}
|
||
|
#if DBG==1
|
||
|
else
|
||
|
{
|
||
|
CairoleDebugOut((DEB_WARN,
|
||
|
"ICS_ReleaseChannel ChanCtrl not found for ChannelID=%x\n", ChannelID));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
CairoleDebugOut((DEB_CHANNEL,
|
||
|
"ICS_ReleaseChannel ChanCtrl for ChannelID=%x done \n", ChannelID));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#ifdef _CHICAGO_
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: ICS_AsyncReleaseChannel
|
||
|
//
|
||
|
// Synopsis: Used for wmsg protocolls where the call is made async
|
||
|
// by the protocoll itself.
|
||
|
//
|
||
|
// Arguments: [hRpcBind] --
|
||
|
// [ChannelID] --
|
||
|
// [ulMarshalCnt] --
|
||
|
// [fAsync] --
|
||
|
// [immediately] --
|
||
|
// [logical_thread] --
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// History: 3-31-95 JohannP (Johann Posch) Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
extern "C" void ICS_AsyncReleaseChannel(
|
||
|
handle_t hRpcBind, // rpc handle call was made on
|
||
|
DWORD ChannelID, // id for channel to release
|
||
|
ULONG ulMarshalCnt, // count to release
|
||
|
BOOL fAsync, // TRUE -> async (returns immediately)
|
||
|
GUID logical_thread) // logical thread id of caller
|
||
|
{
|
||
|
CairoleDebugOut((DEB_CHANNEL, "ICS_AsyncReleaseChannel for ChannelID=%x\n", ChannelID));
|
||
|
error_status_t errstat; // RPC error status
|
||
|
|
||
|
ICS_ReleaseChannel(
|
||
|
hRpcBind,
|
||
|
ChannelID,
|
||
|
ulMarshalCnt,
|
||
|
fAsync,
|
||
|
logical_thread,
|
||
|
&errstat);
|
||
|
|
||
|
CairoleDebugOut((DEB_CHANNEL,
|
||
|
"ICS_AsyncReleaseChannel ChanCtrl for ChannelID=%x done \n", ChannelID));
|
||
|
}
|
||
|
#endif // _CHICAGO_
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_SyncChannelOp
|
||
|
//
|
||
|
// Synopsis: server side of RPC DoChannelOperation function.
|
||
|
// Increments marshal count for channel
|
||
|
//
|
||
|
// Arguments: [hRpcBind] - rpc handle call was made on
|
||
|
// [ChannelID] - channel to do the release on
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 27-Nov-92 AlexMit Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_SyncChannelOp(
|
||
|
handle_t hRpcBind, // rpc handle call was made on
|
||
|
DWORD ChannelID, // id for channel to release
|
||
|
GUID logical_thread, // logical thread id of caller
|
||
|
DWORD chop, // CHOP_* : what to do
|
||
|
HAPT hapt, // server apartment to chk
|
||
|
const IID *pguid, // for CHOP_DOESSUPPORTIID
|
||
|
error_status_t *perrstat) // RPC error status
|
||
|
{
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*perrstat = 0;
|
||
|
|
||
|
// look for the channel id in the channel list and get the controller.
|
||
|
// if not there, return an error.
|
||
|
|
||
|
CChannelControl *pChanCtrl = ChannelList.LookupControl(ChannelID);
|
||
|
|
||
|
if (pChanCtrl)
|
||
|
{
|
||
|
CairoleDebugOut((DEB_MARSHAL,
|
||
|
"ICS_DoChannelOperation ChannelID=%x\n", ChannelID ));
|
||
|
|
||
|
CALLCATEGORY callcat = CALLCAT_SYNCHRONOUS;
|
||
|
|
||
|
SDoChannelOperation params(
|
||
|
ThreadDoChannelOperation,
|
||
|
callcat,
|
||
|
logical_thread);
|
||
|
|
||
|
params.chop = chop;
|
||
|
params.guid = *pguid;
|
||
|
params.service = NULL;
|
||
|
params.channel_id = ChannelID;
|
||
|
|
||
|
HRESULT hr = pChanCtrl->GetToCOMThread( ¶ms );
|
||
|
pChanCtrl->Release();
|
||
|
|
||
|
// The channel was released in ThreadDoChannelOperation since the
|
||
|
// connection could have rundown during this call causing the
|
||
|
// channel to go away.
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CairoleDebugOut((DEB_WARN,
|
||
|
"ICS_DoChannelOperation Channel not found ChannelID=%x\n",
|
||
|
ChannelID));
|
||
|
return E_HANDLE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_InputSyncChannelOp
|
||
|
//
|
||
|
// Synopsis: server side of RPC DoChannelOperation function.
|
||
|
// Increments marshal count for channel
|
||
|
//
|
||
|
// Arguments: [hRpcBind] - rpc handle call was made on
|
||
|
// [ChannelID] - channel to do the release on
|
||
|
//
|
||
|
// Returns: S_OK, E_HANDLE
|
||
|
//
|
||
|
// History: 27-Nov-92 AlexMit Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_InputSyncChannelOp(
|
||
|
handle_t hRpcBind, // rpc handle call was made on
|
||
|
DWORD ChannelID, // id for channel to release
|
||
|
GUID logical_thread, // logical thread id of caller
|
||
|
DWORD chop, // CHOP_* : what to do
|
||
|
HAPT hapt, // server apartment to chk
|
||
|
const IID *pguid, // for CHOP_DOESSUPPORTIID
|
||
|
error_status_t *perrstat) // RPC error status
|
||
|
{
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*perrstat = 0;
|
||
|
|
||
|
// look for the channel id in the channel list and get the controller.
|
||
|
// if not there, return an error.
|
||
|
|
||
|
CChannelControl *pChanCtrl = ChannelList.LookupControl(ChannelID);
|
||
|
|
||
|
if (pChanCtrl)
|
||
|
{
|
||
|
CairoleDebugOut((DEB_MARSHAL,
|
||
|
"ICS_DoChannelOperation ChannelID=%x\n", ChannelID ));
|
||
|
|
||
|
// We force the call type to input sync because we may be unmarshaling
|
||
|
// an interface on behalf of an input sync call and we will deadlock
|
||
|
// if we post a message. This is done for transfer, add and remove
|
||
|
// marshal connection.
|
||
|
CALLCATEGORY callcat = CALLCAT_INTERNALINPUTSYNC;
|
||
|
|
||
|
SDoChannelOperation params(
|
||
|
ThreadDoChannelOperation,
|
||
|
callcat,
|
||
|
logical_thread);
|
||
|
|
||
|
params.chop = chop;
|
||
|
params.guid = *pguid;
|
||
|
params.service = NULL;
|
||
|
params.channel_id = ChannelID;
|
||
|
|
||
|
HRESULT hr = pChanCtrl->GetToCOMThread( ¶ms );
|
||
|
pChanCtrl->Release();
|
||
|
|
||
|
// The channel was released in ThreadDoChannelOperation since the
|
||
|
// connection could have rundown during this call causing the
|
||
|
// channel to go away.
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CairoleDebugOut((DEB_WARN,
|
||
|
"ICS_DoChannelOperation Channel not found ChannelID=%x\n",
|
||
|
ChannelID));
|
||
|
return E_HANDLE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ICS_RegisterProtseq
|
||
|
//
|
||
|
// Synopsis: server side of RPC RegisterProtseq function. ensures
|
||
|
// that the protseq is registered and returns a new SEndPoint
|
||
|
//
|
||
|
// Arguments: [hRpcBind] - rpc handle call was made on
|
||
|
// [pwszProtseq] - protseq to register
|
||
|
// [ppSEp] - returned array of string bindings
|
||
|
//
|
||
|
// Returns: S_OK,
|
||
|
//
|
||
|
// History: 23-Nov-92 Rickhi Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" HRESULT ICS_RegisterProtseq(
|
||
|
handle_t hRpcBind, // rpc handle call was made on
|
||
|
WCHAR *pwszProtseq, // protseq to register
|
||
|
SEndPoint **ppSEp, // endpoint structure to return
|
||
|
error_status_t *perrstat) // RPC error status
|
||
|
{
|
||
|
HRESULT sc;
|
||
|
|
||
|
// Make sure this does not get inadvertently set by us
|
||
|
*perrstat = 0;
|
||
|
|
||
|
#ifndef _CHICAGO_
|
||
|
sc = LocalService()->RegisterProtseq(pwszProtseq);
|
||
|
|
||
|
*ppSEp = LocalService()->CopySEp();
|
||
|
#else
|
||
|
sc = E_FAIL;
|
||
|
#endif
|
||
|
|
||
|
CairoleDebugOut((DEB_MARSHAL, "ICS_RegisterProtseq %ws\n", pwszProtseq));
|
||
|
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: POBJCTX_rundown
|
||
|
//
|
||
|
// Synopsis: The routine to rundown and destroy state associated with a
|
||
|
// context that dies. Called by RPC runtime when a session
|
||
|
// closes, etc.
|
||
|
//
|
||
|
// Arguments: [phObj] - context handle (pointer to service object)
|
||
|
//
|
||
|
// History: 14-Apr-93 Rickhi Created.
|
||
|
//
|
||
|
// Notes: A connection has been lost. We've got outstanding state,
|
||
|
// pService, that we need to clean up. The cleanup consists
|
||
|
// of finding all channels using the service object and telling
|
||
|
// them that their connection is gone.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
extern "C" void POBJCTX_rundown(POBJCTX phObj)
|
||
|
{
|
||
|
CairoleDebugOut((DEB_MARSHAL, "POBJCTX_rundown called with: %p on thread %x\n",
|
||
|
phObj, GetCurrentThreadId()));
|
||
|
|
||
|
CRpcService *pService = NULL;
|
||
|
|
||
|
if (phObj != 0)
|
||
|
{
|
||
|
// Make sure we know about the context pointer. If we find it,
|
||
|
// Remove the service object from the list so that there are
|
||
|
// no races between Rundown and CoUninitialize.
|
||
|
|
||
|
pService = FindSRVFromContext(phObj, TRUE);
|
||
|
|
||
|
if (pService)
|
||
|
{
|
||
|
// disconnect channels using this object. Do not hold any
|
||
|
// locks across this call, since it might switch threads.
|
||
|
pService->Disconnect();
|
||
|
|
||
|
// here we Release one AddRef since this rundown call
|
||
|
// indicates that the context handle is now destroyed.
|
||
|
pService->Release();
|
||
|
|
||
|
// here we Release the AddRef done by FindSRVFromContext above.
|
||
|
pService->Release();
|
||
|
}
|
||
|
}
|
||
|
}
|