winhttp: Implement WinHttpSendRequest.
This commit is contained in:
parent
266c4b2c04
commit
f07f2304b0
|
@ -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);
|
||||||
|
|
|
@ -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.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue