1730 lines
40 KiB
C++
1730 lines
40 KiB
C++
//+-------------------------------------------------------------------------
|
||
//
|
||
// 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__
|