windows-nt/Source/XPSP1/NT/com/rpc/ndrlib/ccontext.cxx

372 lines
9.3 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/* --------------------------------------------------------------------
Microsoft OS/2 LAN Manager
Copyright(c) Microsoft Corp., 1991
-------------------------------------------------------------------- */
/* --------------------------------------------------------------------
Description :
Provides RPC client side stub context management
History :
stevez 01-15-91 First bits into the bucket.
-------------------------------------------------------------------- */
#include <precomp.hxx>
#include <osfpcket.hxx>
#include <context.hxx>
// The NDR format of a context is a (GUID, long) instead of a pointer
// in the server address space due history. Anyway, we just save this
// cookie, which is sent on the and mapped to and from a pointer
// on the server side.
const ULONG CONTEXT_MAGIC_VALUE = 0xFEDCBA98;
typedef struct _CCONTEXT {
RPC_BINDING_HANDLE hRPC; // binding handle assoicated with context
unsigned long MagicValue;
WIRE_CONTEXT NDR;
} CCONTEXT, *PCCONTEXT;
RPC_BINDING_HANDLE RPC_ENTRY
NDRCContextBinding (
IN NDR_CCONTEXT CContext
)
/*++
Routine Description:
Given a client context handle, we need to extract the binding from it.
If an addressing exception occurs, we need to return invalid handle
rather than GP-fault.
Arguments:
CContext - Supplies the client context handle.
Return Value:
The binding handle associated with the supplied client context handle
will be returned. If the client context handle is invalid, then we
raise the RPC_X_SS_CONTEXT_MISMATCH exception.
--*/
{
__try
{
if ( ((CCONTEXT PAPI *) CContext)->MagicValue != CONTEXT_MAGIC_VALUE )
{
RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
}
}
_except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
|| ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
{
RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
}
return(((CCONTEXT PAPI *) CContext)->hRPC);
}
RPC_STATUS RPC_ENTRY
RpcSsGetContextBinding (
IN void *ContextHandle,
OUT RPC_BINDING_HANDLE PAPI * Binding
)
{
RPC_STATUS Status = RPC_S_OK;
__try
{
if ( ((CCONTEXT PAPI *) ContextHandle)->MagicValue != CONTEXT_MAGIC_VALUE )
{
Status = RPC_S_INVALID_ARG;
}
else
{
*Binding = (((CCONTEXT PAPI *) ContextHandle)->hRPC);
}
}
__except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
|| ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
{
Status = RPC_S_INVALID_ARG;
}
return Status;
}
void RPC_ENTRY
NDRCContextMarshall ( // copy a context to a buffer
IN NDR_CCONTEXT hCC, // context to marshell
OUT void PAPI *pBuff // buffer to marshell to
)
// Copy the interal representation of a context into a buffer
//-----------------------------------------------------------------------//
{
#define hCContext ((CCONTEXT PAPI *) hCC) // cast opaque pointer to internal
THREAD *ThisThread;
ThisThread = RpcpGetThreadPointer();
ASSERT(ThisThread);
ThisThread->SetLastSuccessfullyDestroyedContext(NULL);
if (!hCContext)
memset(pBuff, 0, cbNDRContext);
else
{
// Check the magic value to see if this is a legit context
__try
{
if ( ((CCONTEXT PAPI *) hCContext)->MagicValue != CONTEXT_MAGIC_VALUE )
{
RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
}
}
__except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
|| ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
{
RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
}
memcpy(pBuff, &hCContext->NDR, sizeof(hCContext->NDR));
}
#undef hCContext
}
long
NDRCCopyContextHandle (
IN void *SourceBinding,
OUT void **DestinationBinding
)
/*++
Routine Description:
Duplicates a context handle by copying the binding handle and
the context information.
Arguments:
SourceBinding - the source handle
DestinationBinding - the copied handle on success. Undefined on
failure.
Return Value:
RPC_S_OK for success. RPC_S_* for errors.
--*/
{
CCONTEXT *ContextHandle = (CCONTEXT *)SourceBinding;
CCONTEXT *NewContextHandle;
RPC_BINDING_HANDLE OldBindingHandle;
RPC_STATUS Status;
Status = RpcSsGetContextBinding(ContextHandle, &OldBindingHandle);
if (Status != RPC_S_OK)
return Status;
NewContextHandle = new CCONTEXT;
if (NewContextHandle == NULL)
return RPC_S_OUT_OF_MEMORY;
RpcpMemoryCopy(NewContextHandle, ContextHandle, sizeof(CCONTEXT));
Status = RpcBindingCopy(OldBindingHandle, &NewContextHandle->hRPC);
if (Status != RPC_S_OK)
{
delete NewContextHandle;
return Status;
}
*DestinationBinding = NewContextHandle;
return RPC_S_OK;
}
void
ByteSwapWireContext(
IN WIRE_CONTEXT PAPI * WireContext,
IN unsigned long PAPI * DataRepresentation
)
/*++
Routine Description:
If necessary, the wire context will be byte swapped in place.
Arguments:
WireContext - Supplies the wire context be byte swapped and returns the
resulting byte swapped context.
DataRepresentation - Supplies the data representation of the supplied wire
context.
--*/
{
if ( (*DataRepresentation & NDR_LITTLE_ENDIAN)
!= NDR_LOCAL_ENDIAN )
{
WireContext->ContextType = RpcpByteSwapLong(WireContext->ContextType);
ByteSwapUuid((class RPC_UUID *)&WireContext->ContextUuid);
}
}
void RPC_ENTRY
NDRCContextUnmarshall ( // process returned context
OUT NDR_CCONTEXT PAPI *phCContext,// stub context to update
IN RPC_BINDING_HANDLE hRPC, // binding handle to associate with
IN void PAPI *pBuff, // pointer to NDR wire format
IN unsigned long DataRepresentation // pointer to NDR data rep
)
// Update the users context handle from the servers NDR wire format.
//-----------------------------------------------------------------------//
{
PCCONTEXT hCC = (PCCONTEXT) *phCContext;
THREAD *ThisThread;
ThisThread = RpcpGetThreadPointer();
ASSERT(ThisThread);
ThisThread->SetLastSuccessfullyDestroyedContext(NULL);
ByteSwapWireContext((WIRE_CONTEXT PAPI *) pBuff,
(unsigned long PAPI *) &DataRepresentation);
ASSERT( !RpcpCheckHeap() );
// destory this context if the server returned none
if (RpcpMemoryCompare(pBuff, &NullContext, cbNDRContext) == 0)
{
if (hCC)
{
if (hCC->hRPC)
RpcBindingFree(&(hCC->hRPC)); // discard duplicated binding
hCC->MagicValue = 0;
I_RpcFree(hCC);
}
*phCContext = Nil;
ThisThread->SetLastSuccessfullyDestroyedContext(hCC);
return;
}
PCCONTEXT hCCtemp = 0;
if (! hCC) // allocate new if none existed
{
hCCtemp = (PCCONTEXT) I_RpcAllocate(sizeof(CCONTEXT));
if (hCCtemp == 0)
{
RpcRaiseException(RPC_S_OUT_OF_MEMORY);
}
hCCtemp->MagicValue = CONTEXT_MAGIC_VALUE;
}
else if (RpcpMemoryCompare(&hCC->NDR, pBuff, sizeof(hCC->NDR)) == 0)
{
// the returned context is the same as the app's context.
return;
}
RPC_BINDING_HANDLE hBindtemp ;
if( I_RpcBindingCopy(hRPC, &hBindtemp) != RPC_S_OK )
{
ASSERT( !RpcpCheckHeap() );
I_RpcFree( hCCtemp );
RpcRaiseException(RPC_S_OUT_OF_MEMORY);
}
if ( hCCtemp )
hCC = hCCtemp;
else
RpcBindingFree(&(hCC->hRPC));
memcpy(&hCC->NDR, pBuff, sizeof(hCC->NDR));
hCC->hRPC = hBindtemp;
ASSERT( !RpcpCheckHeap() );
*phCContext = (NDR_CCONTEXT)hCC;
}
void RPC_ENTRY
RpcSsDestroyClientContext (
IN OUT void PAPI * PAPI * ContextHandle
)
/*++
Routine Description:
A client application will use this routine to destroy a context handle
which it no longer needs. This will work without having to contact the
server.
Arguments:
ContextHandle - Supplies the context handle to be destroyed. It will
be set to zero before this routine returns.
Exceptions:
If the context handle is invalid, then the RPC_X_SS_CONTEXT_MISMATCH
exception will be raised.
--*/
{
RPC_BINDING_HANDLE BindingHandle;
RPC_STATUS RpcStatus;
THREAD *ThisThread;
PVOID OldLastSuccessfullyDestroyedContext;
ThisThread = RpcpGetThreadPointer();
if (ThisThread)
{
OldLastSuccessfullyDestroyedContext = ThisThread->GetLastSuccessfullyDestroyedContext();
ThisThread->SetLastSuccessfullyDestroyedContext(NULL);
if (OldLastSuccessfullyDestroyedContext && (*ContextHandle == OldLastSuccessfullyDestroyedContext))
return;
}
BindingHandle = NDRCContextBinding(*ContextHandle);
RpcStatus = RpcBindingFree(&BindingHandle);
PCCONTEXT hCC = (PCCONTEXT) *ContextHandle;
hCC->MagicValue = 0;
I_RpcFree(*ContextHandle);
*ContextHandle = 0;
}