843 lines
20 KiB
C++
843 lines
20 KiB
C++
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||
|
||
Module Name:
|
||
|
||
epmapper.cxx
|
||
|
||
Abstract:
|
||
|
||
This routine implements the server side DCE runtime APIs. The
|
||
routines in this file are used by server applications only.
|
||
|
||
Author:
|
||
|
||
Bharat Shah (barats) 3-5-92
|
||
|
||
Revision History:
|
||
|
||
06-03-96 gopalp Added code to cleanup stale EP Mapper entries.
|
||
|
||
--*/
|
||
|
||
#include <precomp.hxx>
|
||
#include <rpcobj.hxx>
|
||
#include <epmap.h>
|
||
#include <epmp.h>
|
||
#include <twrproto.h>
|
||
#include <startsvc.h>
|
||
#include <hndlsvr.hxx>
|
||
#include <CharConv.hxx>
|
||
|
||
|
||
//
|
||
// Global EP cleanup context handle. Initially NULL, this will
|
||
// be allocated by Endpoint Mapper. As of now, it points to the
|
||
// EP entries registered by this process. This way, the Endpoint
|
||
// Mapper can cleanup entries of this process as soon as process
|
||
// goes away.
|
||
//
|
||
|
||
void * hEpContext = NULL;
|
||
MUTEX *EpContextMutex = NULL;
|
||
|
||
|
||
RPC_STATUS
|
||
InitializeEPMapperClient(
|
||
void
|
||
)
|
||
{
|
||
RPC_STATUS Status = RPC_S_OK;
|
||
|
||
EpContextMutex = new MUTEX(&Status,
|
||
TRUE // pre-allocate semaphore
|
||
);
|
||
|
||
if (EpContextMutex == NULL)
|
||
{
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
|
||
if (Status != RPC_S_OK)
|
||
{
|
||
delete EpContextMutex;
|
||
EpContextMutex = NULL;
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
inline void RequestEPClientMutex(void)
|
||
{
|
||
EpContextMutex->Request();
|
||
}
|
||
|
||
inline void ClearEPClientMutex(void)
|
||
{
|
||
EpContextMutex->Clear();
|
||
}
|
||
|
||
|
||
RPC_STATUS
|
||
BindingAndIfToTower(
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_HANDLE BindingHandle,
|
||
OUT twr_t PAPI * PAPI * Tower
|
||
)
|
||
/*+
|
||
|
||
Routine Description:
|
||
Helper routine that returns a Tower from the Interface Spec
|
||
and a bindinh handle
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Client or Server IfSpec structure.
|
||
|
||
BindingHandle - A partially bound binding handle
|
||
|
||
Tower - Returns a Tower if the Binding Handle had a
|
||
dynamic endpoint, else Tower=NULL. The caller needs
|
||
to free this memory.
|
||
|
||
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 Handle or IfSpec were in valid.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS err = 0;
|
||
unsigned char *Protseq = 0;
|
||
unsigned char *NWAddress= 0;
|
||
unsigned char *Binding = 0;
|
||
unsigned char *Endpoint = 0;
|
||
RPC_CHAR * String = 0;
|
||
RPC_IF_ID Ifid;
|
||
RPC_TRANSFER_SYNTAX Xferid;
|
||
unsigned int Size;
|
||
|
||
*Tower = NULL;
|
||
err = RpcIfInqId(IfSpec, &Ifid);
|
||
if (!err)
|
||
{
|
||
err = I_RpcIfInqTransferSyntaxes(
|
||
IfSpec,
|
||
&Xferid,
|
||
sizeof(Xferid),
|
||
&Size
|
||
);
|
||
}
|
||
|
||
if (!err)
|
||
{
|
||
err = I_RpcBindingInqDynamicEndpoint(BindingHandle, &String);
|
||
}
|
||
|
||
if (err)
|
||
{
|
||
return (err);
|
||
}
|
||
|
||
|
||
if (!err)
|
||
{
|
||
err = RpcBindingToStringBindingA(BindingHandle, &Binding);
|
||
}
|
||
|
||
if (!err)
|
||
{
|
||
if (String != 0)
|
||
{
|
||
// It is a dynamic endpoint
|
||
Endpoint = UnicodeToAnsiString(String, &err);
|
||
if (!err)
|
||
{
|
||
err = RpcStringBindingParseA(
|
||
Binding,
|
||
NULL,
|
||
&Protseq,
|
||
&NWAddress,
|
||
NULL,
|
||
NULL
|
||
);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
err = RpcStringBindingParseA(
|
||
Binding,
|
||
NULL,
|
||
&Protseq,
|
||
&NWAddress,
|
||
&Endpoint,
|
||
NULL
|
||
);
|
||
}
|
||
}
|
||
|
||
if (!err)
|
||
{
|
||
err = TowerConstruct(
|
||
&Ifid,
|
||
&Xferid,
|
||
(char PAPI*)Protseq,
|
||
(char PAPI *)Endpoint,
|
||
(char PAPI *)NWAddress,
|
||
Tower
|
||
);
|
||
}
|
||
|
||
if (Endpoint)
|
||
RpcStringFreeA(&Endpoint);
|
||
|
||
if (String)
|
||
RpcStringFreeA((unsigned char PAPI * PAPI *)&String);
|
||
|
||
if (Protseq)
|
||
RpcStringFreeA(&Protseq);
|
||
|
||
if (NWAddress)
|
||
RpcStringFreeA(&NWAddress);
|
||
|
||
if (Binding)
|
||
RpcStringFreeA(&Binding);
|
||
|
||
return(err);
|
||
}
|
||
|
||
|
||
|
||
|
||
RPC_STATUS
|
||
RegisterEntries(
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_VECTOR * BindingVector,
|
||
IN UUID_VECTOR * ObjUuidVector,
|
||
IN unsigned char * Annotation,
|
||
IN unsigned long ReplaceNoReplace
|
||
)
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
This helper function is called by RpcEpRegister or RpcEpRegisterNoReplace
|
||
Depending on the TypeOp, it tries to Add or replace endpoint entries
|
||
in the EP-database.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Interface Spec Handle for which the entries are to be registered.
|
||
|
||
BindingVector - A Vector of Binding Handles which need to be registered
|
||
|
||
ObjUUIDVector - A Vector of Objects
|
||
|
||
Annotation - A String representing the Annotation
|
||
|
||
TypeOp - A Flag : REGISTER_REPLACE or REGISTER_NO_REPLACE
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Some of the entries specified were successfully registered.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available,
|
||
|
||
EP_S_CANT_PERFORM_OP - Misc. local error occured; e.g. could not bind to
|
||
the EpMapper.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS err;
|
||
unsigned int i, j, k, Entries, CountBH, CountObj;
|
||
RPC_BINDING_HANDLE EpMapperHandle;
|
||
unsigned char * PStringBinding = NULL;
|
||
twr_p_t Twr;
|
||
ept_entry_t * EpEntries = NULL, *p;
|
||
unsigned long ArgC = 0;
|
||
char *ArgV[1] = { NULL };
|
||
|
||
if (BindingVector->Count == 0)
|
||
{
|
||
//
|
||
// PNP
|
||
//
|
||
err = GlobalRpcServer->InterfaceExported(
|
||
(PRPC_SERVER_INTERFACE) IfSpec,
|
||
ObjUuidVector,
|
||
Annotation,
|
||
ReplaceNoReplace);
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
if (err = BindToEpMapper(&EpMapperHandle,
|
||
NULL, // NetworkAddress
|
||
NULL, // Protseq
|
||
0, // Options
|
||
RPC_C_BINDING_DEFAULT_TIMEOUT,
|
||
INFINITE, // CallTimeout
|
||
NULL // AuthInfo
|
||
))
|
||
{
|
||
return err;
|
||
}
|
||
|
||
CountObj = (unsigned int)ObjUuidVector->Count;
|
||
CountBH = (unsigned int) BindingVector->Count;
|
||
|
||
if ((p = (EpEntries = (ept_entry_t *)
|
||
I_RpcAllocate(CountBH * sizeof(ept_entry_t)))) == NULL)
|
||
{
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
for (i = 0, Entries = 0; (!err) && (i < CountBH); i++)
|
||
{
|
||
if (BindingVector->BindingH[i] == 0)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (err = BindingAndIfToTower(IfSpec, BindingVector->BindingH[i], &Twr))
|
||
{
|
||
err = 0;
|
||
continue;
|
||
}
|
||
|
||
if (Twr == NULL)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
Entries ++;
|
||
p->tower = Twr;
|
||
lstrcpyA((char PAPI *)p->annotation, (char PAPI *)Annotation);
|
||
p++;
|
||
}
|
||
|
||
for (j = 0; j < CountObj; j++)
|
||
{
|
||
for (k = 0, p = EpEntries; k < Entries; k++, p++)
|
||
{
|
||
RpcpMemoryCopy(
|
||
(char PAPI *)&p->object,
|
||
(char PAPI *)ObjUuidVector->Uuid[j],
|
||
sizeof(UUID)
|
||
);
|
||
}
|
||
|
||
RequestEPClientMutex();
|
||
RpcTryExcept
|
||
{
|
||
ept_insert_ex(
|
||
EpMapperHandle,
|
||
&hEpContext,
|
||
Entries,
|
||
EpEntries,
|
||
ReplaceNoReplace,
|
||
(error_status PAPI *)&err
|
||
);
|
||
}
|
||
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
||
{
|
||
err = RpcExceptionCode();
|
||
}
|
||
RpcEndExcept
|
||
ClearEPClientMutex();
|
||
|
||
if (err == RPC_S_SERVER_UNAVAILABLE)
|
||
{
|
||
//
|
||
//Try to start the epmapper and retry
|
||
//
|
||
|
||
err = StartServiceIfNecessary();
|
||
|
||
if (err == RPC_S_OK)
|
||
{
|
||
RequestEPClientMutex();
|
||
RpcTryExcept
|
||
{
|
||
ept_insert_ex(
|
||
EpMapperHandle,
|
||
&hEpContext,
|
||
Entries,
|
||
EpEntries,
|
||
ReplaceNoReplace,
|
||
(error_status PAPI *)&err
|
||
);
|
||
}
|
||
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
||
{
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
EPT_S_CANT_CREATE,
|
||
EEInfoDLRegisterEntries10,
|
||
RpcExceptionCode());
|
||
err = EPT_S_CANT_CREATE;
|
||
}
|
||
RpcEndExcept
|
||
ClearEPClientMutex();
|
||
}
|
||
}
|
||
|
||
if (err != RPC_S_OK)
|
||
{
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
EPT_S_CANT_CREATE,
|
||
EEInfoDLRegisterEntries20,
|
||
err);
|
||
err = EPT_S_CANT_CREATE;
|
||
break;
|
||
}
|
||
|
||
// Subsequent Inserts should be (ALWAYS) NOREPLACE
|
||
// ReplaceNoReplace = REGISTER_NOREPLACE;
|
||
|
||
} // for loop over UUID Vectors
|
||
|
||
|
||
for (i = 0, p = EpEntries; i < Entries; i++,p++)
|
||
I_RpcFree(p->tower);
|
||
|
||
if (EpEntries)
|
||
{
|
||
I_RpcFree(EpEntries);
|
||
}
|
||
|
||
RpcBindingFree(&EpMapperHandle);
|
||
|
||
if (err == RPC_S_OK)
|
||
{
|
||
//
|
||
// We successfully registered our bindings,
|
||
// reflect that in the interface so that if we get a
|
||
// PNP notification, we can update the bindings
|
||
//
|
||
err = GlobalRpcServer->InterfaceExported(
|
||
(PRPC_SERVER_INTERFACE) IfSpec,
|
||
ObjUuidVector,
|
||
Annotation,
|
||
ReplaceNoReplace);
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcEpRegisterNoReplaceA (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_VECTOR * BindingVector,
|
||
IN UUID_VECTOR * UuidVector OPTIONAL,
|
||
IN unsigned char * Annotation
|
||
)
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to register
|
||
a series of end points with the local endpoint mapper.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
UUID_VECTOR UuidVectorNull;
|
||
UUID_VECTOR PAPI *PObjUuidVector = &UuidVectorNull;
|
||
UUID NilUuid;
|
||
unsigned char AnnotStr[] = {'\0'};
|
||
THREAD *Thread;
|
||
|
||
if (!ARGUMENT_PRESENT(Annotation))
|
||
Annotation = AnnotStr;
|
||
|
||
if (strlen((char PAPI *)Annotation) >= ep_max_annotation_size)
|
||
return(EPT_S_INVALID_ENTRY);
|
||
|
||
if (!ARGUMENT_PRESENT( BindingVector))
|
||
{
|
||
return(RPC_S_NO_BINDINGS);
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT( UuidVector ))
|
||
{
|
||
PObjUuidVector = UuidVector;
|
||
}
|
||
else
|
||
{
|
||
UuidVectorNull.Count = 1;
|
||
RpcpMemorySet(&NilUuid, 0, sizeof(UUID));
|
||
UuidVectorNull.Uuid[0] = &NilUuid;
|
||
}
|
||
|
||
Thread = ThreadSelf();
|
||
if (Thread)
|
||
{
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
}
|
||
|
||
return(RegisterEntries(
|
||
IfSpec,
|
||
BindingVector,
|
||
PObjUuidVector,
|
||
Annotation,
|
||
EP_REGISTER_NOREPLACE
|
||
));
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcEpRegisterNoReplaceW (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_VECTOR * BindingVector,
|
||
IN UUID_VECTOR * UuidVector OPTIONAL,
|
||
IN unsigned short * Annotation
|
||
)
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to register [Add]
|
||
a series of end points with the local endpoint mapper
|
||
This is the Unicode version of the API.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Server side Interface specification structure generated
|
||
by MIDL, that describes Interface UUId and version
|
||
|
||
Binding Vector - A vector of binding handles that the server has registered
|
||
with the runtime.
|
||
|
||
UuidVector- A vector of Uuids of objects that the server is supporting
|
||
|
||
Annotation - Annotation String
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
CHeapAnsi AnsiString;
|
||
USES_CONVERSION;
|
||
RPC_STATUS err;
|
||
|
||
if (ARGUMENT_PRESENT(Annotation))
|
||
{
|
||
ATTEMPT_HEAP_W2A(AnsiString, Annotation);
|
||
}
|
||
|
||
err = RpcEpRegisterNoReplaceA(
|
||
IfSpec,
|
||
BindingVector,
|
||
UuidVector,
|
||
AnsiString
|
||
);
|
||
|
||
return(err);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcEpRegisterA (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_VECTOR * BindingVector,
|
||
IN UUID_VECTOR * UuidVector OPTIONAL,
|
||
IN unsigned char * Annotation
|
||
)
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to register
|
||
a series of end points with the local endpoint mapper, replacing
|
||
existing database entries in the process.
|
||
|
||
This is the Ansi version of the API.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Server side Interface specification structure generated
|
||
by MIDL, that describes Interface UUId and version
|
||
|
||
Binding Vector- A vector of binding handles that the server has registered
|
||
with the runtime.
|
||
|
||
UuidVector- A vector of Uuids of objects that the server is supporting
|
||
|
||
Annotation - Annotation String
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
UUID_VECTOR UuidVectorNull;
|
||
UUID_VECTOR PAPI *PObjUuidVector = &UuidVectorNull;
|
||
UUID NilUuid;
|
||
unsigned char AnnotStr[] = {'\0'};
|
||
THREAD *Thread;
|
||
|
||
if (!ARGUMENT_PRESENT(Annotation))
|
||
Annotation = AnnotStr;
|
||
|
||
if (strlen((char PAPI *)Annotation) >= ep_max_annotation_size)
|
||
return(EPT_S_INVALID_ENTRY);
|
||
|
||
if (!ARGUMENT_PRESENT( BindingVector))
|
||
{
|
||
return(RPC_S_NO_BINDINGS);
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT( UuidVector ))
|
||
{
|
||
PObjUuidVector = UuidVector;
|
||
}
|
||
else
|
||
{
|
||
UuidVectorNull.Count = 1;
|
||
RpcpMemorySet(&NilUuid, 0, sizeof(UUID));
|
||
UuidVectorNull.Uuid[0] = &NilUuid;
|
||
}
|
||
|
||
Thread = ThreadSelf();
|
||
if (Thread)
|
||
{
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
}
|
||
|
||
return(RegisterEntries(
|
||
IfSpec,
|
||
BindingVector,
|
||
PObjUuidVector,
|
||
Annotation,
|
||
EP_REGISTER_REPLACE
|
||
));
|
||
}
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcEpRegisterW (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_VECTOR * BindingVector,
|
||
IN UUID_VECTOR * UuidVector,
|
||
IN unsigned short * Annotation
|
||
)
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to register
|
||
a series of end points with the local endpoint mapper, replcaing
|
||
existing entries in the process.
|
||
This is the Unicode version of the API.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Server side Interface specification structure generated
|
||
by MIDL, that describes Interface UUId and version
|
||
|
||
Binding Vector- A vector of binding handles that the server has registered
|
||
with the runtime.
|
||
|
||
UuidVector- A vector of Uuids of objects that the server is supporting
|
||
|
||
Annotation - Annotation String
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
USES_CONVERSION;
|
||
CHeapAnsi AnsiString;
|
||
RPC_STATUS err;
|
||
|
||
if (ARGUMENT_PRESENT(Annotation))
|
||
{
|
||
ATTEMPT_HEAP_W2A(AnsiString, Annotation);
|
||
}
|
||
|
||
err = RpcEpRegisterA(
|
||
IfSpec,
|
||
BindingVector,
|
||
UuidVector,
|
||
AnsiString
|
||
);
|
||
|
||
return(err);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcEpUnregister(
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN RPC_BINDING_VECTOR * BindingVector,
|
||
IN UUID_VECTOR * UuidVector
|
||
)
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to unregister
|
||
a series of end points.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Pointer to Interface Specification generated by MIDL
|
||
|
||
BindingVector - A Vector of Binding handles maintained by runtime
|
||
for the server.
|
||
|
||
UuidVector - A Vector of UUIDs for objects supported by the the server
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK -
|
||
|
||
RPC_S_OUT_OF_MEMORY - There is no memory available to construct
|
||
towers
|
||
|
||
--*/
|
||
{
|
||
UUID_VECTOR UuidVectorNull;
|
||
UUID_VECTOR PAPI *PObjUuidVector = &UuidVectorNull;
|
||
UUID NilUuid;
|
||
RPC_STATUS err;
|
||
unsigned int i, j, CountBH, CountObj;
|
||
RPC_BINDING_HANDLE EpMapperHandle;
|
||
ept_entry_t PAPI * EpEntries, * p;
|
||
twr_t PAPI *Twr;
|
||
|
||
if (!ARGUMENT_PRESENT( BindingVector))
|
||
{
|
||
return(RPC_S_NO_BINDINGS);
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT( UuidVector ))
|
||
{
|
||
PObjUuidVector = UuidVector;
|
||
}
|
||
else
|
||
{
|
||
UuidVectorNull.Count = 1;
|
||
RpcpMemorySet(&NilUuid, 0, sizeof(UUID));
|
||
UuidVectorNull.Uuid[0] = &NilUuid;
|
||
}
|
||
|
||
if (err = BindToEpMapper(
|
||
&EpMapperHandle,
|
||
NULL, // NetworkAddress
|
||
NULL, // Protseq
|
||
0, // Options
|
||
RPC_C_BINDING_DEFAULT_TIMEOUT,
|
||
INFINITE, // CallTimeout
|
||
NULL // AuthInfo
|
||
))
|
||
{
|
||
return(err);
|
||
}
|
||
|
||
CountObj = (unsigned int)PObjUuidVector->Count;
|
||
|
||
if ((EpEntries = (ept_entry_t *)
|
||
I_RpcAllocate(sizeof(ept_entry_t)*CountObj)) == NULL)
|
||
{
|
||
RpcBindingFree(&EpMapperHandle);
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
RPC_STATUS FinalStatus = EPT_S_CANT_PERFORM_OP;
|
||
CountBH = (unsigned int) BindingVector->Count;
|
||
|
||
for (i = 0; i < CountBH; i++)
|
||
{
|
||
if (BindingVector->BindingH[i] == 0)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (err = BindingAndIfToTower(IfSpec, BindingVector->BindingH[i], &Twr))
|
||
{
|
||
FinalStatus = err;
|
||
break;
|
||
}
|
||
|
||
if (Twr == NULL)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
for (p=EpEntries,j = 0; j < CountObj; j++,p++)
|
||
{
|
||
RpcpMemoryCopy(
|
||
(char PAPI *)&p->object,
|
||
(char PAPI *)PObjUuidVector->Uuid[j],
|
||
sizeof(UUID)
|
||
);
|
||
p->tower = Twr;
|
||
p->annotation[0] = '\0';
|
||
}
|
||
|
||
RequestEPClientMutex();
|
||
RpcTryExcept
|
||
{
|
||
ept_delete_ex(
|
||
EpMapperHandle,
|
||
&hEpContext,
|
||
CountObj,
|
||
EpEntries,
|
||
(error_status PAPI *)&err
|
||
);
|
||
}
|
||
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
||
{
|
||
err = EPT_S_CANT_PERFORM_OP;
|
||
}
|
||
RpcEndExcept
|
||
ClearEPClientMutex();
|
||
|
||
I_RpcFree(Twr);
|
||
|
||
} // For loop over Binding Handle Vector
|
||
|
||
if (FinalStatus != RPC_S_OK)
|
||
{
|
||
FinalStatus = err;
|
||
}
|
||
|
||
I_RpcFree(EpEntries);
|
||
|
||
RpcBindingFree(&EpMapperHandle);
|
||
|
||
return(FinalStatus);
|
||
}
|