2020-09-30 17:12:29 +02:00

462 lines
9.1 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

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

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
Epts.c
Abstract:
Common code to listen to endpoints in the DCOM service.
Author:
Mario Goertzel [MarioGo]
Revision History:
MarioGo 6/16/1995 Bits 'n pieces
--*/
#ifdef _CHICAGO_
#define ASSERT( exp ) if (! (exp) ) DebugBreak();
#endif
#define WSTR(s) L##s
#include <dcomss.h>
// Globals
// BUGBUG - this info should be read from the registry.
// The index is the protseq tower id.
PROTSEQ_INFO
gaProtseqInfo[] =
{
/* 0x00 */ { STOPPED, 0, 0 },
/* 0x01 */ { STOPPED, 0, 0 },
/* 0x02 */ { STOPPED, 0, 0 },
/* 0x03 */ { STOPPED, 0, 0 },
/* 0x04 */ { STOPPED, L"ncacn_dnet_dsp", L"#69" },
/* 0x05 */ { STOPPED, 0, 0 },
/* 0x06 */ { STOPPED, 0, 0 },
/* 0x07 */ { STOPPED, L"ncacn_ip_tcp", L"135" },
/* 0x08 */ { STOPPED, L"ncadg_ip_udp", L"135" },
/* 0x09 */ { STOPPED, L"ncacn_nb_tcp", L"135" },
/* 0x0a */ { STOPPED, 0, 0 },
/* 0x0b */ { STOPPED, 0, 0 },
/* 0x0c */ { STOPPED, L"ncacn_spx", L"34280" },
/* 0x0d */ { STOPPED, L"ncacn_nb_ipx", L"135" },
/* 0x0e */ { STOPPED, L"ncadg_ipx", L"34280" },
/* 0x0f */ { STOPPED, L"ncacn_np", L"\\pipe\\epmapper" },
/* 0x10 */ { STOPPED, L"ncalrpc", L"epmapper" },
/* 0x11 */ { STOPPED, 0, 0 },
/* 0x12 */ { STOPPED, 0, 0 },
/* 0x13 */ { STOPPED, L"ncacn_nb_nb", L"135" },
/* 0x14 */ { STOPPED, 0, 0 },
/* 0x15 */ { STOPPED, 0, 0 }, // was ncacn_nb_xns - unsupported.
/* 0x16 */ { STOPPED, L"ncacn_at_dsp", L"Endpoint Mapper" },
/* 0x17 */ { STOPPED, L"ncadg_at_ddp", L"Endpoint Mapper" },
/* 0x18 */ { STOPPED, 0, 0 },
/* 0x19 */ { STOPPED, 0, 0 },
/* 0x1A */ { STOPPED, L"ncacn_vns_spp", L"385"}
};
#define PROTSEQ_IDS (sizeof(gaProtseqInfo)/sizeof(PROTSEQ_INFO))
RPC_STATUS
UseProtseqIfNecessary(
IN USHORT id
)
/*++
Routine Description:
Listens to the well known RPC endpoint mapper endpoint
for the protseq. Returns very quickly if the process
is already listening to the protseq.
Arguments:
id - the tower id of protseq. See GetProtseqId() if you don't
already have this valud.
Return Value:
RPC_S_OK - no errors occured.
RPC_S_OUT_OF_RESOURCES - when we're unable to setup security for the endpoint.
RPC_S_INVALID_RPC_PROTSEQ - if id is unknown/invalid.
Any error from RpcServerUseProtseqEp.
--*/
{
RPC_STATUS status = RPC_S_OK;
SECURITY_DESCRIPTOR sd, *psd;
ASSERT(id);
if (id == 0 || id >= PROTSEQ_IDS)
{
ASSERT(0);
return(RPC_S_INVALID_RPC_PROTSEQ);
}
if (gaProtseqInfo[id].state == STARTED)
{
return(RPC_S_OK);
}
if (id == 0x10)
{
// ncalrpc needs a security descriptor.
psd = &sd;
InitializeSecurityDescriptor(
psd,
SECURITY_DESCRIPTOR_REVISION
);
if ( FALSE == SetSecurityDescriptorDacl (
psd,
TRUE, // Dacl present
NULL, // NULL Dacl
FALSE // Not defaulted
) )
{
status = RPC_S_OUT_OF_RESOURCES;
}
}
else
{
psd = 0;
}
if (status == RPC_S_OK )
{
status = RpcServerUseProtseqEpW(gaProtseqInfo[id].pwstrProtseq,
RPC_C_PROTSEQ_MAX_REQS_DEFAULT + 1,
gaProtseqInfo[id].pwstrEndpoint,
psd);
// No locking is done here, the RPC runtime may return duplicate
// endpoint if two threads call this at the same time.
if (status == RPC_S_DUPLICATE_ENDPOINT)
{
ASSERT(gaProtseqInfo[id].state == STARTED);
status = RPC_S_OK;
}
#ifdef DEBUGRPC
if (status != RPC_S_OK)
{
#ifndef _CHICAGO_
DbgPrint("DCOMSS: Unable to listen to %S\n", gaProtseqInfo[id].pwstrProtseq);
#endif
}
#endif
if (status == RPC_S_OK)
{
gaProtseqInfo[id].state = STARTED;
}
}
return(status);
}
PWSTR
GetProtseq(
IN USHORT ProtseqId
)
/*++
Routine Description:
Returns the unicode protseq give the protseqs tower id.
Arguments:
ProtseqId - Tower id of the protseq in question.
Return Value:
NULL if the id is invalid.
non-NULL if the id is valid - note the pointer doesn't need to be freed.
--*/
{
ASSERT(ProtseqId);
if (ProtseqId < PROTSEQ_IDS)
{
return(gaProtseqInfo[ProtseqId].pwstrProtseq);
}
return(0);
}
PWSTR
GetEndpoint(
IN USHORT ProtseqId
)
/*++
Routine Description:
Returns the well known endpoint associated with the protseq.
Arguments:
ProtseqId - the id (See GetProtseqId()) of the protseq in question.
Return Value:
0 - Unknown/invalid id.
!0 - The endpoint associated with the protseq.
note: should not be freed.
--*/
{
ASSERT(ProtseqId);
if (ProtseqId < PROTSEQ_IDS)
{
return(gaProtseqInfo[ProtseqId].pwstrEndpoint);
}
return(0);
}
USHORT
GetProtseqId(
IN PWSTR Protseq
)
/*++
Routine Description:
Returns the tower id for a protseq.
This could be changed to a faster search, but remember that
eventually the table will NOT be static. (ie. we can't just
create a perfect hash based on the static table).
Arguments:
Protseq - a unicode protseq to lookup. It is assumed
to be non-null.
Return Value:
0 - unknown/invalid protseq
non-zero - the id.
--*/
{
int i;
ASSERT(Protseq);
for(i = 1; i < PROTSEQ_IDS; i++)
{
if ( 0 != gaProtseqInfo[i].pwstrProtseq
&& 0 == wcscmp(gaProtseqInfo[i].pwstrProtseq, Protseq))
{
return(i);
}
}
return(0);
}
USHORT
GetProtseqIdAnsi(
IN PSTR pstrProtseq
)
/*++
Routine Description:
Returns the tower id for a protseq.
This could be changed to a faster search, but remember that
eventually the table will NOT be static. (ie. we can't just
create a perfect hash based on the static table).
Arguments:
Protseq - an ansi (8 bit char) protseq to lookup. It is assumed
to be non-null.
Return Value:
0 - unknown/invalid protseq
non-zero - the id.
--*/
{
int i;
ASSERT(pstrProtseq);
for(i = 1; i < PROTSEQ_IDS; i++)
{
if (0 != gaProtseqInfo[i].pwstrProtseq)
{
PWSTR pwstrProtseq = gaProtseqInfo[i].pwstrProtseq;
PSTR pstrT = pstrProtseq;
while(*pstrT && *pwstrProtseq && *pstrT == *pwstrProtseq)
{
pstrT++;
pwstrProtseq++;
}
if (*pstrT == *pwstrProtseq)
{
return(i);
}
}
}
return(0);
}
RPC_STATUS
InitializeEndpointManager(
VOID
)
/*++
Routine Description:
Called when the dcom service starts.
BUGBUG: Should read the protseqs, tower IDs and endpoints from the registry.
Arguments:
None
Return Value:
RPC_S_OUT_OF_MEMORY - if needed
RPC_S_OUT_OF_RESOURCES - usually on registry failures.
--*/
{
return(RPC_S_OK);
}
BOOL
IsLocal(
IN USHORT ProtseqId
)
/*++
Routine Description:
Determines if the protseq id is local-only.
(ncalrpc or mswmsg).
Arguments:
ProtseqId - The id of the protseq in question.
Return Value:
TRUE - if the protseq id is local-only
FALSE - if the protseq id invalid or available remotely.
--*/
{
return(ProtseqId == 0x1 || ProtseqId == 0x10);
}
RPC_STATUS
DelayedUseProtseq(
IN USHORT id
)
/*++
Routine Description:
If the protseq is not being used its state is changed
so that a callto CompleteDelayedUseProtseqs() will actually
cause the server to listen to the protseq.
Arguments:
id - the id of the protseq you wish to listen to.
Return Value:
0 - normally
RPC_S_INVALID_RPC_PROTSEQ - if id is invalud.
--*/
{
if (id < PROTSEQ_IDS)
{
if (gaProtseqInfo[id].pwstrProtseq != 0)
{
if (gaProtseqInfo[id].state == STOPPED)
gaProtseqInfo[id].state = START;
return(RPC_S_OK);
}
}
return(RPC_S_INVALID_RPC_PROTSEQ);
}
VOID
CompleteDelayedUseProtseqs(
VOID
)
/*++
Routine Description:
Start listening to any protseqs previously passed
to DelayedUseProtseq(). No errors are returned,
but informationals are printed on debug builds.
Arguments:
None
Return Value:
None
--*/
{
USHORT i;
for(i = 1; i < PROTSEQ_IDS; i++)
{
if (START == gaProtseqInfo[i].state)
{
RPC_STATUS status = UseProtseqIfNecessary(i);
#ifdef DEBUGRPC
if (RPC_S_OK == status)
ASSERT(gaProtseqInfo[i].state == STARTED);
#endif
}
}
}