# HTTP PUT problem using WinInet.lib



## UsaSzerelem (May 10, 2008)

Hello All,

I need to programatically upload a file to an IIS server. For this I wrote a small proof of concept app that uses WinInet.lib that runs on my Vista machine and connects to a server that runs IIS 7.0 The app appears to work just fine, but at the end of the HttpQueryInfo() call with the HTTP_QUERY_STATUS_CODE I get a 404 response. Analyzing the log on the IIS server reveals the following:

#Date: 2008-05-09 23:43:40
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status time-taken
2008-05-09 23:43:40 192.168.1.253 GET /Upload/ - 80 - 192.168.1.253 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506) 200 0 0 50
2008-05-09 23:44:02 192.168.1.253 PUT /Upload/Test.txt - 80 - 192.168.1.185 HttpSend 404 0 2 200
2008-05-09 23:47:12 192.168.1.253 GET / - 80 - 192.168.1.253 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506) 200 0 0 100
2008-05-09 23:48:44 192.168.1.253 PUT /Upload/Test.txt - 80 - 192.168.1.185 HttpSend 404 0 64 110
2008-05-09 23:58:16 192.168.1.253 PUT /Upload/Test.txt - 80 - 192.168.1.185 HttpSend 404 0 64 150

I abbreviate the code here for the sake of brevety:

1.- Calling my class as follows:
int _tmain(int argc, _TCHAR* argv[])
{
CHttpSend Http;

if ( Http.Init( TEXT("http://192.168.1.253/Upload/Test.txt") ) == true )
{
Http.SendFile( TEXT("c:\\Develop\\Test.txt") );
}

return 0;
}

2.- Abbreviated CHttpSend::Init() is as follows:


m_hInternet = InternetOpen( TEXT("HttpSend"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0) ;

URL_COMPONENTS urlComp = { 0 };
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { 0 };
TCHAR szPath[INTERNET_MAX_PATH_LENGTH] = { 0 };
TCHAR szExtra[INTERNET_MAX_PATH_LENGTH] = { 0 };

urlComp.dwStructSize = sizeof(urlComp);
urlComp.lpszHostName = szHostName;
urlComp.dwHostNameLength = sizeof(szHostName) - 1;
urlComp.lpszUrlPath = szPath;
urlComp.dwUrlPathLength = sizeof(szPath) - 1;
urlComp.lpszExtraInfo = szExtra;
urlComp.dwExtraInfoLength= sizeof(szExtra) - 1;

InternetCrackUrl( pszUrl, 0, ICU_ESCAPE, &urlComp);

// At this point szHostName contains "192.168.1.253"
// At this point urlComp.nPort is 80. I made sure it doesn't conflict with default website.

m_hHttp = InternetConnect( m_hInternet, szHostName, urlComp.nPort,
 0, 0, INTERNET_SERVICE_HTTP, 0, 0);


3.- Abbreviated CHttpSend::SendFile() is as follows:


hRequest = HttpOpenRequest (
m_hHttp, TEXT("PUT"), m_pszUrl, NULL, 
NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0
);

memset(&IBuff, 0, sizeof(IBuff));
IBuff.dwStructSize = sizeof(IBuff);
IBuff.dwBufferTotal = File.Length();
ulBytesToSend = IBuff.dwBufferTotal;

HttpSendRequestEx( hRequest, &IBuff, NULL, HSR_INITIATE, 0);

// Do a number of InternetWriteFile() calls as we are reading from
// the file to send.

InternetWriteFile( hRequest, pBuff, ulBytes, &ulWritten );

// Once all the file content was process
HttpEndRequest( hRequest, NULL, 0, 0 );

// And finally I do the HttpQueryInfo() which fails with a 404

if ( HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE, szBuff, &dwSize, &dw ) == TRUE )
{
UINT uRetCode = _wtol( szBuff );

if ( uRetCode < 400 )
bRet = true;
}

I suspect that there could be some IIS related configuration, but I think to have it wide open from a security point of view. I am able to browse the directory from a remote Internet Explorer.

Any help in this matter is greatly appreciated and thank you in advance.
Martin
:wave:


----------

