Techniques IDL pour une meilleure conception d’interface et de méthode
Envisagez d'utiliser les techniques spécifiques à IDL suivantes pour améliorer la sécurité et les performances lorsque vous développez des interfaces et des méthodes RPC qui gèrent à la fois des données conformes et variantes. Les attributs mentionnés dans cette rubrique sont les attributs IDL définis sur les paramètres de méthode qui gèrent soit des données conformes (par exemple, les attributs [size_is] et [max_is]) soit des données variantes (par exemple, les attributs [length_is] et [string] ).
Utilisation de l'attribut [range] avec des paramètres de données conformes
L'attribut [range] demande au runtime RPC d'effectuer une validation de taille supplémentaire pendant le processus de démarshalage des données. Plus précisément, il vérifie que la taille fournie des données transmises en tant que paramètre associé se situe dans la plage spécifiée.
L'attribut [range] n'affecte pas le format du fil.
Si la valeur sur le fil est en dehors de la plage autorisée, RPC lèvera une exception RPC_X_INVALID_BOUND ou RPC_X_BAD_STUB_DATA. Cela fournit un niveau supplémentaire de validation des données et peut aider à éviter les erreurs de sécurité courantes telles que les dépassements de mémoire tampon. De même, l'utilisation de [range] peut améliorer les performances de l'application, car les données conformes marquées par celui-ci ont des contraintes clairement définies disponibles pour examen par le service RPC.
Règles de gestion de la mémoire de stub du serveur RPC
Il est important de comprendre les règles de gestion de la mémoire de remplacement du serveur RPC lors de la création des fichiers IDL pour une application compatible RPC. Les applications peuvent améliorer l'utilisation des ressources du serveur en utilisant [range] conjointement avec des données conformes comme indiqué ci-dessus, ainsi qu'en évitant délibérément l'application d'attributs IDL de données de longueur variable comme [length_is] aux données conformes.
L'application de [length_is] aux champs de structure de données définis dans un fichier IDL n'est pas recommandée.
Meilleures pratiques pour les paramètres de données de longueur variable
Voici plusieurs bonnes pratiques à prendre en compte lors de la définition des attributs IDL pour les structures de données, les paramètres de méthode et les champs de taille variable.
Utilisez une corrélation précoce. Il est généralement préférable de définir le paramètre ou le champ de taille variable de telle sorte qu'il apparaisse immédiatement après le type intégral de contrôle.
Par exemple :
earlyCorr ( [in, range(MIN_COUNT, MAX_COUNT)] long size, [in,size_is(size)] char *pv );
est mieux que
lateCorr ( [in,size_is(size)] char *pv, [in, range(MIN_COUNT, MAX_COUNT)] long size) );
où earlyCorr déclare le paramètre size immédiatement avant le paramètre de données de longueur variable, et lateCorr déclare le paramètre size après celui-ci. L’utilisation d’une correspondance précoce améliore globalement les performances, en particulier dans les cas où la méthode est fréquemment appelée.
Pour les paramètres marqués avec le tuple d'attribut [out, size_is] et où la longueur des données est connue du côté client ou lorsque le client a une limite supérieure raisonnable, la définition de la méthode doit être similaire à la suivante en termes d'attribution et de séquence des paramètres. :
outKnownSize ( [in,range(MIN_COUNT, MAX_COUNT)] long lSize, [out,size_is(lSize)] UserDataType * pArr );
Dans ce cas, le client fournit un tampon de taille fixe pour pArr, permettant au service RPC côté serveur d'allouer un tampon de taille raisonnable avec un bon degré d'assurance. Notez que dans l'exemple, les données sont reçues du serveur ([out]). La définition est similaire pour les données transmises au serveur ([in]).
Pour les situations où le composant côté serveur d'une application RPC décide de la longueur des données, la définition de la méthode doit être similaire à ce qui suit :
typedef [range(MIN_COUNT,MAX_COUNT)] long RANGED_LONG; outUnknownSize ( [out] RANGED_LONG *pSize, [out,size_is(,*pSize)] UserDataType **ppArr );
RANGED_LONG est un type défini pour les stubs client et serveur, et d'une taille spécifiée que le client peut anticiper correctement. Dans l'exemple, le client transmet ppArr comme NULL et le composant d'application du serveur RPC alloue la quantité correcte de mémoire. Au retour, le service RPC côté client alloue la mémoire pour les données renvoyées.
Si le client souhaite envoyer un sous-ensemble d'un grand tableau conforme au serveur, l'application peut spécifier la taille du sous-ensemble, comme illustré dans l'exemple suivant :
inConformantVaryingArray ( [in,range(MIN_COUNT,MAX_COUNT)] long lSize, [in] long lLength, [in,size_is(lSize), length_is(lLength)] UserDataType *pArr );
De cette façon, RPC ne transmettra que les éléments lLength du tableau à travers le fil. Cependant, cette définition oblige le service RPC à allouer une mémoire de taille lSize côté serveur.
Si le composant de l'application client détermine la taille maximale d'un tableau que le serveur peut renvoyer, mais autorise le serveur à transmettre un sous-ensemble de ce tableau, l'application peut spécifier un tel comportement en définissant l'IDL similaire à l'exemple suivant :
inMaxSizeOutLength ( [in, range(MIN_COUNT, MAX_COUNT)] long lSize, [out] long *pLength, [out,size_is(lSize), length_is(*pLength)] UserDataType *pArr );
Le composant d'application client spécifie la taille maximale du tableau et le serveur spécifie le nombre d'éléments qu'il renvoie au client.
Si le composant d'application serveur doit renvoyer une chaîne au composant d'application client et si le client connaît la taille maximale à renvoyer depuis le serveur, l'application peut utiliser un type de chaîne conforme, comme illustré dans l'exemple suivant :
outStringKnownSize ( [in,range(MIN_COUNT, MAX_STRING)] long lSize, [out,size_is(lSize),string] wchar_t *pString );
Si le composant de l'application client ne doit pas contrôler la taille de la chaîne, le service RPC peut allouer spécifiquement la mémoire, comme illustré dans l'exemple suivant :
outStringUnknownSize ( [out] LPWSTR *ppStr );
Le composant d'application client doit définir ppStr sur NULL lors de l'appel de la méthode RPC.