Fonction FormatMessage (winbase.h)

Formate une chaîne de message. La fonction nécessite une définition de message en tant qu’entrée. La définition du message peut provenir d’une mémoire tampon passée dans la fonction. Il peut provenir d’une ressource de table de messages dans un module déjà chargé. Ou l’appelant peut demander à la fonction de rechercher la définition du message dans les ressources de la table de messages du système. La fonction recherche la définition du message dans une ressource de table de messages en fonction d’un identificateur de message et d’un identificateur de langue. La fonction copie le texte du message mis en forme dans une mémoire tampon de sortie, en traitant les séquences d’insertion incorporées si nécessaire.

Syntaxe

DWORD FormatMessage(
  [in]           DWORD   dwFlags,
  [in, optional] LPCVOID lpSource,
  [in]           DWORD   dwMessageId,
  [in]           DWORD   dwLanguageId,
  [out]          LPTSTR  lpBuffer,
  [in]           DWORD   nSize,
  [in, optional] va_list *Arguments
);

Paramètres

[in] dwFlags

Options de mise en forme et comment interpréter le paramètre lpSource . L’octet de faible ordre de dwFlags spécifie la façon dont la fonction gère les sauts de ligne dans la mémoire tampon de sortie. L’octet de faible ordre peut également spécifier la largeur maximale d’une ligne de sortie mise en forme.

Ce paramètre peut prendre une ou plusieurs des valeurs suivantes.

Valeur Signification
FORMAT_MESSAGE_ALLOCATE_BUFFER
0x00000100
La fonction alloue une mémoire tampon suffisamment grande pour contenir le message mis en forme et place un pointeur vers la mémoire tampon allouée à l’adresse spécifiée par lpBuffer. Le paramètre lpBuffer est un pointeur vers un LPTSTR ; vous devez caster le pointeur vers un LPTSTR (par exemple, (LPTSTR)&lpBuffer). Le paramètre nSize spécifie le nombre minimal de TCHAR à allouer pour une mémoire tampon de message de sortie. L’appelant doit utiliser la fonction LocalFree pour libérer la mémoire tampon quand elle n’est plus nécessaire.

Si la longueur du message mis en forme dépasse 128 000 octets, FormatMessage échoue et un appel suivant à GetLastError retourne ERROR_MORE_DATA.

Dans les versions précédentes de Windows, cette valeur n’était pas disponible pour être utilisée lors de la compilation d’applications du Windows Store. À partir de Windows 10 cette valeur peut être utilisée.

Windows Server 2003 et Windows XP :

Si la longueur du message mis en forme dépasse 128 000 octets, FormatMessage n’échoue pas automatiquement avec une erreur de ERROR_MORE_DATA.

FORMAT_MESSAGE_ARGUMENT_ARRAY
0x00002000
Le paramètre Arguments n’est pas une structure va_list , mais un pointeur vers un tableau de valeurs qui représentent les arguments.

Cet indicateur ne peut pas être utilisé avec des valeurs entières 64 bits. Si vous utilisez un entier 64 bits, vous devez utiliser la structure va_list .

FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Le paramètre lpSource est un handle de module contenant la ou les ressources de table de message à rechercher. Si ce handle lpSource a la valeur NULL, le fichier image de l’application du processus actuel est recherché. Cet indicateur ne peut pas être utilisé avec FORMAT_MESSAGE_FROM_STRING.

Si le module n’a pas de ressource de table de messages, la fonction échoue avec ERROR_RESOURCE_TYPE_NOT_FOUND.

FORMAT_MESSAGE_FROM_STRING
0x00000400
Le paramètre lpSource est un pointeur vers une chaîne terminée par null qui contient une définition de message. La définition de message peut contenir des séquences d’insertion, tout comme le texte du message dans une ressource de table de messages. Cet indicateur ne peut pas être utilisé avec FORMAT_MESSAGE_FROM_HMODULE ou FORMAT_MESSAGE_FROM_SYSTEM.
FORMAT_MESSAGE_FROM_SYSTEM
0x00001000
La fonction doit rechercher le message demandé dans les ressources de table de message système. Si cet indicateur est spécifié avec FORMAT_MESSAGE_FROM_HMODULE, la fonction recherche la table des messages système si le message est introuvable dans le module spécifié par lpSource. Cet indicateur ne peut pas être utilisé avec FORMAT_MESSAGE_FROM_STRING.

Si cet indicateur est spécifié, une application peut transmettre le résultat de la fonction GetLastError pour récupérer le texte du message pour une erreur définie par le système.

FORMAT_MESSAGE_IGNORE_INSERTS
0x00000200
Les séquences d’insertion dans la définition du message, telles que %1, doivent être ignorées et transmises à la mémoire tampon de sortie sans modification. Cet indicateur est utile pour extraire un message en vue d’une mise en forme ultérieure. Si cet indicateur est défini, le paramètre Arguments est ignoré.
 

L’octet d’ordre inférieur de dwFlags peut spécifier la largeur maximale d’une ligne de sortie mise en forme. Voici les valeurs possibles de l’octet de bas ordre.

Valeur Signification
0
Il n’existe aucune restriction de largeur de ligne de sortie. La fonction stocke les sauts de ligne qui se trouvent dans le texte de définition du message dans la mémoire tampon de sortie.
FORMAT_MESSAGE_MAX_WIDTH_MASK
0x000000FF
La fonction ignore les sauts de ligne régulière dans le texte de définition du message. La fonction stocke les sauts de ligne codés en dur dans le texte de définition du message dans la mémoire tampon de sortie. La fonction ne génère aucun nouveau saut de ligne.
 

Si l’octet de faible ordre est une valeur différente de zéro autre que FORMAT_MESSAGE_MAX_WIDTH_MASK, il spécifie le nombre maximal de caractères dans une ligne de sortie. La fonction ignore les sauts de ligne régulière dans le texte de définition du message. La fonction ne fractionne jamais une chaîne délimitée par des espaces blancs sur un saut de ligne. La fonction stocke les sauts de ligne codés en dur dans le texte de définition du message dans la mémoire tampon de sortie. Les sauts de ligne codés en dur sont codés avec la séquence d’échappement %n.

[in, optional] lpSource

Emplacement de la définition du message. Le type de ce paramètre dépend des paramètres du paramètre dwFlags .

dwFlags Réglage Signification
FORMAT_MESSAGE_FROM_HMODULE
0x00000800
Handle du module qui contient la table des messages à rechercher.
FORMAT_MESSAGE_FROM_STRING
0x00000400
Pointeur vers une chaîne qui se compose d’un texte de message non mis en forme. Il sera analysé pour les insertions et mis en forme en conséquence.
 

Si aucun de ces indicateurs n’est défini dans dwFlags, lpSource est ignoré.

[in] dwMessageId

Identificateur du message demandé. Ce paramètre est ignoré si dwFlags inclut FORMAT_MESSAGE_FROM_STRING.

[in] dwLanguageId

Identificateur de langue pour le message demandé. Ce paramètre est ignoré si dwFlags inclut FORMAT_MESSAGE_FROM_STRING.

Si vous passez un LANGID spécifique dans ce paramètre, FormatMessage retourne un message pour ce LANGID uniquement. Si la fonction ne trouve pas de message pour ce LANGID, elle définit Last-Error sur ERROR_RESOURCE_LANG_NOT_FOUND. Si vous passez zéro, FormatMessage recherche un message pour les LANGIDs dans l’ordre suivant :

  1. Langue neutre
  2. LANGID de thread, en fonction de la valeur des paramètres régionaux du thread
  3. LANGID par défaut de l’utilisateur, en fonction de la valeur des paramètres régionaux par défaut de l’utilisateur
  4. LANGID par défaut du système, en fonction de la valeur des paramètres régionaux par défaut du système
  5. Français
Si FormatMessage ne recherche pas de message pour l’un des LANGID précédents, il retourne toute chaîne de message de langue présente. Si cela échoue, il retourne ERROR_RESOURCE_LANG_NOT_FOUND.

[out] lpBuffer

Pointeur vers une mémoire tampon qui reçoit la chaîne terminée par null qui spécifie le message mis en forme. Si dwFlags inclut FORMAT_MESSAGE_ALLOCATE_BUFFER, la fonction alloue une mémoire tampon à l’aide de la fonction LocalAlloc et place le pointeur vers la mémoire tampon à l’adresse spécifiée dans lpBuffer.

Cette mémoire tampon ne peut pas dépasser 64 000 octets.

[in] nSize

Si l’indicateur FORMAT_MESSAGE_ALLOCATE_BUFFER n’est pas défini, ce paramètre spécifie la taille de la mémoire tampon de sortie, en TCHAR. Si FORMAT_MESSAGE_ALLOCATE_BUFFER est défini, ce paramètre spécifie le nombre minimal de TCHAR à allouer à une mémoire tampon de sortie.

La mémoire tampon de sortie ne peut pas dépasser 64 000 octets.

[in, optional] Arguments

Tableau de valeurs utilisées comme valeurs d’insertion dans le message mis en forme. Un %1 dans la chaîne de format indique la première valeur du tableau Arguments ; un %2 indique le deuxième argument ; et ainsi de suite.

L’interprétation de chaque valeur dépend des informations de mise en forme associées à l’insertion dans la définition de message. La valeur par défaut consiste à traiter chaque valeur comme un pointeur vers une chaîne terminée par null.

Par défaut, le paramètre Arguments est de type va_list*, qui est un type de données spécifique au langage et à l’implémentation pour décrire un nombre variable d’arguments. L’état de l’argument va_list n’est pas défini lors du retour de la fonction . Pour réutiliser le va_list , détruisez le pointeur de la liste d’arguments de variables à l’aide de va_end et réinitialisez-le avec va_start.

Si vous n’avez pas de pointeur de type va_list*, spécifiez l’indicateur FORMAT_MESSAGE_ARGUMENT_ARRAY et passez un pointeur à un tableau de valeurs DWORD_PTR ; ces valeurs sont entrées dans le message mis en forme en tant que valeurs d’insertion. Chaque insertion doit avoir un élément correspondant dans le tableau.

Valeur retournée

Si la fonction réussit, la valeur de retour est le nombre de TCHAR stockés dans la mémoire tampon de sortie, à l’exclusion du caractère null de fin.

Si la fonction échoue, la valeur de retour est égale à zéro. Pour obtenir des informations détaillées sur l’erreur, appelez GetLastError.

Remarques

Dans le texte du message, plusieurs séquences d’échappement sont prises en charge pour la mise en forme dynamique du message. Ces séquences d’échappement et leurs significations sont présentées dans les tableaux suivants. Toutes les séquences d’échappement commencent par le caractère de pourcentage (%).

Séquence d'échappement Signification
%0 Termine une ligne de texte de message sans nouveau caractère de ligne de fin. Cette séquence d’échappement peut être utilisée pour créer de longues lignes ou pour terminer le message lui-même sans nouveau caractère de ligne de fin. Il est utile pour les messages d’invite.
%n ! chaîne de format ! Identifie une séquence d’insertion. La valeur de n peut être comprise entre 1 et 99. La chaîne de format (qui doit être entourée de points d’exclamation) est facultative et la valeur par défaut est !s ! si l’option n’est pas spécifiée. Pour plus d’informations, consultez Champs de spécification de format.

La chaîne de format peut inclure un spécificateur de largeur et de précision pour les chaînes et un spécificateur de largeur pour les entiers. Utilisez un astérisque () pour spécifier la largeur et la précision. Par exemple, %1 !. *s ! ou %1 !*u !.

Si vous n’utilisez pas les spécificateurs de largeur et de précision, les nombres d’insertion correspondent directement aux arguments d’entrée. Par exemple, si la chaîne source est « %1 %2 %1 » et que les arguments d’entrée sont « Bill » et « Bob », la chaîne de sortie mise en forme est « Bill Bob Bill ».

Toutefois, si vous utilisez un spécificateur de largeur et de précision, les nombres d’insertion ne correspondent pas directement aux arguments d’entrée. Par exemple, les numéros d’insertion de l’exemple précédent peuvent passer à « %1 !*.*s ! %4 %5 !*s ! ».

Les nombres d’insertion varient selon que vous utilisez un tableau d’arguments (FORMAT_MESSAGE_ARGUMENT_ARRAY) ou un va_list. Pour un tableau d’arguments, le numéro d’insertion suivant est n+2 si la chaîne de format précédente contenait un astérisque et est n+3 si deux astérisques ont été spécifiés. Pour une va_list, le numéro d’insertion suivant est n+1 si la chaîne de format précédente contenait un astérisque et est n+2 si deux astérisques ont été spécifiés.

Si vous souhaitez répéter « Bill », comme dans l’exemple précédent, les arguments doivent inclure « Bill » deux fois. Par exemple, si la chaîne source est « %1 !*.*s ! %4 %5 !*s ! », les arguments peuvent être, 4, 2, Bill, Bob, 6, Bill (si vous utilisez l’indicateur FORMAT_MESSAGE_ARGUMENT_ARRAY ). La chaîne mise en forme serait alors « Bi Bob Bill ».

La répétition de nombres d’insertion lorsque la chaîne source contient des spécificateurs de largeur et de précision peut ne pas produire les résultats prévus. Si vous avez remplacé %5 par %1, la fonction essaie d’imprimer une chaîne à l’adresse 6 (ce qui entraîne probablement une violation d’accès).

Les spécificateurs de format à virgule flottante (e, E, f et g) ne sont pas pris en charge. La solution de contournement consiste à utiliser la fonction StringCchPrintf pour mettre en forme le nombre à virgule flottante dans une mémoire tampon temporaire, puis à utiliser cette mémoire tampon comme chaîne d’insertion.

Les insertions qui utilisent le préfixe I64 sont traitées comme deux arguments 32 bits. Ils doivent être utilisés avant l’utilisation des arguments suivants. Notez qu’il peut être plus facile pour vous d’utiliser StringCchPrintf au lieu de ce préfixe.

 

Tout autre caractère non dédigit suivant un caractère de pourcentage est mis en forme dans le message de sortie sans le caractère de pourcentage. Voici quelques exemples.

Chaîne de format Sortie résultante
%% Un signe de pourcentage unique.
%B Un espace unique. Cette chaîne de format peut être utilisée pour garantir le nombre approprié d’espaces de fin dans une ligne de texte de message.
%. Un point unique. Cette chaîne de format peut être utilisée pour inclure un point unique au début d’une ligne sans terminer la définition du texte du message.
%! Point d’exclamation unique. Cette chaîne de format peut être utilisée pour inclure un point d’exclamation immédiatement après une insertion sans qu’il soit confondu avec le début d’une chaîne de format.
%n Saut de ligne lorsque la chaîne de format se produit à la fin d’une ligne. Cette chaîne de format est utile lorsque FormatMessage fournit des sauts de ligne réguliers afin que le message s’adapte à une certaine largeur.
%r Retour chariot dur sans caractère de nouvelle ligne de fin.
%t Un seul onglet.
 

Remarques sur la sécurité

Si cette fonction est appelée sans FORMAT_MESSAGE_IGNORE_INSERTS, le paramètre Arguments doit contenir suffisamment de paramètres pour satisfaire toutes les séquences d’insertion dans la chaîne de message, et ils doivent être du type correct. Par conséquent, n’utilisez pas de chaînes de message non approuvées ou inconnues avec des insertions activées, car elles peuvent contenir plus de séquences d’insertion que celles d’Arguments , ou celles qui peuvent être du type incorrect. En particulier, il est dangereux de prendre un code d’erreur système arbitraire retourné à partir d’une API et d’utiliser FORMAT_MESSAGE_FROM_SYSTEM sans FORMAT_MESSAGE_IGNORE_INSERTS.

Exemples

La fonction FormatMessage peut être utilisée pour obtenir des chaînes de message d’erreur pour les codes d’erreur système retournés par GetLastError. Pour obtenir un exemple, consultez Récupération du code Last-Error.

L’exemple suivant montre comment utiliser un tableau d’arguments et les spécificateurs de largeur et de précision.
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

void main(void)
{
    LPWSTR pMessage = L"%1!*.*s! %4 %5!*s!";
    DWORD_PTR pArgs[] = { (DWORD_PTR)4, (DWORD_PTR)2, (DWORD_PTR)L"Bill",  // %1!*.*s! refers back to the first insertion string in pMessage
         (DWORD_PTR)L"Bob",                                                // %4 refers back to the second insertion string in pMessage
         (DWORD_PTR)6, (DWORD_PTR)L"Bill" };                               // %5!*s! refers back to the third insertion string in pMessage
    const DWORD size = 100+1;
    WCHAR buffer[size];


    if (!FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                       pMessage, 
                       0,
                       0,
                       buffer, 
                       size, 
                       (va_list*)pArgs))
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
        return;
    }

    // Buffer contains "  Bi Bob   Bill".
    wprintf(L"Formatted message: %s\n", buffer);
}


L’exemple suivant montre comment implémenter l’exemple précédent à l’aide de va_list.

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <stdio.h>

LPWSTR GetFormattedMessage(LPWSTR pMessage, ...);

void main(void)
{
    LPWSTR pBuffer = NULL;
    LPWSTR pMessage = L"%1!*.*s! %3 %4!*s!";

    // The variable length arguments correspond directly to the format
    // strings in pMessage.
    pBuffer = GetFormattedMessage(pMessage, 4, 2, L"Bill", L"Bob", 6, L"Bill");
    if (pBuffer)
    {
        // Buffer contains "  Bi Bob   Bill".
        wprintf(L"Formatted message: %s\n", pBuffer);
        LocalFree(pBuffer);
    }
    else
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
    }
}

// Formats a message string using the specified message and variable
// list of arguments.
LPWSTR GetFormattedMessage(LPWSTR pMessage, ...)
{
    LPWSTR pBuffer = NULL;

    va_list args = NULL;
    va_start(args, pMessage);

    FormatMessage(FORMAT_MESSAGE_FROM_STRING |
                  FORMAT_MESSAGE_ALLOCATE_BUFFER,
                  pMessage, 
                  0,
                  0,
                  (LPWSTR)&pBuffer, 
                  0, 
                  &args);

    va_end(args);

    return pBuffer;
}

Configuration requise

Condition requise Valeur
Client minimal pris en charge Windows XP [applications de bureau | applications UWP]
Serveur minimal pris en charge Windows Server 2003 [applications de bureau | applications UWP]
Plateforme cible Windows
En-tête winbase.h (inclure Windows.h)
Bibliothèque Kernel32.lib
DLL Kernel32.dll

Voir aussi

Fonctions de gestion des erreurs

Compilateur de messages

Tables de messages