Handles et objets

AttentionArticle en cours de rédaction.

Introduction

Il y a essentiellement 3 catégories d'objets :
Les premiers supportent plusieurs handles et les autres n'en supportent qu'un seul.
Les handles de ces derniers ne peuvent donc pas être hérités ou dupliqués.
Les handles sur des objets utilisateurs sont utilisables par tous les processus.
Les handles sur des objets GDI ne sont utilisables que par le processus qui les a créés.
Lors de la création d'un objet, un handle sur celui-ci est aussi créé. Celui-ci sera valide tant que l'objet existera. Dès que l'objet est détruit, le handle devient invalide.
Les handles sur des objets du noyau sont spécifiques à un processus. Pour obtenir un handle, un processus doit soit créer un nouvel objet, soit ouvrir un objet existant (créé par un autre processus). Pour se faire, un processus doit connaître le nom de cet objet et y avoir accès.

Pour contrôler l'accès aux ressources système, Windows utilise des objets qu'il met à disposition des applications via des handle. Les objets sont gérés en interne par Windows et sont inaccessibles aux programmes. Pour permettre à un programme d'accéder et de modifier un objet, Windows attribue à chaque objet un identifiant unique qui sera utilisé par le programme pour désigner l'objet à modifier. Cet identifiant s'appelle un handle (poignée en anglais). Pour accéder à un objet, un programme est obligé de passer par les fonctions de l'API Win32 en spécifiant l'objet à l'aide du handle. Les fonctions de l'API se débrouillent alors pour retrouver l'objet en question et le modifier, si la modification demandée est valide. En retournant un handle sur l'objet au lieu de retourner son adresse, les programmes sont ainsi obligés de passer par Windows pour modifier l'objet.
Il y a deux avantages à procéder ainsi :
- le premier est évident : la sécurité. Windows s'assure ainsi de la validité des objets et des modifications qui leur sont apportées.
- la seconde est moins évidente : une encapsulation synonyme d'évolutivité et de compatibilité. En effet, les programmes n'ont aucune idée de la structure interne de l'objet. Si l'accès direct à l'objet via un pointeur était permis, certains programmes, dans le but d'être plus performant, accèderaient directement à ces objets à l'aide de leurs propres routines de bas niveau. En évitant cela, Microsoft peut du jour au lendemain modifier totalement la structure interne d'un objet (pour par exemple le rendre plus performant, le rendre compatible avec une innovation technique, ...). Ainsi, même si plusieurs versions de Windows gèrent de manière totalement différente un même objet, les programmes n'ont pas à s'en soucier et fonctionneront sans problème quelque soit la version.

Il faut bien distinguer un objet de son handle. Un handle désigne un objet unique, mais certains objets peuvent avoir plusieurs handle. Ainsi, ce n'est pas parce qu'un handle devient invalide que l'objet est détruit. De même, ce n'est pas parce que l'on crée un handle que l'objet désigné vient d'être créé. On peut en effet obtenir un handle sur un objet existant.
Pour chaque objet, il existe donc 4 fonctions :
- créer l'objet
- créer un handle sur l'objet
- fermer un handle de cet objet
- détruire l'objet

Le terme de fermer un handle permet de bien faire ressurgir qu'il ne s'agit que d'un lien qui peut être rompu.
La fermeture d'un handle n'entraîne donc pas forcément la destruction d'un objet. Ce ne sera le cas que si le dernier handle de l'objet est fermé. En revanche, la destruction d'un objet invalide tous ses handles.
La création d'un handle peut être effectuée :
- de manière directe avec DuplicateHandle par exemple
- de manière indirecte en créant un objet et en recevant son handle en retour (CreateWindow, CreateFont, ...)

De même, la fermeture d'un handle peut se faire :
- de manière directe via CloseHandle
- indirectement en détruisant l'objet désigné par le handle. Le handle devient alors invalide.

Quand un processus se termine, Windows ferme automatiquement tous les handles et détruit tous les objets créés.
Quand un thread se termine, seuls certains objets créés par ce thread sont détruits (window, hook, window position, et objets DDE).

Bien que la destruction des objets et fermeture des handles soit faîte automatiquement par Windows lorsque le programme se termine, il convient de le faire dès qu'un objet ou handle n'est plus utilisé car ceux-ci consomment de la mémoire.

Les objets sont divisés en 3 catégories : utilisateurs, GDI, noyaux.
Les objets utilisateurs sont utilisés pour la gestion des fenêtres, les objets GDI gèrent le graphisme, et les objets noyaux gèrent la mémoire, les processus, et la communication inter-process (IPC).
Chaque objet possède sa propre liste de contrôles d'accès (ACL : Access-Control List) qui décrit les actions qu'il est possible d'effectuer sur celui-ci. Lorsqu'un processus désire un handle sur cet objet, Windows examine cette liste .
Un handle (poignée en anglais) est en fait un identifiant (numéro unique) attribué à un objet géré par Windows. L'objet en question peut être une fenêtre, un fichier, une image, une police, ...
Un handle permet donc de désigner un objet, mais contrairement à un pointeur le programmeur n'a pas la possibilité de modifier directement l'objet. Il doit pour cela passer par les fonctions de Windows qui à partir de cet handle vont retrouver l'objet et le modifier, après avoir vérifié que la modification demandée est valide.
C'est donc un excellent moyen pour s'assurer de la validité des objets manipulés par un programme.

Pour plus d'informations, référez-vous à l'article About Handles and Objects.
A suivre ...


Sommaire