Recuperando dados de comprimento desconhecido

Muitas funções retornam uma quantidade potencialmente grande de dados para um endereço fornecido como um dos parâmetros pelo aplicativo. Em todos esses casos, a operação é executada de forma semelhante, se não idêntica. O parâmetro que aponta para o local dos dados retornados usará a convenção de notação em que pb ou pv são os dois primeiros caracteres do nome do parâmetro. Outro parâmetro terá pcb como os três primeiros caracteres do nome do parâmetro. Esse parâmetro representa o tamanho, em bytes, dos dados que serão retornados para o local pb ou pv. Por exemplo, considere a seguinte especificação de função:

#include <windows.h>

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

Neste exemplo, pbData é um ponteiro para o local onde os dados serão retornados e pcbData é o tamanho, em bytes, dos dados retornados.

Observação

O parâmetro complementar para o parâmetro pcb pode, às vezes, carregar um prefixo ligeiramente diferente, como p ou pv. Além disso, para parâmetros complementares que usam a combinação de prefixos pwsz e pcch, o parâmetro pcch é a contagem, em caracteres (Unicode ou ASCII, conforme aplicável), dos dados retornados.

 

Se o buffer especificado pelo parâmetro pbData não for grande o suficiente para manter os dados retornados, a função definirá o código ERROR_MORE_DATA (que pode ser visto chamando a função GetLastError ) e armazenará o tamanho do buffer necessário, em bytes, na variável apontada por pcbData.

Se NULL for entrada para pbData e pcbData não for NULL, nenhum erro será retornado e a função retornará o tamanho, em bytes, do buffer de memória necessário na variável apontada por pcbData. Isso permite que um aplicativo determine o tamanho de e a melhor maneira de alocar um buffer para os dados retornados.

Observação

Quando NULL é uma entrada para pbData determinar o tamanho necessário para garantir que os dados retornados se ajustem ao buffer especificado, a segunda chamada para a função que preenche o buffer com os dados desejados pode não usar todo o buffer. Após a segunda chamada, o tamanho real dos dados retornados está contido em pcbData. Use esse tamanho ao processar os dados.

 

O exemplo a seguir mostra como os parâmetros de entrada e saída podem ser implementados para essa finalidade.

//-------------------------------------------------------------------
// 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);
}