windows-nt/Source/XPSP1/NT/com/rpc/runtime/mtrt/handle.hxx
2020-09-26 16:20:57 +08:00

1431 lines
34 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1990 - 1999
//
// File: handle.hxx
//
//--------------------------------------------------------------------------
/* --------------------------------------------------------------------
Microsoft OS/2 LAN Manager
Copyright(c) Microsoft Corp., 1990
-------------------------------------------------------------------- */
/* --------------------------------------------------------------------
File: handle.hxx
Description:
All of the classes in the handle management layer which are common to
both the client runtime and the server runtime are in this file. The
classes used only by the server runtime live in hndlsvr.hxx. The
classes described here are independent of specific RPC protocol as
well as transport.
The class GENERIC_OBJECT is used is the root for the handle class hierarchy.
It provides dynamic type checking for all handles.
The MESSAGE_OBJECT class provides a common protocol for all of the handle
types which know to send and receive messages.
The CCONNECTION class represents a call handle on the client side.
The BINDING_HANDLE class is a binding handle as used by a client to perform
remote procedure calls.
GENERIC_OBJECT
MESSAGE_OBJECT
CCONNECTION
BINDING_HANDLE
History :
mikemon ??-??-?? Beginning of time (at least for this file).
mikemon 12-28-90 Cleaned up the comments.
Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
-------------------------------------------------------------------- */
#ifndef __HANDLE_HXX__
#define __HANDLE_HXX__
// These are the types for all of the handles visible outside of the
// RPC runtime. Since they are just defines, we might as well stick
// the server handle types here as well.
#define OBJECT_DELETED 0x00000001
#define DG_CCALL_TYPE 0x00000004
#define DG_SCALL_TYPE 0x00000008
#define DG_BINDING_HANDLE_TYPE 0x00000010
#define OSF_CCALL_TYPE 0x00000020
#define OSF_SCALL_TYPE 0x00000040
#define OSF_CCONNECTION_TYPE 0x00000080
#define OSF_SCONNECTION_TYPE 0x00000100
#define OSF_CASSOCIATION_TYPE 0x00000200
#define OSF_ASSOCIATION_TYPE 0x00000400
#define OSF_ADDRESS_TYPE 0x00000800
#define LRPC_CCALL_TYPE 0x00001000
#define LRPC_SCALL_TYPE 0x00002000
#define LRPC_CASSOCIATION_TYPE 0x00004000
#define LRPC_SASSOCIATION_TYPE 0x00008000
#define LRPC_BINDING_HANDLE_TYPE 0x00010000
#define SVR_BINDING_HANDLE_TYPE 0x00020000
#define DG_CCONNECTION_TYPE 0x00040000
#define DG_SCONNECTION_TYPE 0x00080000
#define OSF_BINDING_HANDLE_TYPE 0x00100000
#define DG_CALLBACK_TYPE 0x00200000
#define DG_ADDRESS_TYPE 0x00400000
#define LRPC_ADDRESS_TYPE 0x00800000
#define DG_CASSOCIATION_TYPE 0x01000000
#define DG_SASSOCIATION_TYPE 0x02000000
#define CONTEXT_TYPE 0x04000000
#define HTTP_CLIENT_IN_CHANNEL 0x10000000
#define HTTP_CLIENT_OUT_CHANNEL 0x10000010
typedef int HANDLE_TYPE;
//
// define the base types
//
#define CALL_TYPE (DG_CCALL_TYPE \
| DG_SCALL_TYPE \
| OSF_CCALL_TYPE \
| OSF_SCALL_TYPE \
| LRPC_CCALL_TYPE \
| LRPC_SCALL_TYPE \
| DG_CALLBACK_TYPE)
#define BINDING_HANDLE_TYPE (OSF_BINDING_HANDLE_TYPE \
| DG_BINDING_HANDLE_TYPE \
| LRPC_BINDING_HANDLE_TYPE \
| SVR_BINDING_HANDLE_TYPE )
#define CCALL_TYPE (DG_CCALL_TYPE \
| OSF_CCALL_TYPE \
| LRPC_CCALL_TYPE)
#define SCALL_TYPE (DG_SCALL_TYPE \
| DG_CALLBACK_TYPE \
| OSF_SCALL_TYPE \
| LRPC_SCALL_TYPE )
typedef struct {
RPC_BINDING_HANDLE hCall;
PRPC_ASYNC_STATE pAsync;
void *Context;
RPC_ASYNC_EVENT Event;
} RPC_APC_INFO;
RPC_HTTP_TRANSPORT_CREDENTIALS_W *ConvertToUnicodeHttpTransportCredentials (
const IN RPC_HTTP_TRANSPORT_CREDENTIALS_A *SourceCredentials
);
void WipeOutAuthIdentity (
IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
);
void FreeHttpTransportCredentials (
IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *Credentials
);
RPC_HTTP_TRANSPORT_CREDENTIALS_W *DuplicateHttpTransportCredentials (
const IN RPC_HTTP_TRANSPORT_CREDENTIALS_W *SourceCredentials
);
RPC_STATUS DecryptAuthIdentity (
IN SEC_WINNT_AUTH_IDENTITY_W *AuthIdentity
);
/* --------------------------------------------------------------------
GENERIC_OBJECT :
The GENERIC_OBJECT class serves as the base for all handles used by the
RPC runtime. It provides type checking of handles. The type checking
is provided in two different ways:
(1) At the front of every object is an unsigned long. This is set to a
specific (magic) value which is checked whenever the handle is validated.
NOTE: Every handle which the user gives us is validated.
(2) We also can dynamically determine the type of the object.
-------------------------------------------------------------------- */
// This is the magic value we stick in the front of every valid
// GENERIC_OBJECT.
#define MAGICLONG 0x89ABCDEF
#define MAGICLONGDEAD 0x99DEAD99
extern RPC_STATUS CaptureLogonid( LUID * LogonId );
extern RPC_STATUS CaptureModifiedId(LUID *ModifiedId);
class THREAD;
class NO_VTABLE GENERIC_OBJECT
{
// This instance variable contains a magic value which is used to
// validate handles.
unsigned long MagicLong;
protected:
HANDLE_TYPE ObjectType;
GENERIC_OBJECT ()
{
MagicLong = MAGICLONG;
#ifdef DEBUGRPC
ObjectType = 0;
#endif
}
~GENERIC_OBJECT ()
{
MagicLong = MAGICLONGDEAD;
#ifdef DEBUGRPC
ASSERT( ObjectType );
#endif
}
public:
// Predicate to test for a valid handle. Note that HandleType may
// specify more than one type of handle. This works because the handle
// types are specified as bits in an unsigned number.
unsigned int // Return zero (0) if the handle is valid and its type
// is one of the types specified by the HandleType argument;
// otherwise, the handle is invalid, and one (1) is returned.
InvalidHandle ( // Check for an invalid handle.
IN HANDLE_TYPE HandleType // Bitmap of one or more handle types to
// be used in validating the handle.
);
HANDLE_TYPE Type (HANDLE_TYPE BaseType)
{
#ifdef DEBUGRPC
ASSERT( ObjectType );
#endif
return (ObjectType & BaseType);
}
virtual void DoNothing(void)
{
}
};
class NO_VTABLE REFERENCED_OBJECT : public GENERIC_OBJECT
{
public:
inline
REFERENCED_OBJECT (
) : RefCount(1) {}
virtual
~REFERENCED_OBJECT (
) {}
virtual void
ProcessSendComplete (
IN RPC_STATUS EventStatus,
IN BUFFER Buffer
) {ASSERT(0);}
virtual void
FreeObject (
);
int
AddReference (
);
inline void SingleThreadedAddReference(void)
{
RefCount.SingleThreadedIncrement();
}
inline void SingleThreadedAddMultipleReferences(long nReferences)
{
RefCount.SingleThreadedIncrement(nReferences);
}
virtual void
RemoveReference (
);
void
Delete (
);
void
Destroy (
);
BOOL
IsDeleted (
);
void SetNotDeleted(void)
{
ObjectType &= ~OBJECT_DELETED;
}
void
SetReferenceCount (
IN int Count
) {RefCount.SetInteger(Count);}
protected:
BOOL SetDeletedFlag(void)
{
int savedObjectType = ObjectType;
if (((savedObjectType & OBJECT_DELETED) == 0) &&
InterlockedCompareExchange((long *)&ObjectType, savedObjectType | OBJECT_DELETED, savedObjectType) == savedObjectType)
{
LogEvent(SU_REFOBJ, EV_DELETE, this, IntToPtr(savedObjectType), RefCount.GetInteger(), 1, 1);
return TRUE;
}
return FALSE;
}
INTERLOCKED_INTEGER RefCount;
};
inline void
REFERENCED_OBJECT::FreeObject (
)
{
delete this;
}
inline int
REFERENCED_OBJECT::AddReference (
)
{
int MyCount;
MyCount = RefCount.Increment();
LogEvent(SU_REFOBJ, EV_INC, this, IntToPtr(ObjectType), MyCount, 1, 1);
return MyCount;
}
inline void
REFERENCED_OBJECT::RemoveReference (
)
{
int MyCount;
LogEvent(SU_REFOBJ, EV_DEC, this, IntToPtr(ObjectType), RefCount.GetInteger(), 1, 1);
MyCount = RefCount.Decrement();
ASSERT(MyCount >= 0);
if (0 == MyCount)
{
FreeObject();
}
}
inline void
REFERENCED_OBJECT::Delete (
)
{
int MyCount;
if (SetDeletedFlag())
{
MyCount = RefCount.Decrement();
ASSERT(MyCount);
}
}
inline void
REFERENCED_OBJECT::Destroy (
)
{
int MyCount;
if (SetDeletedFlag())
{
RemoveReference();
}
}
inline BOOL
REFERENCED_OBJECT::IsDeleted (
)
{
return (ObjectType & OBJECT_DELETED);
}
class BINDING_HANDLE; // forward
/* --------------------------------------------------------------------
MESSAGE_OBJECT :
The MESSAGE_OBJECT class provides the common protocol for all handle types
which can be used to send messages. The common protocol defined includes
message routines, buffer management routines, and routines for querying
calls and bindings.
-------------------------------------------------------------------- */
class NO_VTABLE MESSAGE_OBJECT : public REFERENCED_OBJECT
{
public:
virtual RPC_STATUS // Value to be returned by SendReceive API.
SendReceive ( // Perform a send-receive operation in a handle specific
// way.
IN OUT PRPC_MESSAGE Message
) = 0;
// Perform a send operationin a handle specific way
// this API is used in conjunction with pipes
virtual RPC_STATUS
Send (
IN OUT PRPC_MESSAGE Message
) = 0;
// Perform a receive in a handle specific way
// this API is used in conjunction with pipes
virtual RPC_STATUS
Receive (
IN OUT PRPC_MESSAGE Message,
IN unsigned int Size
) = 0;
// Perform a send operationin a handle specific way
// this API is used in conjunction with pipes
virtual RPC_STATUS
AsyncSend (
IN OUT PRPC_MESSAGE Message
) ;
// Perform a receive in a handle specific way
// this API is used in conjunction with pipes
virtual RPC_STATUS
AsyncReceive (
IN OUT PRPC_MESSAGE Message,
IN unsigned int Size
) ;
virtual RPC_STATUS
SetAsyncHandle (
IN PRPC_ASYNC_STATE pAsync
) ;
virtual RPC_STATUS
AbortAsyncCall (
IN PRPC_ASYNC_STATE pAsync,
IN unsigned long ExceptionCode
) ;
virtual RPC_STATUS
GetCallStatus (
) ;
// on the client side, Message->RpcInterfaceInformation
// points to an RPC_CLIENT_INTERFACE structure. The
// TransferSyntax member on in points to the transfer syntax preferred
// by the stub, and on output is filled by the best estimate of the
// runtime what transfer syntax will be optimal for the call. The
// memory pointed by TransferSyntax on in is owned by the stub and
// is guaranteed to be valid for the duration of the call. On out
// this memory is owned by the runtime and should not be freed by the
// stub. The runtime guarantees it is valid for the lifetime of the
// call (i.e. until calling I_RpcFreeBuffer, or one of the I_Rpc
// functions returns failure.
// On the server side, Message->RpcInterfaceInformation points to
// an RPC_SERVER_INTERFACE structure
virtual RPC_STATUS
NegotiateTransferSyntax (
IN OUT PRPC_MESSAGE Message
) = 0;
virtual RPC_STATUS // Value to be returned by RpcGetBuffer API.
GetBuffer ( // Perform a buffer allocation operation in a handle specific
// way.
IN OUT PRPC_MESSAGE Message,
IN UUID *ObjectUuid
) = 0;
virtual void
FreeBuffer ( // Perform a buffer deallocation operation in a handle
// specific way.
IN PRPC_MESSAGE Message
) = 0;
// deallocate a buffer associated with pipes, in a handle specific way
virtual void
FreePipeBuffer (
IN PRPC_MESSAGE Messsage
) ;
// reallocate a buffer associated with pipes, in a handle specific way
virtual RPC_STATUS
ReallocPipeBuffer (
IN PRPC_MESSAGE Message,
IN unsigned int NewSize
) ;
virtual RPC_STATUS
BindingCopy (
OUT BINDING_HANDLE * PAPI * DestinationBinding,
IN unsigned int MaintainContext
);
virtual BOOL
IsSyncCall (
) ;
};
inline void
MESSAGE_OBJECT::FreePipeBuffer (
IN PRPC_MESSAGE Messsage
)
{
ASSERT(0) ;
return ;
}
inline BOOL
MESSAGE_OBJECT::IsSyncCall (
)
{
return 1;
}
inline RPC_STATUS
MESSAGE_OBJECT::GetCallStatus (
)
{
ASSERT(0 && "improper MESSAGE_OBJECT member called\n");
return (RPC_S_CANNOT_SUPPORT) ;
}
inline RPC_STATUS
MESSAGE_OBJECT::AsyncSend (
IN OUT PRPC_MESSAGE Message
)
{
ASSERT(0 && "improper MESSAGE_OBJECT member called\n");
return (RPC_S_CANNOT_SUPPORT) ;
}
inline RPC_STATUS
MESSAGE_OBJECT::SetAsyncHandle (
IN PRPC_ASYNC_STATE pAsync
)
{
ASSERT(0 && "improper MESSAGE_OBJECT member called\n");
return (RPC_S_CANNOT_SUPPORT) ;
}
inline RPC_STATUS
MESSAGE_OBJECT::AbortAsyncCall (
IN PRPC_ASYNC_STATE pAsync,
IN unsigned long ExceptionCode
)
{
ASSERT(0 && "improper MESSAGE_OBJECT member called\n");
return (RPC_S_CANNOT_SUPPORT) ;
}
// Perform a receive in a handle specific way
// this API is used in conjunction with pipes
inline RPC_STATUS
MESSAGE_OBJECT::AsyncReceive (
IN OUT PRPC_MESSAGE Message,
IN unsigned int Size
)
{
ASSERT(0 && "improper MESSAGE_OBJECT member called\n");
return (RPC_S_CANNOT_SUPPORT) ;
}
inline RPC_STATUS
MESSAGE_OBJECT::ReallocPipeBuffer (
IN PRPC_MESSAGE Messsage,
IN unsigned int NewSize
)
{
ASSERT(0 && "improper MESSAGE_OBJECT member called\n");
return (RPC_S_CANNOT_SUPPORT) ;
}
class SECURITY_CREDENTIALS;
struct CLIENT_AUTH_INFO
{
unsigned long AuthenticationLevel;
unsigned long AuthenticationService;
RPC_CHAR * ServerPrincipalName;
union
{
RPC_AUTH_IDENTITY_HANDLE AuthIdentity; // Client-side only
RPC_AUTHZ_HANDLE PacHandle; // Server-side only
};
unsigned long AuthorizationService;
unsigned long IdentityTracking;
unsigned long ImpersonationType;
unsigned long Capabilities;
unsigned long AdditionalTransportCredentialsType;
void *AdditionalCredentials;
LUID ModifiedId;
BOOL DefaultLogonId;
SECURITY_CREDENTIALS * Credentials;
CLIENT_AUTH_INFO();
CLIENT_AUTH_INFO::CLIENT_AUTH_INFO(
const CLIENT_AUTH_INFO * myAuthInfo,
RPC_STATUS PAPI * pStatus
);
~CLIENT_AUTH_INFO();
BOOL
IsSupportedAuthInfo(
const CLIENT_AUTH_INFO * AuthInfo,
BOOL fNamedPipe = 0
) const;
int
CredentialsMatch(
SECURITY_CREDENTIALS PAPI * Creds
) const;
void ReferenceCredentials() const;
// note that after this method is called, but before destruction of pTarget occurs,
// PrepareForDestructionAfterShallowCopy must be called on target
inline CLIENT_AUTH_INFO *ShallowCopyTo(CLIENT_AUTH_INFO *pTarget)
{
memcpy(pTarget, this, sizeof(CLIENT_AUTH_INFO));
return pTarget;
}
inline void PrepareForDestructionAfterShallowCopy(void)
{
ServerPrincipalName = NULL;
AdditionalCredentials = NULL;
AdditionalTransportCredentialsType = 0;
}
};
inline
CLIENT_AUTH_INFO::CLIENT_AUTH_INFO(
)
{
AuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
AuthenticationService = RPC_C_AUTHN_NONE;
AuthorizationService = RPC_C_AUTHZ_NONE;
ServerPrincipalName = 0;
AuthIdentity = 0;
Credentials = 0;
ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
DefaultLogonId = 1;
AdditionalTransportCredentialsType = 0;
AdditionalCredentials = NULL;
}
#define LOW_BITS 0x0000007L
#define NOT_MULTIPLE_OF_EIGHT(_x_) (_x_ & 0x00000007L)
class NO_VTABLE CALL : public MESSAGE_OBJECT
{
public:
CALL * NestingCall;
PRPC_ASYNC_STATE pAsync ;
long NotificationIssued;
inline
CALL(
)
{
}
// Perform a send operationin a handle specific way
// this API is used in conjunction with pipes
virtual RPC_STATUS
Send (
IN OUT PRPC_MESSAGE Message
) ;
// Perform a receive in a handle specific way
// this API is used in conjunction with pipes
virtual RPC_STATUS
Receive (
IN OUT PRPC_MESSAGE Message,
IN unsigned int Size
) ;
virtual RPC_STATUS
AsyncSend (
IN OUT PRPC_MESSAGE Message
) ;
virtual RPC_STATUS
AsyncReceive (
IN OUT PRPC_MESSAGE Message,
IN unsigned int Size
) ;
virtual RPC_STATUS
SetAsyncHandle (
IN PRPC_ASYNC_STATE pAsync
) ;
virtual RPC_STATUS
AbortAsyncCall (
IN PRPC_ASYNC_STATE pAsync,
IN unsigned long ExceptionCode
) ;
virtual RPC_STATUS
GetCallStatus (
) ;
virtual void
ProcessEvent (
) ;
virtual RPC_STATUS
CancelAsyncCall (
IN BOOL fAbort
);
virtual void
ProcessResponse (
IN BOOL fDirectCall = 0
) ;
virtual RPC_STATUS
Cancel(
void * ThreadHandle
);
virtual unsigned
TestCancel(
);
virtual void
FreeAPCInfo (
IN RPC_APC_INFO *pAPCInfo
) ;
virtual BOOL
IssueNotification (
IN RPC_ASYNC_EVENT Event = RpcCallComplete
) ;
virtual RPC_STATUS
InqSecurityContext (
OUT void **SecurityContextHandle
)
{
return RPC_S_CANNOT_SUPPORT;
}
protected:
RPC_STATUS AsyncStatus ;
RPC_APC_INFO CachedAPCInfo ;
BOOL CachedAPCInfoAvailable ;
THREAD *CallingThread ;
BOOL
QueueAPC (
IN RPC_ASYNC_EVENT Event,
IN void *Context = 0
) ;
// Validates parameters and check whether actual
// notification is necessary. 0 if none is necessary
// or non-zero if notification is necessary. The
// function is non-idempotent, and if called, and
// returns non-zero, the main notification function
// MUST be called (state corruption will occur
// otherwise)
BOOL
IssueNotificationEntry (
IN RPC_ASYNC_EVENT Event = RpcCallComplete
);
// do the actual notification. Caller MUST have
// called IssueNotificationEntry before that, and
// call this only IssueNotificationEntry returns
// non-zero
BOOL
IssueNotificationMain (
IN RPC_ASYNC_EVENT Event = RpcCallComplete
);
};
inline RPC_STATUS
CALL::GetCallStatus (
)
{
return AsyncStatus ;
}
inline RPC_STATUS
CALL::CancelAsyncCall (
IN BOOL fAbort
)
{
return RPC_S_OK;
}
inline RPC_STATUS
CALL::SetAsyncHandle (
IN PRPC_ASYNC_STATE pAsync
)
/*++
Routine Description:
This method is called by the stubs to associate an async handle with
this CCALL.
Arguments:
pAsync - The async handle to association with this CCALL.
Return Value:
RPC_S_OK - Function succeeded
RPC_S_OUT_OF_MEMORY - we ran out of memory
--*/
{
if (pAsync->u.APC.hThread == 0)
{
pAsync->u.APC.hThread = RpcpGetThreadPointer()->ThreadHandle();
}
this->pAsync = pAsync ;
return RPC_S_OK ;
}
class NO_VTABLE CCALL : public CALL
//
// This class represents a call on the client side. It implements
// the pure virtual fns from class CALL.
//
{
public:
BOOL UuidSpecified;
UUID ObjectUuid;
inline
CCALL(
CLIENT_AUTH_INFO * myAuthInfo,
RPC_STATUS __RPC_FAR * pStatus
)
{
UuidSpecified = 0;
}
inline
CCALL(
)
{
}
protected:
// utility function which sets the common debug information for a client call
RPC_STATUS SetDebugClientCallInformation(OUT DebugClientCallInfo **ppClientCallInfo,
OUT CellTag *ClientCallInfoCellTag,
OUT DebugCallTargetInfo **ppCallTargetInfo,
OUT CellTag *CallTargetInfoCellTag,
IN OUT PRPC_MESSAGE Message,
IN DebugThreadInfo *ThreadDebugCell,
IN CellTag ThreadCellTag);
};
RPC_STATUS
DispatchCallback(
IN PRPC_DISPATCH_TABLE DispatchTableCallback,
IN OUT PRPC_MESSAGE Message,
OUT RPC_STATUS PAPI * ExceptionCode
);
class TRANS_INFO; // forward
class DCE_BINDING;
/* --------------------------------------------------------------------
BINDING_HANDLE :
A BINDING_HANDLE is the binding handle used by clients to make remote
procedure calls. We derive the BINDING_HANDLE class from the MESSAGE_OBJECT
class because binding handles are used to send remote procedure calls.
For some operating environments and transports
we need to clean up the transports when the process ends.
-------------------------------------------------------------------- */
class NO_VTABLE BINDING_HANDLE : public MESSAGE_OBJECT
/*++
Class Description:
Fields:
Timeout - Contains the communications timeout for this binding
handle.
ObjectUuid - Contains the object uuid for this binding handle. The
constructor will initialize this value to the null uuid.
NullObjectUuidFlag - Contains a flag which indicates whether or
not the object uuid for this binding handle is the null uuid.
If this flag is non-zero, then this binding handle has the
null uuid as its object uuid; otherwise, the object uuid is
not the null uuid.
EpLookupHandle - Contains the endpoint mapper lookup handle for
this binding handle. This makes it possible to iterate through
all of the endpoints in an endpoint mapper database by trying
to make a remote procedure call, and then, when it fails, calling
RpcBindingReset.
BindingSetKey - Contains the key for this binding handle in the
global set of binding handles.
EntryNameSyntax - Contains the syntax of the entry name field of
this object. This field will be zero if the binding handle
was not imported or looked up.
EntryName - Contains the entry name in the name service where this
binding handle was imported or looked up from. This field will
be zero if the binding handle was not imported or looked up.
ClientAuthInfo - Contains the authentication and authorization information
for this binding handle.
--*/
{
private:
RPC_UUID ObjectUuid;
unsigned int Timeout;
unsigned int NullObjectUuidFlag;
unsigned long EntryNameSyntax;
RPC_CHAR * EntryName;
void PAPI * EpLookupHandle;
ULONG_PTR * OptionsVector;
protected:
CLIENT_AUTH_INFO ClientAuthInfo;
MUTEX BindingMutex;
public:
//
// This is an opaque area of memory set aside for the transport
// to manage transport specific options:
//
void PAPI * pvTransportOptions;
BINDING_HANDLE (
IN OUT RPC_STATUS *pStatus
);
public:
virtual
~BINDING_HANDLE (
);
virtual RPC_STATUS
BindingFree (
) = 0;
RPC_STATUS
Clone(
IN BINDING_HANDLE * OriginalHandle
);
void
InquireObjectUuid (
OUT RPC_UUID PAPI * ObjectUuid
);
void
SetObjectUuid (
IN RPC_UUID PAPI * ObjectUuid
);
virtual RPC_STATUS
PrepareBindingHandle (
IN TRANS_INFO * TransInfo,
IN DCE_BINDING * DceBinding
) = 0;
virtual RPC_STATUS
ToStringBinding (
OUT RPC_CHAR PAPI * PAPI * StringBinding
) = 0;
unsigned int
InqComTimeout (
);
RPC_STATUS
SetComTimeout (
IN unsigned int Timeout
);
RPC_UUID *
InqPointerAtObjectUuid (
);
unsigned int
InqIfNullObjectUuid (
);
virtual RPC_STATUS
ResolveBinding (
IN PRPC_CLIENT_INTERFACE RpcClientInterface
) = 0;
RPC_STATUS
InquireEntryName (
IN unsigned long EntryNameSyntax,
OUT RPC_CHAR PAPI * PAPI * EntryName
);
RPC_STATUS
SetEntryName (
IN unsigned long EntryNameSyntax,
IN RPC_CHAR PAPI * EntryName
);
virtual RPC_STATUS
InquireDynamicEndpoint (
OUT RPC_CHAR PAPI * PAPI * DynamicEndpoint
);
virtual RPC_STATUS
BindingReset (
) = 0;
void PAPI * PAPI *
InquireEpLookupHandle (
);
virtual CLIENT_AUTH_INFO *
InquireAuthInformation (
);
virtual RPC_STATUS
SetAuthInformation (
IN RPC_CHAR PAPI * ServerPrincipalName, OPTIONAL
IN unsigned long AuthenticationLevel,
IN unsigned long AuthenticationService,
IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
IN unsigned long AuthorizationService, OPTIONAL
IN SECURITY_CREDENTIALS PAPI * Credentials = 0, OPTIONAL
IN unsigned long ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE,OPTIONAL
IN unsigned long IdentityTracking = RPC_C_QOS_IDENTITY_STATIC, OPTIONAL
IN unsigned long Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT, OPTIONAL
IN BOOL bAcquireNewCredentials = FALSE, OPTIONAL
IN ULONG AdditionalTransportCredentialsType = 0, OPTIONAL
IN void *AdditionalCredentials = NULL OPTIONAL
);
virtual int
SetServerPrincipalName (
IN RPC_CHAR PAPI *ServerPrincipalName
);
virtual unsigned long
MapAuthenticationLevel (
IN unsigned long AuthenticationLevel
);
virtual BOOL
SetTransportAuthentication(
IN unsigned long ulAuthenticationLevel,
IN unsigned long ulAuthenticationService,
OUT RPC_STATUS *pStatus
);
virtual RPC_STATUS // Value to be returned by SendReceive API.
SendReceive ( // Perform a send-receive operation in a handle specific
// way.
IN OUT PRPC_MESSAGE Message
);
virtual RPC_STATUS
Send (
IN OUT PRPC_MESSAGE Message
) ;
virtual RPC_STATUS
Receive (
IN OUT PRPC_MESSAGE Message,
IN unsigned int Size
) ;
virtual RPC_STATUS // Value to be returned by RpcGetBuffer API.
GetBuffer ( // Perform a buffer allocation operation in a handle specific
// way.
IN OUT PRPC_MESSAGE Message,
IN UUID *ObjectUuid
) = 0;
virtual void
FreeBuffer ( // Perform a buffer deallocation operation in a handle
// specific way.
IN PRPC_MESSAGE Message
);
virtual RPC_STATUS
InquireTransportType(
OUT unsigned int PAPI * Type
) = 0;
virtual RPC_STATUS
ReAcquireCredentialsIfNecessary(
void
);
virtual RPC_STATUS
SetTransportOption( unsigned long option,
ULONG_PTR optionValue );
virtual RPC_STATUS
InqTransportOption( unsigned long option,
ULONG_PTR * pOptionValue );
};
inline unsigned int
BINDING_HANDLE::InqComTimeout (
)
/*++
Routine Description:
All we have got to do is to return the communications timeout for
this binding handle.
Return Value:
The communications timeout in this binding handle will be returned.
--*/
{
return(Timeout);
}
inline RPC_UUID *
BINDING_HANDLE::InqPointerAtObjectUuid (
)
/*++
Routine Description:
This reader returns a pointer to the object uuid contained in this
binding handle.
Return Value:
A pointer to the object uuid contained in this binding handle is
always returned.
--*/
{
return(&ObjectUuid);
}
inline unsigned int
BINDING_HANDLE::InqIfNullObjectUuid (
)
/*++
Routine Description:
This method is used to inquire if the object uuid in this binding
handle is null or not.
Return Value:
Zero will be returned if object uuid is not null, otherwise (the
object uuid is null) zero will be returned.
--*/
{
return(NullObjectUuidFlag);
}
inline void PAPI * PAPI *
BINDING_HANDLE::InquireEpLookupHandle (
)
/*++
Return Value:
A pointer to the endpoint mapper lookup handle for this binding
handle will be returned.
--*/
{
return(&EpLookupHandle);
}
inline CLIENT_AUTH_INFO *
BINDING_HANDLE::InquireAuthInformation (
)
/*++
Return Value:
If this binding handle is authenticated, then a pointer to its
authentication and authorization information will be returned;
otherwise, zero will be returned.
--*/
{
return(&ClientAuthInfo);
}
////////////////////////////////////////////////////////////////////
/// Stub interface information
////////////////////////////////////////////////////////////////////
const int MaximumNumberOfTransferSyntaxes = 2;
const int TransferSyntaxIsServerPreferredFlag = 1;
const int TransferSyntaxListStartFlag = 2;
class TRANSFER_SYNTAX_STUB_INFO
{
public:
RPC_SYNTAX_IDENTIFIER TransferSyntax;
PRPC_DISPATCH_TABLE DispatchTable;
};
class TRANSFER_SYNTAX_INFO_ATOM : public TRANSFER_SYNTAX_STUB_INFO
{
public:
void Init (TRANSFER_SYNTAX_STUB_INFO *TransferSyntaxInfo)
{
Flags = 0;
RpcpMemoryCopy(this, TransferSyntaxInfo, sizeof(TRANSFER_SYNTAX_STUB_INFO));
}
inline BOOL IsTransferSyntaxServerPreferred(void)
{
return (Flags & TransferSyntaxIsServerPreferredFlag);
}
inline void TransferSyntaxIsServerPreferred(void)
{
Flags |= TransferSyntaxIsServerPreferredFlag;
}
inline void TransferSyntaxIsNotServerPreferred(void)
{
Flags &= ~TransferSyntaxIsServerPreferredFlag;
}
inline BOOL IsTransferSyntaxListStart(void)
{
return (Flags & TransferSyntaxListStartFlag);
}
inline void TransferSyntaxIsListStart(void)
{
Flags |= TransferSyntaxListStartFlag;
}
private:
// can be:
// TransferSyntaxIsServerPreferredFlag
// TransferSyntaxListStartFlag
int Flags;
};
// Interface can be both RPC_CLIENT_INTERFACE & RPC_SERVER_INTERFACE
inline BOOL DoesInterfaceSupportMultipleTransferSyntaxes(void *Interface)
{
// the client and server interface have the same layout - we can just
// use one of them
RPC_CLIENT_INTERFACE *ClientInterface = (RPC_CLIENT_INTERFACE *)Interface;
ASSERT ((ClientInterface->Length == sizeof(RPC_CLIENT_INTERFACE))
|| (ClientInterface->Length == NT351_INTERFACE_SIZE));
ASSERT(sizeof(RPC_CLIENT_INTERFACE) == sizeof(RPC_SERVER_INTERFACE));
#if !defined(_WIN64)
if (ClientInterface->Length == NT351_INTERFACE_SIZE)
return FALSE;
#else
ASSERT(ClientInterface->Length == sizeof(RPC_CLIENT_INTERFACE));
#endif
return (ClientInterface->Flags & RPCFLG_HAS_MULTI_SYNTAXES);
}
// And here we have a couple of inline operators for comparing GUIDs.
// There is no particular reason that they should live here.
inline int
operator == (
IN GUID& guid1,
IN GUID& guid2
) {return(RpcpMemoryCompare(&guid1,&guid2,sizeof(GUID)) == 0);}
inline int
operator == (
IN GUID PAPI * guid1,
IN GUID& guid2
) {return(RpcpMemoryCompare(guid1,&guid2,sizeof(GUID)) == 0);}
extern const RPC_SYNTAX_IDENTIFIER *NDR20TransferSyntax;
extern const RPC_SYNTAX_IDENTIFIER *NDR64TransferSyntax;
extern const RPC_SYNTAX_IDENTIFIER *NDRTestTransferSyntax;
extern
int
InitializeClientDLL ( // This routine will be called at DLL load time.
);
extern int
InitializeLoadableTransportClient (
);
extern int
InitializeRpcProtocolOfsClient (
);
extern int
InitializeRpcProtocolDgClient (
);
START_C_EXTERN
extern int
InitializeWinExceptions (
);
END_C_EXTERN
#define DEFAULT_MAX_DATAGRAM_LENGTH (0)
extern unsigned DefaultMaxDatagramLength;
#define DEFAULT_CONNECTION_BUFFER_LENGTH (0)
extern unsigned DefaultConnectionBufferLength;
typedef struct _RPC_RUNTIME_INFO
{
unsigned int Length ;
unsigned long Flags ;
void __RPC_FAR *OldBuffer ;
} RPC_RUNTIME_INFO, __RPC_FAR *PRPC_RUNTIME_INFO ;
void
I_RpcAPCRoutine (
IN RPC_APC_INFO *pAPCInfo
);
inline BOOL IsPartialMessage (RPC_MESSAGE *Message)
{
return (Message->RpcFlags & RPC_BUFFER_PARTIAL);
}
inline BOOL IsExtraMessage (RPC_MESSAGE *Message)
{
return (Message->RpcFlags & RPC_BUFFER_EXTRA);
}
inline BOOL IsAsyncMessage (RPC_MESSAGE *Message)
{
return (Message->RpcFlags & RPC_BUFFER_ASYNC);
}
inline BOOL IsCompleteMessage (RPC_MESSAGE *Message)
{
return (Message->RpcFlags & RPC_BUFFER_COMPLETE);
}
inline BOOL IsNotifyMessage (RPC_MESSAGE *Message)
{
return (!(Message->RpcFlags & RPC_BUFFER_NONOTIFY));
}
inline BOOL IsNonsyncMessage (RPC_MESSAGE *Message)
{
return (Message->RpcFlags & (RPC_BUFFER_ASYNC | RPC_BUFFER_PARTIAL));
}
#define PARTIAL(_Message) ((_Message)->RpcFlags & RPC_BUFFER_PARTIAL)
#define EXTRA(_Message) ((_Message)->RpcFlags & RPC_BUFFER_EXTRA)
#define ASYNC(_Message) ((_Message)->RpcFlags & RPC_BUFFER_ASYNC)
#define COMPLETE(_Message) ((_Message)->RpcFlags & RPC_BUFFER_COMPLETE)
#define NOTIFY(_Message) (!((_Message)->RpcFlags & RPC_BUFFER_NONOTIFY))
#define NONSYNC(_Message) ((_Message)->RpcFlags & \
(RPC_BUFFER_ASYNC | RPC_BUFFER_PARTIAL))
class RPC_SERVER;
class LRPC_SERVER;
extern int RpcHasBeenInitialized;
extern RPC_SERVER * GlobalRpcServer;
extern BOOL g_fClientSideDebugInfoEnabled;
extern BOOL g_fServerSideDebugInfoEnabled;
extern LRPC_SERVER *GlobalLrpcServer;
extern HINSTANCE hInstanceDLL ;
inline BOOL IsClientSideDebugInfoEnabled(void)
{
return g_fClientSideDebugInfoEnabled;
}
inline BOOL IsServerSideDebugInfoEnabled(void)
{
return g_fServerSideDebugInfoEnabled;
}
#endif // __HANDLE_HXX__