Inscription d’interfaces

Cette section présente une présentation détaillée du processus d’inscription d’une interface RPC.

Les informations de cette section sont présentées dans les rubriques suivantes :

Fonctions d’inscription d’interface

Les serveurs inscrivent leurs interfaces en appelant la fonction RpcServerRegisterIf . Les programmes serveur complexes prennent souvent en charge plusieurs interfaces. Les applications serveur doivent appeler cette fonction une fois pour chaque interface qu’elles prennent en charge.

En outre, les serveurs peuvent prendre en charge plusieurs versions de la même interface, chacune avec sa propre implémentation des fonctions de l’interface. Si votre programme serveur effectue cette opération, il doit fournir un ensemble de points d’entrée. Un point d’entrée est une routine de gestionnaire qui distribue les appels pour une version d’une interface. Il doit y avoir un point d’entrée pour chaque version de l’interface. Le groupe de points d’entrée est appelé vecteur de point d’entrée. Pour plus d’informations, consultez Vecteurs de point d’entrée.

En plus de la fonction standard RpcServerRegisterIf, RPC prend également en charge d’autres fonctions d’inscription d’interface. La fonction RpcServerRegisterIf2 étend les fonctionnalités de RpcServerRegisterIf en vous permettant de spécifier un ensemble d’indicateurs d’inscription (voir Indicateurs d’inscription d’interface), le nombre maximal de demandes d’appel de procédure distante simultanées que le serveur peut accepter et la taille maximale en octets des blocs de données entrants.

La bibliothèque RPC contient également une fonction appelée RpcServerRegisterIfEx. Comme la fonction RpcServerRegisterIf , cette fonction inscrit une interface. Votre programme serveur peut également utiliser cette fonction pour spécifier un ensemble d’indicateurs d’inscription (voir Indicateurs d’inscription d’interface), le nombre maximal de demandes d’appel de procédure distante simultanées que le serveur peut accepter et une fonction de rappel de sécurité.

Les fonctions RpcServerRegisterIf, RpcServerRegisterIfEx et RpcServerRegisterIf2 définissent des valeurs dans la table de registre d’interface interne. Cette table est utilisée pour mapper l’UUID d’interface et les UUID d’objet à un EPV de gestionnaire. L’EPV de gestionnaire est un tableau de pointeurs de fonction qui contient exactement un pointeur de fonction pour chaque prototype de fonction dans l’interface spécifiée dans le fichier IDL.

Pour plus d’informations sur la fourniture de plusieurs VPE pour fournir plusieurs implémentations de l’interface, consultez Implémentations d’interface multiples.

La bibliothèque d’exécution utilise la table de registre d’interface (définie par les appels à la fonction RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2) et la table de Registre d’objets (définie par les appels à la fonction RpcObjectSetType) pour mapper les UUID d’interface et d’objet au pointeur de fonction.

Lorsque vous souhaitez que votre programme serveur supprime une interface du registre de la bibliothèque d’exécution RPC, appelez la fonction RpcServerUnregisterIf . Une fois l’interface supprimée du Registre, la bibliothèque d’exécution RPC n’accepte plus les nouveaux appels pour cette interface.

Vecteurs de point d’entrée

Le vecteur de point d’entrée (EPV) du gestionnaire est un tableau de pointeurs de fonction qui pointent vers les implémentations des fonctions spécifiées dans le fichier IDL. Le nombre d’éléments dans le tableau correspond au nombre de fonctions spécifiées dans le fichier IDL. RPC prend en charge plusieurs vecteurs de point d’entrée représentant plusieurs implémentations des fonctions spécifiées dans l’interface.

Le compilateur MIDL génère automatiquement un type de données EPV de gestionnaire à utiliser dans la construction d’EPV de gestionnaire. Le type de données est nommé if-name**_SERVER_EPV**, où if-name spécifie l’identificateur d’interface dans le fichier IDL.

Le compilateur MIDL crée et initialise automatiquement un EPV de gestionnaire par défaut en partant du principe qu’une routine de gestionnaire du même nom existe pour chaque procédure dans l’interface et est spécifiée dans le fichier IDL.

Lorsqu’un serveur propose plusieurs implémentations de la même interface, le serveur doit créer un EPV de gestionnaire supplémentaire pour chaque implémentation. Chaque EPV doit contenir exactement un point d’entrée (adresse d’une fonction) pour chaque procédure définie dans le fichier IDL. L’application serveur déclare et initialise une variable EPV de gestionnaire de type if-name**_SERVER_EPV** pour chaque implémentation supplémentaire de l’interface. Pour inscrire les fichiers EPV, il appelle RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 une fois pour chaque type d’objet qu’il prend en charge.

Lorsque le client effectue un appel de procédure distante au serveur, l’EPV contenant le pointeur de fonction est sélectionné en fonction de l’UUID de l’interface et du type d’objet. Le type d’objet est dérivé de l’UUID de l’objet par la fonction object-inquiry ou le mappage piloté par table contrôlé par RpcObjectSetType.

VPE de gestionnaire

Par défaut, le compilateur MIDL utilise les noms de procédure du fichier IDL d’une interface pour générer un EPV de gestionnaire, que le compilateur place directement dans le stub du serveur. Cet EPV par défaut est initialisé de manière statique à l’aide des noms de procédure déclarés dans la définition d’interface.

Pour inscrire un gestionnaire à l’aide de l’EPV par défaut, spécifiez NULL comme valeur du paramètre MgrEpv dans un appel à la fonction RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 . Si les noms de routine utilisés par un responsable correspondent à ceux de la définition d’interface, vous pouvez inscrire ce gestionnaire à l’aide de l’EPV par défaut de l’interface générée par le compilateur MIDL. Vous pouvez également inscrire un gestionnaire à l’aide d’un EPV que l’application serveur fournit.

Un serveur peut (et parfois doit) créer et inscrire un EPV de gestionnaire non null pour une interface. Pour sélectionner un EPV fourni par l’application serveur, transmettez l’adresse d’un EPV dont la valeur a été déclarée par le serveur comme valeur du paramètre MgrEpv a. Une valeur non null pour un paramètre MgrEpv remplace toujours un EPV par défaut dans le stub du serveur.

Le compilateur MIDL génère automatiquement un type de données EPV de gestionnaire (RPC_MGR_EPV) pour une application serveur à utiliser dans la construction d’EPV de gestionnaire. Un EPV de gestionnaire doit contenir exactement un point d’entrée (adresse de fonction) pour chaque procédure définie dans le fichier IDL.

Un serveur doit fournir un EPV non null dans les cas suivants :

  • Lorsque les noms des routines de gestionnaire diffèrent des noms de procédure déclarés dans la définition d’interface
  • Lorsque le serveur utilise l’EPV par défaut pour inscrire une autre implémentation de l’interface

Un serveur déclare un EPV de gestionnaire en initialisant une variable de type if-name**_SERVER_EPV** pour chaque implémentation de l’interface.

Inscription d’une implémentation unique d’une interface

Lorsqu’un serveur propose une seule implémentation d’une interface, le serveur appelle RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 une seule fois. Dans le cas standard, le serveur utilise l’EPV du gestionnaire par défaut. (L’exception est lorsque le gestionnaire utilise des noms de routine qui diffèrent de ceux déclarés dans l’interface.)

Pour le cas standard, vous fournissez les valeurs suivantes pour les appels à RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 :

  • VPE de gestionnaire

    Pour utiliser l’EPV par défaut, spécifiez une valeur null pour le paramètre MgrEpv a.

  • Type de gestionnaire UUID

    Lorsque vous utilisez l’EPV par défaut, inscrivez l’interface avec un UUID de type gestionnaire nil en fournissant une valeur Null ou un UUID nil pour le paramètre MgrTypeUuid a. Dans ce cas, tous les appels de procédure distante, quel que soit l’UUID d’objet dans leur handle de liaison, sont distribués à l’EPV par défaut, en supposant qu’aucun appel RpcObjectSetType n’a été effectué.

    Vous pouvez également fournir un UUID de type de gestionnaire non nil. Dans ce cas, vous devez également appeler la routine RpcObjectSetType .

Inscription de plusieurs implémentations d’une interface

Vous pouvez fournir plusieurs implémentations de la ou des procédures distantes spécifiées dans le fichier IDL. L’application serveur appelle RpcObjectSetType pour mapper les UUID d’objets à des UUID de type et appelle RpcServerRegisterIfIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 pour associer les EPV de gestionnaire à un type UUID. Lorsqu’un appel de procédure distante arrive avec son objet UUID, la bibliothèque d’exécution du serveur RPC mappe l’UUID d’objet à un type UUID. L’application serveur utilise ensuite le type UUID et l’UUID d’interface pour sélectionner l’EPV du gestionnaire.

Vous pouvez également spécifier votre propre fonction pour résoudre le mappage entre l’UUID d’objet et le type de gestionnaire UUID. Vous spécifiez la fonction de mappage lorsque vous appelez RpcObjectSetInqFn.

Pour proposer plusieurs implémentations d’une interface, un serveur doit inscrire chaque implémentation en appelant RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 séparément. Pour chaque implémentation qu’un serveur inscrit, il fournit le même paramètre IfSpec , mais une paire différente de paramètres MgrTypeUuid et MgrEpv .

Dans le cas de plusieurs gestionnaires, utilisez RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 comme suit :

  • VPE de gestionnaire

    Pour proposer plusieurs implémentations d’une interface, un serveur doit :

    Notez que le serveur peut également s’inscrire auprès de l’EPV du gestionnaire par défaut.

  • Type de gestionnaire UUID

    Fournissez un UUID de type de gestionnaire pour chaque EPV de l’interface. L’UUID de type nil (ou valeur null ) pour le paramètre MgrTypeUuid peut être spécifié pour l’un des EPV de gestionnaire. Chaque type UUID doit être différent.

Règles pour appeler les routines du gestionnaire

La bibliothèque d’exécution RPC distribue un appel de procédure distante entrante à un responsable qui offre l’interface RPC demandée. Lorsque plusieurs gestionnaires sont inscrits pour une interface, la bibliothèque d’exécution RPC doit en sélectionner un. Pour sélectionner un gestionnaire, la bibliothèque runtime RPC utilise l’UUID d’objet spécifié par le handle de liaison de l’appel.

La bibliothèque d’exécution applique les règles suivantes lors de l’interprétation de l’UUID d’objet d’un appel de procédure distante :

  • UUIDs d’objet Nil

    Un UUID d’objet nil se voit automatiquement attribuer le type nil UUID (il est interdit de spécifier un UUID d’objet nil dans la routine RpcObjectSetType ). Par conséquent, un appel de procédure distante dont le handle de liaison contient un UUID d’objet nil est automatiquement envoyé au gestionnaire inscrit avec l’UUID de type nil, le cas échéant.

  • UUIDs d’objet non nul

    En principe, un appel de procédure distante dont le handle de liaison contient un UUID d’objet non nul doit être traité par un gestionnaire dont le type UUID correspond au type de l’UUID de l’objet. Toutefois, pour identifier le gestionnaire approprié, le serveur doit spécifier le type de cet UUID d’objet en appelant la routine RpcObjectSetType .

    Si un serveur ne parvient pas à appeler la routine RpcObjectSetType pour un UUID d’objet non nul, un appel de procédure distante pour cet UUID d’objet est dirigé vers l’EPV du gestionnaire qui traite les appels de procédure distante avec un UUID d’objet nil (autrement dit, le type nil UUID).

    Les appels de procédure distante avec un UUID d’objet non nul dans le handle de liaison ne peuvent pas être exécutés si le serveur a attribué à cet objet non nul un UUID de type UUID en appelant la routine RpcObjectSetType , mais n’a pas également inscrit un EPV de gestionnaire pour ce type UUID en appelant RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2.

Le tableau suivant récapitule les actions que la bibliothèque d’exécution utilise pour sélectionner la routine du gestionnaire.

Objet UUID de l’appel Type d’ensemble de serveur pour l’UUID d’objet ? Type EPV inscrit au serveur ? Action de répartition
Nil Non applicable Oui Utilise le gestionnaire avec l’UUID de type nil.
Nil Non applicable Non Erreur (RPC_S_UNSUPPORTED_TYPE) ; rejette l’appel de procédure distante.
Non nul Oui Oui Utilise le gestionnaire avec le même type UUID.
Non nul Non Ignoré Utilise le gestionnaire avec l’UUID de type nil. Si aucun gestionnaire avec l’UUID de type nul, erreur (RPC_S_UNSUPPORTEDTYPE) ; rejette l’appel de procédure distante.
Non nul Oui Non Erreur (RPC_S_UNSUPPORTEDTYPE) ; rejette l’appel de procédure distante.

 

L’UUID de l’objet de l’appel est l’UUID d’objet trouvé dans un handle de liaison pour un appel de procédure distante.

Le serveur définit le type de l’UUID de l’objet en appelant RpcObjectSetType pour spécifier le type UUID pour un objet.

Le serveur inscrit le type pour l’EPV du gestionnaire en appelant RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 à l’aide du même type UUID.

Notes

L’UUID de l’objet nil se voit toujours attribuer automatiquement le type nil UUID. Il n’est pas autorisé à spécifier un UUID d’objet nil dans la routine RpcObjectSetType .

 

Distribution d’un appel de procédure distante à une routine du gestionnaire de serveur

Les tableaux suivants montrent les étapes que la bibliothèque d’exécution RPC effectue pour distribuer un appel de procédure distante à une routine de gestionnaire de serveur.

Un cas simple où le serveur inscrit l’EPV du gestionnaire par défaut est décrit dans les tableaux suivants.

Table du Registre d’interface

UUID d’interface UUID de type gestionnaire Vecteur de point d’entrée
uuid1 Nil EPV par défaut

 

Table du Registre d’objets

UUID d’objet Type d’objet
Nil Nil
(Tout autre objet UUID) Nil

 

Mappage du handle de liaison à un vecteur de point d’entrée (EPV)

UUID d’interface (à partir du handle de liaison client) UUID d’objet (à partir du handle de liaison client) Type d’objet (à partir de la table du Registre d’objets) Manager EPV (à partir de la table du Registre d’interface)
uuid1 Nil Nil EPV par défaut
Identique à ce qui précède uuidA Nil EPV par défaut

 

Les étapes suivantes décrivent les actions effectuées par la bibliothèque d’exécution du serveur RPC, comme indiqué dans les tableaux précédents, lorsqu’un client avec l’interface UUID uuid1 l’appelle.

  1. Le serveur appelle RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 pour associer une interface qu’il offre à l’UUID de type de gestionnaire nil et à l’EPV du gestionnaire par défaut généré par MIDL. Cet appel ajoute une entrée dans la table du Registre d’interface. L’UUID d’interface est contenu dans le paramètre IfSpec .

  2. Par défaut, la table du Registre d’objets associe tous les UUID d’objets au type UUID nil. Dans cet exemple, le serveur n’appelle pas RpcObjectSetType.

  3. La bibliothèque d’exécution du serveur reçoit un code de procédure distante contenant l’UUID d’interface auquel appartient l’appel et l’UUID de l’objet à partir du handle de liaison de l’appel.

    Pour plus d’informations sur la façon dont un UUID d’objet est défini dans un handle de liaison, consultez les entrées de référence de fonction suivantes :

  4. À l’aide de l’UUID d’interface de l’appel de procédure distante, la bibliothèque d’exécution du serveur localise cet UUID d’interface dans la table du Registre d’interface.

    Si le serveur n’a pas inscrit l’interface à l’aide de RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2, l’appel de procédure distante retourne à l’appelant avec un code RPC_S_UNKNOWN_IF status.

  5. À l’aide de l’UUID de l’objet du handle de liaison, la bibliothèque d’exécution du serveur localise cet UUID d’objet dans la table du Registre d’objets. Dans cet exemple, tous les UUID d’objets sont mappés au type d’objet nil.

  6. La bibliothèque d’exécution du serveur localise le type de gestionnaire nil dans la table du Registre d’interface.

  7. La combinaison de l’UUID d’interface et du type nil dans la table du Registre d’interface est résolue en EPV par défaut, qui contient les routines du gestionnaire de serveur à exécuter pour l’UUID d’interface trouvé dans l’appel de procédure distante.

Supposons que le serveur propose plusieurs interfaces et plusieurs implémentations de chaque interface, comme décrit dans les tableaux suivants.

Table du Registre d’interface

UUID d’interface UUID de type gestionnaire Vecteur de point d’entrée
uuid1 Nil epv1
uuid1 uuid3 epv4
uuid2 uuid4 epv2
uuid2 uuid7 epv3

 

Table du Registre d’objets

UUID d’objet Type d’objet
uuidA uuid3
uuidB uuid7
uuidC uuid7
uuidD uuid3
uuidE uuid3
uuidF uuid8
Nil Nil
(Tout autre UUID) Nil

 

Mappage du handle de liaison à un vecteur point d’entrée

UUID d’interface (à partir du handle de liaison client) UUID d’objet (à partir du handle de liaison client) Type d’objet (à partir de la table du Registre d’objets) Manager EPV (à partir de la table du Registre d’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

 

Les étapes suivantes décrivent les actions effectuées par la bibliothèque d’exécution du serveur, comme indiqué dans les tableaux précédents lorsqu’un client avec l’interface UUID uuid2 et l’objet UUID uuidC l’appelle.

  1. Le serveur appelle RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 pour associer les interfaces qu’il offre aux différents VPE de gestionnaire. Les entrées de la table de Registre d’interface reflètent quatre appels de RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 pour offrir deux interfaces, avec deux implémentations (APE) pour chaque interface.

  2. Le serveur appelle RpcObjectSetType pour établir le type de chaque objet qu’il propose. En plus de l’association par défaut de l’objet nil à un type nil, tous les autres UUID d’objet qui ne figurent pas explicitement dans la table du Registre d’objets sont également mappés à l’UUID de type nil.

    Dans cet exemple, le serveur appelle la routine RpcObjectSetType six fois.

  3. La bibliothèque d’exécution du serveur reçoit un appel de procédure distante contenant l’UUID d’interface auquel l’appel appartient et un UUID d’objet à partir du handle de liaison de l’appel.

  4. À l’aide de l’UUID d’interface de l’appel de procédure distante, la bibliothèque d’exécution du serveur localise l’UUID d’interface dans la table du Registre d’interface.

  5. À l’aide de l’UUID de l’objet uuidC du handle de liaison, la bibliothèque d’exécution du serveur localise l’UUID de l’objet dans la table du Registre d’objets et trouve qu’il correspond au type uuid7.

  6. Pour localiser le type de gestionnaire, la bibliothèque d’exécution du serveur combine l’interface UUID, uuid2 et le type uuid7 dans la table du Registre d’interface. Cela se résout en epv3, qui contient la routine du gestionnaire de serveur à exécuter pour l’appel de procédure distante.

Les routines dans epv2 ne seront jamais exécutées, car le serveur n’a pas appelé la routine RpcObjectSetType pour ajouter des objets de type UUID de type uuid4 à la table du Registre d’objets.

Un appel de procédure distante avec l’interface UUID uuid2 et l’objet UUID uuidF retourne à l’appelant avec un code RPC_S_UNKNOWN_MGR_TYPE status, car le serveur n’a pas appelé RpcServerRegisterIfIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2 pour inscrire l’interface avec un type de gestionnaire uuid8.

Valeurs de retour

Cette fonction retourne l’une des valeurs suivantes.

Valeur Signification
RPC_S_OK Succès
RPC_S_TYPE_ALREADY_REGISTERED Type UUID déjà inscrit

 

Fourniture de votre propre fonction d’interrogation d’objet

Considérez un serveur qui gère des milliers d’objets de nombreux types différents. Chaque fois que le serveur a démarré, l’application serveur doit appeler la fonction RpcObjectSetType pour chacun des objets, même si les clients peuvent ne faire référence qu’à quelques-uns d’entre eux (ou prendre beaucoup de temps pour y faire référence). Ces milliers d’objets étant susceptibles de se trouver sur le disque, la récupération de leurs types prend du temps. En outre, la table interne qui mappera l’UUID de l’objet au type de gestionnaire UUID dupliquerait essentiellement le mappage géré avec les objets eux-mêmes.

Pour plus de commodité, l’ensemble de fonctions RPC inclut la fonction RpcObjectSetInqFn. Avec cette fonction, vous fournissez votre propre fonction d’interrogation d’objets.

Par exemple, vous pouvez fournir votre propre fonction d’interrogation d’objets lorsque vous mappez des objets 100 à 199 au type numéro 1, 200-299 au type numéro 2, et ainsi de suite. La fonction d’interrogation d’objets peut également être étendue à un système de fichiers distribué, où l’application serveur ne dispose pas d’une liste de tous les fichiers (UUID d’objets) disponibles, ou lorsque les UUID d’objets nomment les fichiers dans le système de fichiers et que vous ne souhaitez pas précharger tous les mappages entre les UUID d’objet et les UUID de type.

RpcBindingFromStringBinding

RpcBindingSetObject

RpcNsBindingExport

RpcNsBindingImportBegin

RpcNsBindingLookupBegin

RpcObjectSetType

RpcServerRegisterIf

RpcServerRegisterIf2

RpcServerRegisterIfEx

RpcServerUnregisterIf

RpcServerUnregisterIfEx