Partager via


À propos des tables Atom

Une table atom est une table définie par le système qui stocke des chaînes et des identificateurs correspondants. Une application place une chaîne dans une table atom et reçoit un entier 16 bits, appelé atome, qui peut être utilisé pour accéder à la chaîne. Une chaîne qui a été placée dans une table atom est appelée nom d’atome.

Le système fournit un certain nombre de tables atom. Chaque table atom a un but différent. Par exemple, les applications Dynamic Data Exchange (DDE) utilisent la table atom globale pour partager des chaînes de nom d’élément et de nom de rubrique avec d’autres applications. Au lieu de passer des chaînes réelles, une application DDE transmet des atomes globaux à son application partenaire. Le partenaire utilise les atomes pour obtenir les chaînes de la table atom.

Les applications peuvent utiliser des tables atom locales pour stocker leurs propres associations de noms d’éléments.

Le système utilise des tables Atom qui ne sont pas directement accessibles aux applications. Toutefois, l’application utilise ces atomes lors de l’appel d’une variété de fonctions. Par exemple, les formats de Presse-papiers inscrits sont stockés dans une table atom interne utilisée par le système. Une application ajoute des atomes à cette table atom à l’aide de la fonction RegisterClipboardFormat . En outre, les classes inscrites sont stockées dans une table atom interne utilisée par le système. Une application ajoute des atomes à cette table atom à l’aide de la fonction RegisterClass ou RegisterClassEx .

Les rubriques suivantes sont abordées dans cette section.

Table Atom globale

La table atom globale est disponible pour toutes les applications. Lorsqu’une application place une chaîne dans la table atom globale, le système génère un atome unique dans le système. Toute application qui a l’atome peut obtenir la chaîne qu’elle identifie en interrogeant la table atom globale.

Une application qui définit un format de données DDE privé pour le partage de données avec d’autres applications doit placer le nom du format dans la table atom globale. Cette technique empêche les conflits avec les noms des formats définis par le système ou par d’autres applications, et rend les identificateurs (atomes) pour les messages ou formats disponibles pour les autres applications.

Table Atom utilisateur

Outre la table atom globale, la table atom utilisateur est une autre table atom système qui est également partagée entre tous les processus. La table atom utilisateur est utilisée pour un petit nombre de scénarios internes à win32k ; par exemple, les noms de modules Windows, les chaînes connues dans win32k, les formats OLE, etc. Bien que les applications n’interagissent pas directement avec la table atom utilisateur, elles appellent plusieurs API, telles que RegisterClass, RegisterWindowMessage et RegisterClipboardFormat, qui ajoutent des entrées à la table atom utilisateur. Les entrées ajoutées par RegisterClass peuvent être supprimées par UnregisterClass. Toutefois, les entrées ajoutées par RegisterWindowMessage et RegisterClipboardFormat ne sont pas supprimées tant que la session n’est pas terminée. Si la table atom de l’utilisateur n’a plus d’espace et que la chaîne transmise n’est pas déjà dans la table, l’appel échoue.

Taille de table Atom

De nombreuses API critiques, y compris CreateWindow, s’appuient sur des atomes d’utilisateur. Par conséquent, l’épuisement de l’espace dans la table atom de l’utilisateur entraîne des problèmes graves; par exemple, toutes les applications peuvent ne pas être lancées. Voici quelques recommandations pour vous assurer que votre application utilise efficacement les tables Atom et conserve la fiabilité et les performances de l’application et du système :

  1. Vous devez limiter l’utilisation de votre application de la table atom utilisateur. Le stockage de chaînes uniques à l’aide d’API telles que RegisterClass, RegisterWindowMessageou RegisterClipboardFormat prend de l’espace dans la table atom utilisateur, qui est utilisée globalement par d’autres applications pour inscrire des classes de fenêtre à l’aide de chaînes. Si possible, vous devez utiliser AddAtomDeleteAtom/ pour stocker des chaînes dans une table atom locale, ou GlobalAddAtomGlobalDeleteAtom/ si les atomes sont nécessaires entre processus.

  2. Si l’application provoque des problèmes de table atom utilisateur, vous pouvez examiner la cause racine en connectant le débogueur du noyau et en cassant le processus sur les appels à UserAddAtomEx (bae1 win32kbase!UserAddAtomEx /p <eprocess> "kc10;g"). user32! Recherchez sur la pile d’appels pour voir quelle API est appelée. La méthodologie est similaire à la détection des problèmes de table atom globale expliquée dans Identification des fuites de table Atom globales. Une autre façon de vider le contenu de la table atom utilisateur consiste à appeler GetClipboardFormatName sur la plage d’atomes possibles de 0xC000 à 0xFFFF. Si le nombre total d’atomes augmente régulièrement pendant l’exécution de l’application ou ne revient pas à la ligne de base lorsque l’application est fermée, il y a un problème.

Tables Atom locales

Une application peut utiliser une table atom locale pour gérer efficacement un grand nombre de chaînes utilisées uniquement dans l’application. Ces chaînes et les atomes associés sont disponibles uniquement pour l’application qui a créé la table.

Une application nécessitant la même chaîne dans un certain nombre de structures peut réduire l’utilisation de la mémoire à l’aide d’une table atom locale. Au lieu de copier la chaîne dans chaque structure, l’application peut placer la chaîne dans la table atom et inclure l’atome résultant dans les structures. De cette façon, une chaîne apparaît une seule fois en mémoire, mais peut être utilisée plusieurs fois dans l’application.

Les applications peuvent également utiliser des tables atom locales pour gagner du temps lors de la recherche d’une chaîne particulière. Pour effectuer une recherche, une application n’a besoin que de placer la chaîne de recherche dans la table atom et de comparer l’atome résultant aux atomes dans les structures pertinentes. La comparaison des atomes est généralement plus rapide que la comparaison de chaînes.

Les tables Atom sont implémentées en tant que tables de hachage. Par défaut, une table atom locale utilise 37 compartiments pour sa table de hachage. Toutefois, vous pouvez modifier le nombre de compartiments utilisés en appelant la fonction InitAtomTable . Toutefois, si l’application appelle InitAtomTable, elle doit le faire avant d’appeler d’autres fonctions de gestion atom.

Atom Types

Les applications peuvent créer deux types d’atomes : les atomes de chaîne et les atomes entiers. Les valeurs des atomes entiers et des atomes de chaîne ne se chevauchent pas. Les deux types d’atomes peuvent donc être utilisés dans le même bloc de code.

Plusieurs fonctions acceptent des chaînes ou des atomes comme paramètres. Lors du passage d’un atome à ces fonctions, une application peut utiliser la macro MAKEINTATOM pour convertir l’atome en une forme qui peut être utilisée par la fonction.

Les sections suivantes décrivent les types atom.

Atomes de chaîne

Lorsque les applications transmettent des chaînes terminées par null aux fonctions GlobalAddAtom, AddAtom, GlobalFindAtom et FindAtom , elles reçoivent des atomes de chaîne (entiers 16 bits) en retour. Les atomes de chaîne ont les propriétés suivantes :

  • Les valeurs des atomes de chaîne se trouvent dans la plage 0xC000 (MAXINTATOM) à 0xFFFF.
  • La casse n’est pas significative dans les recherches d’un nom d’atome dans une table atom. En outre, la chaîne entière doit correspondre dans une opération de recherche ; aucune correspondance de sous-chaîne n’est effectuée.
  • La chaîne associée à un atome de chaîne ne peut pas dépasser 255 octets de taille. Cette limitation s’applique à toutes les fonctions atom.
  • Un nombre de références est associé à chaque nom atom. Le nombre est incrémenté chaque fois que le nom de l’atome est ajouté à la table et décrémenté chaque fois que le nom de l’atome est supprimé de celui-ci. Cela empêche différents utilisateurs du même atome de chaîne de détruire les noms d’atomes les uns des autres. Lorsque le nombre de références d’un nom d’atome est égal à zéro, le système supprime l’atome et le nom de l’atome de la table.

Atomes entiers

Les atomes entiers diffèrent des atomes de chaîne de la manière suivante :

  • Les valeurs des atomes entiers se trouvent dans la plage 0x0001 à 0xBFFF (MAXINTATOM– 1).
  • La représentation sous forme de chaîne d’un atome entier est #ddddd, où les valeurs représentées par dddd sont des chiffres décimaux. Les zéros non significatifs sont ignorés.
  • Il n’existe aucun nombre de références ni surcharge de stockage associée à un atome entier.

Nombre de créations et d’utilisations Atom

Une application crée un atome local en appelant la fonction AddAtom ; il crée un atome global en appelant la fonction GlobalAddAtom . Les deux fonctions nécessitent un pointeur vers une chaîne. Le système recherche la table atom appropriée pour la chaîne et retourne l’atome correspondant à l’application. Dans le cas d’un atome de chaîne, si la chaîne réside déjà dans la table atom, le système incrémente le nombre de références pour la chaîne pendant ce processus.

Les appels répétés pour ajouter le même nom d’atome retournent le même atome. Si le nom de l’atome n’existe pas dans la table lorsque AddAtom est appelé, le nom de l’atome est ajouté à la table et un nouvel atome est retourné. S’il s’agit d’un atome de chaîne, son nombre de références est également défini sur un.

Une application doit appeler la fonction DeleteAtom lorsqu’elle n’a plus besoin d’utiliser un atome local ; elle doit appeler la fonction GlobalDeleteAtom lorsqu’elle n’a plus besoin d’un atome global. Dans le cas d’un atome de chaîne, l’une de ces fonctions réduit le nombre de références de l’atome correspondant par un. Lorsque le nombre de références atteint zéro, le système supprime le nom atom de la table.

Le nom atom d’un atome de chaîne reste dans la table atom globale tant que son nombre de références est supérieur à zéro, même après que l’application qui l’a placée dans la table se termine. Une table atom locale est détruite lorsque l’application associée se termine, quel que soit le nombre de références des atomes dans la table.

requêtes Atom-Table

Une application peut déterminer si une chaîne particulière se trouve déjà dans une table atom à l’aide de la fonction FindAtom ou GlobalFindAtom . Ces fonctions recherchent une table atom pour la chaîne spécifiée et, si la chaîne existe, retournent l’atome correspondant.

Une application peut utiliser la fonction GetAtomName ou GlobalGetAtomName pour récupérer une chaîne de nom atom à partir d’une table atom, à condition que l’application ait l’atome correspondant à la chaîne recherchée. Les deux fonctions copient la chaîne atom-name de l’atome spécifié dans une mémoire tampon et retournent la longueur de la chaîne qui a été copiée. GetAtomName récupère une chaîne atom-name à partir d’une table atom locale, et GlobalGetAtomName récupère une chaîne de nom atom à partir de la table atom globale.

Formats de chaîne Atom

Les fonctions AddAtom, GlobalAddAtom, FindAtom et GlobalFindAtom prennent un pointeur vers une chaîne terminée par null. Une application peut spécifier ce pointeur de l’une des manières suivantes.

Format chaîne Description
#Delalande Entier spécifié en tant que chaîne décimale. Utilisé pour créer ou rechercher un atome d’entier.
nom atom de chaîne Nom d’atome de chaîne. Utilisé pour ajouter un nom d’atome de chaîne à une table atom et recevoir un atome en retour.