Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

997 lines
19 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
dgclnt.hxx
Abstract:
This file contains the definitions used by the datagram client.
Author:
Dave Steckler (davidst) 15-Dec-1992
Revision History:
--*/
#ifndef __DGCLNT_HXX__
#define __DGCLNT_HXX__
#define BROADCAST (0x01)
#define UNRESOLVEDEP (0x02)
// Number of times to retry a ping. This is the suggested number.
#define DG_MAX_PINGS 30
// Num times to retry sending a particular fragment
#define DG_MAX_NUM_FRAG_SND_RETRIES 5
// Num times to toss an unexpected pkt while awaiting a fack
#define DG_MAX_NUM_FRAG_RCV_RETRIES 10
//
// Endpoint States (See the Flags in Endpoint)
//
#define NOTINUSE 0x00
#define INUSE 0x01
struct ENDPOINT {
int Flag;
int DictKey;
#ifdef WIN
unsigned int TaskId;
#endif
unsigned long LastUsedTickCount;
void __RPC_FAR * TransportEndpoint;
} ;
typedef ENDPOINT * PENDPOINT;
//
//dict defn require classes - but ENDPOINT is a struct
//this is a ok warning to suppress..
//since dict treats items as opaque entities..
//
#pragma warning(disable:4099)
NEW_SDICT(ENDPOINT);
#pragma warning(default:4099)
class DG_BINDING_HANDLE;
typedef DG_BINDING_HANDLE * PDG_BINDING_HANDLE;
class DG_CASSOCIATION;
typedef DG_CASSOCIATION * PDG_CASSOCIATION;
class DG_CCALL;
typedef DG_CCALL * PDG_CCALL;
class DG_ENDPOINT_MANAGER
/*++
Class Description:
This class represents the EndpointManager. In Datagram RPC,
Runtime tries and shares local Endpoints - i.e. unlike the
Connection Oriented RPC we do not connect a local endpoint to
a single remote server. We can use the same local endpoint for numerous
remote servers.
Endpoint Manager caches endpoint(s) and serializes them such that
a single RPC can be pending per endpoint.
For certain transports this is an overkill. i.e. transport interface
may allow concurrent io. But in general, rpc doesnt count on it.
--*/
{
private:
ENDPOINT_DICT EndpointDictionary;
MUTEX EndpointManagerMutex;
unsigned long TransportEndpointSize;
PDG_RPC_CLIENT_TRANSPORT_INFO ClientTransport;
unsigned long ReferenceCount;
public:
DG_ENDPOINT_MANAGER(
PDG_RPC_CLIENT_TRANSPORT_INFO Transport,
IN OUT RPC_STATUS PAPI * RpcStatus
);
PENDPOINT
AllocateEndpoint(
);
inline
void
FreeEndpoint(
PENDPOINT Endpoint
);
void
DecrementReferenceCount(
void
);
void
IncrementReferenceCount(
void
);
#ifdef WIN
void
CleanupForThisTask(
);
#endif
};
typedef DG_ENDPOINT_MANAGER * PDG_ENDPOINT_MANAGER;
#ifdef WIN
//
// (Windows only) Dictionary of ENDPOINT_MANAGERS
//
NEW_SDICT(DG_ENDPOINT_MANAGER);
extern DG_ENDPOINT_MANAGER_DICT * EpmDict;
#endif
NEW_SDICT(DG_CCALL);
class DG_SECURITY_CONTEXT : public SECURITY_CONTEXT
{
private :
int SecurityContextInitialized;
int MaxTokenLength;
public :
DG_SECURITY_CONTEXT(
CLIENT_AUTH_INFO * myAuthInfo,
unsigned AuthContextId,
RPC_STATUS __RPC_FAR * pStatus
);
RPC_STATUS
InitializeFirstTime(
IN SECURITY_CREDENTIALS * Credentials,
IN RPC_CHAR * ServerPrincipal,
IN unsigned long AuthenticationLevel,
IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
);
RPC_STATUS
InitializeOnCallback(
IN unsigned long DataRep,
IN SECURITY_BUFFER_DESCRIPTOR PAPI * In,
IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * Out
);
RPC_STATUS
SignOrSeal(
IN unsigned long SequenceNumber,
IN unsigned int SignNotSealFlag,
IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
);
RPC_STATUS
VerifyOrUnSealPacket(
IN unsigned long SequenceNumber,
IN unsigned int VerifyNotUnsealFlag,
IN OUT SECURITY_BUFFER_DESCRIPTOR PAPI * BufferDescriptor
);
int
IsSecurityContextInitialized(
);
};
typedef DG_SECURITY_CONTEXT * PDG_SECURITY_CONTEXT;
inline
DG_SECURITY_CONTEXT::DG_SECURITY_CONTEXT(
CLIENT_AUTH_INFO * myAuthInfo,
unsigned AuthContextId,
RPC_STATUS __RPC_FAR * pStatus
)
: SECURITY_CONTEXT(myAuthInfo, AuthContextId, TRUE, pStatus)
{
SecurityContextInitialized = 0;
}
inline int
DG_SECURITY_CONTEXT::IsSecurityContextInitialized(
)
{
return (SecurityContextInitialized);
}
class INTERFACE_AND_OBJECT_LIST
{
public:
inline
INTERFACE_AND_OBJECT_LIST(
)
{
Head = 0;
}
~INTERFACE_AND_OBJECT_LIST(
);
BOOL
Insert(
void __RPC_FAR * Interface,
RPC_UUID __RPC_FAR * Object
);
BOOL
Find(
void __RPC_FAR * Interface,
RPC_UUID __RPC_FAR * Object
);
BOOL
Delete(
void __RPC_FAR * Interface,
RPC_UUID __RPC_FAR * Object
);
private:
struct INTERFACE_AND_OBJECT
{
void __RPC_FAR * Interface;
RPC_UUID Object;
INTERFACE_AND_OBJECT * Next;
inline void
Update(
void __RPC_FAR * a_Interface,
RPC_UUID __RPC_FAR * a_Object
)
{
Interface = a_Interface;
Object = *a_Object;
}
};
INTERFACE_AND_OBJECT * Head;
};
class DG_CASSOCIATION : public DG_ASSOCIATION
/*++
Class Description:
This class represents a "pointer" at a particular server/endpoint.
Binding handles can use this pointer to actually transact
the rpc call.
--*/
{
friend
void __RPC_FAR
conv_are_you_there(
handle_t Binding,
UUID __RPC_FAR *pUuid,
unsigned long ServerBootTime,
error_status_t __RPC_FAR *Status
);
friend
void __RPC_FAR
conv_who_are_you(
IN handle_t Binding,
IN UUID __RPC_FAR * pUuid,
IN unsigned long ServerBootTime,
OUT unsigned long __RPC_FAR * SequenceNumber,
OUT error_status_t __RPC_FAR * Status
);
public:
PDG_RPC_CLIENT_TRANSPORT_INFO pTransport;
PDG_ENDPOINT_MANAGER EndpointManager;
unsigned long AssociationFlag;
unsigned long ServerBootTime;
unsigned long ServerDataRep;
void __RPC_FAR * ServerAddress;
unsigned long ExpirationTime;
//----------------------------------------------------------
DG_CASSOCIATION(
IN PDG_RPC_CLIENT_TRANSPORT_INFO pTransport,
IN PDG_BINDING_HANDLE pBinding,
IN unsigned long UnresolvedEndpointFlag,
IN DCE_BINDING * NewDceBinding,
OUT RPC_STATUS __RPC_FAR * pStatus
);
~DG_CASSOCIATION();
virtual RPC_STATUS
ToStringBinding (
OUT RPC_CHAR __RPC_FAR * __RPC_FAR * StringBinding,
IN RPC_UUID __RPC_FAR * ObjectUuid
);
void
DecrementRefCount(
void
);
void
IncrementRefCount(
void
);
int
CompareWithBinding(
IN PDG_BINDING_HANDLE pBinding
);
BOOL
ComparePartialBinding(
IN PDG_BINDING_HANDLE pBinding,
void __RPC_FAR * Interface
);
BOOL
AddInterface(
void __RPC_FAR * InterfaceInformation,
RPC_UUID __RPC_FAR * ObjectUuid
);
BOOL
RemoveInterface(
void __RPC_FAR * InterfaceInformation,
RPC_UUID __RPC_FAR * ObjectUuid
);
RPC_STATUS
AllocateCCall(
PDG_CCALL __RPC_FAR * ppCCall,
CLIENT_AUTH_INFO * ClientAuthInfo = 0
);
void
InsertInDictionary(
void
);
DCE_BINDING *
DuplicateDceBinding (
void
);
void
FreeCall(
IN DG_CCALL * Call
);
void PAPI *
UpdateServerAddress(
void PAPI * pNewAddress
);
void PAPI *
UpdateAssociationWithAddress(
void PAPI * pNewAddress
);
static void
ScavengerProc(
void * Unused
);
void
ScavengeCalls(
DG_CCALL_DICT * DiscardedCallsDict
);
void
PurgeAmbiguousActivities(
);
void SetErrorFlag () { fErrorFlag = TRUE; }
void ClearErrorFlag() { fErrorFlag = FALSE; }
boolean ErrorFlag () { return fErrorFlag; }
private:
#define MAGIC_ASSOC (0x789aU)
unsigned Magic;
boolean fErrorFlag;
// a string binding for our server
//
DCE_BINDING * pDceBinding;
int DictionaryKey;
DG_CCALL_DICT InactiveCallsDict;
INTERFACE_AND_OBJECT_LIST InterfaceAndObjectDict;
};
inline DCE_BINDING *
DG_CASSOCIATION::DuplicateDceBinding (
)
{
ASSERT(Magic == MAGIC_ASSOC);
return(pDceBinding->DuplicateDceBinding());
}
inline
void
DG_CASSOCIATION::IncrementRefCount(
void
)
{
ASSERT(Magic == MAGIC_ASSOC);
ReferenceCount.Increment();
}
inline
void PAPI *
DG_CASSOCIATION::UpdateServerAddress(
void PAPI * pNewAddress
)
{
//
// The endpoint needs to be changed only if it is unresolved.
//
unsigned long Flag;
ASSERT(Magic == MAGIC_ASSOC);
if (0 == (AssociationFlag & UNRESOLVEDEP))
{
return pNewAddress;
}
Flag = InterlockedExchange((LONG *)&AssociationFlag, 0);
if (0 == Flag)
{
return (pNewAddress);
}
return UpdateAssociationWithAddress(pNewAddress);
}
class DG_BINDING_HANDLE : public BINDING_HANDLE
/*++
Class Description:
This class represents a handle pointing at a particular server/endpoint.
Fields:
pDceBinding - Until a DG_CASSOCIATION is found (or created) for this
binding handle, pDceBinding will point at the appropriate DCE_BINDING.
pBindingHandleMutex - Protects this binding handle.
ReferenceCount - Number of DG_CCALLs currently associated with this
binding handle.
DecrementReferenceCount - Decrements the reference count to this binding
handle. If the reference count hits 0, the binding handle is deleted.
DisassociateFromServer - If this is a BH that we couldnt
successfully use, tear down the association
--*/
{
private:
DG_CASSOCIATION * pCAssociation;
PDG_RPC_CLIENT_TRANSPORT_INFO pTransport;
MUTEX BindingHandleMutex;
unsigned int ReferenceCount;
unsigned ParmBufferLength;
unsigned ParmMaxDatagramLength;
boolean fDynamicEndpoint;
public:
DCE_BINDING * pDceBinding;
DG_BINDING_HANDLE(
IN OUT RPC_STATUS PAPI * RpcStatus
);
~DG_BINDING_HANDLE();
RPC_STATUS
GetBuffer (
IN OUT PRPC_MESSAGE Message
);
RPC_STATUS
BindingCopy (
OUT BINDING_HANDLE * __RPC_FAR * DestinationBinding,
IN unsigned int MaintainContext
);
RPC_STATUS
BindingFree (
);
void
PrepareBindingHandle (
IN void * TransportInterface,
IN DCE_BINDING * DceBinding
);
RPC_STATUS
ToStringBinding (
OUT RPC_CHAR __RPC_FAR * __RPC_FAR * StringBinding
);
RPC_STATUS
ResolveBinding (
IN RPC_CLIENT_INTERFACE __RPC_FAR * RpcClientInterface
);
RPC_STATUS
BindingReset (
);
RPC_STATUS
InquireTransportType(
OUT unsigned int PAPI * Type
)
{
*Type = TRANSPORT_TYPE_DG;
return(RPC_S_OK);
}
PDG_CASSOCIATION
InqCAssociation(
void
);
void
IncrementReferenceCount(
void
);
void
DecrementReferenceCount(
void
);
void
FreeCall(
DG_CCALL * Call
);
void
DisassociateFromServer(
);
unsigned long
MapAuthenticationLevel (
IN unsigned long AuthenticationLevel
);
RPC_STATUS
SetConnectionParameter (
IN unsigned Parameter,
IN unsigned long Value
);
RPC_STATUS
InqConnectionParameter (
IN unsigned Parameter,
IN unsigned long __RPC_FAR * pValue
);
unsigned
InqMaxDatagramLength(
)
{
return ParmMaxDatagramLength;
}
unsigned
InqTransportBufferLength(
)
{
return ParmBufferLength;
}
inline BOOL
IsDynamic()
{
return fDynamicEndpoint;
}
};
inline
PDG_CASSOCIATION
DG_BINDING_HANDLE::InqCAssociation(
void
)
{
return pCAssociation;
}
class DG_CCALL : public CCONNECTION, private DG_PACKET_ENGINE
/*++
Class Description:
This class represents an RPC in progress on the client side.
--*/
{
friend class DG_CASSOCIATION;
friend
void __RPC_FAR
conv_are_you_there(
handle_t Binding,
UUID __RPC_FAR *pUuid,
unsigned long ServerBootTime,
error_status_t __RPC_FAR *Status
);
friend
void __RPC_FAR
conv_who_are_you(
IN handle_t Binding,
IN UUID __RPC_FAR * pUuid,
IN unsigned long ServerBootTime,
OUT unsigned long __RPC_FAR * SequenceNumber,
OUT error_status_t __RPC_FAR * Status
);
friend
void __RPC_FAR
conv_who_are_you_auth(
handle_t Binding,
UUID __RPC_FAR *pUuid,
unsigned long ServerBootTime,
byte __RPC_FAR InData[ ],
long InLength,
long OutMaxLength,
unsigned long __RPC_FAR *SequenceNumber,
UUID __RPC_FAR * pCASUuid,
byte __RPC_FAR OutData[ ],
long __RPC_FAR * pOutLength,
error_status_t __RPC_FAR *Status
) ;
public:
// PENDPOINT - A Transport dependent endpoint .. this is an opaque entity
// that EndpointManager for the transport assigns to us and we
// religiously pass to Send and Recv routines in the transport
//
ENDPOINT * EndpointHandle;
void __RPC_FAR * Endpoint;
#if defined(MULTITHREADED)
DELAYED_ACTION_NODE DelayedAckTimer;
unsigned long ExpirationTime;
#endif
DG_CCALL(
IN PDG_CASSOCIATION pCAssociation,
unsigned AddressSize,
CLIENT_AUTH_INFO * pClientAuthInfo,
OUT RPC_STATUS __RPC_FAR * pStatus
);
virtual
~DG_CCALL();
//------------------------------------------------
//
// implementations of CCONNECTION virtual functions
//
virtual RPC_STATUS
GetBuffer (
IN OUT PRPC_MESSAGE Message
);
virtual RPC_STATUS
SendReceive (
IN OUT PRPC_MESSAGE Message
);
virtual RPC_STATUS
Send(
PRPC_MESSAGE Message
);
virtual RPC_STATUS
Receive(
PRPC_MESSAGE Message,
unsigned MinimumSize
);
virtual void
FreeBuffer (
IN PRPC_MESSAGE Message
);
virtual void
FreePipeBuffer (
IN PRPC_MESSAGE Message
) ;
virtual RPC_STATUS
ReallocPipeBuffer (
IN PRPC_MESSAGE Message,
IN unsigned int NewSize
) ;
inline int
IsSupportedAuthInfo(
IN CLIENT_AUTH_INFO * ClientAuthInfo
);
#if defined(NTENV) || defined(DOSWIN32RPC)
virtual RPC_STATUS
Cancel(
void * ThreadHandle
);
virtual unsigned
TestCancel(
);
#endif
//------------------------------------------------
//
// other public member functions
//
inline void
Initialize(
PDG_BINDING_HANDLE Binding
);
void
SendAck(
);
private:
RPC_UUID ActivityUuid;
PDG_CASSOCIATION pCAssociation;
PDG_BINDING_HANDLE pBindingHandle;
int AssociationKey;
void PAPI * CallbackAddress;
// The number of working packets we've received.
// Used for ping back-off.
//
unsigned WorkingCount;
unsigned UnansweredRequestCount;
// Wait time for ReceivePacket().
//
unsigned Timeout;
boolean UseSecurity;
boolean fNewCall;
boolean InsideCallback;
boolean CallbackCompleted;
boolean ServerResponded;
boolean AckPending;
boolean StaticArgsSent;
boolean AllArgsSent;
#ifdef MULTITHREADED
boolean CancelComplete;
unsigned long CancelTime;
#endif
PDG_SECURITY_CONTEXT ActiveSecurityContext;
PDG_SECURITY_CONTEXT PreviousSecurityContext;
//-----------------------------------------------
RPC_STATUS
SendReceiveRecur(
PRPC_MESSAGE Message,
boolean AllowRetry
);
RPC_STATUS
SendRecur(
PRPC_MESSAGE Message,
boolean AllowRetry
);
RPC_STATUS
SingleSendReceive(
);
RPC_STATUS
SendSomething(
);
RPC_STATUS
SendFragment(
PRPC_MESSAGE pMessage,
PNCA_PACKET_HEADER pBaseHeader
);
RPC_STATUS
SendQuit(
);
inline RPC_STATUS
SendPing(
);
virtual RPC_STATUS
SealAndSendPacket(
PNCA_PACKET_HEADER pHeader
);
//-----------------------------------------------
RPC_STATUS
DealWithNocall(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithFault(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithWorking(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithRequest(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithResponse(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithFack(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithQuack(
PDG_PACKET pPacket
);
RPC_STATUS
DealWithAuthCallback(
IN void PAPI * InToken,
IN long InTokenLengh,
OUT void PAPI * OutToken,
OUT long MaxOutTokenLength,
OUT long PAPI * OutTokenLength
);
//-----------------------------------------------
void
FreeInParms(
PRPC_MESSAGE pMessage
);
void
CleanupCall(
PRPC_MESSAGE pMessage
);
void
InitErrorPacket(
PNCA_PACKET_HEADER pHeader,
unsigned char PacketType,
RPC_STATUS RpcStatus
);
void
FreeEndpoint(
);
RPC_STATUS
InitializeSecurityContext(
);
RPC_STATUS
VerifyPacket(
PDG_PACKET pPacket
);
RPC_STATUS
BeforeSendReceive(
PRPC_MESSAGE Message
);
RPC_STATUS
AfterSendReceive(
PRPC_MESSAGE Message,
RPC_STATUS Status
);
void
BuildNcaPacketHeader(
PNCA_PACKET_HEADER pNcaPacketHeader,
PRPC_MESSAGE Message
);
RPC_STATUS
MaybeSendReceive(
IN OUT PRPC_MESSAGE Message
);
};
RPC_STATUS
InitializeClientGlobals(
);
#endif __DGCLNT_HXX__