Récupération des données de longueur inconnue

De nombreuses fonctions retournent une quantité potentiellement importante de données à une adresse fournie comme l’un des paramètres par l’application. Dans tous ces cas, l’opération est effectuée de manière similaire, si elle n’est pas identique. Le paramètre qui pointe vers l’emplacement des données retournées utilise la convention de notation où pb ou pv sont les deux premiers caractères du nom du paramètre. Un autre paramètre aura une carte de travail sous la forme des trois premiers caractères du nom du paramètre. Ce paramètre représente la taille, en octets, des données qui seront retournées à l’emplacement pb ou pv. Par exemple, tenez compte de la spécification de fonction suivante :

#include <windows.h>

BOOL WINAPI SomeFunction(
  PCCRL_CONTEXT pCrlContext,  // in
  DWORD dwPropId,             // in
  BYTE *pbData,               // out
  DWORD *pcbData              // in/out
);

Dans cet exemple, pbData est un pointeur vers l’emplacement où les données seront retournées, et la taille, en octets, des données retournées est la taille, en octets, des données retournées.

Notes

Le paramètre complémentaire au paramètre de pca peut parfois porter un préfixe légèrement différent, tel que p ou pv. En outre, pour les paramètres compagnons à l’aide de la combinaison de préfixes pwsz et pcch, le paramètre pcch est le nombre, en caractères (Unicode ou ASCII, le cas échéant), des données retournées.

 

Si la mémoire tampon spécifiée par le paramètre pbData n’est pas suffisamment volumineuse pour contenir les données retournées, la fonction définit le code ERROR_MORE_DATA (qui peut être vu en appelant la fonction GetLastError ) et stocke la taille de mémoire tampon requise, en octets, dans la variable pointée par le fournisseur de données.

Si NULL est une entrée pour pbData et qu’il n’est pas NULL, aucune erreur n’est retournée, et la fonction retourne la taille, en octets, de la mémoire tampon nécessaire dans la variable pointée par les données de fondata. Cela permet à une application de déterminer la taille et la meilleure façon d’allouer, une mémoire tampon pour les données retournées.

Notes

Lorsque la valeur NULL est entrée pour pbData pour déterminer la taille nécessaire pour s’assurer que les données retournées s’intègrent dans la mémoire tampon spécifiée, le deuxième appel à la fonction qui remplit la mémoire tampon avec les données souhaitées peut ne pas utiliser la mémoire tampon entière. Après le deuxième appel, la taille réelle des données retournées est contenue dans la structure de l’application. Utilisez cette taille lors du traitement des données.

 

L’exemple suivant montre comment les paramètres d’entrée et de sortie peuvent être implémentés à cet effet.

//-------------------------------------------------------------------
// Copyright (C) Microsoft.  All rights reserved.
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

void MyHandleError(char *s);

void main()
{

// Set up SomeFunction variables.
PCCRL_CONTEXT pCrlContext; // Initialized elsewhere.
DWORD dwPropId;            // Initialized elsewhere.
DWORD cbData;
BYTE  *pbData;

// Call SomeFunction to set cbData, the size of 
// the buffer needed for pbData.
if(SomeFunction(
     pCrlContext, 
     dwPropId, 
     NULL, 
     &cbData))
{
       printf("The function succeeded.\n");
}
else
{

// The function call failed. Handle the error.
       MyHandleError("Function call failed.");
}

// The call succeeded; the size for the needed buffer, in bytes, 
// now resides in cbData.

// Malloc memory for the size of the message.
if(pbData = (BYTE*)malloc(cbData))
{
   printf("Memory has been allocated.\n");
}
else
{

   // The allocation failed. Write an error message and exit.
   MyHandleError("Malloc operation failed. ");
}

// The space for the buffer has been allocated.
// Call SomeFunction to fill the buffer with the data.
if(SomeFunction(
      pCrlContext, 
      dwPropId, 
      pbData, 
      &cbData))
{
       printf("The function succeeded.\n");
}
else
{

   // The second function call failed. Handle the error.
   MyHandleError("The second call to the function failed.");
}

// The function succeeded; the data is now in the buffer
// pointed to by pbData. Note that cbData is
// updated with the actual size of the data returned. Use this size 
// to process bytes of pbData.

// When you have finished using the allocated memory, free it.
free(pbData);

} // End of main

//  This example uses the function MyHandleError, a simple error
//  handling function, to print an error message to the 
//  standard error (stderr) file and exit the program. 
//  For most applications, replace this function with one 
//  that does more extensive error reporting.
void MyHandleError(char *s)
{
    fprintf(stderr,"An error occurred in running the program.\n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr,"Error number %x.\n",GetLastError());
    fprintf(stderr,"Program terminating.\n");
    exit(1);
}