urlmon: Added support for sending post data from stream.
This commit is contained in:
parent
d563d5b35c
commit
237264dc61
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue