Получение данных неизвестной длины
Многие функции возвращают потенциально большой объем данных в адрес, предоставленный приложением в качестве одного из параметров. Во всех этих случаях операция выполняется аналогичным, если не идентичным, образом. Параметр, указывающий на расположение возвращаемых данных, будет использовать соглашение о нотации, где pb или pv являются первыми двумя символами имени параметра. Еще один параметр будет содержать pcb в качестве первых трех символов имени параметра. Этот параметр представляет размер (в байтах) данных, которые будут возвращены в расположение pb или pv. Например, рассмотрим следующую спецификацию функции:
#include <windows.h>
BOOL WINAPI SomeFunction(
PCCRL_CONTEXT pCrlContext, // in
DWORD dwPropId, // in
BYTE *pbData, // out
DWORD *pcbData // in/out
);
В этом примере pbData — это указатель на расположение, в котором будут возвращены данные, а pcbData — это размер возвращаемых данных в байтах.
Примечание
Параметр-компаньон для параметра pcb иногда может иметь несколько другой префикс, например p или pv. Кроме того, для сопутствующих параметров, использующих сочетание префиксов pwsz и pcch, параметр pcch — это количество возвращаемых данных в символах (Юникод или ASCII, если применимо).
Если буфер, заданный параметром pbData , недостаточно велик для хранения возвращаемых данных, функция задает код ERROR_MORE_DATA (который можно увидеть, вызвав функцию GetLastError ) и сохраняет требуемый размер буфера в байтах в переменной, на которую указывает pcbData.
Если значение NULL является входным значением для pbData , а pcbData не равно NULL, ошибка не возвращается, а функция возвращает размер необходимого буфера памяти в переменной, на которую указывает pcbData. Это позволяет приложению определить размер и оптимальный способ выделения буфера для возвращаемых данных.
Примечание
Если для pbData задано значение NULL, чтобы определить размер, необходимый для того, чтобы возвращаемые данные помещались в указанный буфер, второй вызов функции, которая заполняет буфер нужными данными, может не использовать весь буфер. После второго вызова фактический размер возвращаемых данных содержится в pcbData. Используйте этот размер при обработке данных.
В следующем примере показано, как для этой цели можно реализовать входные и выходные параметры.
//-------------------------------------------------------------------
// 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);
}