检索未知长度的数据
许多函数可能会将大量数据返回到应用程序作为参数之一提供的地址。 在所有这些情况下,操作以类似(如果不完全相同)的方式执行。 指向返回的数据位置的参数将使用表示法约定,其中 pb 或 pv 是参数名称的前两个字符。 另一个参数将包含作为参数名称的前三个字符。 此参数表示将返回到 pb 或 pv 位置的数据的大小(以字节为单位)。 例如,请考虑以下函数规范:
#include <windows.h>
BOOL WINAPI SomeFunction(
PCCRL_CONTEXT pCrlContext, // in
DWORD dwPropId, // in
BYTE *pbData, // out
DWORD *pcbData // in/out
);
在此示例中, pbData 是指向将返回数据的位置的指针, 而“pbData” 是返回的数据的大小(以字节为单位)。
注意
该参数的配套参数有时可能带有略有不同的前缀,例如 p 或 pv。 此外,对于使用前缀 pwsz 和 pcch 的组合的配套参数,pcch 参数是返回数据的计数(以字符为单位), (Unicode 或 ASCII(如适用) )。
如果 pbData 参数指定的缓冲区不够大,无法容纳返回的数据,该函数将设置ERROR_MORE_DATA代码 (可通过调用 getLastError 函数) 来查看,并将所需的缓冲区大小(以字节为单位)存储在 由bmbData指向的变量中。
如果为 pbData 输入 NULL,而 pbData 不为 NULL,则不返回任何错误,并且该函数返回由bmbData指向的变量中所需内存缓冲区的大小(以字节为单位)。 这样,应用程序就可以确定为返回的数据分配缓冲区的大小和最佳方式。
注意
当为 pbData 输入 NULL 以确定确保返回的数据适合指定缓冲区所需的大小时,对使用所需数据填充缓冲区的函数的第二次调用可能不会使用整个缓冲区。 第二次调用后,返回的数据的实际大小包含在 “bdata”中。 处理数据时使用此大小。
下面的示例演示如何为此实现输入和输出参数。
//-------------------------------------------------------------------
// 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);
}