|
|
/*++
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;
if (EpContextMutex == NULL) { 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); }
|