Commit 237264dc authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

urlmon: Added support for sending post data from stream.

parent d563d5b3
...@@ -59,6 +59,11 @@ static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request ...@@ -59,6 +59,11 @@ static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request
return S_OK; return S_OK;
} }
static HRESULT FtpProtocol_end_request(Protocol *prot)
{
return E_NOTIMPL;
}
static HRESULT FtpProtocol_start_downloading(Protocol *prot) static HRESULT FtpProtocol_start_downloading(Protocol *prot)
{ {
FtpProtocol *This = ASYNCPROTOCOL_THIS(prot); FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
...@@ -82,6 +87,7 @@ static void FtpProtocol_close_connection(Protocol *prot) ...@@ -82,6 +87,7 @@ static void FtpProtocol_close_connection(Protocol *prot)
static const ProtocolVtbl AsyncProtocolVtbl = { static const ProtocolVtbl AsyncProtocolVtbl = {
FtpProtocol_open_request, FtpProtocol_open_request,
FtpProtocol_end_request,
FtpProtocol_start_downloading, FtpProtocol_start_downloading,
FtpProtocol_close_connection FtpProtocol_close_connection
}; };
......
...@@ -56,6 +56,11 @@ static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD requ ...@@ -56,6 +56,11 @@ static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD requ
return S_OK; return S_OK;
} }
static HRESULT GopherProtocol_end_request(Protocol *prot)
{
return E_NOTIMPL;
}
static HRESULT GopherProtocol_start_downloading(Protocol *prot) static HRESULT GopherProtocol_start_downloading(Protocol *prot)
{ {
return S_OK; return S_OK;
...@@ -69,6 +74,7 @@ static void GopherProtocol_close_connection(Protocol *prot) ...@@ -69,6 +74,7 @@ static void GopherProtocol_close_connection(Protocol *prot)
static const ProtocolVtbl AsyncProtocolVtbl = { static const ProtocolVtbl AsyncProtocolVtbl = {
GopherProtocol_open_request, GopherProtocol_open_request,
GopherProtocol_end_request,
GopherProtocol_start_downloading, GopherProtocol_start_downloading,
GopherProtocol_close_connection GopherProtocol_close_connection
}; };
......
...@@ -71,7 +71,8 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques ...@@ -71,7 +71,8 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
HINTERNET internet_session, IInternetBindInfo *bind_info) HINTERNET internet_session, IInternetBindInfo *bind_info)
{ {
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL; INTERNET_BUFFERSW send_buffer = {sizeof(INTERNET_BUFFERSW)};
LPWSTR addl_header = NULL, post_cookie = NULL;
IServiceProvider *service_provider = NULL; IServiceProvider *service_provider = NULL;
IHttpNegotiate2 *http_negotiate2 = NULL; IHttpNegotiate2 *http_negotiate2 = NULL;
BSTR url, host, user, pass, path; BSTR url, host, user, pass, path;
...@@ -220,13 +221,30 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques ...@@ -220,13 +221,30 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
} }
} }
send_buffer.lpcszHeader = This->full_header;
send_buffer.dwHeadersLength = send_buffer.dwHeadersTotal = strlenW(This->full_header);
if(This->base.bind_info.dwBindVerb != BINDVERB_GET) { if(This->base.bind_info.dwBindVerb != BINDVERB_GET) {
/* Native does not use GlobalLock/GlobalUnlock, so we won't either */ switch(This->base.bind_info.stgmedData.tymed) {
if (This->base.bind_info.stgmedData.tymed != TYMED_HGLOBAL) case TYMED_HGLOBAL:
WARN("Expected This->base.bind_info.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n", /* Native does not use GlobalLock/GlobalUnlock, so we won't either */
This->base.bind_info.stgmedData.tymed); send_buffer.lpvBuffer = This->base.bind_info.stgmedData.u.hGlobal;
else send_buffer.dwBufferLength = send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
optional = (LPWSTR)This->base.bind_info.stgmedData.u.hGlobal; break;
case TYMED_ISTREAM: {
LARGE_INTEGER offset;
send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
This->base.post_stream = This->base.bind_info.stgmedData.u.pstm;
IStream_AddRef(This->base.post_stream);
offset.QuadPart = 0;
IStream_Seek(This->base.post_stream, offset, STREAM_SEEK_SET, NULL);
break;
}
default:
FIXME("Unsupported This->base.bind_info.stgmedData.tymed %d\n", This->base.bind_info.stgmedData.tymed);
}
} }
b = TRUE; b = TRUE;
...@@ -234,8 +252,11 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques ...@@ -234,8 +252,11 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
if(!res) if(!res)
WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError()); WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
res = HttpSendRequestW(This->base.request, This->full_header, lstrlenW(This->full_header), if(This->base.post_stream)
optional, optional ? This->base.bind_info.cbstgmedData : 0); res = HttpSendRequestExW(This->base.request, &send_buffer, NULL, 0, 0);
else
res = HttpSendRequestW(This->base.request, send_buffer.lpcszHeader, send_buffer.dwHeadersLength,
send_buffer.lpvBuffer, send_buffer.dwBufferLength);
if(!res && GetLastError() != ERROR_IO_PENDING) { if(!res && GetLastError() != ERROR_IO_PENDING) {
WARN("HttpSendRequest failed: %d\n", GetLastError()); WARN("HttpSendRequest failed: %d\n", GetLastError());
return INET_E_DOWNLOAD_FAILURE; return INET_E_DOWNLOAD_FAILURE;
...@@ -244,6 +265,19 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques ...@@ -244,6 +265,19 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
return S_OK; return S_OK;
} }
static HRESULT HttpProtocol_end_request(Protocol *protocol)
{
BOOL res;
res = HttpEndRequestW(protocol->request, NULL, 0, 0);
if(!res && GetLastError() != ERROR_IO_PENDING) {
FIXME("HttpEndRequest failed: %u\n", GetLastError());
return E_FAIL;
}
return S_OK;
}
static HRESULT HttpProtocol_start_downloading(Protocol *prot) static HRESULT HttpProtocol_start_downloading(Protocol *prot)
{ {
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
...@@ -332,6 +366,7 @@ static void HttpProtocol_close_connection(Protocol *prot) ...@@ -332,6 +366,7 @@ static void HttpProtocol_close_connection(Protocol *prot)
static const ProtocolVtbl AsyncProtocolVtbl = { static const ProtocolVtbl AsyncProtocolVtbl = {
HttpProtocol_open_request, HttpProtocol_open_request,
HttpProtocol_end_request,
HttpProtocol_start_downloading, HttpProtocol_start_downloading,
HttpProtocol_close_connection HttpProtocol_close_connection
}; };
......
...@@ -104,6 +104,8 @@ static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar) ...@@ -104,6 +104,8 @@ static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar)
{ {
PROTOCOLDATA data; PROTOCOLDATA data;
TRACE("(%p)->(%p)\n", protocol, ar);
if(!ar->dwResult) { if(!ar->dwResult) {
WARN("request failed: %d\n", ar->dwError); WARN("request failed: %d\n", ar->dwError);
return; return;
...@@ -191,6 +193,42 @@ static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR contex ...@@ -191,6 +193,42 @@ static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR contex
} }
} }
static HRESULT write_post_stream(Protocol *protocol)
{
BYTE buf[0x20000];
DWORD written;
ULONG size;
BOOL res;
HRESULT hres;
protocol->flags &= ~FLAG_REQUEST_COMPLETE;
while(1) {
size = 0;
hres = IStream_Read(protocol->post_stream, buf, sizeof(buf), &size);
if(FAILED(hres) || !size)
break;
res = InternetWriteFile(protocol->request, buf, size, &written);
if(!res) {
FIXME("InternetWriteFile failed: %u\n", GetLastError());
hres = E_FAIL;
break;
}
}
if(SUCCEEDED(hres)) {
IStream_Release(protocol->post_stream);
protocol->post_stream = NULL;
hres = protocol->vtbl->end_request(protocol);
}
if(FAILED(hres))
return report_result(protocol, hres);
return S_OK;
}
static HINTERNET create_internet_session(IInternetBindInfo *bind_info) static HINTERNET create_internet_session(IInternetBindInfo *bind_info)
{ {
LPWSTR global_user_agent = NULL; LPWSTR global_user_agent = NULL;
...@@ -293,6 +331,9 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data) ...@@ -293,6 +331,9 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
return S_OK; return S_OK;
} }
if(protocol->post_stream)
return write_post_stream(protocol);
if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) { if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) {
hres = protocol->vtbl->start_downloading(protocol); hres = protocol->vtbl->start_downloading(protocol);
if(FAILED(hres)) { if(FAILED(hres)) {
...@@ -450,5 +491,10 @@ void protocol_close_connection(Protocol *protocol) ...@@ -450,5 +491,10 @@ void protocol_close_connection(Protocol *protocol)
if(protocol->connection) if(protocol->connection)
InternetCloseHandle(protocol->connection); InternetCloseHandle(protocol->connection);
if(protocol->post_stream) {
IStream_Release(protocol->post_stream);
protocol->post_stream = NULL;
}
protocol->flags = 0; protocol->flags = 0;
} }
...@@ -103,11 +103,14 @@ typedef struct { ...@@ -103,11 +103,14 @@ typedef struct {
ULONG content_length; ULONG content_length;
ULONG available_bytes; ULONG available_bytes;
IStream *post_stream;
LONG priority; LONG priority;
} Protocol; } Protocol;
struct ProtocolVtbl { struct ProtocolVtbl {
HRESULT (*open_request)(Protocol*,IUri*,DWORD,HINTERNET,IInternetBindInfo*); HRESULT (*open_request)(Protocol*,IUri*,DWORD,HINTERNET,IInternetBindInfo*);
HRESULT (*end_request)(Protocol*);
HRESULT (*start_downloading)(Protocol*); HRESULT (*start_downloading)(Protocol*);
void (*close_connection)(Protocol*); void (*close_connection)(Protocol*);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment