winhttp: Implement WinHttpSendRequest.

This commit is contained in:
Hans Leidekker 2008-08-26 11:03:40 +02:00 committed by Alexandre Julliard
parent 266c4b2c04
commit f07f2304b0
6 changed files with 165 additions and 16 deletions

View File

@ -77,6 +77,8 @@ void release_object( object_header_t *hdr )
TRACE("object %p refcount = %d\n", hdr, refs); TRACE("object %p refcount = %d\n", hdr, refs);
if (!refs) if (!refs)
{ {
if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (request_t *)hdr );
send_callback( hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, &hdr->handle, sizeof(HINTERNET) ); send_callback( hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, &hdr->handle, sizeof(HINTERNET) );
TRACE("destroying object %p\n", hdr); TRACE("destroying object %p\n", hdr);

View File

@ -83,19 +83,6 @@ HRESULT WINAPI DllUnregisterServer(void)
return S_OK; return S_OK;
} }
/***********************************************************************
* WinHttpSendRequest (winhttp.@)
*/
BOOL WINAPI WinHttpSendRequest (HINTERNET hRequest, LPCWSTR pwszHeaders, DWORD dwHeadersLength,
LPVOID lpOptional, DWORD dwOptionalLength, DWORD dwTotalLength,
DWORD_PTR dwContext)
{
FIXME("(%s, %d, %d, %d): stub\n", debugstr_w(pwszHeaders), dwHeadersLength, dwOptionalLength, dwTotalLength);
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
/*********************************************************************** /***********************************************************************
* WinHttpQueryOption (winhttp.@) * WinHttpQueryOption (winhttp.@)
*/ */

View File

@ -21,6 +21,9 @@
#include "wine/debug.h" #include "wine/debug.h"
#include <stdarg.h> #include <stdarg.h>
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
@ -654,3 +657,142 @@ BOOL WINAPI WinHttpQueryHeaders( HINTERNET hrequest, DWORD level, LPCWSTR name,
release_object( &request->hdr ); release_object( &request->hdr );
return ret; return ret;
} }
static BOOL open_connection( request_t *request )
{
connect_t *connect;
char address[32];
WCHAR *addressW;
if (netconn_connected( &request->netconn )) return TRUE;
connect = request->connect;
if (!netconn_resolve( connect->servername, connect->serverport, &connect->sockaddr )) return FALSE;
inet_ntop( connect->sockaddr.sin_family, &connect->sockaddr.sin_addr, address, sizeof(address) );
TRACE("connecting to %s:%u\n", address, ntohs(connect->sockaddr.sin_port));
addressW = strdupAW( address );
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 );
if (!netconn_create( &request->netconn, connect->sockaddr.sin_family, SOCK_STREAM, 0 ))
{
heap_free( addressW );
return FALSE;
}
if (!netconn_connect( &request->netconn, (struct sockaddr *)&connect->sockaddr, sizeof(struct sockaddr_in) ))
{
netconn_close( &request->netconn );
heap_free( addressW );
return FALSE;
}
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, 0 );
heap_free( addressW );
return TRUE;
}
void close_connection( request_t *request )
{
if (!netconn_connected( &request->netconn )) return;
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 0 );
netconn_close( &request->netconn );
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 );
}
static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional,
DWORD optional_len, DWORD total_len, DWORD_PTR context )
{
static const WCHAR keep_alive[] = {'K','e','e','p','-','A','l','i','v','e',0};
static const WCHAR no_cache[] = {'n','o','-','c','a','c','h','e',0};
static const WCHAR length_fmt[] = {'%','l','d',0};
BOOL ret = FALSE;
connect_t *connect = request->connect;
session_t *session = connect->session;
WCHAR *req = NULL;
char *req_ascii;
int bytes_sent;
DWORD len;
if (session->agent)
process_header( request, attr_user_agent, session->agent, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
if (connect->hostname)
process_header( request, attr_host, connect->hostname, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
if (optional_len)
{
WCHAR length[21]; /* decimal long int + null */
sprintfW( length, length_fmt, optional_len );
process_header( request, attr_content_length, length, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
}
if (!(request->hdr.flags & WINHTTP_DISABLE_KEEP_ALIVE))
{
process_header( request, attr_connection, keep_alive, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
}
if (request->hdr.flags & WINHTTP_FLAG_REFRESH)
{
process_header( request, attr_pragma, no_cache, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
process_header( request, attr_cache_control, no_cache, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
}
if (headers && !add_request_headers( request, headers, headers_len, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))
{
TRACE("failed to add request headers\n");
return FALSE;
}
if (!(ret = open_connection( request ))) goto end;
if (!(req = build_request_string( request, request->verb, request->path, request->version ))) goto end;
if (!(req_ascii = strdupWA( req ))) goto end;
TRACE("full request: %s\n", debugstr_a(req_ascii));
len = strlen(req_ascii);
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 );
ret = netconn_send( &request->netconn, req_ascii, len, 0, &bytes_sent );
heap_free( req_ascii );
if (!ret) goto end;
if (optional_len && !netconn_send( &request->netconn, optional, optional_len, 0, &bytes_sent )) goto end;
len += optional_len;
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len, sizeof(DWORD) );
end:
heap_free( req );
return ret;
}
/***********************************************************************
* WinHttpSendRequest (winhttp.@)
*/
BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD headers_len,
LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context )
{
BOOL ret;
request_t *request;
TRACE("%p, %s, 0x%x, %u, %u, %lx\n",
hrequest, debugstr_w(headers), headers_len, optional_len, total_len, context);
if (!(request = (request_t *)grab_object( hrequest )))
{
set_last_error( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context );
release_object( &request->hdr );
return ret;
}

View File

@ -177,7 +177,10 @@ HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PO
list_add_head( &session->hdr.children, &connect->hdr.entry ); list_add_head( &session->hdr.children, &connect->hdr.entry );
if (server && !(connect->hostname = strdupW( server ))) goto end; if (server && !(connect->hostname = strdupW( server ))) goto end;
connect->hostport = port; connect->hostport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
if (server && !(connect->servername = strdupW( server ))) goto end;
connect->serverport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
if (!(hconnect = alloc_handle( &connect->hdr ))) goto end; if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
connect->hdr.handle = hconnect; connect->hdr.handle = hconnect;
@ -268,6 +271,8 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
request->connect = connect; request->connect = connect;
list_add_head( &connect->hdr.children, &request->hdr.entry ); list_add_head( &connect->hdr.children, &request->hdr.entry );
if (!netconn_init( &request->netconn )) goto end;
if (!verb) verb = get; if (!verb) verb = get;
if (!object) object = slash; if (!object) object = slash;
if (!version) version = http1_1; if (!version) version = http1_1;

View File

@ -59,7 +59,7 @@ static void test_OpenRequest (void)
ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError()); ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0); ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
todo_wine ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError()); ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
ret = WinHttpCloseHandle(request); ret = WinHttpCloseHandle(request);
ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret); ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
@ -111,7 +111,7 @@ static void test_SendRequest (void)
ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError()); ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, 0); ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, 0);
todo_wine ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError()); ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
for (i = 3; post_data[i]; i++) for (i = 3; post_data[i]; i++)
{ {

View File

@ -123,6 +123,7 @@ BOOL free_handle( HINTERNET );
void set_last_error( DWORD ); void set_last_error( DWORD );
void send_callback( object_header_t *, DWORD, LPVOID, DWORD ); void send_callback( object_header_t *, DWORD, LPVOID, DWORD );
void close_connection( request_t * );
BOOL netconn_close( netconn_t * ); BOOL netconn_close( netconn_t * );
BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int ); BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int );
@ -170,6 +171,18 @@ static inline WCHAR *strdupW( const WCHAR *src )
return dst; return dst;
} }
static inline WCHAR *strdupAW( const char *src )
{
WCHAR *dst = NULL;
if (src)
{
DWORD len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
if ((dst = heap_alloc( len * sizeof(WCHAR) )))
MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
}
return dst;
}
static inline char *strdupWA( const WCHAR *src ) static inline char *strdupWA( const WCHAR *src )
{ {
char *dst = NULL; char *dst = NULL;