WinInet の InternetReadFile (C++)に問題があります。
まれに、関数が失敗し、GetLastError が前述のエラー0x8007007aを返します(ErrorLookup によると、「システム コールに渡されたデータ領域が小さすぎます」に対応します)。
これに関していくつか質問があります。
- まれにこれが発生するのに、他のケースでは問題なく動作するのはなぜですか (もちろん、常に同じ ~15MB の zip ファイルをダウンロードすることについて話しているのです)。
- これは、API 呼び出しに渡されるバッファ サイズに本当に関連していますか? この呼び出しには、1024 バイトの const バッファー サイズを使用しています。より大きなバッファ サイズを使用する必要がありますか? もしそうなら、どうすれば「正しい」バッファサイズを知ることができますか?
- このエラーが発生した場合、実行時に回復するにはどうすればよいですか?
コード スニペットの追加 (いくつかの初期化コードが必要なため、これはそのままでは機能しないことに注意してください):
#define HTTP_RESPONSE_BUFFER_SIZE 1024
std::vector<char> responseBuffer;
DWORD dwResponseBytesRead = 0;
do
{
const size_t oldBufferSize = responseBuffer.size();
responseBuffer.resize(oldBufferSize + HTTP_RESPONSE_BUFFER_SIZE);
// Now we read again to the last place we stopped
// writing in the previous iteration.
dwResponseBytesRead = 0;
BOOL bInternetReadFile = ::InternetReadFile(hOpenRequest, // hFile. Retrieved from a previous call to ::HttpOpenRequest
(LPVOID)&responseBuffer[oldBufferSize], // lpBuffer.
HTTP_RESPONSE_BUFFER_SIZE, // dwNumberOfBytesToRead.
&dwResponseBytesRead); // lpdwNumberOfBytesRead.
if(!bInternetReadFile)
{
// Do clean up and exit.
DWORD dwErr = ::GetLastError(); // This, in some cases, will return: 0x7a
HRESULT hr = HRESULT_FROM_WIN32(dwErr); // This, in some cases, will return: 0x8007007a
return;
}
// Adjust the buffer according to the actual number of bytes read.
responseBuffer.resize(oldBufferSize + dwResponseBytesRead);
}
while(dwResponseBytesRead != 0);