Article ID: 2001156 - View products that this article applies to.
Consider the following scenario:
Your application is programmatically uploading files to a WebDav directory hosted on IIS 7, by using the WinInet API to send a HTTP PUT verb. You may experience that your application, which was working correctly on IIS6 and Windows Server 2003, may fail to upload files to the IIS 7 WebDav directory, even though no code changes have been made to your WinInet application.
The cause of this issue is due to a design change for WebDav running on IIS 7. WebDav running on IIS 7 now requires authentication and will not work if only Anonymous Authentication is used. As a result of this, your application which has been using the WinInet API sequence of HttpSendRequestEx, InternetWriteFile, HttpEndRequest will experience that the call to HttpEndRequest returns FALSE and GetLastError() will indicate an error code of 12032 - ERROR_INTERNET_FORCE_RETRY.
The resolution to this issue is to retry the same sequence of operations, namely:
until HttpEndRequest does not return FALSE and GetLastError() does not report back 12032 (or there is some other error). If IIS is presented with wrong authentication information, then IIS will keep returning an HTTP 401 error for each retry; therefore, you will need to keep track of how many times the HttpEndRequest function returns back error 12032 and hence prevent running into an infinite loop.
In the case of Windows NTLM Authentication, HttpEndRequest will return back error 12032 for a maximum of two times to satisfy the 3 way NTLM handshake. The first 12032 error will indicate a HTTP 401 error response from the server and the second 12032 error will indicate the Type-2 NTLM handshake message from the server following which, if valid authentication info is passed to IIS, the user will be authenticated correctly and the upload will be successful.
When you use a retry logic to call the above functions in a loop, notice that the call to InternetWriteFile is being made multiple times. What this means is that the call to InternetWriteFile will end up writing the data over the network and this will cause a waste of bandwidth. To prevent this from happening, you can send a dummy HTTP HEAD request to the server which will "pre-authenticate" the request and cause the subsequent call of HttpSendRequest to not send the HTTP Payload when InternetWriteFile is called. If you are familiar with Network Monitor or WinInet logging, you will see that the first PUT request sent to the server will have a Content-Length of zero, which prevents the payload transfer and the payload will not be transferred until the NTLM handshake is complete.
The WebDav feature does not require you to use Windows Authentication; you can configure your WebDav server to use Basic Authentication over SSL which will ensure the safety of the data upload. When Basic authentication is configured, you can directly inject a valid base-64 encoded username password string in the outgoing request, which will prevent IIS returning back a HTTP 401 error and therefore HttpEndRequest will not return back error 12032. You can add the Basic authentication information to the outgoing request by calling the WinInet API:
Do this before calling HttpSendRequestEx to directly inject the Authorization header in the outgoing HTTP request.
The following code sample shows how you can use the retry logic to handle the error 12032 return response from HttpEndRequest. Please note that this sample does not cover the "pre authenticate" request discussed above. In order to Pre-Authenticate, all you will need to do is to call HttpOpenRequest, HttpSendRequest with the HTTP HEAD verb to the target server before you call the HttpSendRequestEx code below.
(http://go.microsoft.com/fwlink/?LinkId=151500)for other considerations.
Article ID: 2001156 - Last Review: December 29, 2010 - Revision: 3.0