Commit 5505413a authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

winhttp: Implement IWinHttpRequest::get_ResponseStream.

parent 6f046e0f
...@@ -3695,12 +3695,203 @@ done: ...@@ -3695,12 +3695,203 @@ done:
return HRESULT_FROM_WIN32( err ); return HRESULT_FROM_WIN32( err );
} }
struct stream
{
IStream IStream_iface;
LONG refs;
char *data;
ULARGE_INTEGER pos, size;
};
static inline struct stream *impl_from_IStream( IStream *iface )
{
return CONTAINING_RECORD( iface, struct stream, IStream_iface );
}
static HRESULT WINAPI stream_QueryInterface( IStream *iface, REFIID riid, void **obj )
{
struct stream *stream = impl_from_IStream( iface );
TRACE("%p, %s, %p\n", stream, debugstr_guid(riid), obj);
if (IsEqualGUID( riid, &IID_IStream ) || IsEqualGUID( riid, &IID_IUnknown ))
{
*obj = iface;
}
else
{
FIXME("interface %s not implemented\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
IStream_AddRef( iface );
return S_OK;
}
static ULONG WINAPI stream_AddRef( IStream *iface )
{
struct stream *stream = impl_from_IStream( iface );
return InterlockedIncrement( &stream->refs );
}
static ULONG WINAPI stream_Release( IStream *iface )
{
struct stream *stream = impl_from_IStream( iface );
LONG refs = InterlockedDecrement( &stream->refs );
if (!refs)
{
heap_free( stream->data );
heap_free( stream );
}
return refs;
}
static HRESULT WINAPI stream_Read( IStream *iface, void *buf, ULONG len, ULONG *read )
{
struct stream *stream = impl_from_IStream( iface );
ULONG size;
if (stream->pos.QuadPart >= stream->size.QuadPart)
{
*read = 0;
return S_FALSE;
}
size = min( stream->size.QuadPart - stream->pos.QuadPart, len );
memcpy( buf, stream->data + stream->pos.QuadPart, size );
stream->pos.QuadPart += size;
*read = size;
return S_OK;
}
static HRESULT WINAPI stream_Write( IStream *iface, const void *buf, ULONG len, ULONG *written )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_Seek( IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *newpos )
{
struct stream *stream = impl_from_IStream( iface );
if (origin == STREAM_SEEK_SET)
stream->pos.QuadPart = move.QuadPart;
else if (origin == STREAM_SEEK_CUR)
stream->pos.QuadPart += move.QuadPart;
else if (origin == STREAM_SEEK_END)
stream->pos.QuadPart = stream->size.QuadPart - move.QuadPart;
if (newpos) newpos->QuadPart = stream->pos.QuadPart;
return S_OK;
}
static HRESULT WINAPI stream_SetSize( IStream *iface, ULARGE_INTEGER newsize )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_CopyTo( IStream *iface, IStream *stream, ULARGE_INTEGER len, ULARGE_INTEGER *read,
ULARGE_INTEGER *written )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_Commit( IStream *iface, DWORD flags )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_Revert( IStream *iface )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_LockRegion( IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_UnlockRegion( IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_Stat( IStream *iface, STATSTG *stg, DWORD flag )
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI stream_Clone( IStream *iface, IStream **stream )
{
FIXME("\n");
return E_NOTIMPL;
}
static const IStreamVtbl stream_vtbl =
{
stream_QueryInterface,
stream_AddRef,
stream_Release,
stream_Read,
stream_Write,
stream_Seek,
stream_SetSize,
stream_CopyTo,
stream_Commit,
stream_Revert,
stream_LockRegion,
stream_UnlockRegion,
stream_Stat,
stream_Clone
};
static HRESULT WINAPI winhttp_request_get_ResponseStream( static HRESULT WINAPI winhttp_request_get_ResponseStream(
IWinHttpRequest *iface, IWinHttpRequest *iface,
VARIANT *body ) VARIANT *body )
{ {
FIXME("\n"); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
return E_NOTIMPL; DWORD err = ERROR_SUCCESS;
struct stream *stream;
TRACE("%p, %p\n", request, body);
if (!body) return E_INVALIDARG;
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_SENT)
{
err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND;
goto done;
}
if (!(stream = heap_alloc( sizeof(*stream) )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
stream->IStream_iface.lpVtbl = &stream_vtbl;
stream->refs = 1;
if (!(stream->data = heap_alloc( request->offset )))
{
heap_free( stream );
err = ERROR_OUTOFMEMORY;
goto done;
}
memcpy( stream->data, request->buffer, request->offset );
stream->pos.QuadPart = 0;
stream->size.QuadPart = request->offset;
V_VT( body ) = VT_UNKNOWN;
V_UNKNOWN( body ) = (IUnknown *)&stream->IStream_iface;
done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_get_Option( static HRESULT WINAPI winhttp_request_get_Option(
......
...@@ -2624,11 +2624,15 @@ static void test_IWinHttpRequest(void) ...@@ -2624,11 +2624,15 @@ static void test_IWinHttpRequest(void)
IWinHttpRequest *req; IWinHttpRequest *req;
BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL; BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
BSTR date, today, connection, value = NULL; BSTR date, today, connection, value = NULL;
VARIANT async, empty, timeout, body, proxy_server, bypass_list, data; VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data;
VARIANT_BOOL succeeded; VARIANT_BOOL succeeded;
LONG status; LONG status;
WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE]; WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
SYSTEMTIME st; SYSTEMTIME st;
IStream *stream, *stream2;
LARGE_INTEGER pos;
char buf[128];
DWORD count;
GetSystemTime( &st ); GetSystemTime( &st );
WinHttpTimeFromSystemTime( &st, todayW ); WinHttpTimeFromSystemTime( &st, todayW );
...@@ -2680,8 +2684,7 @@ static void test_IWinHttpRequest(void) ...@@ -2680,8 +2684,7 @@ static void test_IWinHttpRequest(void)
hr = IWinHttpRequest_Abort( req ); hr = IWinHttpRequest_Abort( req );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = IWinHttpRequest_Release( req ); IWinHttpRequest_Release( req );
ok( hr == S_OK, "got %08x\n", hr );
hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req ); hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
...@@ -2714,8 +2717,7 @@ static void test_IWinHttpRequest(void) ...@@ -2714,8 +2717,7 @@ static void test_IWinHttpRequest(void)
hr = IWinHttpRequest_Abort( req ); hr = IWinHttpRequest_Abort( req );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = IWinHttpRequest_Release( req ); IWinHttpRequest_Release( req );
ok( hr == S_OK, "got %08x\n", hr );
hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req ); hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
...@@ -2974,6 +2976,41 @@ static void test_IWinHttpRequest(void) ...@@ -2974,6 +2976,41 @@ static void test_IWinHttpRequest(void)
hr = VariantClear( &body ); hr = VariantClear( &body );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
VariantInit( &body );
V_VT( &body ) = VT_ERROR;
hr = IWinHttpRequest_get_ResponseStream( req, &body );
ok( hr == S_OK, "got %08x\n", hr );
ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
ok( hr == S_OK, "got %08x\n", hr );
ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
buf[0] = 0;
count = 0xdeadbeef;
hr = IStream_Read( stream, buf, 128, &count );
ok( hr == S_OK, "got %08x\n", hr );
ok( count != 0xdeadbeef, "count not set\n" );
ok( buf[0], "no data\n" );
VariantInit( &body2 );
V_VT( &body2 ) = VT_ERROR;
hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
ok( hr == S_OK, "got %08x\n", hr );
ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
ok( hr == S_OK, "got %08x\n", hr );
ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
IStream_Release( stream2 );
hr = VariantClear( &body );
ok( hr == S_OK, "got %08x\n", hr );
hr = VariantClear( &body2 );
ok( hr == S_OK, "got %08x\n", hr );
hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list ); hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
...@@ -3003,8 +3040,19 @@ static void test_IWinHttpRequest(void) ...@@ -3003,8 +3040,19 @@ static void test_IWinHttpRequest(void)
hr = IWinHttpRequest_Abort( req ); hr = IWinHttpRequest_Abort( req );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = IWinHttpRequest_Release( req ); IWinHttpRequest_Release( req );
pos.QuadPart = 0;
IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
ok( hr == S_OK, "got %08x\n", hr );
buf[0] = 0;
count = 0xdeadbeef;
hr = IStream_Read( stream, buf, 128, &count );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
ok( count != 0xdeadbeef, "count not set\n" );
ok( buf[0], "no data\n" );
IStream_Release( stream );
hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req ); hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
...@@ -3020,8 +3068,7 @@ static void test_IWinHttpRequest(void) ...@@ -3020,8 +3068,7 @@ static void test_IWinHttpRequest(void)
hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded ); hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = IWinHttpRequest_Release( req ); IWinHttpRequest_Release( req );
ok( hr == S_OK, "got %08x\n", hr );
SysFreeString( method ); SysFreeString( method );
SysFreeString( url ); SysFreeString( url );
......
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