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)
http://bugs.winehq.org/show_bug.cgi?id=31051
Bruno Jesus 00cpxxx@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |00cpxxx@gmail.com
--- Comment #1 from Bruno Jesus 00cpxxx@gmail.com 2012-06-30 14:28:12 CDT --- Do you have any real application that depends on this or can you share a piece of code that reproduces the issue?
http://bugs.winehq.org/show_bug.cgi?id=31051
--- Comment #2 from Ron van der Wal support@tarma.com 2012-06-30 18:39:37 CDT --- Created attachment 40813 --> http://bugs.winehq.org/attachment.cgi?id=40813 HttpEnumHeaders() showing enumerative use of HttpQueryInfo()
http://bugs.winehq.org/show_bug.cgi?id=31051
--- Comment #3 from Ron van der Wal support@tarma.com 2012-06-30 18:40:53 CDT --- Yes, the Publish or Perish [PoP] software (http://www.harzing.com/pop.htm) came across this problem.
We added an internal workaround for two Wine bugs in the PoP code to make sure that it would not get into an infinite loop, but that should not have been necessary.
The attached source code (taken verbatim from PoP) shows how HttpQueryInfo() is used and already includes two (2) workarounds for anomalous Wine behavior:
(1) For some values of dwInfoLevel, Wine's HttpQueryInfo() returns a nonzero (i.e., True) function value but zero (0) bytes of data; this should have been a FALSE function result because the requested header apparently doesn't exist.
WORKAROUND: We detect the case of dwReqSize == 0 separately
(2) For other values of dwInfoLevel, Wine's HttpQueryInfo() ignores the value in *lpdwIndex as reported earlier.
WORKAROUND: We calculate and remember a Fletcher-32 checksum on the returned data and compare that with the next iteration's checksum to see if Wine returns the same data; if so, we break the enumeration.
http://bugs.winehq.org/show_bug.cgi?id=31051
--- Comment #4 from Ron van der Wal support@tarma.com 2012-07-02 17:30:24 CDT --- ADDITIONAL, CORRECTION: *lpdwIndex need only be updated (if lpdwIndex is non-NULL) if another same-named header is in fact available, for example when enumerating Set-Cookie headers.
However, the original reported bug still stands: If *lpdwIndex exceeds the highest valid header index available for the given dwInfoLevel, then the function should fail with error code ERROR_HTTP_HEADER_NOT_FOUND.
From the Microsoft documentation for HttpQueryInfo():
"lpdwIndex [in, out]
Pointer to a zero-based header index used to enumerate multiple headers with the same name. When calling the function, this parameter is the index of the specified header to return. When the function returns, this parameter is the index of the next header. If the next index cannot be found, ERROR_HTTP_HEADER_NOT_FOUND is returned."
Note that this CORRECTION invalidates the original enumeration sample, but that the information in the original report concerning the affected HTTP_QUERY_* values is still correct.
http://bugs.winehq.org/show_bug.cgi?id=31051
Sebastian Lackner sebastian@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |sebastian@fds-team.de
--- Comment #5 from Sebastian Lackner sebastian@fds-team.de --- Bruno pointed me to this bug report while I was working on a similar one: http://bugs.winehq.org/show_bug.cgi?id=20497 (dwIndex is incremented, even if the function fails with ERROR_INSUFFICIENT_BUFFER).
I think most of the issues mentioned in this bug should already be fixed:
* Current versions of wine indeed pay attention to the passed dwIndex value * They also return ERROR_HTTP_HEADER_NOT_FOUND if the header was not found
Could you guys please retest with a current version of wine?
http://bugs.winehq.org/show_bug.cgi?id=31051
--- Comment #6 from Ron van der Wal support@tarma.com --- Thanks for the heads up Sebastian,
We added workaround code for this Wine problem back in 2012 and tested it then to verify that it worked correctly (both on Wine and on Windows).
As far as I am aware, Publish or Perish still functions correctly on Wine with that workaround (last version I tested was 1.7.something), and we do not want to make changes to tried and tested code; not after two years of first reporting the problem.
Sorry about that.
https://bugs.winehq.org/show_bug.cgi?id=31051
Sebastian Lackner sebastian@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |FIXED
--- Comment #7 from Sebastian Lackner sebastian@fds-team.de --- As pointed out in comment #5, the original issue is most likely already fixed since some time. Without any test application it doesn't make much sense to keep this bug open.
https://bugs.winehq.org/show_bug.cgi?id=31051
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #8 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 1.7.49.