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
- Vecteurs de point d’entrée
- VPE de gestionnaire
- Inscription d’une implémentation unique d’une interface
- Inscription de plusieurs implémentations d’une interface
- Règles pour appeler les routines du gestionnaire
- Distribution d’un appel de procédure distante à une routine Server-Manager
- Fourniture de votre propre fonction de Object-Inquiry
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 :
- Créez un EPV de gestionnaire non null pour chaque implémentation supplémentaire.
- Spécifiez une valeur non null pour le paramètre MgrEpv a dans RpcServerRegisterIf, RpcServerRegisterIfEx ou RpcServerRegisterIf2.
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.
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 .
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.
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 :
À 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.
À 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.
La bibliothèque d’exécution du serveur localise le type de gestionnaire nil dans la table du Registre d’interface.
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.
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.
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.
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.
À 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.
À 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.
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.
Rubriques connexes