不明な長さのデータの取得
多くの関数は、アプリケーションによってパラメーターの 1 つとして提供されるアドレスに大量のデータを返す可能性があります。 いずれの場合も、操作は同じではないにしても同様の方法で実行されます。 返されるデータの場所を指すパラメーターでは、pb または pv がパラメーター名の最初の 2 文字である表記規則が使用されます。 別のパラメーターには、パラメーター名の最初の 3 文字として 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 は返されるデータのサイズ (バイト単位) です。
Note
pcb パラメーターのコンパニオン パラメーターは、p や pv など、少し異なるプレフィックスを持つ場合があります。 また、プレフィックス pwsz と pcch の組み合わせを使用するコンパニオン パラメーターの場合、pcch パラメーターは、返されるデータの文字数 (必要に応じて Unicode または ASCII) です。
pbData パラメーターで指定されたバッファーが、返されたデータを保持するのに十分な大きさでない場合、関数はERROR_MORE_DATA コード (GetLastError 関数を呼び出すことで確認できます) を設定し、必要なバッファー サイズを pcbData が指す変数にバイト単位で格納します。
pbData に対して NULL が入力され、pcbData が NULL でない場合、エラーは返されず、関数は pcbData が指す変数内の必要なメモリ バッファーのサイズ (バイト単位) を返します。 これにより、アプリケーションは、返されるデータのバッファーのサイズと割り当て方法を決定できます。
Note
返されたデータが指定されたバッファーに収まるようにするために必要なサイズを決定するために pbData に NULL が入力されている場合、バッファーに目的のデータを設定する関数の 2 回目の呼び出しでバッファー全体が使用されないことがあります。 2 回目の呼び出しの後、返されるデータの実際のサイズは 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);
}