http://bugs.winehq.org/show_bug.cgi?id=31051
Bug #: 31051 Summary: HttpQueryInfo() erroneously ignores lpdwIndex argument for some info levels Product: Wine Version: unspecified Platform: x86 OS/Version: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: wininet AssignedTo: wine-bugs@winehq.org ReportedBy: support@tarma.com Classification: Unclassified
The HttpQueryInfo() function should return data based on both the dwInfoLevel and the *lpdwIndex arguments (if the latter is specified). In particular, *lpdwIndex may be used by the caller to enumerate multiple headers with the same name, like this idiom:
/* ...various irrelevant details and other error handling omitted...*/ DWORD dwIndex = 0; while (HttpQueryInfo(hRequest, dwInfoLevel, pBuffer, dwBufSize, &dwIndex)) { /* ...process the returned data... */ }
This enumerates potentially multiple like-named headers for the given dwInfoLevel. It relies on HttpQueryInfo() to do the following (see Microsoft Win32 API docs for HttpQueryInfo()):
(1) Check if the dwIndex-th header is available for dwInfoLevel; if not, return FALSE and SetLastError(ERROR_HTTP_HEADER_NOT_FOUND).
(2) If the dwIndex-th header is available, then return its data (subject to buffer space etc.) and increment *(&dwIndex).
For several of the possible dwInfoLevels, Wine's HttpQueryInfoW() implementation has the following problems:
(P1) It does not check its *lpdwIndex value, but returns the same data and an ERROR_SUCCESS result regardless of that value; and
(P2) It does not always increment *lpdwIndex if the current function call is successful.
It keeps returning the same data regardless of the value of *lpdwIndex, and keeps returning TRUE. This leads to infinite loops in the caller when used with (variations of) the above enumeration idiom.
In particular, this erroneous behavior occurs with the following dwInfoLevels (see implementation of HTTP_HttpQueryInfoW() in dlls\wininet\http.c):
HTTP_QUERY_RAW_HEADERS_CRLF:
EXPECTED: Should return data and increment *lpdwIndex for *lpdwIndex==0 only, and return ERROR_HTTP_HEADER_NOT_FOUND for all other values of *lpdwIndex.
ACTUAL: Instead, always returns ERROR_SUCCESS except if the destination buffer is too small. It also does not increment *lpdwIndex if it returns ERROR_SUCCESS.
HTTP_QUERY_RAW_HEADERS: (ditto) HTTP_QUERY_STATUS_TEXT: (ditto) HTTP_QUERY_VERSION: (ditto)