WinInet InternetReadFile返回0x8007007a(传递给系统调用的数据区域太小)

WinInet InternetReadFile returns 0x8007007a (The data area passed to a system call is too small)

本文关键字:数据区 数据 区域 系统调用 返回 InternetReadFile 0x8007007a WinInet      更新时间:2023-10-16

我对WinInet的InternetReadFile(C++)有问题
在极少数情况下,函数会失败,GetLastError会返回上述错误0x8007007a(根据ErrorLookup,这对应于"传递给系统调用的数据区域太小")。

我对此有几个问题:

  1. 为什么这种情况在一些罕见的情况下发生,但在其他情况下有效很好(我当然是说总是下载相同的~15MBzip文件)
  2. 这真的与传递给API调用的缓冲区大小有关吗?我为这个调用使用了1024字节的常量缓冲区大小。我应该使用更大的缓冲区大小吗?如果是,我如何知道"正确"的缓冲区大小
  3. 如果出现此错误,我可以在运行时做些什么来恢复

添加一个代码片段(注意,这不会按原样工作,因为需要一些初始化代码):

#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);

这是InternetReadFile:的一个记录错误

WinINet尝试一次一行地将HTML写入lpBuffer缓冲区。如果应用程序的缓冲区太小,无法容纳至少一行生成的HTML,则会返回错误代码error_INSUFFIENT_buffer,以指示应用程序需要更大的缓冲区。

因此,您应该通过增加缓冲区大小来处理这个错误。只需将尺寸增加一倍,必要时可重复使用。

有一些不一致之处值得商榷。目前还不清楚你是否正在阅读一个HTML文件,15MB似乎太多了。另一个是,这个错误应该会很好地重复。但最麻烦的是错误代码值,它被封装在HRESULT中,这是COM组件将返回的错误代码。您应该从GetLastError()返回一个Windows错误代码,只有0x7a,而不是0x8007007a。

请确保您的错误检查是正确的。仅当InternetReadFile()返回FALSE时调用GetLastError()。如果检查出来(请始终发布一个片段),那么请考虑这个错误实际上是在上游生成的,可能是防火墙或脆弱的反恶意软件。