mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1648 lines
36 KiB
1648 lines
36 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
Implements the RPC on Windows Messages protocol engine for the server.
|
|
|
|
Author:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <sysinc.h>
|
|
#include <rpc.h>
|
|
#include <rpcdcep.h>
|
|
#include <rpcerrp.h>
|
|
#include <rpcssp.h>
|
|
#include <util.hxx>
|
|
#include <rpcuuid.hxx>
|
|
#include <mutex.hxx>
|
|
#include <threads.hxx>
|
|
#include <sdict.hxx>
|
|
#include <sdict2.hxx>
|
|
#include <binding.hxx>
|
|
#include <handle.hxx>
|
|
#include <secclnt.hxx>
|
|
#include <secsvr.hxx>
|
|
#include <hndlsvr.hxx>
|
|
#include <critsec.hxx>
|
|
#include <wmsgheap.hxx>
|
|
#include <wmsgpack.hxx>
|
|
#include <wmsgport.hxx>
|
|
#include <wmsgthrd.hxx>
|
|
#include <wmsgsys.hxx>
|
|
#include <wmsgsvr.hxx>
|
|
|
|
|
|
LRESULT
|
|
ConnectPortAsyncProc(
|
|
UINT MsgType,
|
|
LPARAM lParam,
|
|
void * Context
|
|
)
|
|
{
|
|
WMSG_ADDRESS * Address = (WMSG_ADDRESS *) Context;
|
|
WMSG_PACKET * Packet = (WMSG_PACKET *)lParam;
|
|
|
|
// DispatchConnectRequest and DispatchAsyncCall both validiate the
|
|
// incoming packet.
|
|
|
|
if (Address == NULL) {
|
|
return (TRUE); // Server dereferenced Connect Port and deleted Address
|
|
}
|
|
|
|
switch(Packet->Type())
|
|
{
|
|
case BIND:
|
|
Address->DispatchConnectRequest(InSendMessage(), Packet);
|
|
break;
|
|
case ASYNC_REQUEST:
|
|
{
|
|
WMSG_ASSOCIATION *TmpAssociation;
|
|
|
|
TmpAssociation = new WMSG_ASSOCIATION;
|
|
|
|
if (TmpAssociation == NULL)
|
|
{
|
|
// ugly
|
|
WmsgHeapFree(Packet->Request.GlobalBuf);
|
|
WmsgHeapFree(Packet);
|
|
return(TRUE);
|
|
}
|
|
|
|
TmpAssociation->DispatchAsyncCall(Packet, Address);
|
|
|
|
delete(TmpAssociation);
|
|
break;
|
|
}
|
|
default:
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: Invalid packet type %08x in connect dispatch\n",
|
|
Packet->Type());
|
|
#endif
|
|
ASSERT(0);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
LRESULT
|
|
ServerPortAsyncProc(
|
|
UINT MsgType,
|
|
LPARAM lParam,
|
|
void * Context
|
|
)
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
WMSG_BIND_MESSAGE * Bind;
|
|
WMSG_ASSOCIATION * Association = (WMSG_ASSOCIATION *) Context;
|
|
WMSG_PACKET *InputPacket = (WMSG_PACKET *)lParam;
|
|
|
|
if (MsgType == WMSG_CLOSE)
|
|
{
|
|
if (Association->CallsDispatched)
|
|
Association->DeferClose = TRUE;
|
|
else
|
|
delete Association;
|
|
return (TRUE);
|
|
}
|
|
|
|
ASSERT(MsgType == WMSG_RPCMSG);
|
|
|
|
switch (InputPacket->Type()) {
|
|
case BIND:
|
|
InputPacket->Bind.Status = Association->AddBinding(InputPacket);
|
|
|
|
if (!InSendMessage()) {
|
|
|
|
InputPacket->Common.DestinationPort = Association->ServerPort->PeerPort;
|
|
|
|
if (PostMessage(Association->ServerPort->PeerPort->hWnd,
|
|
WMSG_RPCMSG,
|
|
(WPARAM) 0,
|
|
(LPARAM) InputPacket) == FALSE) {
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: send WMSG_BIND_MESSAGE failed %d\n",
|
|
GetLastError());
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
case REQUEST:
|
|
Association->DispatchRequest(InputPacket);
|
|
break;
|
|
default:
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: Bad Input packet ServerPortAsyncProc MsgType=%d\n", MsgType);
|
|
#endif
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
WMSG_ADDRESS::WMSG_ADDRESS (
|
|
OUT RPC_STATUS * RpcStatus
|
|
) : RPC_ADDRESS(RpcStatus)
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
ThreadId = GetCurrentThreadId();
|
|
WmsgListenPort = NULL;
|
|
ActiveCallCount = 0;
|
|
ServerListeningFlag = 0;
|
|
}
|
|
|
|
WMSG_ADDRESS::~WMSG_ADDRESS (
|
|
)
|
|
{
|
|
if (WmsgListenPort) {
|
|
WmsgListenPort->SetAsyncProc(NULL, NULL);
|
|
WmsgListenPort->hWnd = NULL;
|
|
WmsgListenPort->Dereference();
|
|
WmsgListenPort = NULL;
|
|
}
|
|
}
|
|
|
|
RPC_STATUS
|
|
WMSG_ADDRESS::DeleteSelf (
|
|
)
|
|
{
|
|
if (ThreadId != GetCurrentThreadId()) {
|
|
return (RPC_E_WRONG_THREAD);
|
|
}
|
|
|
|
if (AssocGroups.Size() != 0) {
|
|
return (RPC_S_CALL_IN_PROGRESS);
|
|
}
|
|
|
|
delete this;
|
|
|
|
return (RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_ADDRESS::FireUpManager (
|
|
IN unsigned int MinimumConcurrentCalls
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
No Op.
|
|
|
|
Arguments:
|
|
|
|
MinimumConcurrentCalls - Unused.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - We successfully fired up the manager.
|
|
|
|
RPC_S_OUT_OF_THREADS - We could not create one thread.
|
|
|
|
--*/
|
|
{
|
|
UNUSED(MinimumConcurrentCalls);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_ADDRESS::ServerStartingToListen (
|
|
IN unsigned int MinimumCallThreads,
|
|
IN unsigned int MaximumConcurrentCalls
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets called when RpcServerListen is called by the application.
|
|
We need to create the threads we need to receive remote procedure calls.
|
|
|
|
Arguments:
|
|
|
|
MinimumCallThreads - Supplies the minimum number of threads which we
|
|
must create.
|
|
|
|
MaximumConcurrentCalls - Unused.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - Ok, this address is all ready to start listening for remote
|
|
procedure calls.
|
|
|
|
RPC_S_OUT_OF_THREADS - We could not create enough threads so that we
|
|
have at least the minimum number of call threads required (as
|
|
specified by the MinimumCallThreads argument).
|
|
|
|
--*/
|
|
{
|
|
UNUSED(MaximumConcurrentCalls);
|
|
|
|
AddressMutex.Request();
|
|
ServerListeningFlag = 1;
|
|
AddressMutex.Clear();
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
void
|
|
WMSG_ADDRESS::ServerStoppedListening (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We just need to indicate that the server is no longer listening, and
|
|
set the minimum call thread count to one.
|
|
|
|
--*/
|
|
{
|
|
ServerListeningFlag = 0;
|
|
}
|
|
|
|
|
|
unsigned int
|
|
WMSG_ADDRESS::InqNumberOfActiveCalls (
|
|
)
|
|
/*++
|
|
|
|
Return Value:
|
|
|
|
The number of active calls on this address will be returned.
|
|
|
|
--*/
|
|
{
|
|
return(ActiveCallCount);
|
|
}
|
|
|
|
void
|
|
WMSG_ADDRESS::BeginNewCall(
|
|
)
|
|
{
|
|
InterlockedIncrement(&ActiveCallCount);
|
|
}
|
|
|
|
void
|
|
WMSG_ADDRESS::EndCall(
|
|
)
|
|
{
|
|
InterlockedDecrement(&ActiveCallCount);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_ADDRESS::SetupAddressWithEndpoint (
|
|
IN RPC_CHAR PAPI * Endpoint,
|
|
OUT RPC_CHAR PAPI * PAPI * lNetworkAddress,
|
|
OUT unsigned int PAPI * NumNetworkAddress,
|
|
IN void PAPI * SecurityDescriptor, OPTIONAL
|
|
IN unsigned int PendingQueueSize,
|
|
IN RPC_CHAR PAPI * RpcProtocolSequence,
|
|
IN unsigned long EndpointFlags,
|
|
IN unsigned long NICFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We need to setup the connection port and get ready to receive remote
|
|
procedure calls. We will use the name of this machine as the network
|
|
address.
|
|
|
|
Arguments:
|
|
|
|
Endpoint - Supplies the endpoint to be used will this address.
|
|
|
|
NetworkAddress - Returns the network address for this server. The
|
|
ownership of the buffer allocated to contain the network address
|
|
passes to the caller.
|
|
|
|
SecurityDescriptor - Optionally supplies a security descriptor to
|
|
be placed on this address.
|
|
|
|
PendingQueueSize - Unused.
|
|
|
|
RpcProtocolSequence - Unused.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - We successfully setup this address.
|
|
|
|
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
|
invalid.
|
|
|
|
RPC_S_CANT_CREATE_ENDPOINT - The endpoint format is correct, but
|
|
the endpoint can not be created.
|
|
|
|
RPC_S_INVALID_ENDPOINT_FORMAT - The endpoint is not a valid
|
|
endpoint for this particular transport interface.
|
|
|
|
RPC_S_OUT_OF_RESOURCES - Insufficient resources are available to
|
|
setup the address.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to setup
|
|
the address.
|
|
|
|
--*/
|
|
{
|
|
BOOL Boolean;
|
|
DWORD NetworkAddressLength = MAX_COMPUTERNAME_LENGTH + 1;
|
|
RPC_STATUS RpcStatus;
|
|
WMSG_PROC * Proc;
|
|
char * PAPI * tmpPtr;
|
|
|
|
UNUSED(PendingQueueSize);
|
|
UNUSED(RpcProtocolSequence);
|
|
|
|
ThreadSelf(); // Make sure we have thread context.
|
|
|
|
*lNetworkAddress = new RPC_CHAR[MAX_COMPUTERNAME_LENGTH + 1 + sizeof(RPC_CHAR *)];
|
|
if ( *lNetworkAddress == 0 ) {
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
tmpPtr = (char * PAPI *) *lNetworkAddress;
|
|
|
|
tmpPtr[0] = (char *) *lNetworkAddress + sizeof(RPC_CHAR * ) ;
|
|
|
|
*NumNetworkAddress = 1;
|
|
|
|
Boolean = GetComputerName((char *)tmpPtr[0], &NetworkAddressLength);
|
|
|
|
#ifdef DEBUGRPC
|
|
|
|
if ( Boolean != TRUE ) {
|
|
PrintToDebugger("WMSG-S : GetComputerName : %d\n", GetLastError());
|
|
}
|
|
|
|
#endif
|
|
|
|
ASSERT( Boolean == TRUE );
|
|
|
|
WmsgListenPort = new WMSG_CONNECT_PORT;
|
|
|
|
if (WmsgListenPort == NULL) {
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
WmsgListenPort->SetAsyncProc(ConnectPortAsyncProc, this);
|
|
|
|
RpcStatus = WmsgListenPort->BindToName((LPCSTR)Endpoint);
|
|
if (RpcStatus != RPC_S_OK) {
|
|
WmsgListenPort->Dereference();
|
|
WmsgListenPort = NULL;
|
|
return (RpcStatus);
|
|
}
|
|
|
|
return (RPC_S_OK);
|
|
}
|
|
|
|
|
|
static RPC_CHAR HexDigits[] =
|
|
{
|
|
RPC_CONST_CHAR('0'),
|
|
RPC_CONST_CHAR('1'),
|
|
RPC_CONST_CHAR('2'),
|
|
RPC_CONST_CHAR('3'),
|
|
RPC_CONST_CHAR('4'),
|
|
RPC_CONST_CHAR('5'),
|
|
RPC_CONST_CHAR('6'),
|
|
RPC_CONST_CHAR('7'),
|
|
RPC_CONST_CHAR('8'),
|
|
RPC_CONST_CHAR('9'),
|
|
RPC_CONST_CHAR('A'),
|
|
RPC_CONST_CHAR('B'),
|
|
RPC_CONST_CHAR('C'),
|
|
RPC_CONST_CHAR('D'),
|
|
RPC_CONST_CHAR('E'),
|
|
RPC_CONST_CHAR('F')
|
|
};
|
|
|
|
|
|
static RPC_CHAR PAPI *
|
|
ULongToHexString (
|
|
IN RPC_CHAR PAPI * String,
|
|
IN unsigned long Number
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We convert an unsigned long into hex representation in the specified
|
|
string. The result is always eight characters long; zero padding is
|
|
done if necessary.
|
|
|
|
Arguments:
|
|
|
|
String - Supplies a buffer to put the hex representation into.
|
|
|
|
Number - Supplies the unsigned long to convert to hex.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the end of the hex string is returned.
|
|
|
|
--*/
|
|
{
|
|
*String++ = HexDigits[(Number >> 28) & 0x0F];
|
|
*String++ = HexDigits[(Number >> 24) & 0x0F];
|
|
*String++ = HexDigits[(Number >> 20) & 0x0F];
|
|
*String++ = HexDigits[(Number >> 16) & 0x0F];
|
|
*String++ = HexDigits[(Number >> 12) & 0x0F];
|
|
*String++ = HexDigits[(Number >> 8) & 0x0F];
|
|
*String++ = HexDigits[(Number >> 4) & 0x0F];
|
|
*String++ = HexDigits[Number & 0x0F];
|
|
return(String);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_ADDRESS::SetupAddressUnknownEndpoint (
|
|
OUT RPC_CHAR PAPI * PAPI * Endpoint,
|
|
OUT RPC_CHAR PAPI * PAPI * lNetworkAddress,
|
|
OUT unsigned int PAPI * NumNetworkAddress,
|
|
IN void PAPI * SecurityDescriptor, OPTIONAL
|
|
IN unsigned int PendingQueueSize,
|
|
IN RPC_CHAR PAPI * RpcProtocolSequence,
|
|
IN unsigned long EndpointFlags,
|
|
IN unsigned long NICFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is like WMSG_ADDRESS::SetupAddressWithEndpoint except we need to
|
|
make up the endpoint.
|
|
|
|
Arguments:
|
|
|
|
Endpoint - Returns the endpoint for this address. The ownership
|
|
of the buffer allocated to contain the endpoint passes to the
|
|
caller.
|
|
|
|
NetworkAddress - Returns the network address for this server. The
|
|
ownership of the buffer allocated to contain the network address
|
|
passes to the caller.
|
|
|
|
SecurityDescriptor - Optionally supplies a security descriptor to
|
|
be placed on this address.
|
|
|
|
PendingQueueSize - Unused.
|
|
|
|
RpcProtocolSequence - Unused.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - We successfully setup this address.
|
|
|
|
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
|
invalid.
|
|
|
|
RPC_S_OUT_OF_RESOURCES - Insufficient resources are available to
|
|
setup the address.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to setup
|
|
the address.
|
|
|
|
--*/
|
|
{
|
|
|
|
return(RPC_S_CANNOT_SUPPORT);
|
|
|
|
#if 0
|
|
RPC_STATUS RpcStatus;
|
|
RPC_CHAR DynamicEndpoint[64];
|
|
RPC_CHAR * String;
|
|
|
|
UNUSED(PendingQueueSize);
|
|
UNUSED(RpcProtocolSequence);
|
|
|
|
for (;;)
|
|
{
|
|
String = DynamicEndpoint;
|
|
|
|
*String++ = RPC_CONST_CHAR('W');
|
|
*String++ = RPC_CONST_CHAR('M');
|
|
*String++ = RPC_CONST_CHAR('S');
|
|
*String++ = RPC_CONST_CHAR('G');
|
|
|
|
String = ULongToHexString(String, WmsgSystemGetNextSequenceNumber());
|
|
*String++ = RPC_CONST_CHAR('.');
|
|
String = ULongToHexString(String, 1);
|
|
*String = 0;
|
|
|
|
RpcStatus = SetupAddressWithEndpoint(DynamicEndpoint, lNetworkAddress,
|
|
NumNetworkAddress,
|
|
SecurityDescriptor, 0, 0);
|
|
|
|
if ( RpcStatus != RPC_S_DUPLICATE_ENDPOINT )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( RpcStatus == RPC_S_OK )
|
|
{
|
|
*Endpoint = DuplicateString(DynamicEndpoint);
|
|
if ( *Endpoint == 0 )
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
#if DBG
|
|
|
|
if ( ( RpcStatus != RPC_S_INVALID_SECURITY_DESC )
|
|
&& ( RpcStatus != RPC_S_OUT_OF_RESOURCES )
|
|
&& ( RpcStatus != RPC_S_OUT_OF_MEMORY ) )
|
|
{
|
|
PrintToDebugger("WMSG-S : SetupAddressWithEndpoint : %d\n", RpcStatus);
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
ASSERT( ( RpcStatus == RPC_S_INVALID_SECURITY_DESC )
|
|
|| ( RpcStatus == RPC_S_OUT_OF_RESOURCES )
|
|
|| ( RpcStatus == RPC_S_OUT_OF_MEMORY ) );
|
|
|
|
return(RpcStatus);
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
WMSG_ADDRESS::DispatchConnectRequest(
|
|
BOOL fInputSyncCall,
|
|
WMSG_PACKET * BindPacket
|
|
)
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
WMSG_DATA_PORT * ServerPort;
|
|
WMSG_DATA_PORT * ClientPort;
|
|
WMSG_ASSOCIATION * Association;
|
|
WMSG_SASSOC_GROUP * AssocGroup;
|
|
WMSG_THREAD *Thread;
|
|
|
|
//
|
|
// BUGBUG: When return before posting the reply (which is done
|
|
// several times, we deadlock the client. What should we do?
|
|
//
|
|
|
|
if (BindPacket->Type() != BIND)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: Invalid bind packet: %p %p\n",
|
|
this, BindPacket);
|
|
#endif
|
|
ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
|
|
ClientPort = BindPacket->Bind.ClientPort;
|
|
ASSERT(ClientPort != NULL);
|
|
|
|
Thread = WmsgThreadGet();
|
|
if ( (Thread == 0)
|
|
|| (Thread->IsListening() == FALSE))
|
|
{
|
|
if (Thread == 0)
|
|
RpcStatus = RPC_S_OUT_OF_RESOURCES;
|
|
else
|
|
RpcStatus = RPC_S_NOT_LISTENING;
|
|
|
|
goto send_bind_ack;
|
|
}
|
|
|
|
ServerPort = WmsgListenPort->Accept(ClientPort);
|
|
if (ServerPort == NULL) {
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: Accept failed %x\n", WmsgListenPort);
|
|
#endif
|
|
RpcStatus = RPC_S_OUT_OF_MEMORY;
|
|
goto send_bind_ack;
|
|
}
|
|
|
|
ASSERT(ServerPort->PeerPort == ClientPort);
|
|
|
|
Association = new WMSG_ASSOCIATION();
|
|
if (Association == NULL) {
|
|
ServerPort->Dereference();
|
|
ServerPort = NULL;
|
|
RpcStatus = RPC_S_OUT_OF_MEMORY;
|
|
goto send_bind_ack;
|
|
}
|
|
|
|
Association->ServerPort = ServerPort;
|
|
|
|
ServerPort->SetAsyncProc(ServerPortAsyncProc, Association);
|
|
|
|
AssocGroup = FindAssocGroup(ClientPort->ProcessId);
|
|
if (AssocGroup == NULL) {
|
|
AssocGroup = new WMSG_SASSOC_GROUP(this, ClientPort->ProcessId);
|
|
if (AssocGroup == NULL)
|
|
{
|
|
delete Association;
|
|
RpcStatus = RPC_S_OUT_OF_MEMORY;
|
|
goto send_bind_ack;
|
|
}
|
|
}
|
|
|
|
Association->AssocGroup = AssocGroup;
|
|
AssocGroup->AddRef();
|
|
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: Association %x assigned to ag=%x addr=%x\n", Association, AssocGroup, this);
|
|
#endif
|
|
RpcStatus = Association->AddBinding(BindPacket);
|
|
|
|
send_bind_ack:
|
|
|
|
BindPacket->Bind.Status = RpcStatus;
|
|
|
|
if (!InSendMessage()) {
|
|
|
|
BindPacket->Common.DestinationPort = ClientPort;
|
|
|
|
if (PostMessage(ClientPort->hWnd,
|
|
WMSG_RPCMSG,
|
|
(WPARAM) 0,
|
|
(LPARAM) BindPacket) == FALSE) {
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: send WMSG_BIND_MESSAGE failed %d\n",
|
|
GetLastError());
|
|
#endif
|
|
delete Association;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
WMSG_SASSOC_GROUP *
|
|
WMSG_ADDRESS::FindAssocGroup(
|
|
LONG ClientId
|
|
)
|
|
{
|
|
WMSG_SASSOC_GROUP * AssocGroup;
|
|
|
|
ASSERT(ThreadId == GetCurrentThreadId());
|
|
|
|
AssocGroups.Reset();
|
|
while ( (AssocGroup = AssocGroups.Next()) != 0) {
|
|
if (AssocGroup->ReferenceCount > 0 && AssocGroup->ClientId == ClientId) {
|
|
return (AssocGroup);
|
|
}
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
WMSG_ASSOCIATION::WMSG_ASSOCIATION (
|
|
)
|
|
/*++
|
|
|
|
--*/
|
|
{
|
|
CallsDispatched = 0;
|
|
|
|
DeferClose = FALSE;
|
|
|
|
ServerPort = NULL;
|
|
|
|
AssocGroup = NULL;
|
|
}
|
|
|
|
|
|
WMSG_ASSOCIATION::~WMSG_ASSOCIATION (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will call this routine when the client has notified us that this port
|
|
has closed, and there are no calls outstanding on it.
|
|
|
|
--*/
|
|
{
|
|
WMSG_SBINDING * Binding;
|
|
|
|
if (AssocGroup != NULL) {
|
|
AssocGroup->Dereference();
|
|
AssocGroup = NULL;
|
|
}
|
|
|
|
GlobalMutexRequest();
|
|
|
|
if (ServerPort) {
|
|
ServerPort->Disconnect();
|
|
ServerPort->Dereference();
|
|
ServerPort = NULL;
|
|
}
|
|
|
|
Bindings.Reset();
|
|
|
|
while (Binding = Bindings.Next()) {
|
|
Bindings.Delete(Binding->PresentationContext);
|
|
delete Binding;
|
|
}
|
|
|
|
GlobalMutexClear();
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_ASSOCIATION::AddBinding (
|
|
IN OUT WMSG_PACKET * BindPacket
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will attempt to add a new binding to this association.
|
|
|
|
Arguments:
|
|
|
|
BindExchange - Supplies a description of the interface to which the
|
|
client wish to bind.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
RPC_SYNTAX_IDENTIFIER TransferSyntax;
|
|
RPC_INTERFACE * RpcInterface;
|
|
WMSG_SBINDING * Binding;
|
|
WMSG_BIND_MESSAGE *Bind = &BindPacket->Bind;
|
|
|
|
RpcStatus = AssocGroup->Address->FindInterfaceTransfer(&Bind->InterfaceId,
|
|
&Bind->TransferSyntax,
|
|
1,
|
|
&TransferSyntax,
|
|
&RpcInterface);
|
|
if ( RpcStatus != RPC_S_OK ) {
|
|
return(RpcStatus);
|
|
}
|
|
|
|
Binding = new WMSG_SBINDING(RpcInterface, &Bind->TransferSyntax);
|
|
if ( Binding == 0 ) {
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
Binding->PresentationContext = Bindings.Insert(Binding);
|
|
if ( Binding->PresentationContext == -1 ) {
|
|
delete Binding;
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
Bind->PresentationContext = Binding->PresentationContext;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_ASSOCIATION::DispatchRequest (
|
|
WMSG_PACKET * ThePacket
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will process the original request message in this routine, dispatch
|
|
the remote procedure call to the stub, and then send the response
|
|
message.
|
|
|
|
Arguments:
|
|
|
|
Any - Supplies the request message which was received from
|
|
the client.
|
|
|
|
Return Value:
|
|
|
|
The reply message to be sent to the client will be returned.
|
|
BUGBUG: This is a lie. The return value is a status and it's ignored.
|
|
|
|
--*/
|
|
{
|
|
RPC_MESSAGE Message;
|
|
WMSG_REQUEST_MESSAGE * Request;
|
|
WMSG_SBINDING * SBinding;
|
|
WMSG_THREAD *Thread;
|
|
WMSG_SCALL SCall(this);
|
|
RPC_STATUS RpcStatus, ExceptionCode;
|
|
unsigned int Flags;
|
|
|
|
ASSERT(ThePacket->Type() == REQUEST);
|
|
|
|
ASSERT(ServerPort);
|
|
|
|
Request = &ThePacket->Request;
|
|
|
|
Thread = WmsgThreadGet();
|
|
if ( Thread == 0
|
|
|| Thread->IsListening() == FALSE)
|
|
{
|
|
ServerPort->FreeBuffer(Request->GlobalBuf);
|
|
Request->GlobalBuf = 0;
|
|
if (Thread == 0)
|
|
SetupFault(ThePacket, RPC_S_OUT_OF_RESOURCES);
|
|
else
|
|
SetupFault(ThePacket, RPC_S_NOT_LISTENING);
|
|
goto Reply;
|
|
}
|
|
|
|
SBinding = Bindings.Find(Request->PresentationContext);
|
|
if ( SBinding == 0 )
|
|
{
|
|
ServerPort->FreeBuffer(Request->GlobalBuf);
|
|
Request->GlobalBuf = 0;
|
|
SetupFault(ThePacket, RPC_S_UNKNOWN_IF);
|
|
goto Reply;
|
|
}
|
|
|
|
SCall.SBinding = SBinding;
|
|
|
|
Message.Buffer = Request->GlobalBuf;
|
|
Message.BufferLength = (unsigned int)Request->GlobalBufSize;
|
|
Message.TransferSyntax = &SBinding->TransferSyntax;
|
|
Message.ProcNum = Request->ProcedureNumber;
|
|
Message.RpcFlags = Flags = Request->Flags;
|
|
Message.Handle = &SCall;
|
|
|
|
// NDR_DREP_ASCII | NDR_DREP_LITTLE_ENDIAN | NDR_DREP_IEEE
|
|
|
|
Message.DataRepresentation = 0x00 | 0x10 | 0x0000;
|
|
|
|
if ( Request->ObjectUuidFlag != 0 ) {
|
|
SCall.ObjectUuidFlag = 1;
|
|
RpcpMemoryCopy(&SCall.ObjectUuid, &Request->ObjectUuid, sizeof(UUID));
|
|
}
|
|
|
|
CallsDispatched++;
|
|
|
|
RpcpSetThreadContext(&SCall);
|
|
|
|
// pipes not supported on WMSG,
|
|
// the received buffer is always complete
|
|
Message.RpcFlags = RPC_BUFFER_COMPLETE ;
|
|
|
|
if ( SCall.ObjectUuidFlag != 0 ) {
|
|
RpcStatus = SBinding->RpcInterface->DispatchToStubWithObject(
|
|
&Message,
|
|
&SCall.ObjectUuid,
|
|
0,
|
|
&ExceptionCode);
|
|
} else {
|
|
RpcStatus = SBinding->RpcInterface->DispatchToStub(&Message, 0,
|
|
&ExceptionCode);
|
|
}
|
|
RpcpSetThreadContext(0);
|
|
|
|
CallsDispatched--;
|
|
|
|
if (DeferClose) {
|
|
PostMessage(ServerPort->hWnd, WMSG_CLOSE, NULL, (LPARAM)ServerPort);
|
|
DeferClose = FALSE;
|
|
}
|
|
|
|
// Done processing, input arugments have been freed.
|
|
|
|
Request->GlobalBuf = 0;
|
|
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
if (RpcStatus == RPC_P_EXCEPTION_OCCURED)
|
|
{
|
|
SetupFault(ThePacket, ExceptionCode);
|
|
goto Reply;
|
|
}
|
|
if (RpcStatus == RPC_S_NOT_LISTENING)
|
|
{
|
|
RpcStatus = RPC_S_SERVER_TOO_BUSY;
|
|
}
|
|
SetupFault(ThePacket, RpcStatus);
|
|
}
|
|
|
|
Reply:
|
|
|
|
// Sending a fault or server's reply.
|
|
|
|
ASSERT( ThePacket->Type() == FAULT
|
|
|| ThePacket->Type() == REQUEST);
|
|
|
|
// For async calls free everything associated with this call and return.
|
|
if (Flags & RPCFLG_ASYNCHRONOUS)
|
|
{
|
|
if (ThePacket->Type() == REQUEST)
|
|
{
|
|
ServerPort->FreeBuffer(Message.Buffer);
|
|
}
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
// Finish the response packet. If there's a fault, we're ready to send it.
|
|
if (ThePacket->Type() == REQUEST)
|
|
{
|
|
WMSG_RESPONSE_MESSAGE *Response = &ThePacket->Response;
|
|
|
|
// We've processed the request ok, now send the reply
|
|
|
|
Response->Common.Type = RESPONSE;
|
|
Response->Flags = Flags;
|
|
Response->GlobalBuf = Message.Buffer;
|
|
Response->GlobalBufSize = Message.BufferLength;
|
|
}
|
|
|
|
// For normal calls we must post the reply, for input sync calls,
|
|
// we just return which returns control to the client.
|
|
|
|
if ( ! (Flags & RPCFLG_INPUT_SYNCHRONOUS))
|
|
{
|
|
ThePacket->Common.DestinationPort = ServerPort->PeerPort;
|
|
if (PostMessage(ServerPort->PeerPort->hWnd,
|
|
WMSG_RPCMSG,
|
|
(WPARAM) 0,
|
|
(LPARAM) ThePacket) == FALSE)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-S: PM failed %d, client crash? Throwing away reply: %p\n",
|
|
GetLastError(), ThePacket);
|
|
#endif
|
|
if (ThePacket->Type() == RESPONSE)
|
|
{
|
|
ServerPort->FreeBuffer(ThePacket->Response.GlobalBuf);
|
|
ThePacket->Response.GlobalBuf = 0;
|
|
}
|
|
|
|
ServerPort->FreeBuffer(ThePacket);
|
|
|
|
// If the client really crashed we have(!)
|
|
return (RPC_S_CALL_FAILED);
|
|
}
|
|
}
|
|
|
|
return (RPC_S_OK);
|
|
}
|
|
|
|
|
|
void
|
|
WMSG_ASSOCIATION::DispatchAsyncCall (
|
|
WMSG_PACKET *ThePacket,
|
|
WMSG_ADDRESS *Address
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will process the original request message in this routine, dispatch
|
|
the remote procedure call to the stub, and then free to results.
|
|
|
|
Arguments:
|
|
|
|
Any - Supplies the request message which was received from
|
|
the client. This must be an ASYNC_REQUEST.
|
|
|
|
Return Value:
|
|
|
|
n/a
|
|
|
|
--*/
|
|
{
|
|
RPC_MESSAGE Message;
|
|
WMSG_REQUEST_MESSAGE * Request;
|
|
WMSG_SBINDING * SBinding;
|
|
WMSG_SCALL *SCall;
|
|
WMSG_THREAD *Thread;
|
|
RPC_STATUS RpcStatus, ExceptionCode;
|
|
RPC_SYNTAX_IDENTIFIER TransferSyntax;
|
|
RPC_INTERFACE * RpcInterface;
|
|
unsigned int Flags;
|
|
|
|
ASSERT(ThePacket->Type() == ASYNC_REQUEST)
|
|
|
|
ASSERT(AssocGroup == 0);
|
|
|
|
Thread = WmsgThreadGet();
|
|
if ( Thread == 0
|
|
|| Thread->IsListening() == FALSE)
|
|
return;
|
|
|
|
AssocGroup = new WMSG_SASSOC_GROUP(Address,
|
|
ThePacket->AsyncRequest.ProcessId);
|
|
|
|
// AssocGroup is dereferenced when TmpAssoc is deleted.
|
|
|
|
if (AssocGroup == NULL)
|
|
return;
|
|
|
|
|
|
ASSERT(ServerPort == 0);
|
|
ServerPort = new WMSG_DATA_PORT;
|
|
|
|
// ServerPort deleted when TmpAssoc is deleted.
|
|
|
|
if (ServerPort == NULL)
|
|
return;
|
|
|
|
SCall = new WMSG_SCALL(this);
|
|
|
|
if (SCall == NULL)
|
|
return;
|
|
|
|
Request = &ThePacket->Request;
|
|
|
|
RpcStatus = AssocGroup->Address->FindInterfaceTransfer(
|
|
&ThePacket->AsyncRequest.InterfaceId,
|
|
&ThePacket->AsyncRequest.TransferSyntax,
|
|
1,
|
|
&TransferSyntax,
|
|
&RpcInterface);
|
|
|
|
if (RpcStatus == RPC_S_OK)
|
|
{
|
|
SBinding = new WMSG_SBINDING(RpcInterface, &ThePacket->AsyncRequest.TransferSyntax);
|
|
if ( SBinding == 0 )
|
|
{
|
|
RpcStatus = RPC_S_UNKNOWN_IF;
|
|
}
|
|
}
|
|
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
ServerPort->FreeBuffer(Request->GlobalBuf);
|
|
Request->GlobalBuf = 0;
|
|
ServerPort->FreeBuffer(ThePacket);
|
|
}
|
|
|
|
SCall->SBinding = SBinding;
|
|
|
|
Message.Buffer = Request->GlobalBuf;
|
|
Message.BufferLength = (unsigned int)Request->GlobalBufSize;
|
|
Message.TransferSyntax = &SBinding->TransferSyntax;
|
|
Message.ProcNum = Request->ProcedureNumber;
|
|
Message.RpcFlags = Flags = Request->Flags;
|
|
Message.Handle = SCall;
|
|
|
|
// NDR_DREP_ASCII | NDR_DREP_LITTLE_ENDIAN | NDR_DREP_IEEE
|
|
|
|
Message.DataRepresentation = 0x00 | 0x10 | 0x0000;
|
|
|
|
if ( Request->ObjectUuidFlag != 0 ) {
|
|
SCall->ObjectUuidFlag = 1;
|
|
RpcpMemoryCopy(&SCall->ObjectUuid, &Request->ObjectUuid, sizeof(UUID));
|
|
}
|
|
|
|
RpcpSetThreadContext(&SCall);
|
|
|
|
// pipes not supported on WMSG,
|
|
// the received buffer is always complete
|
|
Message.RpcFlags = RPC_BUFFER_COMPLETE ;
|
|
|
|
if ( SCall->ObjectUuidFlag != 0 ) {
|
|
RpcStatus = SBinding->RpcInterface->DispatchToStubWithObject(
|
|
&Message,
|
|
&SCall->ObjectUuid,
|
|
0,
|
|
&ExceptionCode);
|
|
} else {
|
|
RpcStatus = SBinding->RpcInterface->DispatchToStub(&Message, 0,
|
|
&ExceptionCode);
|
|
}
|
|
RpcpSetThreadContext(0);
|
|
|
|
// Done processing, input arguments have been freed.
|
|
|
|
Request->GlobalBuf = 0;
|
|
|
|
if (RpcStatus == RPC_S_OK)
|
|
{
|
|
ServerPort->FreeBuffer(Message.Buffer);
|
|
}
|
|
|
|
ServerPort->FreeBuffer(ThePacket);
|
|
delete SBinding;
|
|
delete SCall;
|
|
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("WMSG-C: Unconnected async call completed: 0x%08x\n", RpcStatus);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
static unsigned char AlignFour[4] =
|
|
{
|
|
0,
|
|
3,
|
|
2,
|
|
1
|
|
};
|
|
|
|
inline RPC_STATUS
|
|
WMSG_ASSOCIATION::SetupFault(
|
|
WMSG_PACKET *Packet,
|
|
RPC_STATUS RpcStatus
|
|
)
|
|
{
|
|
Packet->Common.Type = FAULT;
|
|
Packet->Fault.Status = RpcStatus;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::GetBuffer (
|
|
IN OUT PRPC_MESSAGE Message
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will allocate a buffer which will be used to either send a request
|
|
or receive a response.
|
|
|
|
Arguments:
|
|
|
|
Message - Supplies the length of the buffer that is needed. The buffer
|
|
will be returned.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - A buffer has been successfully allocated. It will be of at
|
|
least the required length.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allocate that
|
|
large a buffer.
|
|
|
|
--*/
|
|
{
|
|
Message->Buffer = Association->ServerPort->GetBuffer(Message->BufferLength);
|
|
if (Message->Buffer == NULL) {
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
ASSERT( ((unsigned long) Message->Buffer) % 8 == 0 );
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
WMSG_SCALL::FreeBuffer (
|
|
IN PRPC_MESSAGE Message
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will free the supplied buffer.
|
|
|
|
Arguments:
|
|
|
|
Message - Supplies the buffer to be freed.
|
|
|
|
--*/
|
|
{
|
|
Association->ServerPort->FreeBuffer(Message->Buffer);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::ImpersonateClient (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will impersonate the client which made the remote procedure call.
|
|
|
|
--*/
|
|
{
|
|
return (RPC_S_CANNOT_SUPPORT);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::RevertToSelf (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This reverts a server thread back to itself after impersonating a client.
|
|
We just check to see if the server thread is impersonating; this optimizes
|
|
the common case.
|
|
|
|
--*/
|
|
{
|
|
return (RPC_S_CANNOT_SUPPORT);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::IsClientLocal (
|
|
OUT unsigned int * ClientLocalFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
A client using WMSG will always be local.
|
|
|
|
Arguments:
|
|
|
|
ClientLocalFlag - Returns a flag which will always be set to a non-zero
|
|
value indicating that the client is local.
|
|
|
|
--*/
|
|
{
|
|
UNUSED(this);
|
|
|
|
*ClientLocalFlag = 1;
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::ConvertToServerBinding (
|
|
OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If possible, convert this call into a server binding, meaning a
|
|
binding handle pointing back to the client.
|
|
|
|
Arguments:
|
|
|
|
ServerBinding - Returns the server binding.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - The server binding has successfully been created.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allocate
|
|
a new binding handle.
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
RPC_CHAR UuidString[37];
|
|
RPC_CHAR * StringBinding;
|
|
DWORD NetworkAddressLength = MAX_COMPUTERNAME_LENGTH + 1;
|
|
BOOL Boolean;
|
|
RPC_CHAR * NetworkAddress;
|
|
|
|
if ( ObjectUuidFlag != 0 ) {
|
|
ObjectUuid.ConvertToString(UuidString);
|
|
UuidString[36] = 0;
|
|
}
|
|
|
|
NetworkAddress = new RPC_CHAR[NetworkAddressLength];
|
|
if ( NetworkAddress == 0 ) {
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
Boolean = GetComputerName((char *)NetworkAddress, &NetworkAddressLength);
|
|
|
|
#ifdef DEBUGRPC
|
|
|
|
if ( Boolean != TRUE ) {
|
|
PrintToDebugger("WMSG-S : GetComputerName : %d\n", GetLastError());
|
|
}
|
|
|
|
#endif
|
|
|
|
ASSERT( Boolean == TRUE );
|
|
|
|
RpcStatus = RpcStringBindingCompose((ObjectUuidFlag != 0 ? UuidString : 0),
|
|
RPC_CONST_STRING("mswmsg"), NetworkAddress, 0, 0, &StringBinding);
|
|
delete NetworkAddress;
|
|
if ( RpcStatus != RPC_S_OK ) {
|
|
return(RpcStatus);
|
|
}
|
|
|
|
RpcStatus = RpcBindingFromStringBinding(StringBinding, ServerBinding);
|
|
RpcStringFree(&StringBinding);
|
|
return(RpcStatus);
|
|
}
|
|
|
|
|
|
void
|
|
WMSG_SCALL::InquireObjectUuid (
|
|
OUT RPC_UUID * ObjectUuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine copies the object uuid from the call into the supplied
|
|
ObjectUuid argument.
|
|
|
|
Arguments:
|
|
|
|
ObjectUuid - Returns a copy of the object uuid passed by the client
|
|
in the remote procedure call.
|
|
|
|
--*/
|
|
{
|
|
if ( ObjectUuidFlag == 0 )
|
|
{
|
|
ObjectUuid->SetToNullUuid();
|
|
}
|
|
else
|
|
{
|
|
ObjectUuid->CopyUuid(&(this->ObjectUuid));
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::ToStringBinding (
|
|
OUT RPC_CHAR ** StringBinding
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We need to convert this call into a string binding. We will ask the
|
|
address for a binding handle which we can then convert into a string
|
|
binding.
|
|
|
|
Arguments:
|
|
|
|
StringBinding - Returns the string binding for this call.
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
BINDING_HANDLE * BindingHandle;
|
|
RPC_STATUS RpcStatus;
|
|
|
|
BindingHandle = Association->AssocGroup->Address->InquireBinding();
|
|
|
|
if ( BindingHandle == 0 ) {
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
RpcStatus = BindingHandle->ToStringBinding(StringBinding);
|
|
BindingHandle->BindingFree();
|
|
return(RpcStatus);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::MonitorAssociation (
|
|
IN PRPC_RUNDOWN RundownRoutine,
|
|
IN void * Context
|
|
)
|
|
{
|
|
ASSERT(Association != NULL);
|
|
|
|
ASSERT(Association->AssocGroup != NULL);
|
|
|
|
#ifdef DEBUGRPC_DETAIL
|
|
PrintToDebugger("WMSG-S: MonitorAssociation (%x) ass=%x, ag=%x\n", Context, Association, Association->AssocGroup);
|
|
#endif
|
|
|
|
return(Association->AssocGroup->MonitorAssociation(RundownRoutine, Context));
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::StopMonitorAssociation (
|
|
)
|
|
{
|
|
ASSERT(Association != NULL);
|
|
|
|
ASSERT(Association->AssocGroup != NULL);
|
|
|
|
#ifdef DEBUGRPC_DETAIL
|
|
PrintToDebugger("WMSG-S: StopMonitorAssociation ass=%x, ag=%x\n", Association, Association->AssocGroup);
|
|
#endif
|
|
|
|
return(Association->AssocGroup->StopMonitorAssociation());
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::GetAssociationContext (
|
|
OUT void ** AssociationContext
|
|
)
|
|
{
|
|
ASSERT(Association != NULL);
|
|
|
|
ASSERT(Association->AssocGroup != NULL);
|
|
|
|
*AssociationContext = Association->AssocGroup->AssociationContext();
|
|
|
|
#ifdef DEBUGRPC_DETAIL
|
|
PrintToDebugger("WMSG-S: GetAssociationContext got %x ass=%x, ag=%x\n", *AssociationContext, Association, Association->AssocGroup);
|
|
#endif
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::SetAssociationContext (
|
|
IN void * Context
|
|
)
|
|
{
|
|
ASSERT(Association != NULL);
|
|
|
|
ASSERT(Association->AssocGroup != NULL);
|
|
|
|
Association->AssocGroup->SetAssociationContext(Context);
|
|
|
|
#ifdef DEBUGRPC_DETAIL
|
|
PrintToDebugger("WMSG-S: SetAssociationContext(%x) ass=%x\n, ag=%x", Context, Association, Association->AssocGroup);
|
|
#endif
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::InquireAuthClient (
|
|
OUT RPC_AUTHZ_HANDLE PAPI * Privileges,
|
|
OUT RPC_CHAR PAPI * PAPI * ServerPrincipalName, OPTIONAL
|
|
OUT unsigned long PAPI * AuthenticationLevel,
|
|
OUT unsigned long PAPI * AuthenticationService,
|
|
OUT unsigned long PAPI * AuthorizationService
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Each protocol module must define this routine: it is used to obtain
|
|
the authentication and authorization information about a client making
|
|
the remote procedure call represented by this.
|
|
|
|
Arguments:
|
|
|
|
Privileges - Returns a the privileges of the client.
|
|
|
|
ServerPrincipalName - Returns the server principal name which the client
|
|
specified.
|
|
|
|
AuthenticationLevel - Returns the authentication level requested by
|
|
the client.
|
|
|
|
AuthenticationService - Returns the authentication service requested by
|
|
the client.
|
|
|
|
AuthorizationService - Returns the authorization service requested by
|
|
the client.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_CANNOT_SUPPORT - This value will always be returned.
|
|
|
|
--*/
|
|
{
|
|
UNUSED(this);
|
|
UNUSED(Privileges);
|
|
UNUSED(ServerPrincipalName);
|
|
UNUSED(AuthenticationLevel);
|
|
UNUSED(AuthenticationService);
|
|
UNUSED(AuthorizationService);
|
|
|
|
return(RPC_S_CANNOT_SUPPORT);
|
|
}
|
|
|
|
RPC_STATUS
|
|
WMSG_SCALL::SendReceive(
|
|
IN OUT PRPC_MESSAGE Message
|
|
)
|
|
{
|
|
return (RPC_S_CANNOT_SUPPORT);
|
|
}
|
|
|
|
WMSG_SASSOC_GROUP::WMSG_SASSOC_GROUP(
|
|
WMSG_ADDRESS * Address,
|
|
LONG ClientId
|
|
)
|
|
{
|
|
this->Address = Address;
|
|
|
|
this->ClientId = ClientId;
|
|
|
|
ReferenceCount = 0;
|
|
|
|
Key = Address->AssocGroups.Insert(this);
|
|
}
|
|
|
|
WMSG_SASSOC_GROUP::~WMSG_SASSOC_GROUP(
|
|
)
|
|
{
|
|
ASSERT(Address != NULL);
|
|
|
|
Address->AssocGroups.Delete(Key);
|
|
}
|
|
|
|
void
|
|
WMSG_SASSOC_GROUP::AddRef(
|
|
)
|
|
{
|
|
InterlockedIncrement(&ReferenceCount);
|
|
}
|
|
|
|
void
|
|
WMSG_SASSOC_GROUP::Dereference(
|
|
)
|
|
{
|
|
if (InterlockedDecrement(&ReferenceCount) == 0) {
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
|
|
RPC_ADDRESS *
|
|
WmsgCreateRpcAddress (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We just to create a new WMSG_ADDRESS. This routine is a proxy for the
|
|
new constructor to isolate the other modules.
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS RpcStatus = RPC_S_OK;
|
|
RPC_ADDRESS * RpcAddress;
|
|
|
|
RpcAddress = new WMSG_ADDRESS(&RpcStatus);
|
|
if ( RpcStatus != RPC_S_OK ) {
|
|
return(NULL);
|
|
}
|
|
return(RpcAddress);
|
|
}
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
I_RpcServerThreadPauseListening(
|
|
)
|
|
{
|
|
WMSG_THREAD *Thread;
|
|
|
|
InitializeIfNecessary();
|
|
|
|
Thread = WmsgThreadGet();
|
|
|
|
if (Thread)
|
|
{
|
|
if (Thread->IsListening() == FALSE)
|
|
return(RPC_S_NOT_LISTENING);
|
|
|
|
if (Thread)
|
|
Thread->Pause();
|
|
}
|
|
else
|
|
return(RPC_S_OUT_OF_RESOURCES);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
I_RpcServerThreadContinueListening(
|
|
)
|
|
{
|
|
WMSG_THREAD *Thread;
|
|
|
|
InitializeIfNecessary();
|
|
|
|
Thread = WmsgThreadGet();
|
|
|
|
if (Thread)
|
|
{
|
|
if (Thread->IsListening() == TRUE)
|
|
return(RPC_S_ALREADY_LISTENING);
|
|
|
|
if (Thread)
|
|
Thread->Continue();
|
|
}
|
|
else
|
|
return(RPC_S_OUT_OF_RESOURCES);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|