882 lines
22 KiB
C++
882 lines
22 KiB
C++
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||
|
||
Module Name:
|
||
|
||
epclnt.cxx
|
||
|
||
Abstract:
|
||
|
||
This file contains the client runtime entry points into the
|
||
endpoint mapper dll.
|
||
|
||
Author:
|
||
|
||
Michael Montague (mikemon) 06-Jan-1992
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
#include <precomp.hxx>
|
||
#include <epmp.h>
|
||
#include <epmap.h>
|
||
#include <twrproto.h>
|
||
#include <CharConv.hxx>
|
||
#include <OsfPcket.hxx>
|
||
#include <BitSet.hxx>
|
||
#include <ProtBind.hxx>
|
||
#include <OsfClnt.hxx>
|
||
|
||
extern RPC_STATUS __RPC_FAR
|
||
MapFromNcaStatusCode (
|
||
IN unsigned long NcaStatus
|
||
);
|
||
|
||
static ProtseqEndpointPair EpMapperTable[] =
|
||
|
||
{
|
||
"ncacn_np", "\\pipe\\epmapper",
|
||
"ncalrpc", "epmapper",
|
||
"ncacn_ip_tcp", "135",
|
||
"ncadg_ip_udp", "135",
|
||
#ifdef NETBIOS_ON
|
||
"ncacn_nb_nb", "135",
|
||
"ncacn_nb_tcp", "135",
|
||
"ncacn_nb_ipx", "135",
|
||
#endif
|
||
#ifdef SPX_ON
|
||
"ncacn_spx", "34280",
|
||
#endif
|
||
#ifdef IPX_ON
|
||
"ncadg_ipx", "34280",
|
||
#endif
|
||
#ifdef APPLETALK_ON
|
||
"ncacn_at_dsp", "Endpoint Mapper",
|
||
#endif
|
||
#ifdef NCADG_MQ_ON
|
||
"ncadg_mq", "EpMapper",
|
||
#endif
|
||
"ncacn_http", "593"
|
||
};
|
||
|
||
unsigned long PartialRetries=0;
|
||
unsigned long ReallyTooBusy=0;
|
||
|
||
typedef struct _EP_LOOKUP_DATA
|
||
{
|
||
unsigned int NumberOfEndpoints;
|
||
unsigned int MaximumEndpoints;
|
||
unsigned int CurrentEndpoint;
|
||
RPC_CHAR * PAPI * Endpoints;
|
||
} EP_LOOKUP_DATA;
|
||
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
EpResolveEndpoint (
|
||
IN UUID PAPI * ObjectUuid, OPTIONAL
|
||
IN RPC_SYNTAX_IDENTIFIER PAPI * IfId,
|
||
IN RPC_SYNTAX_IDENTIFIER PAPI * XferId,
|
||
IN RPC_CHAR PAPI * RpcProtocolSequence,
|
||
IN RPC_CHAR PAPI * NetworkAddress,
|
||
IN RPC_CHAR PAPI * Options,
|
||
IN OUT void PAPI * PAPI * EpLookupHandle,
|
||
IN unsigned ConnTimeout,
|
||
IN ULONG CallTimeout,
|
||
IN CLIENT_AUTH_INFO *AuthInfo, OPTIONAL
|
||
OUT RPC_CHAR * PAPI * Endpoint
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The runtime will call this routine to resolve an endpoint.
|
||
|
||
Arguments:
|
||
|
||
ObjectUuid - Optional specifies the object uuid in the binding
|
||
for which we are trying to resolve an endpoint.
|
||
|
||
Ifid - Pointer to the Syntax Identifier for the Interface
|
||
|
||
Xferid - Pointer to the Syntax Identifier for the Transfer Syntax.
|
||
|
||
RpcProtocolSequence - Supplies the rpc protocol sequence contained
|
||
in the binding.
|
||
|
||
NetworkAddress - Supplies the network address. This will be used
|
||
to contact the endpoint mapper on that machine in order to
|
||
resolve the endpoint.
|
||
|
||
EpLookupHandle - Supplies the current version of the lookup handle
|
||
for this iteration through the endpoint mapper. A new value
|
||
for the lookup handle will be returned. If RPC_S_NO_ENDPOINT_FOUND
|
||
is returned, this parameter will be set to its initial value,
|
||
zero.
|
||
|
||
ConnTimeout - the connection timeout
|
||
|
||
CallTimeout - the call timeout
|
||
|
||
AutInfo - any auth info that needs to be used during the resolution process
|
||
|
||
Endpoint - Returns the endpoint resolved by the endpoint mapper on
|
||
the machine specified by the network address argument. The
|
||
storage for the endpoint must have been allocated using the
|
||
runtime API I_RpcAllocate.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The endpoint was successfully resolved.
|
||
|
||
EP_S_NOT_REGISTERED - There are no more endpoints to be found
|
||
for the specified combination of interface, network address,
|
||
and lookup handle.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allow
|
||
resolution of the endpoint.
|
||
|
||
EP_S_CANT_PERFORM_OP - The operation failed due to misc. error e.g.
|
||
unable to bind to the EpMapper.
|
||
|
||
--*/
|
||
{
|
||
RPC_BINDING_HANDLE MapperHandle;
|
||
RPC_STATUS RpcStatus;
|
||
twr_p_t InputTower = 0;
|
||
twr_p_t OutputTower[4];
|
||
unsigned long Returned;
|
||
error_status ErrorStatus;
|
||
ept_lookup_handle_t ContextHandle = 0;
|
||
EP_LOOKUP_DATA PAPI * EpLookupData = (EP_LOOKUP_DATA PAPI *)
|
||
*EpLookupHandle;
|
||
unsigned long RetryCount, i;
|
||
unsigned char PAPI * EPoint;
|
||
|
||
CHeapAnsi AnsiNWAddr, AnsiOptions;
|
||
CStackAnsi AnsiProtseq;
|
||
CNlUnicode nlEndpoint;
|
||
|
||
|
||
ASSERT(*Endpoint == 0);
|
||
|
||
|
||
|
||
// We have already taken all of the endpoints from the endpoint mapper;
|
||
// now we just return them back to the runtime one at a time.
|
||
|
||
ReturnEndpointFromList:
|
||
|
||
if ( EpLookupData != 0 )
|
||
{
|
||
|
||
// When we reach the end of the list of endpoints, return an error,
|
||
// and set things up so that we will start at the beginning again.
|
||
|
||
if ( EpLookupData->CurrentEndpoint == EpLookupData->NumberOfEndpoints )
|
||
{
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
EPT_S_NOT_REGISTERED,
|
||
EEInfoDLEpResolveEndpoint10,
|
||
RpcProtocolSequence,
|
||
NetworkAddress,
|
||
IfId->SyntaxGUID.Data1,
|
||
(ULONG)((EpLookupData->CurrentEndpoint << 16) | EpLookupData->NumberOfEndpoints));
|
||
EpLookupData->CurrentEndpoint = 0;
|
||
return(EPT_S_NOT_REGISTERED);
|
||
}
|
||
|
||
*Endpoint = DuplicateString(
|
||
EpLookupData->Endpoints[EpLookupData->CurrentEndpoint]);
|
||
EpLookupData->CurrentEndpoint += 1;
|
||
|
||
if ( *Endpoint == 0 )
|
||
{
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
// Otherwise, we need to take the list of endpoints from the endpoint
|
||
// mapper.
|
||
|
||
EpLookupData = (EP_LOOKUP_DATA PAPI *) RpcpFarAllocate(
|
||
sizeof(EP_LOOKUP_DATA));
|
||
if ( EpLookupData == 0 )
|
||
{
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
EpLookupData->MaximumEndpoints = 64;
|
||
EpLookupData->Endpoints = (RPC_CHAR * PAPI *) RpcpFarAllocate(
|
||
sizeof(RPC_CHAR PAPI *) * EpLookupData->MaximumEndpoints);
|
||
if ( EpLookupData->Endpoints == 0 )
|
||
{
|
||
RpcpFarFree(EpLookupData);
|
||
EpLookupData = 0;
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
EpLookupData->NumberOfEndpoints = 0;
|
||
EpLookupData->CurrentEndpoint = 0;
|
||
|
||
RpcStatus = AnsiNWAddr.Attach(NetworkAddress);
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
ASSERT( RpcStatus == RPC_S_OUT_OF_MEMORY );
|
||
RpcpFarFree(EpLookupData);
|
||
EpLookupData = 0;
|
||
return(RpcStatus);
|
||
}
|
||
|
||
i = 1+RpcpStringLength(RpcProtocolSequence);
|
||
*(AnsiProtseq.GetPAnsiString()) = (char *)_alloca(i);
|
||
RpcStatus = AnsiProtseq.Attach(RpcProtocolSequence, i, i * 2);
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
ASSERT( RpcStatus == RPC_S_OUT_OF_MEMORY );
|
||
RpcpFarFree(EpLookupData);
|
||
EpLookupData = 0;
|
||
return(RpcStatus);
|
||
}
|
||
|
||
RpcStatus = AnsiOptions.Attach(Options);
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
ASSERT( RpcStatus == RPC_S_OUT_OF_MEMORY );
|
||
RpcpFarFree(EpLookupData);
|
||
EpLookupData = 0;
|
||
return(RpcStatus);
|
||
}
|
||
|
||
RpcStatus = BindToEpMapper(&MapperHandle,
|
||
NetworkAddress,
|
||
RpcProtocolSequence,
|
||
Options,
|
||
ConnTimeout,
|
||
CallTimeout,
|
||
AuthInfo
|
||
);
|
||
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
MapperHandle = 0;
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
RpcStatus = TowerConstruct((RPC_IF_ID PAPI *) IfId,
|
||
(RPC_TRANSFER_SYNTAX PAPI *) XferId, (char PAPI *) AnsiProtseq,
|
||
NULL, (char PAPI *) AnsiNWAddr, &InputTower);
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
for (RetryCount = 0;;)
|
||
{
|
||
|
||
OutputTower[0] = 0;
|
||
OutputTower[1] = 0;
|
||
OutputTower[2] = 0;
|
||
OutputTower[3] = 0;
|
||
|
||
RpcTryExcept
|
||
{
|
||
ept_map(MapperHandle, ObjectUuid, InputTower, &ContextHandle, 4L,
|
||
&Returned, &OutputTower[0], &ErrorStatus);
|
||
}
|
||
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
||
{
|
||
ErrorStatus = RpcExceptionCode();
|
||
}
|
||
RpcEndExcept
|
||
|
||
if ( ErrorStatus == RPC_S_SERVER_TOO_BUSY)
|
||
{
|
||
if (RetryCount < 3)
|
||
{
|
||
RetryCount ++;
|
||
PartialRetries++;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
ReallyTooBusy++;
|
||
}
|
||
|
||
}
|
||
|
||
if ( ErrorStatus != 0 )
|
||
{
|
||
// For DCE interop the endpoint mapper returns DCE errors on the
|
||
// wire. We need to map some of them to the MS RPC ones.
|
||
|
||
switch (ErrorStatus)
|
||
{
|
||
case EP_S_CANT_PERFORM_OP :
|
||
RpcStatus = EPT_S_CANT_PERFORM_OP;
|
||
break;
|
||
|
||
case EP_S_NOT_REGISTERED :
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
EPT_S_NOT_REGISTERED,
|
||
EEInfoDLEpResolveEndpoint20,
|
||
RpcProtocolSequence,
|
||
NetworkAddress,
|
||
IfId->SyntaxGUID.Data1,
|
||
(ULONGLONG)MapperHandle);
|
||
RpcStatus = EPT_S_NOT_REGISTERED;
|
||
break;
|
||
|
||
default :
|
||
RpcStatus = MapFromNcaStatusCode(ErrorStatus);
|
||
break;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
ASSERT( ((Returned != 0) || (ContextHandle == 0)) && (Returned <= 4) );
|
||
|
||
for (i = 0; i < Returned; i++)
|
||
{
|
||
if (OutputTower[i] == 0)
|
||
{
|
||
return RPC_S_OUT_OF_MEMORY ;
|
||
}
|
||
|
||
RpcStatus = TowerExplode(
|
||
OutputTower[i],
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
(char PAPI * PAPI *) &EPoint,
|
||
NULL
|
||
);
|
||
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
break;
|
||
}
|
||
|
||
RpcStatus = nlEndpoint.Attach((char *)EPoint);
|
||
*Endpoint = nlEndpoint;
|
||
|
||
I_RpcFree(EPoint);
|
||
|
||
if ( *Endpoint == 0 )
|
||
{
|
||
RpcStatus = RPC_S_OUT_OF_MEMORY;
|
||
break;
|
||
}
|
||
|
||
EpLookupData->Endpoints[EpLookupData->NumberOfEndpoints] =
|
||
*Endpoint;
|
||
EpLookupData->NumberOfEndpoints += 1;
|
||
if ( EpLookupData->NumberOfEndpoints ==
|
||
EpLookupData->MaximumEndpoints )
|
||
{
|
||
goto OutsideTheLoop;
|
||
}
|
||
}//..for Loop over parse all towers/eps in this loop
|
||
|
||
for (i = 0; i < Returned; i++)
|
||
{
|
||
MIDL_user_free(OutputTower[i]);
|
||
}
|
||
|
||
if ( (ContextHandle == 0) || (RpcStatus != RPC_S_OK) )
|
||
{
|
||
break;
|
||
}
|
||
} //..for loop over get all endpoints
|
||
|
||
OutsideTheLoop:
|
||
|
||
ASSERT( InputTower != 0 );
|
||
I_RpcFree(InputTower);
|
||
|
||
CleanupAndReturn:
|
||
|
||
if ( MapperHandle != 0 )
|
||
{
|
||
RPC_STATUS Status = RpcBindingFree(&MapperHandle);
|
||
ASSERT( Status == RPC_S_OK );
|
||
}
|
||
|
||
if ( ContextHandle != 0 )
|
||
{
|
||
RpcSsDestroyClientContext(&ContextHandle);
|
||
}
|
||
|
||
if ( ( RpcStatus == EPT_S_NOT_REGISTERED )
|
||
|| ( RpcStatus == RPC_S_OK ) )
|
||
{
|
||
if ( EpLookupData->NumberOfEndpoints != 0 )
|
||
{
|
||
*EpLookupHandle = EpLookupData;
|
||
goto ReturnEndpointFromList;
|
||
}
|
||
RpcStatus = EPT_S_NOT_REGISTERED;
|
||
}
|
||
|
||
if ( EpLookupData != 0 )
|
||
{
|
||
if ( EpLookupData->Endpoints != 0 )
|
||
{
|
||
while ( EpLookupData->NumberOfEndpoints > 0 )
|
||
{
|
||
EpLookupData->NumberOfEndpoints -= 1;
|
||
delete EpLookupData->Endpoints[EpLookupData->NumberOfEndpoints];
|
||
}
|
||
RpcpFarFree(EpLookupData->Endpoints);
|
||
}
|
||
RpcpFarFree(EpLookupData);
|
||
}
|
||
|
||
return(RpcStatus);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
EpGetEpmapperEndpoint(
|
||
IN OUT RPC_CHAR * PAPI * Endpoint,
|
||
IN RPC_CHAR PAPI * Protseq
|
||
)
|
||
/*+
|
||
|
||
Routine Description:
|
||
|
||
Returns the Endpoint mappers well known endpoint for a given
|
||
protocol sequence.
|
||
|
||
Arguments:
|
||
|
||
Endpoint - Place to store the epmappers well known endpoint.
|
||
|
||
Protsq - Protocol sequence the client wishes to use.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Found the protocol sequence in the epmapper table and
|
||
am returning the associated well known endpoint.
|
||
|
||
EPT_S_CANT_PERFORM_OP - Protocol sequence not found.
|
||
|
||
--*/
|
||
|
||
{
|
||
RPC_STATUS Status = EPT_S_CANT_PERFORM_OP;
|
||
RPC_STATUS rc;
|
||
unsigned int i, Count;
|
||
|
||
CStackAnsi AnsiProtseq;
|
||
CNlUnicode nlEndpoint;
|
||
|
||
unsigned char PAPI * Epoint;
|
||
|
||
if (Protseq != NULL)
|
||
{
|
||
|
||
#ifdef UNICODE
|
||
//Must convert the protocol sequence into an ansi string from unicode
|
||
i = 1 + RpcpStringLength(Protseq);
|
||
*(AnsiProtseq.GetPAnsiString()) = (char *)_alloca(i);
|
||
rc = AnsiProtseq.Attach(Protseq, i, i * 2);
|
||
|
||
if ( rc != RPC_S_OK )
|
||
{
|
||
ASSERT( rc == RPC_S_OUT_OF_MEMORY );
|
||
return(Status);
|
||
}
|
||
|
||
#else
|
||
|
||
AnsiProtseq = Protseq;
|
||
|
||
#endif
|
||
|
||
|
||
Count = sizeof(EpMapperTable)/sizeof(EpMapperTable[0]);
|
||
|
||
for (i = 0; i < Count; i++)
|
||
{
|
||
|
||
|
||
//Search for the protocol sequence client is using.
|
||
|
||
|
||
if ( RpcpStringCompareA((char PAPI *)AnsiProtseq,
|
||
(char PAPI *)EpMapperTable[i].Protseq) )
|
||
{
|
||
|
||
//Not yet found.
|
||
continue;
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
//Found a match. Grab the epmappers known endpoint.
|
||
|
||
|
||
Epoint = (unsigned char __RPC_FAR *)(EpMapperTable[i].Endpoint);
|
||
|
||
rc = nlEndpoint.Attach((char *)Epoint);
|
||
*Endpoint = nlEndpoint;
|
||
|
||
Status = RPC_S_OK;
|
||
break;
|
||
|
||
}
|
||
} //for
|
||
}//if
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
BindToEpMapper(
|
||
OUT RPC_BINDING_HANDLE PAPI * MapperHandle,
|
||
IN RPC_CHAR * NWAddress OPTIONAL,
|
||
IN RPC_CHAR * Protseq OPTIONAL,
|
||
IN RPC_CHAR * Options OPTIONAL,
|
||
IN unsigned ConnTimeout,
|
||
IN ULONG CallTimeout,
|
||
IN CLIENT_AUTH_INFO *AuthInfo OPTIONAL
|
||
)
|
||
/*+
|
||
|
||
Routine Description:
|
||
|
||
This helper routine is used to by RpcEpRegister[NoReplace],
|
||
RpcEpUnRegister and EpResolveEndpoint(epclnt.cxx) to bind to
|
||
the EpMapper. If a Protseq is supplied, that particular protseq
|
||
is tried, otherwise lrpc is used to connect to the local epmapper.
|
||
If a NW Address is specified EpMapper at that host is contacted, else
|
||
local Endpoint mapper is used.
|
||
|
||
Arguments:
|
||
|
||
MapperHandle- Returns binding handle to the Endpoint mapper
|
||
|
||
NWAddress - NW address of the Endpoint mapper to bind to.
|
||
Ignored if protseq is NULL.
|
||
|
||
Protseq - Protocol sequence the client wishes to use.
|
||
NULL indicates a call to the local endpoint mapper.
|
||
|
||
ConnTimeout - the connection timeout
|
||
|
||
CallTimeout - the call timeout
|
||
|
||
AuthInfo - authentication information for the resolution
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The ansi string was successfully converted into a unicode
|
||
string.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available for the unicode
|
||
string.
|
||
|
||
EP_S_CANT_PERFORM_OP - The binding was unsuccessful, possibly because
|
||
the protocol sequence is not supported.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status = EPT_S_CANT_PERFORM_OP;
|
||
RPC_CHAR * BindingString = NULL;
|
||
unsigned int i, Count;
|
||
BOOL fHttp = FALSE;
|
||
|
||
Count = sizeof(EpMapperTable)/sizeof(EpMapperTable[0]);
|
||
|
||
// If Protseq == NULL use lrpc.
|
||
if (NULL == Protseq)
|
||
{
|
||
ASSERT(NWAddress == 0);
|
||
BindingString = RPC_STRING_LITERAL("ncalrpc:[epmapper]");
|
||
}
|
||
else
|
||
{
|
||
char * AnsiProtseq;
|
||
|
||
AnsiProtseq = (char *) _alloca(1+RpcpStringLength(Protseq));
|
||
if (!AnsiProtseq)
|
||
{
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
|
||
SimpleUnicodeToAnsi(Protseq, AnsiProtseq);
|
||
|
||
if (Options)
|
||
{
|
||
fHttp = (0 == RpcpStringCompare(Protseq, RPC_STRING_LITERAL("ncacn_http")));
|
||
}
|
||
|
||
for (i = 0; i < Count; i++)
|
||
{
|
||
if (RpcpStringCompareA(AnsiProtseq,
|
||
(char PAPI *) EpMapperTable[i].Protseq) )
|
||
continue;
|
||
|
||
// Found it.
|
||
|
||
RPC_CHAR * Endpoint;
|
||
|
||
Endpoint = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * (1+strlen(EpMapperTable[i].Endpoint)));
|
||
if (!Endpoint)
|
||
{
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
|
||
SimpleAnsiToPlatform(EpMapperTable[i].Endpoint, Endpoint);
|
||
|
||
Status = RpcStringBindingCompose( NULL,
|
||
Protseq,
|
||
NWAddress,
|
||
Endpoint,
|
||
(fHttp ? Options : 0),
|
||
&BindingString);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (BindingString)
|
||
{
|
||
Status = RpcBindingFromStringBinding(BindingString, MapperHandle);
|
||
}
|
||
|
||
if (BindingString != NULL && Protseq != NULL)
|
||
{
|
||
RpcStringFree(&BindingString);
|
||
}
|
||
|
||
if (Status != RPC_S_OK)
|
||
{
|
||
return(EPT_S_CANT_PERFORM_OP);
|
||
}
|
||
|
||
if (AuthInfo && (RpcpStringNCompare(Protseq, RPC_STRING_LITERAL("ncacn_"), 6) == 0))
|
||
{
|
||
Status = SetAuthInformation (*MapperHandle, AuthInfo);
|
||
|
||
if (Status != RPC_S_OK)
|
||
return Status;
|
||
}
|
||
|
||
Status = RpcMgmtSetComTimeout(*MapperHandle, ConnTimeout);
|
||
|
||
if (Status != RPC_S_OK)
|
||
{
|
||
return(EPT_S_CANT_PERFORM_OP);
|
||
}
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
void RPC_ENTRY
|
||
EpFreeLookupHandle (
|
||
IN void PAPI * EpLookupHandle
|
||
)
|
||
{
|
||
EP_LOOKUP_DATA PAPI * EpLookupData = (EP_LOOKUP_DATA PAPI *) EpLookupHandle;
|
||
|
||
if ( EpLookupData->Endpoints != 0 )
|
||
{
|
||
while ( EpLookupData->NumberOfEndpoints > 0 )
|
||
{
|
||
EpLookupData->NumberOfEndpoints -= 1;
|
||
delete EpLookupData->Endpoints[EpLookupData->NumberOfEndpoints];
|
||
}
|
||
RpcpFarFree(EpLookupData->Endpoints);
|
||
}
|
||
RpcpFarFree(EpLookupData);
|
||
}
|
||
|
||
HPROCESS hRpcssContext = 0;
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcServerAllocateIpPort(
|
||
IN DWORD Flags,
|
||
OUT USHORT *pPort
|
||
)
|
||
{
|
||
USHORT Port;
|
||
RPC_STATUS status;
|
||
RPC_BINDING_HANDLE hServer;
|
||
PORT_TYPE type;
|
||
|
||
*pPort = 0;
|
||
|
||
// Figure out what sort of port to allocate
|
||
|
||
if (Flags & RPC_C_USE_INTERNET_PORT)
|
||
{
|
||
type = PORT_INTERNET;
|
||
Flags &= ~RPC_C_USE_INTERNET_PORT;
|
||
}
|
||
else if (Flags & RPC_C_USE_INTRANET_PORT)
|
||
{
|
||
type = PORT_INTRANET;
|
||
Flags &= ~RPC_C_USE_INTRANET_PORT;
|
||
}
|
||
else
|
||
{
|
||
type = PORT_DEFAULT;
|
||
}
|
||
|
||
// Setup process context in the endpoint mapper if needed.
|
||
|
||
if (hRpcssContext == 0)
|
||
{
|
||
HPROCESS hProcess;
|
||
|
||
status = RpcBindingFromStringBinding(RPC_STRING_LITERAL("ncalrpc:[epmapper]"),
|
||
&hServer);
|
||
if (status != RPC_S_OK)
|
||
{
|
||
return(status);
|
||
}
|
||
|
||
hProcess = 0;
|
||
|
||
status = OpenEndpointMapper(hServer,
|
||
&hProcess);
|
||
|
||
RPC_STATUS statust =
|
||
RpcBindingFree(&hServer);
|
||
ASSERT(statust == RPC_S_OK);
|
||
|
||
if (status != RPC_S_OK)
|
||
{
|
||
return(status);
|
||
}
|
||
|
||
GlobalMutexRequest();
|
||
|
||
if (hRpcssContext != 0)
|
||
{
|
||
ASSERT(hRpcssContext != hProcess);
|
||
RpcSmDestroyClientContext(&hProcess);
|
||
}
|
||
else
|
||
{
|
||
hRpcssContext = hProcess;
|
||
}
|
||
|
||
GlobalMutexClear();
|
||
}
|
||
|
||
// Actually allocate a port.
|
||
|
||
RPC_STATUS allocstatus;
|
||
|
||
status = AllocateReservedIPPort(hRpcssContext,
|
||
type,
|
||
&allocstatus,
|
||
pPort);
|
||
|
||
if (status != RPC_S_OK)
|
||
{
|
||
ASSERT(*pPort == 0);
|
||
return(status);
|
||
}
|
||
|
||
return(allocstatus);
|
||
}
|
||
|
||
// Very special code for our older (NT 3.1 Era) servers.
|
||
//
|
||
// These server send out unique pointers which will confuse our
|
||
// stubs while unmarshalling. Here we go through and fixup the
|
||
// node id's to look like full pointers.
|
||
//
|
||
// This code can be removed when support for NT 3.1 era servers
|
||
// is no longer required.
|
||
|
||
extern "C"
|
||
void FixupForUniquePointerServers(PRPC_MESSAGE pMessage)
|
||
{
|
||
int CurrentPointer = 3;
|
||
unsigned int NumberOfPointers;
|
||
unsigned int i;
|
||
unsigned long __RPC_FAR *pBuffer;
|
||
|
||
pBuffer = (unsigned long __RPC_FAR *) pMessage->Buffer;
|
||
|
||
// The output buffer looks like:
|
||
|
||
// [ out-context handle (20b) ]
|
||
// [ count (4b) ]
|
||
// [ max (4b) ]
|
||
// [ min (4b) ]
|
||
// [ length (4b) ] // should be the same as count
|
||
// [ pointer node (count of them) ]
|
||
|
||
ASSERT(pBuffer[5] == pBuffer[8]);
|
||
|
||
NumberOfPointers = pBuffer[5];
|
||
|
||
ASSERT(pMessage->BufferLength >= 4 * 9 + 4 * NumberOfPointers);
|
||
|
||
for(i = 0; i < NumberOfPointers; i++)
|
||
{
|
||
if (pBuffer[9 + i] != 0)
|
||
{
|
||
pBuffer[9 + i] = CurrentPointer;
|
||
CurrentPointer++;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
#if defined(WIN) || defined(WIN32)
|
||
|
||
void __RPC_FAR * __RPC_API
|
||
MIDL_user_allocate(
|
||
size_t Size
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
MIDL generated stubs need this routine.
|
||
|
||
Arguments:
|
||
|
||
Size - Supplies the length of the memory to allocate in bytes.
|
||
|
||
Return Value:
|
||
|
||
The buffer allocated will be returned, if there is sufficient memory,
|
||
otherwise, zero will be returned.
|
||
|
||
--*/
|
||
{
|
||
void PAPI * pvBuf;
|
||
|
||
pvBuf = I_RpcAllocate(Size);
|
||
|
||
return(pvBuf);
|
||
}
|
||
|
||
void __RPC_API
|
||
MIDL_user_free (
|
||
void __RPC_FAR *Buf
|
||
)
|
||
{
|
||
|
||
I_RpcFree(Buf);
|
||
|
||
}
|
||
|
||
#endif
|