summaryrefslogblamecommitdiffstats
path: root/private/rpc/ndrlib/ccontext.cxx
blob: 4ac7170e666a33fd8349c6e62cb9bb1ab2789276 (plain) (tree)




















































































































































































































































































































                                                                                   
/* --------------------------------------------------------------------

                      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.

-------------------------------------------------------------------- */

#ifdef NTENV

extern "C"
{
#include <sysinc.h>
}

#else // NTENV

#include <sysinc.h>

#endif // NTENV

#include <rpc.h>
#include <rpcdcep.h>
#include <rpcndr.h>
#include <util.hxx>
#include <osfpcket.hxx>

#ifdef NTENV
#include <memory.h>
#endif // NTENV

#ifdef WIN
#define memset _fmemset
#define memcpy _fmemcpy
#define memcmp _fmemcmp
#endif // WIN

// 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.

#define CONTEXT_MAGIC_VALUE 0xFEDCBA98

typedef struct _WIRE_CONTEXT
{
    unsigned long ContextType;
    UUID ContextUuid;
} WIRE_CONTEXT;

typedef struct _CCONTEXT {

    RPC_BINDING_HANDLE hRPC;	// binding handle assoicated with context

    unsigned long MagicValue;
    WIRE_CONTEXT NDR;

} CCONTEXT, *PCCONTEXT;

static unsigned char NilContext[20];


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.

--*/
{
#ifdef NTENV

    RpcTryExcept
        {
        if ( ((CCONTEXT PAPI *) CContext)->MagicValue != CONTEXT_MAGIC_VALUE )
            {
            RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
            }
        }
    RpcExcept(   ( RpcExceptionCode() == STATUS_ACCESS_VIOLATION )
              || ( RpcExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
        {
        RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
        }
    RpcEndExcept

#else // NTENV

    if (   ( CContext == 0 )
        || ( ((CCONTEXT PAPI *) CContext)->MagicValue != CONTEXT_MAGIC_VALUE ) )
        {
        RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
        }

#endif // NTENV

    return(((CCONTEXT PAPI *) CContext)->hRPC);
}


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 opeqe pointer to internal

    if (!hCContext)
        memset(pBuff, 0, cbNDRContext);
    else
        {

        // Check the magic value to see if this is a legit context
        
        RpcTryExcept
            {
            if ( ((CCONTEXT PAPI *) hCContext)->MagicValue != CONTEXT_MAGIC_VALUE )
                {
                RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
                }
            }
        RpcExcept(1)
            {
            RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
            }
        RpcEndExcept
        
     	memcpy(pBuff, &hCContext->NDR, sizeof(hCContext->NDR));
        }

#undef hCContext
}


static 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 ) 
        {
        ByteSwapLong(WireContext->ContextType);
        ByteSwapLong(WireContext->ContextUuid.Data1);
        ByteSwapShort(WireContext->ContextUuid.Data2);
        ByteSwapShort(WireContext->ContextUuid.Data3);
        }
}

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) ((long) *phCContext);

    // destory this context if the server returned none

    ByteSwapWireContext((WIRE_CONTEXT PAPI *) pBuff,
            (unsigned long PAPI *) &DataRepresentation);

    ASSERT( !RpcpCheckHeap() );

    if (memcmp(pBuff, NilContext, cbNDRContext) == 0)
	{
	if (hCC)
	    {
	    if (hCC->hRPC)
		RpcBindingFree(&(hCC->hRPC));	// discard duplicated binding

            hCC->MagicValue = 0;
	    I_RpcFree(hCC);
	    }

	*phCContext = Nil;
	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 (memcmp(&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;

    BindingHandle = NDRCContextBinding(*ContextHandle);

    RpcStatus = RpcBindingFree(&BindingHandle);
    // ASSERT( RpcStatus == RPC_S_OK ); 

    I_RpcFree(*ContextHandle);
    *ContextHandle = 0;
}