/*++ Copyright (C) Microsoft Corporation, 1991 - 1999 Module Name: binding.hxx Abstract: The class representing a DCE binding lives here. A DCE binding consists of an optional object UUID, an RPC protocol sequence, a network address, an optional endpoint, and zero or more network options. Author: Michael Montague (mikemon) 04-Nov-1991 Revision History: --*/ #ifndef __BINDING_HXX__ #define __BINDING_HXX__ class BINDING_HANDLE; class DCE_BINDING /*++ Class Description: Instances of this class represent an internalized form of a string binding. In particular, a string binding can be used to construct an instance of DCE_BINDING. We parse the string binding into its components and convert the object UUID from a string to a UUID. Fields: ObjectUuid - Contains the object uuid for this binding. This field will always contain a valid object uuid. If no object uuid was specified in the string binding used to create an instance, then ObjectUuid will be the NULL UUID. RpcProtocolSequence - Contains the rpc protocol sequence for this binding. This field will always either point to a string or be zero. NetworkAddress - Contains the network addres for this binding. This field will always be zero or point to a string (which is the network address for this dce binding). Endpoint - Contains the endpoint for this binding, which will either pointer to a string or be zero. Options - Contains the optional network options for this binding. As will the other fields, this field will either point to a string, or be zero. --*/ { private: RPC_CHAR * RpcProtocolSequence; RPC_CHAR * NetworkAddress; RPC_CHAR * Endpoint; RPC_CHAR * Options; RPC_UUID ObjectUuid; public: DCE_BINDING ( IN RPC_CHAR PAPI * ObjectUuid OPTIONAL, IN RPC_CHAR PAPI * RpcProtocolSequence OPTIONAL, IN RPC_CHAR PAPI * NetworkAddress OPTIONAL, IN RPC_CHAR PAPI * Endpoint OPTIONAL, IN RPC_CHAR PAPI * Options OPTIONAL, OUT RPC_STATUS PAPI * Status ); DCE_BINDING ( IN RPC_CHAR PAPI * StringBinding, OUT RPC_STATUS PAPI * Status ); ~DCE_BINDING ( ); RPC_CHAR PAPI * StringBindingCompose ( IN RPC_UUID PAPI * Uuid OPTIONAL, IN BOOL fStatic = 0 ); RPC_CHAR PAPI * ObjectUuidCompose ( OUT RPC_STATUS PAPI * Status ); RPC_CHAR PAPI * RpcProtocolSequenceCompose ( OUT RPC_STATUS PAPI * Status ); RPC_CHAR PAPI * NetworkAddressCompose ( OUT RPC_STATUS PAPI * Status ); RPC_CHAR PAPI * EndpointCompose ( OUT RPC_STATUS PAPI * Status ); RPC_CHAR PAPI * OptionsCompose ( OUT RPC_STATUS PAPI * Status ); BINDING_HANDLE * CreateBindingHandle ( OUT RPC_STATUS PAPI * Status ); RPC_CHAR * InqNetworkAddress ( ); RPC_CHAR * InqEndpoint ( ); BOOL IsNullEndpoint ( void ); RPC_CHAR * InqNetworkOptions ( ); RPC_CHAR * InqRpcProtocolSequence ( ); void AddEndpoint( IN RPC_CHAR *Endpoint ); RPC_STATUS ResolveEndpointIfNecessary ( IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation, IN RPC_UUID * ObjectUuid, IN OUT void PAPI * PAPI * EpLookupHandle, IN BOOL UseEpMapperEp, IN unsigned ConnTimeout, IN ULONG CallTimeout, IN CLIENT_AUTH_INFO *AuthInfo OPTIONAL ); int Compare ( IN DCE_BINDING * DceBinding, OUT BOOL *fOnlyEndpointDiffers ); int CompareWithoutSecurityOptions ( IN DCE_BINDING * DceBinding, OUT BOOL *fOnlyEndpointDiffers ); DCE_BINDING * DuplicateDceBinding ( ); void MakePartiallyBound ( ); BOOL MaybeMakePartiallyBound ( IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation, IN RPC_UUID * ObjectUuid ); BOOL IsNamedPipeTransport ( ) { return (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncacn_np")) == 0); } }; inline RPC_CHAR * DCE_BINDING::InqNetworkAddress ( ) /*++ Routine Description: A pointer to the network address for this address is returned. --*/ { return(NetworkAddress); } inline RPC_CHAR * DCE_BINDING::InqEndpoint ( ) /*++ Routine Description: A pointer to the endpoint for this address is returned. --*/ { return(Endpoint); } inline BOOL DCE_BINDING::IsNullEndpoint ( void ) /*++ Routine Description: Returns non-zero if the endpoint is NULL. --*/ { return ((Endpoint == NULL) || (Endpoint[0] == 0)); } inline RPC_CHAR * DCE_BINDING::InqNetworkOptions ( ) /*++ Routine Description: A pointer to the network options for this address is returned. --*/ { return(Options); } inline RPC_CHAR * DCE_BINDING::InqRpcProtocolSequence ( ) /*++ Routine Description: A pointer to the rpc protocol sequence for this binding is returned. --*/ { return(RpcProtocolSequence); } #define MAX_PROTSEQ_LENGTH MAX_DLLNAME_LENGTH class LOADABLE_TRANSPORT; class TRANS_INFO /*++ Class Description: Fields: pTransportInterface - Contains all of the required information about a loadable transport so that we can make use of it. --*/ { private: RPC_TRANSPORT_INTERFACE pTransportInterface; LOADABLE_TRANSPORT *LoadableTrans ; RPC_CHAR RpcProtocolSequence[MAX_PROTSEQ_LENGTH + 1]; public: TRANS_INFO ( IN RPC_TRANSPORT_INTERFACE pTransportInterface, IN RPC_CHAR *ProtocolSeq, IN LOADABLE_TRANSPORT *LoadableTrans ) ; BOOL MatchProtseq( IN RPC_CHAR *ProtocolSeq ) ; BOOL MatchId ( IN unsigned short Id ); RPC_TRANSPORT_INTERFACE InqTransInfo ( ); RPC_STATUS StartServerIfNecessary( ); RPC_STATUS CreateThread ( ); }; inline TRANS_INFO::TRANS_INFO ( IN RPC_TRANSPORT_INTERFACE pTransportInterface, IN RPC_CHAR *ProtocolSeq, IN LOADABLE_TRANSPORT *LoadableTrans ) { this->pTransportInterface = pTransportInterface ; RpcpStringCopy(RpcProtocolSequence, ProtocolSeq) ; this->LoadableTrans = LoadableTrans ; } inline BOOL TRANS_INFO::MatchProtseq( IN RPC_CHAR *ProtocolSeq ) { if (RpcpStringCompare(ProtocolSeq, RpcProtocolSequence) == 0) { return 1 ; } return 0; } inline BOOL TRANS_INFO::MatchId ( IN unsigned short Id ) { if (pTransportInterface->TransId == Id) { return 1; } return 0; } inline RPC_TRANSPORT_INTERFACE TRANS_INFO::InqTransInfo ( ) { return pTransportInterface ; } NEW_SDICT (TRANS_INFO); class LOADABLE_TRANSPORT /*++ Class Description: This class is used as an item in a dictionary of loaded loadable transports. It contains the information we are interested in, the RPC_TRANSPORT_INTERFACE, as well as the name of the dll we loaded the transport interface from. The dll name is the key to the dictionary. Fields: DllName - Contains the name of the dll from which we loaded this transport interface. LoadedDll - Contains the dll which we had to load to get the transport support. We need to save this information so that under Windows when the runtime is unloaded, we can unload all of the transports. --*/ { private: // accessed by all threads independently - put in separate cache line LONG ThreadsStarted ; RPC_CHAR DllName[MAX_DLLNAME_LENGTH + 1]; // accessed by all threads independently - put in separate cache line // NumThreads is the number of threads actually doing a listen on the // completion port - this excludes the ones that are doing processing LONG NumThreads; DLL * LoadedDll; TRANS_INFO_DICT ProtseqDict ; // accessed by all threads independently - put in a separate cache line // ThreadsDoingLongWait is the number of threads that are waiting on // the completion port and their wait timeout is > MAX_SHORT_THREAD_TIMEOUT // In other words, those threads are not guaranteed to check for // garbage collection before gThreadTimeout INTERLOCKED_INTEGER ThreadsDoingLongWait; LONG Reserved0[7]; // read-only often used section PROCESS_CALLS ProcessCallsFunc; long nOptimalNumberOfThreads; #ifndef NO_PLUG_AND_PLAY LISTEN_FOR_PNP_NOTIFICATIONS PnpListen; friend void ProcessNewAddressEvent(LOADABLE_TRANSPORT *pLoadableTransport, IN RPC_TRANSPORT_EVENT Event, IN RPC_STATUS EventStatus, IN PVOID pEventContext, IN UINT BufferLength, IN BUFFER Buffer, IN PVOID pSourceContext); #endif FuncGetHandleForThread GetHandleForThread; FuncReleaseHandleForThread ReleaseHandleForThread; LONG Reserved1[3]; // accessed by all threads independently - put in separate cache line LONG Reserved2[7]; // the total number of worker threads on the completion port - this // includes the ones that are listening, and the one that have picked // up work items and are working on them. INTERLOCKED_INTEGER nThreadsAtCompletionPort; // accessed by all threads independently - put in separate cache line LONG Reserved3[7]; int nActivityValue; public: LOADABLE_TRANSPORT ( IN RPC_TRANSPORT_INTERFACE pTransportInterface, IN RPC_CHAR * DllName, IN RPC_CHAR PAPI * ProtocolSequence, IN DLL *LoadableTransportDll, IN FuncGetHandleForThread GetHandleForThread, IN FuncReleaseHandleForThread ReleaseHandleForThread, OUT RPC_STATUS *Status, OUT TRANS_INFO * PAPI *TransInfo ); TRANS_INFO * MapProtocol ( IN RPC_CHAR * DllName, IN RPC_CHAR PAPI * ProtocolSequence ); TRANS_INFO * MatchId ( IN unsigned short Id ); void ProcessIOEvents ( ); RPC_STATUS StartServerIfNecessary ( ); RPC_STATUS ProcessCalls ( IN INT Timeout, OUT RPC_TRANSPORT_EVENT *pEvent, OUT RPC_STATUS *pEventStatus, OUT PVOID *ppEventContext, OUT UINT *pBufferLength, OUT BUFFER *pBuffer, OUT PVOID *ppSourceContext); RPC_STATUS CreateThread (void); // N.B. This can return negative numbers in rare race // conditions - make sure you handle it inline long GetThreadsDoingShortWait ( void ) { return (NumThreads - ThreadsDoingLongWait.GetInteger()); } }; inline RPC_STATUS TRANS_INFO::StartServerIfNecessary ( ) { return LoadableTrans->StartServerIfNecessary() ; } inline RPC_STATUS TRANS_INFO::CreateThread ( ) { return LoadableTrans->CreateThread(); } NEW_SDICT(LOADABLE_TRANSPORT); extern LOADABLE_TRANSPORT_DICT * LoadedLoadableTransports; RPC_STATUS LoadableTransportInfo ( IN RPC_CHAR * DllName, IN RPC_CHAR PAPI * RpcProtocolSequence, OUT TRANS_INFO * PAPI *pTransInfo ); extern BOOL GetTransportEntryPoints(IN DLL *LoadableTransportDll, OUT TRANSPORT_LOAD *TransportLoad, OUT FuncGetHandleForThread *GetHandleForThread, OUT FuncReleaseHandleForThread *ReleaseHandleForThread ); extern void UnjoinCompletionPort ( void ); extern RPC_STATUS IsRpcProtocolSequenceSupported ( IN RPC_CHAR PAPI * RpcProtocolSequence ); RPC_STATUS OsfMapRpcProtocolSequence ( IN BOOL ServerSideFlag, IN RPC_CHAR PAPI * RpcProtocolSequence, OUT TRANS_INFO * PAPI *ClientTransInfo ) ; extern BINDING_HANDLE * OsfCreateBindingHandle ( ); extern BINDING_HANDLE * LrpcCreateBindingHandle ( ); extern BINDING_HANDLE * DgCreateBindingHandle ( void ); extern RPC_CHAR * AllocateEmptyString ( void ); extern RPC_CHAR * DuplicateString ( IN RPC_CHAR PAPI * String ); #define DuplicateStringPAPI DuplicateString #define AllocateEmptyStringPAPI AllocateEmptyString #define DG_EVENT_CALLBACK_COMPLETE 0x9991 #define CO_EVENT_BIND_TO_SERVER 0x9992 // don't use 9993 - it's already used #define IN_PROXY_IIS_DIRECT_RECV 0x9994 #define HTTP2_DIRECT_RECEIVE 0x9995 #define PLUG_CHANNEL_DIRECT_SEND 0x9996 #define CHANNEL_DATA_ORIGINATOR_DIRECT_SEND 0x9997 #define HTTP2_RESCHEDULE_TIMER 0x9998 #define HTTP2_FLOW_CONTROL_DIRECT_SEND 0x9999 #define HTTP2_WINHTTP_DIRECT_RECV 0x999A #define HTTP2_WINHTTP_DIRECT_SEND 0x999B #define HTTP2_ABORT_CONNECTION 0x999C #define HTTP2_RECYCLE_CHANNEL 0x999D extern UUID MgmtIf; extern UUID NullUuid; typedef void ProcessIOEventFunc(LOADABLE_TRANSPORT *pLoadableTransport, IN RPC_TRANSPORT_EVENT Event, IN RPC_STATUS EventStatus, IN PVOID pEventContext, IN UINT BufferLength, IN BUFFER Buffer, IN PVOID pSourceContext); BOOL ProcessIOEventsWrapper( IN LOADABLE_TRANSPORT *Transport ) ; void ProcessDgClientPacket( IN DWORD Status, IN DG_TRANSPORT_ENDPOINT LocalEndpoint, IN void * PacketHeader, IN unsigned long PacketLength, IN DatagramTransportPair *AddressPair ); void ProcessDgServerPacket( IN DWORD Status, IN DG_TRANSPORT_ENDPOINT LocalEndpoint, IN void * PacketHeader, IN unsigned long PacketLength, IN DatagramTransportPair *AddressPair ); #endif // __BINDING_HXX__