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

1730 lines
38 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1990 - 1999
//
// File: osfsvr.hxx
//
//--------------------------------------------------------------------------
/* --------------------------------------------------------------------
File : osfsvr.hxx
Title : Classes for the OSF RPC protocol module (server classes).
Description :
History :
mikemon ??-??-?? Beginning of recorded history.
mikemon 10-15-90 Changed the shutdown functionality to PauseExecution
rather than suspending and resuming a thread.
mikemon 10-16-90 Added ListenThreadCompleted to OSF_ADDRESS.
Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
-------------------------------------------------------------------- */
#ifndef __OSFSVR_HXX__
#define __OSFSVR_HXX__
enum OSF_SCALL_STATE
{
NewRequest,
CallCancelled,
CallAborted,
CallCompleted,
ReceivedCallback,
ReceivedCallbackReply,
ReceivedFault
};
class OSF_SCONNECTION;
class OSF_SCALL;
NEW_SDICT(OSF_ASSOCIATION);
#define InqTransAddress(RpcTransportAddress) \
((OSF_ADDRESS *) \
((char *) RpcTransportAddress - sizeof(OSF_ADDRESS)))
#define InqTransSConnection(RpcTransportConnection) \
((OSF_SCONNECTION *) \
((char *) RpcTransportConnection - sizeof(OSF_SCONNECTION)))
#define InqTransSCall(RpcSourceContext) \
((OSF_SCALL *) ((char *) RpcSourceContext - sizeof(OSF_SCALL)))
NEW_SDICT(OSF_SCONNECTION);
const int NumberOfAssociationsDictionaries = 8;
const int MutexAllocationSize = ( ((unsigned long)(sizeof(MUTEX)) + ((4)-1)) & ~(4 - 1) );
class OSF_ADDRESS : public RPC_ADDRESS
/*++
Class Description:
Fields:
SetupAddressOccurred - Contains a flag which indicates whether or
not SetupAddressWithEndpoint or SetupAddressUnknownEndpoint
have been called and returned success. A value of non-zero
indicates that the above (SetupAddress* has been called and
succeeded) occured.
ServerInfo - Contains the pointers to the loadable transport
routines for the transport type of this address.
--*/
{
private:
OSF_ASSOCIATION_DICT Associations[NumberOfAssociationsDictionaries];
unsigned char AssociationBucketMutexMemory[MutexAllocationSize * NumberOfAssociationsDictionaries];
RPC_CONNECTION_TRANSPORT * ServerInfo;
unsigned int SetupAddressOccurred;
int ServerListeningFlag;
DebugEndpointInfo *DebugCell;
CellTag DebugCellTag;
public:
OSF_ADDRESS (
IN TRANS_INFO * RpcTransInfoInfo,
IN OUT RPC_STATUS * RpcStatus
);
~OSF_ADDRESS (
);
virtual RPC_STATUS
ServerStartingToListen (
IN unsigned int MinimumCallThreads,
IN unsigned int MaximumConcurrentCalls
);
virtual RPC_STATUS
ServerSetupAddress (
IN RPC_CHAR * NetworkAddress,
IN RPC_CHAR * *Endpoint,
IN unsigned int PendingQueueSize,
IN void * SecurityDescriptor, OPTIONAL
IN unsigned long EndpointFlags,
IN unsigned long NICFlags,
OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector
);
#ifndef NO_PLUG_AND_PLAY
virtual void
PnpNotify (
);
#endif
OSF_SCONNECTION *
NewConnection (
);
RPC_TRANSPORT_ADDRESS
InqRpcTransportAddress (
);
RPC_STATUS
CompleteListen (
);
RPC_STATUS
CreateThread (
);
virtual unsigned int // Returns the length of the secondary address.
TransSecondarySize ( // The length will be used to allocate a buffer.
);
virtual RPC_STATUS
TransSecondary ( // Places the secondary address in the specified buffer.
IN unsigned char * Address, // Buffer for the address.
IN unsigned int AddressLength // Length of the buffer.
);
void
ServerStoppedListening (
);
OSF_ASSOCIATION * // Returns the association deleted or 0.
RemoveAssociation ( // Remove the association specified by Key from this
// address.
IN int Key,
IN OSF_ASSOCIATION *pAssociation
);
int // Indicates success (0), or an error (-1).
AddAssociation ( // Add the specified association to this address.
IN OSF_ASSOCIATION * TheAssociation
);
OSF_ASSOCIATION *
FindAssociation (
IN unsigned long AssociationGroupId,
IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
);
int
IsServerListening (
) ;
void *
operator new (
size_t allocBlock,
unsigned int xtraBytes
);
inline static int GetHashBucketForAssociation(IN unsigned long AssociationGroupId)
{
return (AssociationGroupId % NumberOfAssociationsDictionaries);
}
inline MUTEX *GetAssociationBucketMutex(IN int HashIndex)
{
MUTEX *pMutex;
pMutex = (MUTEX *)(&AssociationBucketMutexMemory[MutexAllocationSize * HashIndex]);
ASSERT((((ULONG_PTR)pMutex) % 4) == 0);
return pMutex;
}
inline void GetDebugCellIDForThisObject(OUT DebugCellID *CellID)
{
GetDebugCellIDFromDebugCell((DebugCellUnion *)DebugCell, &DebugCellTag, CellID);
}
virtual void
DestroyContextHandlesForInterface (
IN RPC_SERVER_INTERFACE PAPI * RpcInterfaceInformation,
IN BOOL RundownContextHandles
);
};
inline RPC_STATUS
OSF_ADDRESS::CreateThread (
)
{
return TransInfo->CreateThread();
}
inline RPC_TRANSPORT_ADDRESS
OSF_ADDRESS::InqRpcTransportAddress (
)
/*++
Return Value:
A pointer to the transport data for this address will be returned.
--*/
{
return((RPC_TRANSPORT_ADDRESS)
(((char *) this) + sizeof(OSF_ADDRESS)));
}
inline void *
OSF_ADDRESS::operator new (
size_t allocBlock,
unsigned int xtraBytes
)
{
void * pvTemp = RpcpFarAllocate(allocBlock + xtraBytes);
return(pvTemp);
}
inline int
OSF_ADDRESS::IsServerListening (
)
{
return ServerListeningFlag ;
}
#define RPCSTATUS_GET_CREATETHREAD(x) Server->CreateThread( \
(THREAD_PROC)&ReceiveLotsaCallsWrapper,x);
class OSF_SBINDING
{
private:
RPC_INTERFACE * Interface;
unsigned int PresentContext;
unsigned long CurrentSecId;
int SelectedTransferSyntaxIndex; // zero based
public:
unsigned long SequenceNumber ;
OSF_SBINDING ( // Constructor.
IN RPC_INTERFACE * TheInterface,
IN int PContext,
IN int SelectedTransferSyntaxIndex
);
RPC_INTERFACE *
GetInterface (
) {return(Interface);}
unsigned int
GetPresentationContext (
) {return(PresentContext);}
inline RPC_STATUS
CheckSecurity (
SCALL * Call,
unsigned long AuthId
);
void GetSelectedTransferSyntaxAndDispatchTable(
OUT RPC_SYNTAX_IDENTIFIER **SelectedTransferSyntax,
OUT PRPC_DISPATCH_TABLE *SelectedDispatchTable)
{
Interface->GetSelectedTransferSyntaxAndDispatchTable(SelectedTransferSyntaxIndex,
SelectedTransferSyntax, SelectedDispatchTable);
}
#if DBG
inline void
InterfaceForCallDoesNotUseStrict (
void
)
{
Interface->InterfaceDoesNotUseStrict();
}
#endif
};
inline RPC_STATUS
OSF_SBINDING::CheckSecurity(
SCALL * Call,
unsigned long AuthId
)
{
if ( (Interface->IsSecurityCallbackReqd() == 0) ||
((SequenceNumber == Interface->SequenceNumber)
&& (AuthId == CurrentSecId)) )
{
return (RPC_S_OK);
}
RPC_STATUS Status = Interface->CheckSecurityIfNecessary(Call);
Call->RevertToSelf();
if (Status == RPC_S_OK)
{
SequenceNumber = Interface->SequenceNumber ;
CurrentSecId = AuthId;
return (RPC_S_OK);
}
else
{
SequenceNumber = 0;
}
return (RPC_S_ACCESS_DENIED);
}
class OSF_SCONNECTION;
NEW_SDICT(OSF_SBINDING);
NEW_SDICT(SECURITY_CONTEXT);
class OSF_SCALL : public SCALL
/*++
Class Description:
Fields:
ObjectUuid - Contains the object UUID specified for the remote
procedure call by the client.
ObjectUuidSpecified - Contains a flag which indicates whether
or not the remote procedure call specified an object UUID.
This field will be zero if an object UUID was not specified
in the call, and non-zero if one was specified.
ServerSecurityContext - Contains the security context for this connection
if security is being performed at the rpc protocol level.
AuthenticationLevel - Contains a value indicating what authentication
is being performed at the rpc protocol level. A value of
RPC_C_AUTHN_LEVEL_NONE indicates that no authentication is being
performed at the rpc protocol level.
AuthenticationService - Contains which authentication service is being
used at the rpc protocol level.
AuthorizationService - Contains which authorization service is being
used at the rpc protocol level.
AdditionalSpaceForSecurity - Contains the amount of space to save for
security in each buffer we allocate.
CachedBuffer - Contains cached buffer.
CachedBufferLength - Contains the length of the cached buffer.
DceSecurityInfo - Contains the security information necessary for
DCE security to work correctly.
SavedPac - While a call is being dispatched to manager, the manager
could query for a PAC. However, manager is not explicitly going
to free the PAC. Runtime is supposed to do that. This feild
takes care of that.
AuthzSvc - Authorization service
--*/
{
friend OSF_SCONNECTION;
private:
// data member ordering is optimized for locality
// If you modify something, make sure that the section boundaries are
// preserved. It is assumed that in the common case the OSF_SCALL is used
// by a thread at a time. Ordering is by frequency of usage, regardless of
// read/write
// Most frequently used section ( >= 3 times per call):
OSF_SCONNECTION *Connection;
OSF_SBINDING * CurrentBinding;
void *CurrentBuffer;
unsigned int CurrentBufferLength ;
int CurrentOffset;
ULONG MaxSecuritySize;
// the info for the first call. This has to be on the
// heap, because it is used on the async paths
// recursive callback info is on the stack, because we
// know in recursive callback we're only sync
RPC_MESSAGE FirstCallRpcMessage;
RPC_RUNTIME_INFO FirstCallRuntimeInfo;
// ~2 times per call use
OSF_ADDRESS *Address;
unsigned long CallId;
int CallStack;
void *LastBuffer;
int DispatchBufferOffset;
ULONG MaximumFragmentLength;
MUTEX CallMutex;
BOOL FirstSend;
// ~1 time per call use
unsigned int ObjectUuidSpecified;
BOOL fCallDispatched;
int ProcNum;
OSF_SCALL_STATE CurrentState;
BOOL fSecurityFailure;
THREAD * Thread;
int DispatchFlags;
CellTag CellTag;
DebugCallInfo *DebugCell;
// not used or used few times
int FirstFrag ;
BOOL fPipeCall;
int AllocHint;
ULONG RcvBufferLength;
ULONG NeededLength;
ULONG ActualBufferLength;
QUEUE BufferQueue;
BOOL fChoked;
BOOL fPeerChoked;
int CallOrphaned;
unsigned long SavedHeaderSize;
void * SavedHeader;
EVENT SyncEvent;
void *SendContext;
RPC_UUID ObjectUuid;
void
UpdateBuffersAfterNonLastSend (
IN PVOID NewBuffer,
IN int RemainingLength,
IN OUT RPC_MESSAGE *Message
)
{
if (RemainingLength)
{
Message->Buffer = NewBuffer;
Message->BufferLength = RemainingLength;
ActualBufferLength = RemainingLength;
}
else
{
Message->Buffer = 0;
Message->BufferLength = 0;
ActualBufferLength = 0;
}
}
public:
LONG CancelPending;
OSF_SCALL (
IN OSF_SCONNECTION *Connection,
IN OUT RPC_STATUS *Status
);
virtual ~OSF_SCALL (
);
virtual RPC_STATUS
SendReceive (
IN OUT PRPC_MESSAGE Message
);
virtual RPC_STATUS
NegotiateTransferSyntax (
IN OUT PRPC_MESSAGE Message
);
virtual RPC_STATUS
GetBuffer (
IN OUT PRPC_MESSAGE Message,
IN UUID *ObjectUuid
);
RPC_STATUS
GetBufferDo (
IN OUT void ** ppBuffer,
IN unsigned int culRequiredLength,
IN BOOL fDataValid = 0,
IN unsigned int DataLength = 0,
IN unsigned long Extra = 0
);
void
FreeBufferDo (
IN void *pBuffer
);
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
) ;
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
) ;
void
SendFault (
IN RPC_STATUS Status,
IN int DidNotExecute
);
RPC_STATUS
TransGetBuffer ( // Allocate a buffer of the specified size.
OUT void * * Buffer,
IN unsigned int BufferLength
);
virtual void
TransFreeBuffer ( // Free a buffer.
IN void * Buffer
);
virtual BOOL
IsSyncCall (
);
virtual RPC_STATUS
InquireAuthClient (
OUT RPC_AUTHZ_HANDLE * Privileges,
OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
OUT unsigned long * AuthenticationLevel,
OUT unsigned long * AuthenticationService,
OUT unsigned long * AuthorizationService,
IN unsigned long Flags
);
virtual RPC_STATUS
InquireCallAttributes (
IN OUT void *RpcCallAttributes
);
virtual void
ProcessSendComplete (
IN RPC_STATUS EventStatus,
IN BUFFER Buffer
);
void
SetCallId(
unsigned long CallId
);
BOOL
BeginRpcCall (
IN rpcconn_common * Packet,
IN unsigned int PacketLength
);
BOOL
ProcessReceivedPDU (
IN rpcconn_common * Packet,
IN unsigned int PacketLength,
IN BOOL fDispatch = 0
);
RPC_STATUS
GetCoalescedBuffer (
IN PRPC_MESSAGE Message,
BOOL fForceExtra
);
BOOL
DispatchRPCCall (
IN unsigned char PTYPE,
IN unsigned short OpNum
);
void
DispatchHelper (
);
RPC_STATUS
Send(
IN OUT PRPC_MESSAGE Message
) ;
RPC_STATUS
SendRequestOrResponse (
IN OUT PRPC_MESSAGE Message,
IN unsigned char PacketType
);
RPC_STATUS
SendNextFragment (
void
);
void
InquireObjectUuid (
OUT RPC_UUID * ObjectUuid
);
RPC_STATUS
ConvertToServerBinding (
OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
);
RPC_STATUS
ToStringBinding (
OUT RPC_CHAR * * StringBinding
);
RPC_STATUS
Cancel(
void * ThreadHandle
);
unsigned
TestCancel(
);
RPC_STATUS
ImpersonateClient (
);
RPC_STATUS
RevertToSelf (
);
virtual RPC_STATUS
GetAuthorizationContext (
IN BOOL ImpersonateOnReturn,
IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
IN PLARGE_INTEGER pExpirationTime OPTIONAL,
IN LUID Identifier,
IN DWORD Flags,
IN PVOID DynamicGroupArgs OPTIONAL,
OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
);
virtual RPC_STATUS
GetAssociationContextCollection (
OUT ContextCollection **CtxCollection
) ;
virtual RPC_STATUS
IsClientLocal (
OUT unsigned int * ClientLocalFlag
) ;
virtual RPC_STATUS
InqTransportType(
OUT unsigned int __RPC_FAR * Type
) ;
void
ActivateCall (
);
virtual void
FreeObject (
);
virtual void
RemoveReference (
);
void * operator new (
size_t allocBlock,
unsigned int xtraBytes
);
void
CleanupCall (
);
void CleanupCallAndSendFault (IN RPC_STATUS Status,
IN int DidNotExecute);
virtual RPC_STATUS
InqConnection (
OUT void **ConnId,
OUT BOOL *pfFirstCall
);
void
AbortCall (
)
{
CallMutex.Request();
CurrentState = CallAborted;
AsyncStatus = RPC_S_CALL_FAILED;
// Wake up the thread that was flow controlled, if any
if (fChoked == 1)
{
// Raising event for choked OSF_SCALL
fChoked = 0;
SyncEvent.Raise();
CallMutex.Clear();
// Since this is a pipe call, cleanup will be done on the send
// thread; so return.
return;
}
CallMutex.Clear();
if (fCallDispatched == 0)
{
CleanupCall();
//
// Remove the reply reference
//
RemoveReference();
//
// Remove the dispatch reference
//
RemoveReference();
return;
}
if (CallStack > 0)
{
SyncEvent.Raise();
}
}
virtual RPC_STATUS
InqSecurityContext (
OUT void **SecurityContextHandle
);
inline void DeactivateCall(void)
{
if (DebugCell)
{
DebugCell->Status = csAllocated;
// take down the async and pipe call flags
// since they are per call instance
DebugCell->CallFlags &= ~(DBGCELL_ASYNC_CALL | DBGCELL_PIPE_CALL);
}
}
RPC_STATUS
InqLocalConnAddress (
IN OUT void *Buffer,
IN OUT unsigned long *BufferSize,
OUT unsigned long *AddressFormat
);
#if DBG
virtual void
InterfaceForCallDoesNotUseStrict (
void
);
#endif
void
WakeUpPipeThreadIfNecessary (
IN RPC_STATUS Status
);
};
inline void *
OSF_SCALL::operator new (
size_t allocBlock,
unsigned int xtraBytes
)
{
void * pvTemp = RpcpFarAllocate(allocBlock + xtraBytes);
return(pvTemp);
}
inline BOOL
OSF_SCALL::IsSyncCall (
)
{
return !pAsync ;
}
inline void
OSF_SCALL::SetCallId(
unsigned long Call
)
{
CallId = Call;
}
NEW_SDICT2(OSF_SCALL, PVOID);
class OSF_SCONNECTION : public SCONNECTION
/*++
Class Description:
Fields:
Association - Contains the association to which this connection
belongs. This field will be zero until after the initial client
bind request has been accepted.
SavedHeader - Unbyte swapped header + - do that check sums work
ServerInfo - Contains the pointers to the loadable transport
routines for the transport type of this connection.
ConnectionClosedFlag - Contains a flag which will be non-zero if
the connection is closed, and zero otherwise.
ReferenceCount - The open connection and each dispatched call
own one reference.
--*/
{
friend OSF_SCALL;
friend OSF_ADDRESS;
private:
// data member ordering is optimized for locality
// If you modify something, make sure that the section boundaries are
// preserved. It is assumed that in the common case the OSF_SCALL is used
// by a thread at a time. Ordering is by frequency of usage, regardless of
// read/write
// Most frequenty used section (>= 3 times per call)
BOOL fExclusive;
BOOL CachedSCallAvailable;
CLIENT_AUTH_INFO AuthInfo; // actually, only the AuthLevel is used, but we don't want to
// split it
// ~2 times per call
RPC_CONNECTION_TRANSPORT * ServerInfo;
unsigned int AdditionalSpaceForSecurity;
unsigned int ConnectionClosedFlag;
public:
RPC_TRANSPORT_CONNECTION TransConnection;
private:
SECURITY_CONTEXT * CurrentSecurityContext;
// ~1 times per call
OSF_ASSOCIATION * Association;
OSF_ADDRESS *Address;
unsigned long DataRep;
unsigned long RpcSecurityBeingUsed;
DCE_SECURITY_INFO DceSecurityInfo;
OSF_SCALL *CachedSCall;
OSF_SBINDING_DICT Bindings;
DebugConnectionInfo *DebugCell;
public:
unsigned short MaxFrag;
private:
CellTag DebugCellTag;
// actively used in non-nominal paths
OSF_SCALL_DICT2 CallDict;
MUTEX ConnMutex;
SECURITY_CONTEXT_DICT SecurityContextDict;
void * SavedHeader;
unsigned long SavedHeaderSize;
// not used or used few times
unsigned AuthContextId;
unsigned long SecurityContextAltered;
unsigned long CurrentCallId;
BOOL AuthContinueNeeded;
BOOL fDontFlush;
DCE_INIT_SECURITY_INFO InitSecurityInfo;
public:
BOOL fFirstCall;
BOOL fCurrentlyDispatched;
QUEUE CallQueue;
OSF_SCONNECTION (
IN OSF_ADDRESS * TheAddress,
IN RPC_CONNECTION_TRANSPORT * ServerInfo,
IN OUT RPC_STATUS * RpcStatus
);
~OSF_SCONNECTION (
);
virtual RPC_STATUS
TransSend (
IN void * Buffer,
IN unsigned int BufferLength
);
virtual RPC_STATUS
TransAsyncSend (
IN void * Buffer,
IN unsigned int BufferLength,
IN void *SendContext
);
virtual RPC_STATUS
TransAsyncReceive (
);
virtual void
FreeObject (
);
void
AbortConnection (
);
unsigned int
TransMaximumSend (
);
RPC_STATUS
TransImpersonateClient (
);
void
TransRevertToSelf (
);
void
TransQueryClientProcess (
OUT RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
);
RPC_STATUS
TransQueryClientNetworkAddress (
OUT RPC_CHAR ** NetworkAddress
);
void
SetDictKey (
IN int DictKey
);
void * operator new (
size_t allocBlock,
unsigned int xtraBytes
);
RPC_STATUS
SendFragment(
IN OUT rpcconn_common *pFragment,
IN unsigned int LastFragmentFlag,
IN unsigned int HeaderSize,
IN unsigned int MaxSecuritySize,
IN unsigned int DataLength,
IN unsigned int MaximumFragmentLength,
IN unsigned char *MyReservedForSecurity,
IN BOOL fAsync = 0,
IN void *SendContext = 0
) ;
RPC_STATUS
InquireAuthClient (
OUT RPC_AUTHZ_HANDLE * Privileges,
OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
OUT unsigned long * AuthenticationLevel,
OUT unsigned long * AuthenticationService,
OUT unsigned long * AuthorizationService,
IN unsigned long Flags
);
RPC_STATUS
InquireCallAttributes (
IN OUT void *RpcCallAttributes
);
RPC_STATUS
ImpersonateClient (
);
RPC_STATUS
RevertToSelf (
);
RPC_STATUS
GetAssociationContextCollection (
OUT ContextCollection **AssociationContext
);
RPC_STATUS
IsClientLocal (
OUT unsigned int * ClientLocalFlag
);
RPC_STATUS
TransGetBuffer ( // Allocate a buffer of the specified size.
OUT void * * Buffer,
IN unsigned int BufferLength
);
virtual void
TransFreeBuffer ( // Free a buffer.
IN void * Buffer
);
int
AssociationRequested (
IN rpcconn_bind * BindPacket,
IN unsigned int BindPacketLength
);
RPC_STATUS
EatAuthInfoFromPacket (
IN rpcconn_request * Request,
IN OUT int * RequestLength,
IN OUT void * *SavedHeader,
IN OUT unsigned long *SavedHeaderSize
);
int // Indicates success (0), or an internal error code.
AlterContextRequested ( // Process the alter context request. Send
// a reply.
IN rpcconn_alter_context * pAlterContext,
IN unsigned int culAlterContextLength
);
int // Indicates success (0), or an internal error code.
SendBindNak ( // Construct and send the bind nak packet using the
// specified reject reason.
IN p_reject_reason_t reject_reason,
IN unsigned long CallId
);
unsigned int
InqMaximumFragmentLength (
);
inline
SECURITY_CONTEXT *
FindSecurityContext(
unsigned long Id,
unsigned long Level,
unsigned long Svc
);
BOOL
MaybeQueueThisCall (
IN OSF_SCALL *ThisCall
);
void
AbortQueuedCalls (
);
void
DispatchQueuedCalls (
);
inline BOOL IsExclusive(void)
{
return fExclusive;
}
private:
int
ProcessPContextList (
IN OSF_ADDRESS * Address,
IN p_cont_list_t * PContextList,
IN OUT unsigned int * PContextListLength,
OUT p_result_list_t * ResultList
);
RPC_STATUS
GetServerPrincipalName (
IN unsigned long Flags,
OUT RPC_CHAR **ServerPrincipalName OPTIONAL
);
public:
void
SendFault (
IN RPC_STATUS Status,
IN int DidNotExecute,
IN unsigned long CallId,
IN p_context_id_t p_cont_id = 0
);
BOOL
PickleEEInfoIntoPacket (
IN size_t PickleStartOffset,
OUT PVOID *Packet,
OUT size_t *PacketSize);
OSF_ASSOCIATION *
TheAssociation (
) {return(Association);}
void
RemoveFromAssociation (
);
virtual RPC_STATUS
InqTransportType(
OUT unsigned int __RPC_FAR * Type
) ;
OSF_SBINDING *
LookupBinding (
IN p_context_id_t PresentContextId
);
inline void
CleanupPac(
);
void
ProcessReceiveComplete (
IN RPC_STATUS EventStatus,
IN BUFFER Buffer,
IN UINT BufferLength
);
void
FreeSCall (
IN OSF_SCALL *SCall,
IN BOOL fRemove = 0
);
OSF_SCALL *
FindCall (
unsigned long CallId
);
inline RPC_STATUS
InqLocalConnAddress (
IN OUT void *Buffer,
IN OUT unsigned long *BufferSize,
OUT unsigned long *AddressFormat
)
{
// Querying the local address has some transient
// effects on the Winsock options for the connection.
// We cannot do this on non-exclusive connections
// as it may affect calls in progress
if (ServerInfo->QueryLocalAddress && fExclusive)
{
return ServerInfo->QueryLocalAddress(TransConnection,
Buffer,
BufferSize,
AddressFormat);
}
else
return RPC_S_CANNOT_SUPPORT;
}
inline BOOL IsHttpTransport (
void
)
{
return (ServerInfo->SetLastBufferToFree != NULL);
}
inline RPC_STATUS SetLastBufferToFree (
IN void *BufferToFree
)
{
ASSERT(ServerInfo->SetLastBufferToFree);
return ServerInfo->SetLastBufferToFree (TransConnection, BufferToFree);
}
};
inline OSF_SCALL *
OSF_SCONNECTION::FindCall (
unsigned long CallId
)
{
OSF_SCALL *SCall;
ConnMutex.Request();
SCall = CallDict.Find(ULongToPtr(CallId));
if (SCall)
{
SCall->AddReference(); // CALL++
}
ConnMutex.Clear();
return SCall;
}
inline void *
OSF_SCONNECTION::operator new (
size_t allocBlock,
unsigned int xtraBytes
)
{
void * pvTemp = RpcpFarAllocate(allocBlock + xtraBytes);
return(pvTemp);
}
inline void
OSF_SCONNECTION::CleanupPac (
)
{
if ((CurrentSecurityContext != 0) && (AuthInfo.PacHandle != 0))
{
CurrentSecurityContext->DeletePac( AuthInfo.PacHandle );
AuthInfo.PacHandle = 0;
}
}
inline
SECURITY_CONTEXT *
OSF_SCONNECTION::FindSecurityContext(
unsigned long Id,
unsigned long Level,
unsigned long Svc
)
{
SECURITY_CONTEXT *Sec;
DictionaryCursor cursor;
SecurityContextDict.Reset(cursor);
while ( (Sec = SecurityContextDict.Next(cursor)) != 0 )
{
if ( (Sec->AuthContextId == Id)
&&(Sec->AuthenticationLevel == Level)
&&(Sec->AuthenticationService == Svc) )
{
break;
}
}
return (Sec);
}
inline RPC_STATUS
OSF_SCONNECTION::InqTransportType(
OUT unsigned int __RPC_FAR * Type
)
{
*Type = TRANSPORT_TYPE_CN ;
return (RPC_S_OK) ;
}
inline unsigned int
OSF_SCONNECTION::InqMaximumFragmentLength (
)
/*++
Return Value:
The maximum fragment length negotiated for this connection will be
returned.
--*/
{
return(MaxFrag);
}
inline RPC_STATUS
OSF_SCALL::InquireAuthClient (
OUT RPC_AUTHZ_HANDLE * Privileges,
OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
OUT unsigned long * AuthenticationLevel,
OUT unsigned long * AuthenticationService,
OUT unsigned long * AuthorizationService,
IN unsigned long Flags
)
{
return Connection->InquireAuthClient(Privileges,
ServerPrincipalName,
AuthenticationLevel,
AuthenticationService,
AuthorizationService,
Flags);
}
inline RPC_STATUS
OSF_SCALL::InquireCallAttributes (
IN OUT void *RpcCallAttributes
)
{
return Connection->InquireCallAttributes(RpcCallAttributes);
}
inline RPC_STATUS
OSF_SCALL::IsClientLocal (
OUT unsigned int * ClientLocalFlag
)
{
return Connection->IsClientLocal(ClientLocalFlag);
}
inline RPC_STATUS
OSF_SCALL::InqTransportType(
OUT unsigned int __RPC_FAR * Type
)
{
return Connection->InqTransportType(Type);
}
inline RPC_STATUS
OSF_SCALL::InqSecurityContext (
OUT void **SecurityContextHandle
)
{
*SecurityContextHandle = Connection->CurrentSecurityContext->InqSecurityContext();
return RPC_S_OK;
}
inline void
OSF_SCALL::ActivateCall (
)
{
CallStack = 0;
ObjectUuidSpecified = 0;
CallOrphaned = 0;
CurrentBuffer = 0;
CurrentBufferLength = 0 ;
CurrentOffset = 0;
AsyncStatus = RPC_S_OK;
Address = Connection->Address;
fPipeCall = 0;
fCallDispatched = 0;
DispatchBuffer = 0;
DispatchBufferOffset = 0;
AllocHint = 0;
RcvBufferLength = 0;
CurrentState = NewRequest;
FirstFrag = 1;
pAsync = 0;
CachedAPCInfoAvailable = 1;
NestingCall = 0;
FirstSend = 1;
NeededLength = 0;
LastBuffer = 0;
MaxSecuritySize = 0;
MaximumFragmentLength = Connection->MaxFrag;
fChoked = 0;
fPeerChoked = 0;
fSecurityFailure = 0;
DispatchFlags = RPC_BUFFER_COMPLETE;
CurrentBinding = 0;
if (DebugCell)
{
DebugCell->Status = csActive;
}
//
// Start out with two references. One for the dispatch
// and the other for the reply. This overrides the default
// which is one reference.
//
//
// Try changing this to a better interlocked operation
//
// we have the following special case to take care of:
// for performance reasons, the previous call will make
// itself available before it takes down its references.
// We may start piling our references on top of its
// references, thus preventing the refcount from dropping
// to zero, and leaving one extra refcount on the connection
// (because the call will drop its refcount on the connection
// only when its own refcount goes to 0). This if statement
// will detect when this special case happens, and will
// drop the connection refcount for the previous call
if ((AddReference() > 1) && (Connection->CachedSCall == this) && (Connection->IsExclusive()))
Connection->RemoveReference();
AddReference();
}
inline void
OSF_SCALL::RemoveReference (
)
{
OSF_SCALL *DeletedCall;
int refcount;
if (Connection->fExclusive)
{
REFERENCED_OBJECT::RemoveReference();
}
else
{
Connection->ConnMutex.Request();
refcount = RefCount.Decrement();
LogEvent(SU_SCALL, EV_DEC, this, 0, refcount, 1);
if (refcount == 0)
{
DeletedCall = Connection->CallDict.Delete(ULongToPtr(CallId));
Connection->ConnMutex.Clear();
ASSERT(DeletedCall == 0 || DeletedCall == this);
FreeObject();
//
// Warning: The SCALL could have been nuked at this point.
// DO NOT touch the SCALL after this
//
}
else
{
Connection->ConnMutex.Clear();
}
}
}
inline void
OSF_SCALL::CleanupCall (
)
{
BUFFER Buffer;
unsigned int ignore;
BOOL fMutexTaken = FALSE;
BOOL IsExclusiveConnection = Connection->IsExclusive();
if (pAsync)
{
DoPostDispatchProcessing();
ASSERT(fCallDispatched);
FreeBufferDo(DispatchBuffer);
if (IsExclusiveConnection)
{
CurrentBinding->GetInterface()->EndCall(0, 1);
}
}
if (fCallDispatched == 0 && DispatchBuffer)
{
FreeBufferDo(DispatchBuffer);
}
if (IsExclusiveConnection)
{
if (CurrentBinding->GetInterface()->IsAutoListenInterface())
{
CurrentBinding->GetInterface()->EndAutoListenCall();
}
}
Connection->CleanupPac();
DeactivateCall();
// For non-exclusive pipe calls we need to make the call available and
// free the buffers within a critical section. This ensures that another
// thread will not pick up the available call and start adding buffers to the
// queue while we are wiping it out.
if (fPipeCall && !IsExclusiveConnection)
{
CallMutex.Request();
fMutexTaken = TRUE;
}
if (IsExclusiveConnection)
{
Connection->CachedSCallAvailable = 1;
}
// Buffers must not be left over from this call
// If there are left over buffers, free them
if (!BufferQueue.IsQueueEmpty())
{
if (fMutexTaken == FALSE)
CallMutex.Request();
while (Buffer = BufferQueue.TakeOffQueue(&ignore))
{
Connection->TransFreeBuffer((char *) Buffer-sizeof(rpcconn_response));
}
CallMutex.Clear();
fMutexTaken = FALSE;
}
if (fMutexTaken == TRUE)
CallMutex.Clear();
}
inline void
OSF_SCALL::FreeObject (
)
/*++
Function Name:CleanupCall
Parameters:
Description:
Returns:
--*/
{
LogEvent(SU_SCALL, EV_DELETE, this, 0, 0, 0);
Connection->FreeSCall(this);
}
inline RPC_STATUS
OSF_SCALL::InqConnection (
OUT void **ConnId,
OUT BOOL *pfFirstCall
)
{
ASSERT(Connection);
*ConnId = Connection;
if (InterlockedIncrement((LONG *) &(Connection->fFirstCall)) == 1)
{
*pfFirstCall = 1;
}
else
{
*pfFirstCall = 0;
}
return RPC_S_OK;
}
class OSF_ASSOCIATION : public ASSOCIATION_HANDLE
{
private:
int ConnectionCount;
unsigned long AssociationGroupId;
int AssociationDictKey;
OSF_ADDRESS * Address;
RPC_CLIENT_PROCESS_IDENTIFIER ClientProcess;
public:
OSF_ASSOCIATION (
IN OSF_ADDRESS * TheAddress,
IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess,
OUT RPC_STATUS * Status
);
~OSF_ASSOCIATION ( // Destructor.
);
void
AddConnection ( // Add a connection to the association.
void
);
// Remove a connection from the association without taking
// the mutex. Returns non-zero if 'this' is to be deleted
BOOL
RemoveConnectionUnsafe (
void
);
void
RemoveConnection ( // Remove a connection from the association.
void
);
int // Returns the association group id for this association.
AssocGroupId (
void
)
{
return(AssociationGroupId);
}
OSF_ADDRESS *
TheAddress (
void
)
{
return(Address);
}
int
IsMyAssocGroupId (
IN unsigned long PossibleAssocGroupId,
IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
);
virtual RPC_STATUS CreateThread(void);
};
inline int
OSF_ASSOCIATION::IsMyAssocGroupId (
IN unsigned long PossibleAssocGroupId,
IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
)
/*++
Routine Description:
We compare the supplied possible association group id against my
association group id in this routine.
Arguments:
PossibleAssocGroupId - Supplies a possible association group id to
compare against mine.
ClientProcess - Supplies the identifier for the client process at the
other end of the connection requesting this association.
Return Value:
Non-zero will be returned if the possible association group id is the
same as my association group id.
--*/
{
return( ( PossibleAssocGroupId == AssociationGroupId )
&& ( !(this->ClientProcess.Compare(ClientProcess))));
}
inline void
OSF_ASSOCIATION::AddConnection (
)
{
int HashBucketNumber;
// get the hashed bucket
HashBucketNumber = Address->GetHashBucketForAssociation(AssociationGroupId);
// verify the bucket is locked
Address->GetAssociationBucketMutex(HashBucketNumber)->VerifyOwned();
ConnectionCount ++;
}
inline void
OSF_SCONNECTION::RemoveFromAssociation (
)
/*++
Routine Description:
This connection will be removed from the association. We need to do
this so that context rundown will occur, even though the connection
has not been deleted yet.
--*/
{
if ( Association != 0 )
{
Association->RemoveConnection();
Association = 0;
}
}
extern RPC_TRANSPORT_INTERFACE_HEADER *
LoadableTransportServerInfo (
IN RPC_CHAR * DllName,
IN RPC_CHAR * RpcProtocolSequence,
OUT RPC_STATUS * Status
);
#endif // __OSFSVR_HXX__