Condividi tramite


Recupero di dati di lunghezza sconosciuta

Molte funzioni restituiscono una quantità potenzialmente elevata di dati a un indirizzo fornito come uno dei parametri dell'applicazione. In tutti questi casi, l'operazione viene eseguita in modo simile, se non identico. Il parametro che punta alla posizione dei dati restituiti userà la convenzione di notazione in cui pb o pv sono i primi due caratteri del nome del parametro. Un altro parametro avrà pcb come primi tre caratteri del nome del parametro. Questo parametro rappresenta le dimensioni, in byte, dei dati che verranno restituiti alla posizione pb o pv. Si consideri ad esempio la specifica della funzione seguente:

#include <windows.h>

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

In questo esempio, pbData è un puntatore alla posizione in cui verranno restituiti i dati e pcbData è la dimensione, in byte, dei dati restituiti.

Nota

Il parametro complementare al parametro pcb può talvolta portare un prefisso leggermente diverso, ad esempio p o pv. Inoltre, per i parametri complementari che usano la combinazione di prefissi pwsz e pcch, il parametro pcch è il conteggio, in caratteri (Unicode o ASCII, come applicabile), dei dati restituiti.

 

Se il buffer specificato dal parametro pbData non è sufficientemente grande da contenere i dati restituiti, la funzione imposta il codice ERROR_MORE_DATA (che può essere visualizzato chiamando la funzione GetLastError) e archivia le dimensioni del buffer richieste, in byte, nella variabile a cui punta pcbData.

Se NULL è l'input per pbData e pcbData non è NULL, non viene restituito alcun errore e la funzione restituisce la dimensione, in byte, del buffer di memoria necessario nella variabile a cui punta pcbData. Ciò consente a un'applicazione di determinare le dimensioni e il modo migliore per allocare, un buffer per i dati restituiti.

Nota

Quando NULL è input per pbData per determinare le dimensioni necessarie per garantire che i dati restituiti si adattino al buffer specificato, la seconda chiamata alla funzione che popola il buffer con i dati desiderati potrebbe non usare l'intero buffer. Dopo la seconda chiamata, le dimensioni effettive dei dati restituiti sono contenute in pcbData. Usare queste dimensioni durante l'elaborazione dei dati.

 

Nell'esempio seguente viene illustrato come implementare i parametri di input e output a questo scopo.

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