1535 lines
34 KiB
C++
1535 lines
34 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (C) Microsoft Corporation, 1992 - 1999
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
lpcsvr.hxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Class definition for the server side of RPC on LPC protocol
|
|||
|
engine.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Steven Zeck (stevez) 12/17/91 (spcsvr.hxx)
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
16-Dec-1992 mikemon
|
|||
|
|
|||
|
Rewrote the majority of the code and added comments.
|
|||
|
|
|||
|
-- mazharm code fork from spcsvr.hxx
|
|||
|
|
|||
|
05/13/96 mazharm merged WMSG/LRPC into a common protocol
|
|||
|
9/22/97 no more WMSG
|
|||
|
|
|||
|
Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
|
|||
|
Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
|
|||
|
--*/
|
|||
|
|
|||
|
#ifndef __LPCSVR_HXX__
|
|||
|
#define __LPCSVR_HXX__
|
|||
|
|
|||
|
class LRPC_SASSOCIATION;
|
|||
|
class LRPC_CASSOCIATION;
|
|||
|
class LRPC_ADDRESS;
|
|||
|
class LRPC_SERVER ;
|
|||
|
class LRPC_SCALL ;
|
|||
|
class LRPC_SERVER ;
|
|||
|
class LRPC_CASSOCIATION_DICT;
|
|||
|
|
|||
|
|
|||
|
// the next four are protected by the LrpcMutex
|
|||
|
extern LRPC_CASSOCIATION_DICT * LrpcAssociationDict;
|
|||
|
|
|||
|
// the number of associations in the LrpcAssociationDict
|
|||
|
// dictionary that have their fAssociationLingered member set
|
|||
|
extern long LrpcLingeredAssociations;
|
|||
|
|
|||
|
// the total number of LRPC associations destroyed in this process
|
|||
|
// this is used to dynamically turn on garbage collection if
|
|||
|
// necessary
|
|||
|
extern ULONG LrpcDestroyedAssociations;
|
|||
|
|
|||
|
// each time the number of destroyed associations is divisible by
|
|||
|
// NumberOfLrpcDestroyedAssociationsToSample, we check this timestamp
|
|||
|
// and compare it to the current. If the difference is more than
|
|||
|
// DestroyedLrpcAssociationBatchThreshold, we will turn on
|
|||
|
// garbage collection automatically
|
|||
|
extern ULARGE_INTEGER LastDestroyedAssociationsBatchTimestamp;
|
|||
|
|
|||
|
const ULONG NumberOfLrpcDestroyedAssociationsToSample = 128;
|
|||
|
|
|||
|
// in 100 nano-second intervals, this constant is 1 second
|
|||
|
const DWORD DestroyedLrpcAssociationBatchThreshold = 1000 * 10 * 1000;
|
|||
|
|
|||
|
// 4 is an arbitrary number designed to ensure reasonably sized cache
|
|||
|
// Feel free to change it if there is a perf reason for that
|
|||
|
const long MaxLrpcLingeredAssociations = 4;
|
|||
|
extern LRPC_SERVER *GlobalLrpcServer;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
InitializeLrpcServer(
|
|||
|
) ;
|
|||
|
|
|||
|
extern RPC_STATUS
|
|||
|
InitializeLrpcIfNecessary(
|
|||
|
) ;
|
|||
|
|
|||
|
#define LrpcSetEndpoint(Endpoint) (\
|
|||
|
GlobalLrpcServer->SetEndpoint(Endpoint))
|
|||
|
#define LrpcGetEndpoint(Endpoint) (\
|
|||
|
GlobalLrpcServer->GetEndpoint(Endpoint))
|
|||
|
|
|||
|
NEW_SDICT(LRPC_SASSOCIATION);
|
|||
|
NEW_SDICT(LRPC_SCALL) ;
|
|||
|
|
|||
|
#define SERVER_KEY_MASK 0x8000
|
|||
|
#define SERVERKEY(_x_) ((_x_) & 0x80000000)
|
|||
|
|
|||
|
#define CLEANUP goto cleanup
|
|||
|
|
|||
|
#define COPYMSG(LrpcCopy, LrpcMessage) \
|
|||
|
LrpcCopy->LpcHeader.ClientId = LrpcMessage->LpcHeader.ClientId ; \
|
|||
|
LrpcCopy->LpcHeader.CallbackId = LrpcMessage->LpcHeader.CallbackId ; \
|
|||
|
LrpcCopy->LpcHeader.MessageId = LrpcMessage->LpcHeader.MessageId ; \
|
|||
|
LrpcCopy->LpcHeader.u2.s2.DataInfoOffset = \
|
|||
|
LrpcMessage->LpcHeader.u2.s2.DataInfoOffset
|
|||
|
|
|||
|
#define INITMSG(LrpcMessage, CId, Cbd, MId) \
|
|||
|
(LrpcMessage)->LpcHeader.ClientId = ClientIdToMsgClientId(CId) ;\
|
|||
|
(LrpcMessage)->LpcHeader.CallbackId = Cbd ;\
|
|||
|
(LrpcMessage)->LpcHeader.MessageId = MId
|
|||
|
|
|||
|
#define AllocateMessage() ((LRPC_MESSAGE *) RpcAllocateBuffer(sizeof(LRPC_MESSAGE)))
|
|||
|
#define FreeMessage(x) (RpcFreeBuffer((x)))
|
|||
|
|
|||
|
//
|
|||
|
// The high bit of the sequence number
|
|||
|
// is used to determine if it is a client or server
|
|||
|
// key.
|
|||
|
// CAUTION: Big endian implementations need to swap this
|
|||
|
// around
|
|||
|
//
|
|||
|
typedef struct {
|
|||
|
USHORT AssocKey;
|
|||
|
USHORT SeqNumber;
|
|||
|
} LPC_KEY;
|
|||
|
|
|||
|
|
|||
|
class LRPC_SERVER
|
|||
|
{
|
|||
|
private:
|
|||
|
LRPC_ADDRESS *Address ;
|
|||
|
RPC_CHAR * Endpoint;
|
|||
|
BOOL EndpointInitialized ;
|
|||
|
MUTEX ServerMutex ;
|
|||
|
|
|||
|
public:
|
|||
|
LRPC_SERVER(
|
|||
|
IN OUT RPC_STATUS *Status
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
InitializeAsync (
|
|||
|
) ;
|
|||
|
|
|||
|
void
|
|||
|
GetEndpoint(
|
|||
|
IN RPC_CHAR *Endpoint
|
|||
|
)
|
|||
|
{
|
|||
|
RpcpStringCopy(Endpoint, this->Endpoint) ;
|
|||
|
}
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
SetEndpoint(
|
|||
|
IN RPC_CHAR *Endpoint
|
|||
|
)
|
|||
|
{
|
|||
|
if (EndpointInitialized == 0)
|
|||
|
{
|
|||
|
this->Endpoint = DuplicateString(Endpoint) ;
|
|||
|
if (this->Endpoint == 0)
|
|||
|
{
|
|||
|
return RPC_S_OUT_OF_MEMORY ;
|
|||
|
}
|
|||
|
|
|||
|
EndpointInitialized = 1 ;
|
|||
|
}
|
|||
|
|
|||
|
return RPC_S_OK ;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
AcquireMutex(
|
|||
|
)
|
|||
|
{
|
|||
|
ServerMutex.Request() ;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
ReleaseMutex(
|
|||
|
)
|
|||
|
{
|
|||
|
ServerMutex.Clear() ;
|
|||
|
}
|
|||
|
|
|||
|
void VerifyOwned(void)
|
|||
|
{
|
|||
|
ServerMutex.VerifyOwned();
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
TryRequestMutex (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
return ServerMutex.TryRequest();
|
|||
|
}
|
|||
|
} ;
|
|||
|
|
|||
|
inline void LrpcMutexRequest(void)
|
|||
|
{
|
|||
|
GlobalLrpcServer->AcquireMutex();
|
|||
|
}
|
|||
|
|
|||
|
inline void LrpcMutexClear(void)
|
|||
|
{
|
|||
|
GlobalLrpcServer->ReleaseMutex();
|
|||
|
}
|
|||
|
|
|||
|
inline void LrpcMutexVerifyOwned(void)
|
|||
|
{
|
|||
|
GlobalLrpcServer->VerifyOwned();
|
|||
|
}
|
|||
|
|
|||
|
inline BOOL LrpcMutexTryRequest(void)
|
|||
|
{
|
|||
|
return GlobalLrpcServer->TryRequestMutex();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
class LRPC_ADDRESS : public RPC_ADDRESS
|
|||
|
/*++
|
|||
|
|
|||
|
Class Description:
|
|||
|
|
|||
|
Fields:
|
|||
|
|
|||
|
LpcAddressPort - Contains the connection port which this address will
|
|||
|
use to wait for clients to connect.
|
|||
|
|
|||
|
CallThreadCount - Contains the number of call threads we have executing.
|
|||
|
|
|||
|
MinimumCallThreads - Contains the minimum number of call threads.
|
|||
|
|
|||
|
ServerListeningFlag - Contains a flag indicating whether or not the server
|
|||
|
is listening for remote procedure calls. A non-zero value indicates
|
|||
|
that it is listening.
|
|||
|
|
|||
|
ActiveCallCount - Contains the number of remote procedure calls active
|
|||
|
on this address.
|
|||
|
|
|||
|
AssociationDictionary - Contains the dictionary of associations on this
|
|||
|
address. We need this to map from an association key into the
|
|||
|
correct association. This is necessary to prevent a race condition
|
|||
|
between deleting an association and using it.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
private:
|
|||
|
|
|||
|
HANDLE LpcAddressPort;
|
|||
|
long CallThreadCount;
|
|||
|
long MinimumCallThreads;
|
|||
|
LRPC_SASSOCIATION_DICT AssociationDictionary;
|
|||
|
int AssociationCount ;
|
|||
|
USHORT SequenceNumber;
|
|||
|
CellTag DebugCellTag;
|
|||
|
DebugEndpointInfo *DebugCell;
|
|||
|
|
|||
|
// not protected - operated by interlocks. We push on the list,
|
|||
|
// but we never pop, knowing addresses don't get deleted.
|
|||
|
LRPC_ADDRESS *AddressChain;
|
|||
|
|
|||
|
// the next three are protected by the LrpcMutex
|
|||
|
// If TickleMessage is non-zero, this means that the
|
|||
|
// address has been prepared for tickling. Once it
|
|||
|
// is initialized, fTickleMessageAvailable is used
|
|||
|
// to tell whether the TickleMessage is currently posted
|
|||
|
// or not. If it is already posted, no need to repost.
|
|||
|
BOOL fTickleMessageAvailable;
|
|||
|
LRPC_BIND_EXCHANGE *TickleMessage;
|
|||
|
UNICODE_STRING ThisAddressLoopbackString;
|
|||
|
|
|||
|
// the number of threads on this address doing long wait
|
|||
|
INTERLOCKED_INTEGER ThreadsDoingLongWait;
|
|||
|
|
|||
|
public:
|
|||
|
unsigned int ServerListeningFlag ;
|
|||
|
BOOL fServerThreadsStarted;
|
|||
|
|
|||
|
LRPC_ADDRESS (
|
|||
|
OUT RPC_STATUS * Status
|
|||
|
);
|
|||
|
|
|||
|
~LRPC_ADDRESS (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
if (DebugCell)
|
|||
|
{
|
|||
|
FreeCell(DebugCell, &DebugCellTag);
|
|||
|
DebugCell = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
ServerStartingToListen (
|
|||
|
IN unsigned int MinimumCallThreads,
|
|||
|
IN unsigned int MaximumConcurrentCalls
|
|||
|
);
|
|||
|
|
|||
|
virtual void
|
|||
|
ServerStoppedListening (
|
|||
|
);
|
|||
|
|
|||
|
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
|
|||
|
) ;
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
LRPC_ADDRESS::CompleteListen (
|
|||
|
);
|
|||
|
|
|||
|
inline void
|
|||
|
DereferenceAssociation (
|
|||
|
IN LRPC_SASSOCIATION * Association
|
|||
|
);
|
|||
|
|
|||
|
friend BOOL
|
|||
|
RecvLotsaCallsWrapper(
|
|||
|
IN LRPC_ADDRESS * Address
|
|||
|
);
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
BeginLongCall(
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
EndLongCall(
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
inline BOOL
|
|||
|
PrepareForLoopbackTicklingIfNecessary (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
LrpcMutexVerifyOwned();
|
|||
|
|
|||
|
if (TickleMessage)
|
|||
|
return TRUE;
|
|||
|
|
|||
|
return PrepareForLoopbackTickling();
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
LoopbackTickle (
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
inline BOOL
|
|||
|
IsPreparedForLoopbackTickling (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
return (TickleMessage != NULL);
|
|||
|
}
|
|||
|
|
|||
|
inline LRPC_ADDRESS *
|
|||
|
GetNextAddress (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
return AddressChain;
|
|||
|
}
|
|||
|
|
|||
|
inline int
|
|||
|
GetNumberOfThreadsDoingShortWait (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
return CallThreadCount - ThreadsDoingLongWait.GetInteger();
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
ActuallySetupAddress (
|
|||
|
IN RPC_CHAR *Endpoint,
|
|||
|
IN void * SecurityDescriptor
|
|||
|
);
|
|||
|
|
|||
|
inline LRPC_SASSOCIATION *
|
|||
|
ReferenceAssociation (
|
|||
|
IN unsigned long AssociationKey
|
|||
|
);
|
|||
|
|
|||
|
inline LRPC_CASSOCIATION *
|
|||
|
ReferenceClientAssoc (
|
|||
|
IN unsigned long AssociationKey
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
ReceiveLotsaCalls (
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
DealWithNewClient (
|
|||
|
IN LRPC_MESSAGE * ConnectionRequest
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
DealWithConnectResponse (
|
|||
|
IN LRPC_MESSAGE * ConnectResponse
|
|||
|
) ;
|
|||
|
|
|||
|
void
|
|||
|
RejectNewClient (
|
|||
|
IN LRPC_MESSAGE * ConnectionRequest,
|
|||
|
IN RPC_STATUS Status
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
DealWithLRPCRequest (
|
|||
|
IN LRPC_MESSAGE * LrpcMessage,
|
|||
|
IN LRPC_MESSAGE * LrpcReplyMessage,
|
|||
|
IN LRPC_SASSOCIATION *Association,
|
|||
|
OUT LRPC_MESSAGE **LrpcResponse
|
|||
|
) ;
|
|||
|
|
|||
|
BOOL fKeepThread(
|
|||
|
)
|
|||
|
{
|
|||
|
// we keep at least two threads per address, to avoid creating the
|
|||
|
// second thread each time a call arrives. Note that the second
|
|||
|
// thread is free to timeout on the port and exit, the question
|
|||
|
// is that it doesn't exit immediately after the call, as this will
|
|||
|
// cause unnecessary creation/deletions of threads
|
|||
|
return (((CallThreadCount - ActiveCallCount) <= 2)
|
|||
|
|| (CallThreadCount <= MinimumCallThreads));
|
|||
|
}
|
|||
|
|
|||
|
typedef enum
|
|||
|
{
|
|||
|
asctDestroyContextHandle = 0,
|
|||
|
asctCleanupIdleSContext
|
|||
|
} AssociationCallbackType;
|
|||
|
|
|||
|
void
|
|||
|
EnumerateAndCallEachAssociation (
|
|||
|
IN AssociationCallbackType asctType,
|
|||
|
IN OUT void *Context OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
virtual void
|
|||
|
DestroyContextHandlesForInterface (
|
|||
|
IN RPC_SERVER_INTERFACE PAPI * RpcInterfaceInformation,
|
|||
|
IN BOOL RundownContextHandles
|
|||
|
);
|
|||
|
|
|||
|
virtual void
|
|||
|
CleanupIdleSContexts (
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
PrepareForLoopbackTickling (
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
void HandleInvalidAssociationReference (
|
|||
|
IN LRPC_MESSAGE *RequestMessage,
|
|||
|
IN OUT LRPC_MESSAGE **ReplyMessage,
|
|||
|
IN ULONG AssociationKey
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
class LRPC_SBINDING
|
|||
|
/*++
|
|||
|
|
|||
|
Class Description:
|
|||
|
|
|||
|
Each object of this class represents a binding to an interface by a
|
|||
|
client.
|
|||
|
|
|||
|
Fields:
|
|||
|
|
|||
|
RpcInterface - Contains a pointer to the bound interface.
|
|||
|
|
|||
|
PresentationContext - Contains the key which the client will send when
|
|||
|
it wants to use this binding.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
friend class LRPC_SASSOCIATION;
|
|||
|
friend class LRPC_SCALL;
|
|||
|
friend class LRPC_ADDRESS;
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
RPC_INTERFACE * RpcInterface;
|
|||
|
int PresentationContext;
|
|||
|
int SelectedTransferSyntaxIndex;
|
|||
|
unsigned long SequenceNumber ;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
LRPC_SBINDING (
|
|||
|
IN RPC_INTERFACE * RpcInterface,
|
|||
|
IN int SelectedTransferSyntax
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
We will construct a LRPC_SBINDING.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RpcInterface - Supplies the bound interface.
|
|||
|
|
|||
|
TransferSyntax - Supplies the transfer syntax which the client will use
|
|||
|
over this binding.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
this->RpcInterface = RpcInterface;
|
|||
|
SequenceNumber = 0;
|
|||
|
SelectedTransferSyntaxIndex = SelectedTransferSyntax;
|
|||
|
}
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
CheckSecurity (
|
|||
|
SCALL * Context
|
|||
|
);
|
|||
|
|
|||
|
inline unsigned short GetOnTheWirePresentationContext(void)
|
|||
|
{
|
|||
|
return (unsigned short)PresentationContext;
|
|||
|
}
|
|||
|
|
|||
|
inline void SetPresentationContextFromPacket(unsigned short PresentContext)
|
|||
|
{
|
|||
|
PresentationContext = (int) PresentContext;
|
|||
|
}
|
|||
|
|
|||
|
inline int GetPresentationContext (void)
|
|||
|
{
|
|||
|
return PresentationContext;
|
|||
|
}
|
|||
|
|
|||
|
inline void SetPresentationContext (int PresentContext)
|
|||
|
{
|
|||
|
PresentationContext = PresentContext;
|
|||
|
}
|
|||
|
|
|||
|
inline void GetSelectedTransferSyntaxAndDispatchTable(
|
|||
|
OUT RPC_SYNTAX_IDENTIFIER **SelectedTransferSyntax,
|
|||
|
OUT PRPC_DISPATCH_TABLE *SelectedDispatchTable)
|
|||
|
{
|
|||
|
RpcInterface->GetSelectedTransferSyntaxAndDispatchTable(SelectedTransferSyntaxIndex,
|
|||
|
SelectedTransferSyntax, SelectedDispatchTable);
|
|||
|
}
|
|||
|
|
|||
|
DWORD GetInterfaceFirstDWORD(void)
|
|||
|
{
|
|||
|
return RpcInterface->GetInterfaceFirstDWORD();;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
typedef void * LRPC_BUFFER;
|
|||
|
|
|||
|
NEW_SDICT(LRPC_SBINDING);
|
|||
|
NEW_SDICT(LRPC_CLIENT_BUFFER);
|
|||
|
NEW_SDICT2(LRPC_SCALL, PVOID);
|
|||
|
NEW_NAMED_SDICT2(LRPC_SCALL_THREAD, LRPC_SCALL, HANDLE);
|
|||
|
|
|||
|
#define USER_NAME_LEN 256
|
|||
|
#define DOMAIN_NAME_LEN 128
|
|||
|
|
|||
|
extern const SID AnonymousSid;
|
|||
|
|
|||
|
|
|||
|
class LRPC_SCONTEXT
|
|||
|
{
|
|||
|
public:
|
|||
|
HANDLE hToken;
|
|||
|
LUID ClientLuid;
|
|||
|
RPC_CHAR *ClientName;
|
|||
|
int RefCount;
|
|||
|
LRPC_SASSOCIATION *Association;
|
|||
|
AUTHZ_CLIENT_CONTEXT_HANDLE AuthzClientContext;
|
|||
|
|
|||
|
LRPC_SCONTEXT (
|
|||
|
IN HANDLE MyToken,
|
|||
|
IN LUID *UserLuid,
|
|||
|
IN LRPC_SASSOCIATION *MyAssociation,
|
|||
|
IN BOOL fDefaultLogonId,
|
|||
|
IN BOOL fAnonymousToken
|
|||
|
);
|
|||
|
|
|||
|
~LRPC_SCONTEXT (
|
|||
|
void
|
|||
|
);
|
|||
|
|
|||
|
void AddReference();
|
|||
|
void RemoveReference();
|
|||
|
void Destroy();
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
GetUserName (
|
|||
|
IN OUT ULONG *ClientPrincipalNameBufferLength OPTIONAL,
|
|||
|
OUT RPC_CHAR **UserName,
|
|||
|
IN HANDLE hUserToken OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
static const unsigned int Deleted = 1;
|
|||
|
static const unsigned int DefaultLogonId = 2;
|
|||
|
static const unsigned int Anonymous = 4;
|
|||
|
static const unsigned int ServerSideOnly = 8;
|
|||
|
|
|||
|
inline void SetDeletedFlag(void)
|
|||
|
{
|
|||
|
Flags.SetFlagUnsafe(Deleted);
|
|||
|
}
|
|||
|
inline void ClearDeletedFlag(void)
|
|||
|
{
|
|||
|
Flags.ClearFlagUnsafe(Deleted);
|
|||
|
}
|
|||
|
inline BOOL GetDeletedFlag(void)
|
|||
|
{
|
|||
|
return Flags.GetFlag(Deleted);
|
|||
|
}
|
|||
|
|
|||
|
inline void SetDefaultLogonIdFlag(void)
|
|||
|
{
|
|||
|
Flags.SetFlagUnsafe(DefaultLogonId);
|
|||
|
}
|
|||
|
inline void ClearDefaultLogonIdFlag(void)
|
|||
|
{
|
|||
|
Flags.ClearFlagUnsafe(DefaultLogonId);
|
|||
|
}
|
|||
|
inline BOOL GetDefaultLogonIdFlag(void)
|
|||
|
{
|
|||
|
return Flags.GetFlag(DefaultLogonId);
|
|||
|
}
|
|||
|
|
|||
|
inline void SetAnonymousFlag(void)
|
|||
|
{
|
|||
|
Flags.SetFlagUnsafe(Anonymous);
|
|||
|
}
|
|||
|
inline void ClearAnonymousFlag(void)
|
|||
|
{
|
|||
|
Flags.ClearFlagUnsafe(Anonymous);
|
|||
|
}
|
|||
|
inline BOOL GetAnonymousFlag(void)
|
|||
|
{
|
|||
|
return Flags.GetFlag(Anonymous);
|
|||
|
}
|
|||
|
|
|||
|
inline void SetServerSideOnlyFlag(void)
|
|||
|
{
|
|||
|
Flags.SetFlagUnsafe(ServerSideOnly);
|
|||
|
}
|
|||
|
inline void ClearServerSideOnlyFlag(void)
|
|||
|
{
|
|||
|
Flags.ClearFlagUnsafe(ServerSideOnly);
|
|||
|
}
|
|||
|
inline BOOL GetServerSideOnlyFlag(void)
|
|||
|
{
|
|||
|
return Flags.GetFlag(ServerSideOnly);
|
|||
|
}
|
|||
|
|
|||
|
static const ULONG CONTEXT_IDLE_TIMEOUT = 2 * 60 * 1000; // 2 minutes
|
|||
|
|
|||
|
inline void UpdateLastAccessTime (void)
|
|||
|
{
|
|||
|
LastAccessTime = NtGetTickCount();
|
|||
|
}
|
|||
|
|
|||
|
inline BOOL IsIdle (void)
|
|||
|
{
|
|||
|
// make sure if the tick count wraps the calculation is still valid
|
|||
|
return (NtGetTickCount() - LastAccessTime > CONTEXT_IDLE_TIMEOUT);
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
static TOKEN_USER *
|
|||
|
GetSID (
|
|||
|
IN HANDLE hToken
|
|||
|
);
|
|||
|
|
|||
|
static RPC_STATUS
|
|||
|
LookupUser (
|
|||
|
IN SID *pSid,
|
|||
|
OUT RPC_CHAR **UserName
|
|||
|
);
|
|||
|
|
|||
|
// changed either on creation, or within
|
|||
|
// the Association mutex
|
|||
|
CompositeFlags Flags;
|
|||
|
|
|||
|
// the last access time for server side only contexts.
|
|||
|
// Undefined if the context is not server side only
|
|||
|
// It is used to determine whether the context is idle
|
|||
|
ULONG LastAccessTime;
|
|||
|
};
|
|||
|
|
|||
|
NEW_SDICT(LRPC_SCONTEXT);
|
|||
|
|
|||
|
|
|||
|
class LRPC_SASSOCIATION : public ASSOCIATION_HANDLE
|
|||
|
/*++
|
|||
|
|
|||
|
Class Description:
|
|||
|
|
|||
|
|
|||
|
Fields:
|
|||
|
|
|||
|
LpcServerPort - Contains the LPC server communication port.
|
|||
|
|
|||
|
Bindings - Contains the dictionary of bindings with the client. This
|
|||
|
information is necessary to dispatch remote procedure calls to the
|
|||
|
correct stub.
|
|||
|
|
|||
|
Address - Contains the address which this association is over.
|
|||
|
|
|||
|
AssociationReferenceCount - Contains a count of the number of objects
|
|||
|
referencing this association. This will be the number of outstanding
|
|||
|
remote procedure calls, and one for LPC (because of the context
|
|||
|
pointer). We will protect this fielding using the global mutex.
|
|||
|
|
|||
|
Buffers - Contains the dictionary of buffers to be written into the
|
|||
|
client's address space on demand.
|
|||
|
|
|||
|
AssociationKey - Contains the key for this association in the dictionary
|
|||
|
of associations maintained by the address.
|
|||
|
|
|||
|
ClientThreadDict - This dictionary contains one entry per client thread. Each entry
|
|||
|
contains a list of SCALLS representing calls made by that client thread. The
|
|||
|
calls need to be causally ordered.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
friend class LRPC_ADDRESS;
|
|||
|
friend class LRPC_SCALL;
|
|||
|
friend class LRPC_SCONTEXT;
|
|||
|
friend void
|
|||
|
SetFaultPacket (
|
|||
|
IN LRPC_MESSAGE *LrpcMessage,
|
|||
|
IN RPC_STATUS Status,
|
|||
|
IN int Flags,
|
|||
|
IN LRPC_SCALL *CurrentCall OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
long AssociationReferenceCount;
|
|||
|
USHORT DictionaryKey;
|
|||
|
USHORT SequenceNumber;
|
|||
|
HANDLE LpcServerPort;
|
|||
|
HANDLE LpcReplyPort ;
|
|||
|
LRPC_ADDRESS * Address;
|
|||
|
LRPC_SBINDING_DICT Bindings;
|
|||
|
int Aborted ;
|
|||
|
long Deleted ;
|
|||
|
LRPC_SCALL *CachedSCall;
|
|||
|
LONG CachedSCallAvailable;
|
|||
|
BOOL fFirstCall;
|
|||
|
LRPC_CLIENT_BUFFER_DICT Buffers ;
|
|||
|
MUTEX AssociationMutex ;
|
|||
|
QUEUE FreeSCallQueue ;
|
|||
|
LRPC_SCALL_THREAD_DICT2 ClientThreadDict ;
|
|||
|
LRPC_SCONTEXT_DICT SContextDict;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
LRPC_SCALL_DICT2 SCallDict ;
|
|||
|
|
|||
|
|
|||
|
LRPC_SASSOCIATION (
|
|||
|
IN LRPC_ADDRESS * Address,
|
|||
|
IN RPC_STATUS *Status
|
|||
|
);
|
|||
|
|
|||
|
~LRPC_SASSOCIATION (
|
|||
|
);
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
AddBinding (
|
|||
|
IN OUT LRPC_BIND_EXCHANGE * BindExchange
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
DealWithBindMessage (
|
|||
|
IN LRPC_MESSAGE * LrpcMessage
|
|||
|
);
|
|||
|
|
|||
|
LRPC_MESSAGE *
|
|||
|
DealWithCopyMessage (
|
|||
|
IN LRPC_COPY_MESSAGE * LrpcMessage
|
|||
|
) ;
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ReplyMessage (
|
|||
|
IN LRPC_MESSAGE * LrpcMessage
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
SaveToken (
|
|||
|
IN LRPC_MESSAGE *LrpcMessage,
|
|||
|
OUT HANDLE *pTokenHandle,
|
|||
|
IN BOOL fRestoreToken = 0
|
|||
|
) ;
|
|||
|
|
|||
|
LRPC_MESSAGE *
|
|||
|
DealWithBindBackMessage (
|
|||
|
IN LRPC_MESSAGE *BindBack
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
BindBack (
|
|||
|
IN RPC_CHAR *Endpoint,
|
|||
|
IN DWORD pAssocKey
|
|||
|
) ;
|
|||
|
|
|||
|
LRPC_MESSAGE *
|
|||
|
DealWithPartialRequest (
|
|||
|
IN LRPC_MESSAGE **LrpcMessage
|
|||
|
) ;
|
|||
|
|
|||
|
void
|
|||
|
Delete(
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
AllocateSCall (
|
|||
|
IN LRPC_MESSAGE *LrpcMessage,
|
|||
|
IN LRPC_MESSAGE *LrpcReply,
|
|||
|
IN unsigned int Flags,
|
|||
|
IN LRPC_SCALL **SCall
|
|||
|
) ;
|
|||
|
|
|||
|
void
|
|||
|
FreeSCall (
|
|||
|
LRPC_SCALL *SCall
|
|||
|
) ;
|
|||
|
|
|||
|
int
|
|||
|
MaybeQueueSCall (
|
|||
|
IN LRPC_SCALL *SCall
|
|||
|
) ;
|
|||
|
|
|||
|
LRPC_SCALL *
|
|||
|
GetNextSCall (
|
|||
|
IN LRPC_SCALL *SCall
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
GetClientName (
|
|||
|
IN LRPC_SCALL *SCall,
|
|||
|
IN OUT ULONG *ClientPrincipalNameBufferLength OPTIONAL, // in bytes
|
|||
|
OUT RPC_CHAR **ClientPrincipalName
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
AbortAssociation (
|
|||
|
)
|
|||
|
{
|
|||
|
Aborted = 1 ;
|
|||
|
}
|
|||
|
|
|||
|
LRPC_SCONTEXT *
|
|||
|
FindSecurityContext (
|
|||
|
ULONG SecurityContextId
|
|||
|
)
|
|||
|
{
|
|||
|
LRPC_SCONTEXT *SContext;
|
|||
|
|
|||
|
AssociationMutex.Request();
|
|||
|
SContext = SContextDict.Find(SecurityContextId);
|
|||
|
if (SContext)
|
|||
|
{
|
|||
|
SContext->AddReference();
|
|||
|
}
|
|||
|
AssociationMutex.Clear();
|
|||
|
|
|||
|
return SContext;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
IsAborted(
|
|||
|
)
|
|||
|
{
|
|||
|
return Aborted ;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
MaybeDereference (
|
|||
|
)
|
|||
|
{
|
|||
|
if (Aborted)
|
|||
|
{
|
|||
|
Delete() ;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LRPC_ADDRESS *
|
|||
|
InqAddress(
|
|||
|
)
|
|||
|
{
|
|||
|
return Address ;
|
|||
|
}
|
|||
|
|
|||
|
virtual RPC_STATUS CreateThread(void);
|
|||
|
virtual void RundownNotificationCompleted(void);
|
|||
|
|
|||
|
void
|
|||
|
CleanupIdleSContexts (
|
|||
|
void
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
class LRPC_SCALL : public SCALL
|
|||
|
/*++
|
|||
|
|
|||
|
Class Description:
|
|||
|
|
|||
|
Fields:
|
|||
|
|
|||
|
Association - Contains the association over which the remote procedure
|
|||
|
call was received. We need this information to make callbacks and
|
|||
|
to send the reply.
|
|||
|
|
|||
|
LrpcMessage - Contains the request message. We need this to send callbacks
|
|||
|
as well as the reply.
|
|||
|
|
|||
|
SBinding - Contains the binding being used for this remote procedure call.
|
|||
|
|
|||
|
ObjectUuidFlag - Contains a flag indicting whether or not an object
|
|||
|
uuid was specified for this remote procedure call. A non-zero
|
|||
|
value indicates that an object uuid was specified.
|
|||
|
|
|||
|
ObjectUuid - Optionally contains the object uuid for this call, if one
|
|||
|
was specified.
|
|||
|
|
|||
|
ClientId - Contains the thread identifier of the thread which made the
|
|||
|
remote procedure call.
|
|||
|
|
|||
|
MessageId - Contains an identifier used by LPC to identify the current
|
|||
|
remote procedure call.
|
|||
|
|
|||
|
PushedResponse - When the client needs to send a large response to the
|
|||
|
server it must be transfered via a request. This holds the pushed
|
|||
|
response until the request gets here.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
friend class LRPC_SASSOCIATION;
|
|||
|
friend class LRPC_ADDRESS;
|
|||
|
friend void
|
|||
|
SetFaultPacket (
|
|||
|
IN LRPC_MESSAGE *LrpcMessage,
|
|||
|
IN RPC_STATUS Status,
|
|||
|
IN int Flags,
|
|||
|
IN LRPC_SCALL *CurrentCall OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
private:
|
|||
|
CLIENT_AUTH_INFO AuthInfo;
|
|||
|
LRPC_SASSOCIATION * Association;
|
|||
|
LRPC_MESSAGE * LrpcRequestMessage;
|
|||
|
LRPC_MESSAGE * LrpcReplyMessage;
|
|||
|
LRPC_SBINDING * SBinding;
|
|||
|
unsigned int ObjectUuidFlag;
|
|||
|
ULONG CallId;
|
|||
|
CLIENT_ID ClientId;
|
|||
|
ULONG MessageId;
|
|||
|
ULONG CallbackId;
|
|||
|
void * PushedResponse;
|
|||
|
ULONG CurrentBufferLength ;
|
|||
|
int BufferComplete ;
|
|||
|
LRPC_MESSAGE *LrpcAsyncReplyMessage;
|
|||
|
unsigned int Flags ;
|
|||
|
BOOL FirstSend ;
|
|||
|
BOOL PipeSendCalled ;
|
|||
|
int Deleted ;
|
|||
|
RPC_UUID ObjectUuid;
|
|||
|
|
|||
|
DebugCallInfo *DebugCell;
|
|||
|
|
|||
|
// Async RPC
|
|||
|
EVENT *ReceiveEvent ;
|
|||
|
MUTEX *CallMutex ;
|
|||
|
|
|||
|
// the cell tag to the DebugCell above
|
|||
|
CellTag DebugCellTag;
|
|||
|
|
|||
|
ULONG RcvBufferLength ;
|
|||
|
BOOL ReceiveComplete ;
|
|||
|
BOOL AsyncReply ;
|
|||
|
LRPC_SCALL *NextSCall ;
|
|||
|
LRPC_SCALL *LastSCall ;
|
|||
|
ULONG NeededLength;
|
|||
|
|
|||
|
BOOL fSyncDispatch ;
|
|||
|
BOOL Choked ;
|
|||
|
long CancelPending;
|
|||
|
|
|||
|
RPC_MESSAGE RpcMessage;
|
|||
|
RPC_RUNTIME_INFO RuntimeInfo;
|
|||
|
QUEUE BufferQueue ;
|
|||
|
|
|||
|
RPC_CHAR *ClientPrincipalName;
|
|||
|
public:
|
|||
|
LRPC_SCONTEXT *SContext;
|
|||
|
|
|||
|
LRPC_SCALL (OUT RPC_STATUS *RpcStatus)
|
|||
|
{
|
|||
|
ObjectType = LRPC_SCALL_TYPE;
|
|||
|
ReceiveEvent = 0;
|
|||
|
CallMutex = 0;
|
|||
|
LrpcAsyncReplyMessage = 0;
|
|||
|
ClientPrincipalName = NULL;
|
|||
|
*RpcStatus = RPC_S_OK;
|
|||
|
|
|||
|
if (IsServerSideDebugInfoEnabled())
|
|||
|
{
|
|||
|
DebugCell = (DebugCallInfo *)AllocateCell(&DebugCellTag);
|
|||
|
if (DebugCell == NULL)
|
|||
|
*RpcStatus = RPC_S_OUT_OF_MEMORY;
|
|||
|
else
|
|||
|
{
|
|||
|
memset(DebugCell, 0, sizeof(DebugCallInfo));
|
|||
|
DebugCell->FastInit = 0;
|
|||
|
DebugCell->Type = dctCallInfo;
|
|||
|
DebugCell->Status = (BYTE)csAllocated;
|
|||
|
DebugCell->CallFlags = DBGCELL_CACHED_CALL | DBGCELL_LRPC_CALL;
|
|||
|
DebugCell->LastUpdateTime = NtGetTickCount();
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
DebugCell = NULL;
|
|||
|
}
|
|||
|
|
|||
|
~LRPC_SCALL (
|
|||
|
)
|
|||
|
{
|
|||
|
if (ReceiveEvent)
|
|||
|
{
|
|||
|
if (CallId != (ULONG) -1)
|
|||
|
{
|
|||
|
Association->AssociationMutex.Request() ;
|
|||
|
Association->SCallDict.Delete(ULongToPtr(CallId));
|
|||
|
Association->AssociationMutex.Clear() ;
|
|||
|
}
|
|||
|
|
|||
|
delete ReceiveEvent;
|
|||
|
delete CallMutex ;
|
|||
|
}
|
|||
|
|
|||
|
if (DebugCell)
|
|||
|
{
|
|||
|
FreeCell(DebugCell, &DebugCellTag);
|
|||
|
}
|
|||
|
|
|||
|
if (LrpcAsyncReplyMessage)
|
|||
|
{
|
|||
|
FreeMessage(LrpcAsyncReplyMessage);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
NegotiateTransferSyntax (
|
|||
|
IN OUT PRPC_MESSAGE Message
|
|||
|
);
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
GetBuffer (
|
|||
|
IN OUT PRPC_MESSAGE Message,
|
|||
|
IN UUID *ObjectUuid
|
|||
|
);
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
SendReceive (
|
|||
|
IN OUT PRPC_MESSAGE Message
|
|||
|
);
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
Send (
|
|||
|
IN OUT PRPC_MESSAGE Messsage
|
|||
|
) ;
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
Receive (
|
|||
|
IN 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 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
|
|||
|
ImpersonateClient (
|
|||
|
);
|
|||
|
|
|||
|
virtual 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
|
|||
|
IsClientLocal (
|
|||
|
OUT unsigned int * ClientLocalFlag
|
|||
|
);
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
ConvertToServerBinding (
|
|||
|
OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
|
|||
|
);
|
|||
|
|
|||
|
virtual void
|
|||
|
InquireObjectUuid (
|
|||
|
OUT RPC_UUID * ObjectUuid
|
|||
|
);
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
ToStringBinding (
|
|||
|
OUT RPC_CHAR ** StringBinding
|
|||
|
);
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
GetAssociationContextCollection (
|
|||
|
OUT ContextCollection **CtxCollection
|
|||
|
);
|
|||
|
|
|||
|
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 RPC_STATUS
|
|||
|
InqTransportType(
|
|||
|
OUT unsigned int __RPC_FAR * Type
|
|||
|
)
|
|||
|
{
|
|||
|
*Type = TRANSPORT_TYPE_LPC ;
|
|||
|
|
|||
|
return (RPC_S_OK) ;
|
|||
|
}
|
|||
|
|
|||
|
virtual BOOL
|
|||
|
IsSyncCall (
|
|||
|
)
|
|||
|
{
|
|||
|
return !pAsync ;
|
|||
|
}
|
|||
|
|
|||
|
virtual unsigned
|
|||
|
TestCancel(
|
|||
|
)
|
|||
|
{
|
|||
|
return InterlockedExchange(&CancelPending, 0);
|
|||
|
}
|
|||
|
|
|||
|
virtual void
|
|||
|
FreeObject (
|
|||
|
) ;
|
|||
|
|
|||
|
BOOL
|
|||
|
IsClientAsync (
|
|||
|
)
|
|||
|
{
|
|||
|
return ((Flags & LRPC_SYNC_CLIENT) == 0);
|
|||
|
}
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
ActivateCall (
|
|||
|
IN LRPC_SASSOCIATION * Association,
|
|||
|
IN LRPC_MESSAGE * LrpcMessage,
|
|||
|
IN LRPC_MESSAGE * LrpcReplyMessage,
|
|||
|
IN unsigned int Flags
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
description
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
arg1 - description
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS Status = RPC_S_OK;
|
|||
|
|
|||
|
this->Association = Association;
|
|||
|
this->LrpcRequestMessage = LrpcMessage;
|
|||
|
this->LrpcReplyMessage = LrpcReplyMessage;
|
|||
|
ObjectUuidFlag = 0;
|
|||
|
PushedResponse = 0;
|
|||
|
CurrentBufferLength = 0;
|
|||
|
BufferComplete = 0;
|
|||
|
this->Flags = Flags ;
|
|||
|
FirstSend = 1;
|
|||
|
PipeSendCalled = 0;
|
|||
|
Deleted = 0;
|
|||
|
SBinding = 0;
|
|||
|
SetReferenceCount(2);
|
|||
|
pAsync = 0;
|
|||
|
NextSCall = 0;
|
|||
|
LastSCall = 0;
|
|||
|
CancelPending = 0;
|
|||
|
|
|||
|
if (DebugCell)
|
|||
|
{
|
|||
|
DebugCell->Status = (BYTE)csActive;
|
|||
|
if (Association->CachedSCall == this)
|
|||
|
DebugCell->CallFlags = DBGCELL_CACHED_CALL | DBGCELL_LRPC_CALL;
|
|||
|
else
|
|||
|
DebugCell->CallFlags = DBGCELL_CACHED_CALL;
|
|||
|
DebugCell->LastUpdateTime = NtGetTickCount();
|
|||
|
}
|
|||
|
|
|||
|
// Async RPC stuff
|
|||
|
|
|||
|
RuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
|
|||
|
RpcMessage.ReservedForRuntime = &RuntimeInfo;
|
|||
|
RpcMessage.RpcFlags = 0;
|
|||
|
|
|||
|
if (LrpcMessage->Rpc.RpcHeader.SecurityContextId != -1)
|
|||
|
{
|
|||
|
SContext = Association->FindSecurityContext(
|
|||
|
LrpcMessage->Rpc.RpcHeader.SecurityContextId);
|
|||
|
if (SContext == NULL)
|
|||
|
{
|
|||
|
Status = RPC_S_ACCESS_DENIED;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SContext = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
inline void DeactivateCall (void)
|
|||
|
{
|
|||
|
if (DebugCell)
|
|||
|
{
|
|||
|
DebugCell->Status = (BYTE)csAllocated;
|
|||
|
DebugCell->LastUpdateTime = NtGetTickCount();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
ProcessResponse (
|
|||
|
IN LRPC_MESSAGE **LrpcMessage
|
|||
|
) ;
|
|||
|
|
|||
|
inline RPC_STATUS
|
|||
|
LrpcMessageToRpcMessage (
|
|||
|
IN LRPC_MESSAGE * LrpcMessage,
|
|||
|
IN OUT PRPC_MESSAGE Message
|
|||
|
) ;
|
|||
|
|
|||
|
void
|
|||
|
DealWithRequestMessage (
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
HandleRequest (
|
|||
|
) ;
|
|||
|
|
|||
|
LRPC_SASSOCIATION *
|
|||
|
InqAssociation (
|
|||
|
)
|
|||
|
{
|
|||
|
return Association;
|
|||
|
}
|
|||
|
|
|||
|
LRPC_MESSAGE *
|
|||
|
InitMsg (
|
|||
|
)
|
|||
|
{
|
|||
|
INITMSG(LrpcReplyMessage,
|
|||
|
ClientId,
|
|||
|
CallbackId,
|
|||
|
MessageId) ;
|
|||
|
|
|||
|
LrpcReplyMessage->LpcHeader.u1.s1.TotalLength =
|
|||
|
LrpcReplyMessage->LpcHeader.u1.s1.DataLength+sizeof(PORT_MESSAGE);
|
|||
|
|
|||
|
return LrpcReplyMessage;
|
|||
|
}
|
|||
|
|
|||
|
virtual RPC_STATUS
|
|||
|
InqConnection (
|
|||
|
OUT void **ConnId,
|
|||
|
OUT BOOL *pfFirstCall
|
|||
|
)
|
|||
|
{
|
|||
|
ASSERT(Association);
|
|||
|
*ConnId = Association;
|
|||
|
|
|||
|
if (InterlockedIncrement((LONG *) &(Association->fFirstCall)) == 1)
|
|||
|
{
|
|||
|
*pfFirstCall = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*pfFirstCall = 0;
|
|||
|
}
|
|||
|
|
|||
|
return RPC_S_OK;
|
|||
|
}
|
|||
|
|
|||
|
inline HANDLE InqLocalClientPID (
|
|||
|
void
|
|||
|
)
|
|||
|
{
|
|||
|
return ClientId.UniqueProcess;
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
RPC_STATUS
|
|||
|
GetBufferDo(
|
|||
|
IN OUT PRPC_MESSAGE Message,
|
|||
|
IN unsigned long NewSize,
|
|||
|
IN BOOL fDataValid
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
SetupCall (
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
GetCoalescedBuffer (
|
|||
|
IN PRPC_MESSAGE Message,
|
|||
|
IN BOOL BufferValid
|
|||
|
) ;
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
SendRequest (
|
|||
|
IN OUT PRPC_MESSAGE Messsage,
|
|||
|
OUT BOOL *Shutup
|
|||
|
) ;
|
|||
|
|
|||
|
void
|
|||
|
SendReply (
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SendDGReply (
|
|||
|
IN LRPC_MESSAGE *LrpcMessage
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS NtStatus ;
|
|||
|
|
|||
|
LrpcMessage->LpcHeader.u2.ZeroInit = 0;
|
|||
|
LrpcMessage->LpcHeader.CallbackId = 0;
|
|||
|
LrpcMessage->LpcHeader.MessageId = 0;
|
|||
|
LrpcMessage->LpcHeader.u1.s1.TotalLength =
|
|||
|
LrpcMessage->LpcHeader.u1.s1.DataLength+sizeof(PORT_MESSAGE);
|
|||
|
|
|||
|
NtStatus = NtRequestPort(Association->LpcReplyPort,
|
|||
|
(PORT_MESSAGE *) LrpcMessage);
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
if ((NtStatus != STATUS_INVALID_CID)
|
|||
|
&& (NtStatus != STATUS_REPLY_MESSAGE_MISMATCH)
|
|||
|
&& (NtStatus != STATUS_PORT_DISCONNECTED))
|
|||
|
{
|
|||
|
PrintToDebugger("RPC : NtRequestPort : %lx, 0x%x, 0x%x\n",
|
|||
|
NtStatus, this, Association->LpcReplyPort);
|
|||
|
ASSERT(NtStatus != STATUS_INVALID_HANDLE);
|
|||
|
}
|
|||
|
#endif // DBG
|
|||
|
Association->Delete();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
return NtStatus ;
|
|||
|
}
|
|||
|
|
|||
|
LRPC_SBINDING *
|
|||
|
LookupBinding (
|
|||
|
IN unsigned short PresentContextId
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
inline NTSTATUS
|
|||
|
LRPC_SASSOCIATION::ReplyMessage(
|
|||
|
IN LRPC_MESSAGE * LrpcMessage
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Send a reply to a request
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LrpcMessage - Reply message
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK - Function succeeded
|
|||
|
RPC_S_OUT_OF_MEMORY - we ran out of memory
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS NtStatus ;
|
|||
|
|
|||
|
LrpcMessage->LpcHeader.u1.s1.TotalLength =
|
|||
|
LrpcMessage->LpcHeader.u1.s1.DataLength + sizeof(PORT_MESSAGE);
|
|||
|
|
|||
|
NtStatus = NtReplyPort(LpcServerPort,
|
|||
|
(PORT_MESSAGE *) LrpcMessage) ;
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
PrintToDebugger("RPC : NtReplyPort : %lx, 0x%x, 0x%x\n",
|
|||
|
NtStatus,
|
|||
|
this,
|
|||
|
LpcReplyPort);
|
|||
|
ASSERT(NtStatus != STATUS_INVALID_HANDLE);
|
|||
|
#endif
|
|||
|
Delete();
|
|||
|
}
|
|||
|
|
|||
|
return NtStatus ;
|
|||
|
}
|
|||
|
|
|||
|
inline void
|
|||
|
LRPC_SCONTEXT::AddReference()
|
|||
|
{
|
|||
|
Association->AssociationMutex.VerifyOwned();
|
|||
|
ASSERT(RefCount);
|
|||
|
|
|||
|
RefCount++;
|
|||
|
}
|
|||
|
|
|||
|
inline void
|
|||
|
LRPC_SCONTEXT::RemoveReference()
|
|||
|
{
|
|||
|
LRPC_SASSOCIATION *MyAssoc = Association;
|
|||
|
|
|||
|
Association->AssociationMutex.Request();
|
|||
|
RefCount--;
|
|||
|
if (RefCount == 0)
|
|||
|
{
|
|||
|
delete this;
|
|||
|
}
|
|||
|
MyAssoc->AssociationMutex.Clear();
|
|||
|
}
|
|||
|
|
|||
|
inline void
|
|||
|
LRPC_SCONTEXT::Destroy()
|
|||
|
{
|
|||
|
Association->AssociationMutex.VerifyOwned();
|
|||
|
if (GetDeletedFlag() == 0)
|
|||
|
{
|
|||
|
SetDeletedFlag();
|
|||
|
RefCount--;
|
|||
|
if (RefCount == 0)
|
|||
|
{
|
|||
|
delete this;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif //__LPCSVR_HXX__
|