urlmon: Added support for sending post data from stream.

This commit is contained in:
Jacek Caban 2010-10-06 21:36:44 +02:00 committed by Alexandre Julliard
parent d563d5b35c
commit 237264dc61
5 changed files with 105 additions and 9 deletions

View File

@ -59,6 +59,11 @@ static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request
return S_OK;
}
static HRESULT FtpProtocol_end_request(Protocol *prot)
{
return E_NOTIMPL;
}
static HRESULT FtpProtocol_start_downloading(Protocol *prot)
{
FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
@ -82,6 +87,7 @@ static void FtpProtocol_close_connection(Protocol *prot)
static const ProtocolVtbl AsyncProtocolVtbl = {
FtpProtocol_open_request,
FtpProtocol_end_request,
FtpProtocol_start_downloading,
FtpProtocol_close_connection
};

View File

@ -56,6 +56,11 @@ static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD requ
return S_OK;
}
static HRESULT GopherProtocol_end_request(Protocol *prot)
{
return E_NOTIMPL;
}
static HRESULT GopherProtocol_start_downloading(Protocol *prot)
{
return S_OK;
@ -69,6 +74,7 @@ static void GopherProtocol_close_connection(Protocol *prot)
static const ProtocolVtbl AsyncProtocolVtbl = {
GopherProtocol_open_request,
GopherProtocol_end_request,
GopherProtocol_start_downloading,
GopherProtocol_close_connection
};

View File

@ -71,7 +71,8 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
HINTERNET internet_session, IInternetBindInfo *bind_info)
{
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;
IHttpNegotiate2 *http_negotiate2 = NULL;
BSTR url, host, user, pass, path;
@ -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) {
/* Native does not use GlobalLock/GlobalUnlock, so we won't either */
if (This->base.bind_info.stgmedData.tymed != TYMED_HGLOBAL)
WARN("Expected This->base.bind_info.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n",
This->base.bind_info.stgmedData.tymed);
else
optional = (LPWSTR)This->base.bind_info.stgmedData.u.hGlobal;
switch(This->base.bind_info.stgmedData.tymed) {
case TYMED_HGLOBAL:
/* Native does not use GlobalLock/GlobalUnlock, so we won't either */
send_buffer.lpvBuffer = This->base.bind_info.stgmedData.u.hGlobal;
send_buffer.dwBufferLength = send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
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;
@ -234,8 +252,11 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
if(!res)
WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
res = HttpSendRequestW(This->base.request, This->full_header, lstrlenW(This->full_header),
optional, optional ? This->base.bind_info.cbstgmedData : 0);
if(This->base.post_stream)
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) {
WARN("HttpSendRequest failed: %d\n", GetLastError());
return INET_E_DOWNLOAD_FAILURE;
@ -244,6 +265,19 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
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)
{
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
@ -332,6 +366,7 @@ static void HttpProtocol_close_connection(Protocol *prot)
static const ProtocolVtbl AsyncProtocolVtbl = {
HttpProtocol_open_request,
HttpProtocol_end_request,
HttpProtocol_start_downloading,
HttpProtocol_close_connection
};

View File

@ -104,6 +104,8 @@ static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar)
{
PROTOCOLDATA data;
TRACE("(%p)->(%p)\n", protocol, ar);
if(!ar->dwResult) {
WARN("request failed: %d\n", ar->dwError);
return;
@ -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)
{
LPWSTR global_user_agent = NULL;
@ -293,6 +331,9 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
return S_OK;
}
if(protocol->post_stream)
return write_post_stream(protocol);
if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) {
hres = protocol->vtbl->start_downloading(protocol);
if(FAILED(hres)) {
@ -450,5 +491,10 @@ void protocol_close_connection(Protocol *protocol)
if(protocol->connection)
InternetCloseHandle(protocol->connection);
if(protocol->post_stream) {
IStream_Release(protocol->post_stream);
protocol->post_stream = NULL;
}
protocol->flags = 0;
}

View File

@ -103,11 +103,14 @@ typedef struct {
ULONG content_length;
ULONG available_bytes;
IStream *post_stream;
LONG priority;
} Protocol;
struct ProtocolVtbl {
HRESULT (*open_request)(Protocol*,IUri*,DWORD,HINTERNET,IInternetBindInfo*);
HRESULT (*end_request)(Protocol*);
HRESULT (*start_downloading)(Protocol*);
void (*close_connection)(Protocol*);
};