Création et ouverture de fichiers

La fonction CreateFile permet de créer un fichier ou d'ouvrir un fichier existant. Vous devez indiquer le nom de fichier, les instructions de création et d’autres attributs. Lorsqu’une application crée un fichier, le système d’exploitation l’ajoute au répertoire indiqué.

Le système d’exploitation attribue un identificateur unique, appelé handle, à chaque fichier ouvert ou créé à l’aide de CreateFile. Une application peut utiliser ce handle avec des fonctions qui lisent, décrivent le fichier et écrivent sur celui-ci. Il est valide jusqu’à ce que toutes les références à ce handle soient fermées. Lorsqu’une application démarre, elle hérite de tous les handles ouverts du processus qui l’a démarré, à conditions que les handles ont été créés comme pouvant être hérités.

Une application doit vérifier la valeur du handle renvoyé par CreateFile avant de tenter d’utiliser le handle pour accéder au fichier. Si une erreur se produit, la valeur du handle est INVALID_HANDLE_VALUE et l'application peut utiliser la fonction GetLastError pour en savoir plus.

Lorsqu'une application utilise CreateFile, elle doit utiliser dwDesiredAccess pour indiquer si elle a l’intention d'y accéder en lecture, en écriture, les deux ou aucun des deux. Cela correspond à une demande de mode d'accès. L’application doit également utiliser le paramètre dwCreationDisposition pour indiquer l'action à entreprendre si le fichier existe déjà. C'est ce qu'on appelle la création de disposition. Par exemple, une application peut appeler CreateFile avec dwCreationDisposition défini sur CREATE_ALWAYS pour toujours créer un fichier, même si un fichier du même nom existe déjà. Cela écrasera le fichier existant. L'aboutissement de cette opération dépend de facteurs tels que les attributs et les paramètres de sécurité du fichier précédent (consultez les sections suivantes pour en savoir plus).

Les applications utilisent également CreateFile pour indiquer si elles souhaitent partager le fichier en lecture, en écriture, les deux ou aucun des deux. Il s’agit du mode de partage. Un fichier ouvert qui n’est pas partagé (dwShareMode défini sur zéro) ne peut pas être rouvert, que ce soit par l’application qui l’a ouverte ou par une autre application, tant que son handle n’a pas été fermé. On appelle cela un accès exclusif.

Lorsqu’un processus utilise CreateFile pour tenter d’ouvrir un fichier qui a déjà été ouvert en mode de partage (dwShareMode défini sur une valeur valide non nulle), le système compare les modes d’accès et de partage demandés à ceux spécifiés lors de l’ouverture du fichier. Si vous spécifiez un mode d’accès ou de partage qui est en conflit avec les modes spécifiés dans l’appel précédent, CreateFile échoue.

Le tableau suivant indique les combinaisons valides de deux appels à CreateFile à l'aide de différents modes d'accès et de partage (dwDesiredAccess et dwShareMode, respectivement). L'ordre dans lequel les appels CreateFile sont effectués n'a pas d'importance. Néanmoins, toutes les opérations d’E/S de fichier suivantes sur chaque handle de fichier seront toujours limitées par les modes d’accès et de partage actuels associés à ce handle particulier.

Premier appel à CreateFile Deuxièmes appels valides à CreateFile
GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ FILE_SHARE_WRITE
GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_WRITE, FILE_SHARE_READ FILE_SHARE_WRITE
GENERIC_READ, FILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE

Outre les attributs de fichier standard, vous pouvez spécifier des attributs de sécurité en incluant un pointeur vers une structure SECURITY_ATTRIBUTES en tant que quatrième paramètre de CreateFile. Toutefois, le système de fichiers sous-jacent doit prendre en charge la sécurité pour qu'elle soit efficace. Par exemple, le système de fichiers NTFS le prend en charge, mais pas les différents systèmes de fichiers FAT. Pour en savoir plus sur les attributs de sécurité, consultez Access Control.

Une application qui crée un fichier peut fournir un handle facultatif à un fichier de modèle, à partir duquel CreateFile accepte des attributs de fichier et étendus pour la création du nouveau fichier.

Scénarios CreateFile

Il existe plusieurs cas de figure de base pour lancer l’accès à un fichier à l’aide de la fonction CreateFile. Ils sont résumés ci-dessous :

  • Création d’un fichier lorsqu’un fichier portant ce nom n’existe pas déjà.
  • Création d’un fichier même si un fichier du même nom existe déjà, en effaçant ses données et en partant de zéro.
  • Ouverture d’un fichier existant uniquement s’il existe et s'il est intact.
  • Ouverture d'un fichier existant uniquement s’il existe, en le tronquant pour qu'il soit vide.
  • Ouverture d'un fichier tel quel s'il existe, création d'un fichier s'il n'existe pas.

Ces cas de figure sous-entendent une utilisation appropriée du paramètre dwCreationDisposition. Vous trouverez ci-dessous une décomposition de la façon dont ces scénarios correspondent à des valeurs pour ce paramètre et ce qu'il se passe lorsqu’ils sont utilisés.

Lorsque vous créez ou ouvrez un fichier et qu'il n'existe pas d'autre fichier portant le même nom (dwCreationDisposition défini sur CREATE_NEW, CREATE_ALWAYS, ou OPEN_ALWAYS), la fonction CreateFile procède comme suit :

  • Elle combine les attributs et indicateurs de fichier indiqués par dwFlagsAndAttributes avec FILE_ATTRIBUTE_ARCHIVE.
  • Elle définit la longueur du fichier sur zéro.
  • Elle copie les attributs étendus fournis par le fichier de modèle dans le nouveau fichier si le paramètre hTemplateFile est spécifié (cela remplace tous les indicateurs FILE_ATTRIBUTE_* spécifiés précédemment).
  • Elle définit l’indicateur d’héritage spécifié par le membre bInheritHandle et le descripteur de sécurité indiqué par le membre lpSecurityDescriptor du paramètre lpSecurityAttributes (structure SECURITY_ATTRIBUTES, s'il a été fourni.

Lors de la création d’un fichier, même si un fichier du même nom existe déjà (dwCreationDisposition défini sur CREATE_ALWAYS), la fonction CreateFile procède comme suit :

  • Elle vérifie les attributs de fichier actuels et les paramètres de sécurité pour l’accès en écriture, et échoue si cet accès est refusé.
  • Elle combine les attributs et indicateurs de fichier spécifiés par dwFlagsAndAttributes avec FILE_ATTRIBUTE_ARCHIVE et les attributs de fichier existants.
  • Elle définit la longueur du fichier sur zéro (autrement dit, toutes les données qui se trouvaient dans le fichier sont indisponibles, et le fichier est vide).
  • Elle copie les attributs étendus fournis par le fichier de modèle dans le nouveau fichier si le paramètre hTemplateFile est spécifié (cela remplace tous les indicateurs FILE_ATTRIBUTE_* spécifiés précédemment).
  • Elle définit l'indicateur d'héritage indiqué par le membre bInheritHandle du paramètre lpSecurityAttributes (structure SECURITY_ATTRIBUTES) s'il est fourni, mais ignore le membre lpSecurityDescriptor de la structure SECURITY_ATTRIBUTES.
  • Si elle aboutit (c'est-à-dire si, CreateFile renvoie un handle valide), appeler GetLastError renverra le code ERROR_ALREADY_EXISTS. Dans ce cas précis, il ne s'agit pas réellement d'une erreur si vous souhaitez créer un nouveau fichier vide à la place du fichier existant.

Lorsque vous ouvrez un fichier existant (dwCreationDisposition défini sur OPEN_EXISTING, OPEN_ALWAYS ou TRUNCATE_EXISTING), la fonction CreateFile procède comme suit :

  • Elle vérifie les attributs de fichier actuels et les paramètres de sécurité pour l’accès demandé, et échoue si cet accès est refusé.
  • Elle combine les indicateurs de fichier (FILE_FLAG_*) spécifiés par dwFlagsAndAttributes avec des attributs et existants et ignore les attributs de fichiers (FILE_ATTRIBUTE_*) specifiés par dwFlagsAndAttributes.
  • Elle définit la longueur du fichier sur zéro uniquement si dwCreationDisposition est défini sur TRUNCATE_EXISTING. Sinon, la longueur du fichier actuel est conservée et le fichier est ouvert tel quel.
  • Elle ignore le paramètre hTemplateFile.
  • Elle définit l'indicateur d'héritage indiqué par le membre bInheritHandle du paramètre lpSecurityAttributes (structure SECURITY_ATTRIBUTES) s'il est fourni, mais ignore le membre lpSecurityDescriptor de la structure SECURITY_ATTRIBUTES.

Attributs et répertoires de fichier

Les attributs de fichier font partie des métadonnées associées à un fichier ou à un répertoire. Chaque attribut a des finalités propres et des règles spécifiques sur la façon dont il peut être défini et modifié. Certains attributs s’appliquent uniquement aux fichiers et d'autres, uniquement aux répertoires. Par exemple, l’attribut FILE_ATTRIBUTE_DIRECTORY s’applique uniquement aux répertoires : le système de fichiers l'utilise pour déterminer si un objet sur disque est un répertoire. Toutefois, il ne peut pas être modifié pour un objet de système de fichiers existant.

Certains attributs de fichier peuvent être définis pour un répertoire, mais ne sont pertinents que pour les fichiers créés dans ce répertoire. Ils font office d'attributs par défaut. Par exemple, FILE_ATTRIBUTE_COMPRESSED peut être défini sur un objet annuaire, mais étant donné que l’objet lui-même ne contient pas de données réelles, il n’est pas vraiment compressé. Toutefois, les répertoires marqués avec cet attribut indiquent au système de fichiers de compresser les nouveaux fichiers ajoutés à ce répertoire. Tout attribut de fichier pouvant être défini sur un répertoire et qui sera également défini pour les nouveaux fichiers ajoutés à ce répertoire est appelé attribut hérité.

La fonction CreateFile fournit un paramètre pour définir certains attributs de fichier lors de la création d’un fichier. Généralement, ces attributs sont les plus courants pour une application à utiliser au moment de la création de fichier. Toutefois, tous les attributs de fichier possibles ne sont pas disponibles pour CreateFile. Certains attributs de fichier nécessitent l’utilisation d’autres fonctions, comme SetFileAttributes, DeviceIoControl, ou DecryptFile une fois que le fichier existe déjà. En ce qui concerne FILE_ATTRIBUTE_DIRECTORY, la fonction CreateDirectory est obligatoire lors de la création, car CreateFile ne peut pas créer de répertoires. Les autres attributs de fichier qui nécessitent une gestion spéciale sont FILE_ATTRIBUTE_REPARSE_POINT et FILE_ATTRIBUTE_SPARSE_FILE. Tous deux nécessitent DeviceIoControl. Pour en savoir plus, consultez SetFileAttributes.

Comme indiqué précédemment, l’héritage des attributs de fichier se produit lorsqu’un fichier est créé avec des attributs de fichier, lesquels sont lus à partir des attributs de répertoire où se trouve le fichier. Le tableau suivant récapitule ces attributs hérités et leur relation avec les fonctionnalités CreateFile.

État de l'attribut de répertoire Capacité de CreateFile à ignorer l'héritage pour les nouveaux fichiers
FILE_ATTRIBUTE_COMPRESSED défini.
Aucun contrôle. Utilisez DeviceIoControl pour l'effacer.
FILE_ATTRIBUTE_COMPRESSED non défini.
Aucun contrôle. Utilisez DeviceIoControl pour le définir.
FILE_ATTRIBUTE_ENCRYPTED défini.
Aucun contrôle. Utilisez DecryptFile.
FILE_ATTRIBUTE_ENCRYPTED non défini.
Peut être défini avec CreateFile.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED défini.
Aucun contrôle. Utilisez SetFileAttributes pour l'effacer.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED non défini.
Aucun contrôle. Utilisez SetFileAttributes pour le définir.

Contrôle d’accès

CreateFile

DeviceIoControl

Constantes d’attributs de fichier

Compression et décompression de fichier

Chiffrement des fichiers

Fonctions de gestion des fichiers

Handles et objets

Héritage des handles

Ouverture d’un fichier pour la lecture ou l’écriture

SetFileAttributes