Registrando interfaces

Esta seção apresenta uma discussão detalhada sobre o processo de registro de uma interface RPC.

As informações nesta seção são apresentadas nos seguintes tópicos:

Funções de registro de interface

Os servidores registram suas interfaces chamando a função RpcServerRegisterIf . Programas de servidor complexos geralmente dão suporte a mais de uma interface. Os aplicativos de servidor devem chamar essa função uma vez para cada interface compatível.

Além disso, os servidores podem dar suporte a várias versões da mesma interface, cada uma com sua própria implementação das funções da interface. Se o programa de servidor fizer isso, ele deverá fornecer um conjunto de pontos de entrada. Um ponto de entrada é uma rotina de gerente que despacha chamadas para uma versão de uma interface. Deve haver um ponto de entrada para cada versão da interface. O grupo de pontos de entrada é chamado de vetor de ponto de entrada. Para obter detalhes, consulte Vetores de ponto de entrada.

Além da função padrão RpcServerRegisterIf, o RPC também dá suporte a outras funções de registro de interface. A função RpcServerRegisterIf2 estende os recursos de RpcServerRegisterIf , permitindo que você especifique um conjunto de sinalizadores de registro (consulte Sinalizadores de Registro de Interface), o número máximo de solicitações simultâneas de chamada de procedimento remoto que o servidor pode aceitar e o tamanho máximo em bytes de blocos de dados de entrada.

A biblioteca RPC também contém uma função chamada RpcServerRegisterIfEx. Assim como a função RpcServerRegisterIf , essa função registra uma interface. Seu programa de servidor também pode usar essa função para especificar um conjunto de sinalizadores de registro (consulte Sinalizadores de Registro de Interface), o número máximo de solicitações de chamada de procedimento remoto simultâneas que o servidor pode aceitar e uma função de retorno de chamada de segurança.

As funções RpcServerRegisterIf, RpcServerRegisterIfEx e RpcServerRegisterIf2 definem valores na tabela de registro de interface interna. Essa tabela é usada para mapear a interface UUID e UUIDs de objeto para um EPV do gerenciador. O EPV do gerenciador é uma matriz de ponteiros de função que contém exatamente um ponteiro de função para cada protótipo de função na interface especificada no arquivo IDL.

Para obter informações sobre como fornecer vários EPVs para fornecer várias implementações da interface, consulte Várias implementações de interface.

A biblioteca em tempo de execução usa a tabela de registro de interface (definida por chamadas para a função RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2) e a tabela do registro de objeto (definida por chamadas para a função RpcObjectSetType) para mapear interface e UUIDs de objeto para o ponteiro de função.

Quando quiser que o programa de servidor remova uma interface do registro de biblioteca em tempo de execução RPC, chame a função RpcServerUnregisterIf . Depois que a interface for removida do registro, a biblioteca de tempo de execução RPC não aceitará mais novas chamadas para essa interface.

Vetores de ponto de entrada

O EPV (vetor de ponto de entrada) do gerenciador é uma matriz de ponteiros de função que apontam para implementações das funções especificadas no arquivo IDL. O número de elementos na matriz corresponde ao número de funções especificadas no arquivo IDL. O RPC dá suporte a vários vetores de ponto de entrada que representam várias implementações das funções especificadas na interface.

O compilador MIDL gera automaticamente um tipo de dados EPV do gerenciador para uso na construção de EPVs do gerenciador. O tipo de dados é chamado if-name**_SERVER_EPV**, em que if-name especifica o identificador de interface no arquivo IDL.

O compilador MIDL cria e inicializa automaticamente um EPV de gerenciador padrão com a suposição de que existe uma rotina de gerente com o mesmo nome para cada procedimento na interface e é especificado no arquivo IDL.

Quando um servidor oferece várias implementações da mesma interface, o servidor deve criar um EPV de gerenciador adicional para cada implementação. Cada EPV deve conter exatamente um ponto de entrada (endereço de uma função) para cada procedimento definido no arquivo IDL. O aplicativo de servidor declara e inicializa uma variável EPV de gerenciador do tipo if-name**_SERVER_EPV** para cada implementação adicional da interface. Para registrar os EPVs, ele chama RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 uma vez para cada tipo de objeto compatível.

Quando o cliente faz uma chamada de procedimento remoto para o servidor, o EPV que contém o ponteiro de função é selecionado com base na interface UUID e no tipo de objeto. O tipo de objeto é derivado do objeto UUID pela função object-inquiry ou pelo mapeamento controlado por tabela controlado por RpcObjectSetType.

EPVs do gerente

Por padrão, o compilador MIDL usa os nomes de procedimento do arquivo IDL de uma interface para gerar um EPV do gerenciador, que o compilador coloca diretamente no stub do servidor. Esse EPV padrão é inicializado estaticamente usando os nomes de procedimento declarados na definição da interface.

Para registrar um gerente usando o EPV padrão, especifique NULL como o valor do parâmetro MgrEpv em uma chamada para a função RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 . Se os nomes de rotina usados por um gerente corresponderem aos da definição da interface, você poderá registrar esse gerenciador usando o EPV padrão da interface gerada pelo compilador MIDL. Você também pode registrar um gerenciador usando um EPV fornecido pelo aplicativo de servidor.

Um servidor pode (e às vezes deve) criar e registrar um EPV de gerenciador não nulo para uma interface. Para selecionar um EPV fornecido pelo aplicativo de servidor, passe o endereço de um EPV cujo valor foi declarado pelo servidor como o valor do parâmetro MgrEpv . Um valor não nulo para o parâmetro MgrEpv a sempre substitui um EPV padrão no stub do servidor.

O compilador MIDL gera automaticamente um tipo de dados EPV do gerenciador (RPC_MGR_EPV) para um aplicativo de servidor a ser usado na construção de EPVs do gerenciador. Um EPV do gerente deve conter exatamente um ponto de entrada (endereço de função) para cada procedimento definido no arquivo IDL.

Um servidor deve fornecer um EPV não nulo nos seguintes casos:

  • Quando os nomes das rotinas do gerente diferem dos nomes de procedimento declarados na definição da interface
  • Quando o servidor usa o EPV padrão para registrar outra implementação da interface

Um servidor declara um EPV de gerente inicializando uma variável do tipo if-name**_SERVER_EPV** para cada implementação da interface.

Registrando uma única implementação de uma interface

Quando um servidor oferece apenas uma implementação de uma interface, o servidor chama RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 apenas uma vez. No caso padrão, o servidor usa o EPV do gerenciador padrão. (A exceção é quando o gerente usa nomes de rotina que diferem daqueles declarados na interface.)

Para o caso padrão, você fornece os seguintes valores para chamadas para RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2:

  • EPVs do gerente

    Para usar o EPV padrão, especifique um valor nulo para o parâmetro MgrEpv a.

  • UUID do tipo gerente

    Ao usar o EPV padrão, registre a interface com um UUID de tipo de gerente nulo fornecendo um valor nulo ou um UUID nulo para o parâmetro MgrTypeUuid . Nesse caso, todas as chamadas de procedimento remoto, independentemente da UUID do objeto em seu identificador de associação, são enviadas para o EPV padrão, supondo que nenhuma chamada RpcObjectSetType tenha sido feita.

    Você também pode fornecer um UUID do tipo de gerente não nulo. Nesse caso, você também deve chamar a rotina RpcObjectSetType .

Registrando várias implementações de uma interface

Você pode fornecer mais de uma implementação dos procedimentos remotos especificados no arquivo IDL. O aplicativo de servidor chama RpcObjectSetType para mapear UUIDs de objeto para digitar UUIDs e chama RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 para associar EPVs de gerente a um tipo UUID. Quando uma chamada de procedimento remoto chega com seu objeto UUID, a biblioteca de tempo de execução do servidor RPC mapeia o UUID do objeto para um tipo UUID. Em seguida, o aplicativo de servidor usa o tipo UUID e a interface UUID para selecionar o EPV do gerenciador.

Você também pode especificar sua própria função para resolve o mapeamento do UUID do objeto para o UUID do tipo de gerente. Especifique a função de mapeamento ao chamar RpcObjectSetInqFn.

Para oferecer várias implementações de uma interface, um servidor deve registrar cada implementação chamando RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 separadamente. Para cada implementação que um servidor registra, ele fornece o mesmo parâmetro IfSpec , mas um par diferente de parâmetros MgrTypeUuid e MgrEpv .

No caso de vários gerentes, use RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 da seguinte maneira:

  • EPVs do gerente

    Para oferecer várias implementações de uma interface, um servidor deve:

    Observe que o servidor também pode se registrar com o EPV do gerenciador padrão.

  • UUID do tipo gerente

    Forneça um UUID do tipo gerenciador para cada EPV da interface. O UUID de tipo nulo (ou valor nulo ) para mgrTypeUuid um parâmetro pode ser especificado para um dos EPVs do gerente. Cada UUID de tipo deve ser diferente.

Regras para invocar rotinas do gerente

A biblioteca de tempo de execução RPC envia uma chamada de procedimento remoto de entrada para um gerente que oferece a interface RPC solicitada. Quando vários gerentes são registrados para uma interface, a biblioteca de tempo de execução RPC deve selecionar um deles. Para selecionar um gerenciador, a biblioteca de tempo de execução RPC usa o objeto UUID especificado pelo identificador de associação da chamada.

A biblioteca em tempo de execução aplica as seguintes regras ao interpretar a UUID do objeto de uma chamada de procedimento remoto:

  • UUIDs de objeto Nil

    Um UUID de objeto nulo é atribuído automaticamente ao tipo nulo UUID (é inválido especificar um UUID de objeto nu na rotina RpcObjectSetType ). Portanto, uma chamada de procedimento remoto cujo identificador de associação contém um UUID de objeto nulo é enviada automaticamente para o gerenciador registrado com o tipo nulo UUID, se houver.

  • UUIDs de objeto não nulos

    Em princípio, uma chamada de procedimento remoto cujo identificador de associação contém um UUID de objeto não nulo deve ser processada por um gerenciador cujo tipo UUID corresponde ao tipo do objeto UUID. No entanto, identificar o gerenciador correto requer que o servidor tenha especificado o tipo desse objeto UUID chamando a rotina RpcObjectSetType .

    Se um servidor não chamar a rotina RpcObjectSetType para um UUID de objeto não nulo, uma chamada de procedimento remoto para esse objeto UUID irá para o GERENCIADOr EPV que atende chamadas de procedimento remoto com um UUID de objeto nulo (ou seja, o tipo nu UUID).

    Chamadas de procedimento remoto com um UUID de objeto não nulo no identificador de associação não poderão ser executadas se o servidor atribuído a esse objeto não nulo UUID um tipo UUID chamando a rotina RpcObjectSetType , mas também não registrou um EPV de gerenciador para esse tipo UUID chamando RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2.

A tabela a seguir resume as ações que a biblioteca de tempo de execução usa para selecionar a rotina do gerenciador.

UUID de objeto de chamada Tipo de conjunto de servidores para UUID de objeto? Tipo DE EPV registrado no servidor? Ação de expedição
Nil Não aplicável Sim Usa o gerenciador com o tipo nulo UUID.
Nil Não aplicável Não Erro (RPC_S_UNSUPPORTED_TYPE); rejeita a chamada de procedimento remoto.
Não nulo Sim Sim Usa o gerenciador com o mesmo tipo UUID.
Não nulo Não Ignored Usa o gerenciador com o tipo nulo UUID. Se nenhum gerente com o tipo nulo UUID, erro (RPC_S_UNSUPPORTEDTYPE); rejeita a chamada de procedimento remoto.
Não nulo Sim Não Erro (RPC_S_UNSUPPORTEDTYPE); rejeita a chamada de procedimento remoto.

 

O objeto UUID da chamada é o objeto UUID encontrado em um identificador de associação para uma chamada de procedimento remoto.

O servidor define o tipo do objeto UUID chamando RpcObjectSetType para especificar o tipo UUID para um objeto.

O servidor registra o tipo para o EPV do gerenciador chamando RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 usando o mesmo tipo UUID.

Observação

O UUID do objeto nil é sempre atribuído automaticamente ao tipo nulo UUID. É inválido especificar um UUID de objeto nulo na rotina RpcObjectSetType .

 

Expedindo uma chamada de procedimento remoto para uma rotina de gerenciador de servidores

As tabelas a seguir mostram as etapas que a biblioteca de tempo de execução do RPC executa para expedir uma chamada de procedimento remoto para uma rotina de gerenciador de servidores.

Um caso simples em que o servidor registra o EPV do gerenciador padrão é descrito nas tabelas a seguir.

Tabela do Registro de Interface

Interface UUID Tipo de gerenciador UUID Vetor de ponto de entrada
uuid1 Nil EPV padrão

 

Tabela do Registro de Objeto

UUID do objeto Tipo de objeto
Nil Nil
(Qualquer outro objeto UUID) Nil

 

Mapeando o identificador de associação para um EPV (vetor de ponto de entrada)

UUID de interface (do identificador de associação do cliente) UUID de objeto (do identificador de associação do cliente) Tipo de objeto (da tabela de registro de objeto) EPV do gerenciador (da tabela de registro de interface)
uuid1 Nil Nil EPV padrão
O mesmo que o descrito acima uuidA Nil EPV padrão

 

As etapas a seguir descrevem as ações que a biblioteca de tempo de execução do servidor RPC executa, conforme mostrado nas tabelas anteriores, quando um cliente com interface UUID uuid1 a chama.

  1. O servidor chama RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 para associar uma interface que oferece ao tipo de gerenciador nulo UUID e ao EPV do gerenciador padrão gerado por MIDL. Essa chamada adiciona uma entrada na tabela de registro de interface. A interface UUID está contida no parâmetro IfSpec a.

  2. Por padrão, a tabela do registro de objeto associa todos os UUIDs de objeto ao tipo nulo UUID. Neste exemplo, o servidor não chama RpcObjectSetType.

  3. A biblioteca de tempo de execução do servidor recebe um código de procedimento remoto que contém a interface UUID à qual a chamada pertence e o UUID do objeto do identificador de associação da chamada.

    Consulte as seguintes entradas de referência de função para ver discussões sobre como um UUID de objeto é definido em um identificador de associação:

  4. Usando a interface UUID da chamada de procedimento remoto, a biblioteca de tempo de execução do servidor localiza essa interface UUID na tabela do registro de interface.

    Se o servidor não registrou a interface usando RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2, a chamada de procedimento remoto retornará ao chamador com um código RPC_S_UNKNOWN_IF status.

  5. Usando o objeto UUID do identificador de associação, a biblioteca de tempo de execução do servidor localiza esse objeto UUID na tabela do registro de objeto. Neste exemplo, todos os UUIDs de objeto são mapeados para o tipo de objeto nulo.

  6. A biblioteca em tempo de execução do servidor localiza o tipo de gerenciador nulo na tabela de registro de interface.

  7. A combinação do UUID da interface e do tipo nulo na tabela de registro de interface é resolvida para o EPV padrão, que contém as rotinas do gerenciador de servidor a serem executadas para a interface UUID encontrada na chamada de procedimento remoto.

Suponha que o servidor ofereça várias interfaces e várias implementações de cada interface, conforme descrito nas tabelas a seguir.

Tabela do Registro de Interface

Interface UUID UUID do tipo gerenciador Vetor de ponto de entrada
uuid1 Nil epv1
uuid1 uuid3 epv4
uuid2 uuid4 epv2
uuid2 uuid7 epv3

 

Tabela do Registro de Objeto

UUID do objeto Tipo de objeto
uuidA uuid3
uuidB uuid7
uuidC uuid7
uuidD uuid3
uuidE uuid3
uuidF uuid8
Nil Nil
(Qualquer outro UUID) Nil

 

Mapeando o identificador de associação para um vetor de ponto de entrada

UUID de interface (do identificador de associação do cliente) UUID de objeto (do identificador de associação do cliente) Tipo de objeto (da tabela de registro de objeto) EPV do gerenciador (da tabela de registro de interface)
uuid1 Nil Nil epv1
uuid1 uuidA uuid3 epv4
uuid1 uuidD uuid3 epv4
uuid1 uuidE uuid3 epv4
uuid2 uuidB uuid7 epv3
uuid2 uuidC uuid7 epv3

 

As etapas a seguir descrevem as ações que a biblioteca de tempo de execução do servidor executa, conforme mostrado nas tabelas anteriores, quando um cliente com interface UUID uuid2 e uuidC UUID de objeto o chama.

  1. O servidor chama RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 para associar as interfaces oferecidas aos diferentes EPVs de gerenciador. As entradas na tabela de registro de interface refletem quatro chamadas de RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 para oferecer duas interfaces, com duas implementações (EPVs) para cada interface.

  2. O servidor chama RpcObjectSetType para estabelecer o tipo de cada objeto que ele oferece. Além da associação padrão do objeto nil a um tipo nulo, todos os outros UUIDs de objeto não encontrados explicitamente na tabela do registro de objeto também são mapeados para o tipo nulo UUID.

    Neste exemplo, o servidor chama a rotina RpcObjectSetType seis vezes.

  3. A biblioteca de tempo de execução do servidor recebe uma chamada de procedimento remoto que contém a interface UUID à qual a chamada pertence e um UUID de objeto do identificador de associação da chamada.

  4. Usando a interface UUID da chamada de procedimento remoto, a biblioteca de tempo de execução do servidor localiza a interface UUID na tabela do registro de interface.

  5. Usando o UUID do objeto uuidC do identificador de associação, a biblioteca de tempo de execução do servidor localiza o objeto UUID na tabela do registro de objeto e descobre que ele é mapeado para o tipo uuid7.

  6. Para localizar o tipo de gerenciador, a biblioteca de tempo de execução do servidor combina a interface UUID, uuid2 e o tipo uuid7 na tabela de registro de interface. Isso resolve para epv3, que contém a rotina do gerenciador de servidor a ser executada para a chamada de procedimento remoto.

As rotinas em epv2 nunca serão executadas porque o servidor não chamou a rotina RpcObjectSetType para adicionar objetos com um tipo UUID de uuid4 à tabela do registro de objeto.

Uma chamada de procedimento remoto com a interface UUID uuid2 e uuidF do objeto UUID retorna ao chamador com um código RPC_S_UNKNOWN_MGR_TYPE status porque o servidor não chamou RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 para registrar a interface com um tipo de gerenciador uuid8.

Valores de retorno

Essa função retorna um dos valores a seguir.

Valor Significado
RPC_S_OK Êxito
RPC_S_TYPE_ALREADY_REGISTERED Tipo UUID já registrado

 

Fornecendo sua própria função de investigação de objeto

Considere um servidor que gerencia milhares de objetos de muitos tipos diferentes. Sempre que o servidor fosse iniciado, o aplicativo do servidor teria que chamar a função RpcObjectSetType para cada um dos objetos, embora os clientes possam se referir a apenas alguns deles (ou levar muito tempo para se referir a eles). Esses milhares de objetos provavelmente estarão em disco, portanto, recuperar seus tipos seria demorado. Além disso, a tabela interna que está mapeando o UUID do objeto para o tipo de gerenciador UUID essencialmente duplicaria o mapeamento mantido com os próprios objetos.

Para sua conveniência, o conjunto de funções RPC inclui a função RpcObjectSetInqFn. Com essa função, você fornece sua própria função de consulta de objeto.

Por exemplo, você pode fornecer sua própria função de consulta de objeto ao mapear objetos de 100 a 199 para o tipo número 1, 200–299 para o tipo número 2 e assim por diante. A função de consulta de objeto também pode ser estendida para um sistema de arquivos distribuído, em que o aplicativo servidor não tem uma lista de todos os arquivos (UUIDs de objeto) disponíveis ou quando UUIDs de objeto nome arquivos no sistema de arquivos e você não deseja pré-carregar todos os mapeamentos entre UUIDs de objeto e UUIDs de tipo.

RpcBindingFromStringBinding

RpcBindingSetObject

RpcNsBindingExport

RpcNsBindingImportBegin

RpcNsBindingLookupBegin

RpcObjectSetType

RpcServerRegisterIf

RpcServerRegisterIf2

RpcServerRegisterIfEx

RpcServerUnregisterIf

RpcServerUnregisterIfEx