У меня есть функция, которая асинхронно загружает файл с использованием функций WinINet. Подход я использую:InternetOpenUrl в асинхронном режиме
- InternetOpen
- InternetSetStatusCallback
- InternetOpenUrl (синхронно)
- InternetReadFileEx (асинхронный)
- InternetReadFileEx в функции обратного вызова, пока полученный буфер не равен 0
Как я могу подождать, пока InternetOpenUrl
не будет сделано так, чтобы ручка e вернулось? Если я запустил InternetOpenUrl
async, я не могу сказать, когда получаю последний INTERNET_STATUS_RESPONSE_RECEIVED
из-за возможных перенаправлений. Также, когда сделано InternetOpenUrl
, я хочу позвонить InternetQueryOption
с флагом INTERNET_OPTION_URL
, чтобы получить окончательный URL после всех перенаправлений, если они есть.
std::vector<DOWNLOAD_CONTEXT> contexts;
void Download(TCHAR *url, unsigned int crc32, unsigned int length)
{
HINTERNET hInternet = InternetOpen(_T("Test"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
InternetSetStatusCallback(hInternet, DownloadProgress);
DOWNLOAD_CONTEXT context;
context.hInternet = hInternet;
contexts.push_back(context);
HINTERNET hUrl = InternetOpenUrl(hInternet, url, _T(""), 0, INTERNET_FLAG_RELOAD, DWORD_PTR(&*(contexts.end()-1)));
/* if InternetOpenUrl would have been executed in blocking mode,
here I would have executed the first async InternetReadFileEx,
and InternetQueryOption to get the final URL*/
}
void CALLBACK DownloadProgress(
_In_ HINTERNET hInternet,
_In_ DWORD_PTR dwContext,
_In_ DWORD dwInternetStatus,
_In_ LPVOID lpvStatusInformation,
_In_ DWORD dwStatusInformationLength
)
{
DOWNLOAD_CONTEXT *context = (DOWNLOAD_CONTEXT*)dwContext;
switch (dwInternetStatus)
{
case INTERNET_STATUS_HANDLE_CREATED:
context->hUrl = (HINTERNET)((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwResult;
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
size = 0;
InternetQueryOptionA(context->hUrl, INTERNET_OPTION_URL, nullptr, &size);
link = new char[size];
InternetQueryOptionA(context->hUrl, INTERNET_OPTION_URL, link, &size);
MessageBoxA(NULL, link, "", MB_OK);
delete[] link;
/* if this is the last response (the HTTP status code is 200)
we initiate InternetReadFileEx recursion */
break;
...
default:
MessageBoxA(NULL, "Status: Unknown (%d)\n", "", MB_OK);
break;
}
}
Кроме того, некоторые функции Wininet проваливается с ERROR_INTERNET_INCORRECT_HANDLE_STATE
, внутри обратного вызова, поскольку InternetOpenUrl
еще не сделано. Хотя InternetQueryOption
показывает URL-адрес каждые INTERNET_STATUS_RESPONSE_RECEIVED
.
InternetOpenUrl
будет генерировать следующую последовательность обратного вызова статусов:
- INTERNET_STATUS_HANDLE_CREATED
- INTERNET_STATUS_DETECTING_PROXY
- INTERNET_STATUS_SENDING_REQUEST
- INTERNET_STATUS_REQUEST_SENT
- INTERNET_STATUS_RECEIVING_RESPONSE
- INTERNET_STATUS_RESPONSE_RECE IVED
- INTERNET_STATUS_REDIRECT
- INTERNET_STATUS_DETECTING_PROXY
- INTERNET_STATUS_RESOLVING_NAME
- INTERNET_STATUS_NAME_RESOLVED
- INTERNET_STATUS_CONNECTING_TO_SERVER
- INTERNET_STATUS_CONNECTED_TO_SERVER
- INTERNET_STATUS_SENDING_REQUEST
- INTERNET_STATUS_REQUEST_SENT
- INTERNET_STATUS_RECEIVING_RESPONSE
- INTERNET_STATUS_RESPONSE_RECEIVED
Как я могу сказать, когда последний INTERNET_STATUS_RESPONSE_RECEIVED
прибыл (статус 200 HTTP)?