msado15: Implement _Stream_Read and _Stream_Write.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2019-12-09 11:24:31 +01:00 committed by Alexandre Julliard
parent 6463db0c4b
commit 59c8fb9c3e
3 changed files with 149 additions and 9 deletions

View File

@ -25,4 +25,10 @@ HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Stream_create( void ** ) DECLSPEC_HIDDEN;
static inline void *heap_realloc_zero( void *mem, SIZE_T len )
{
if (!mem) return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
return HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len );
}
#endif /* _WINE_MSADO15_PRIVATE_H_ */

View File

@ -32,10 +32,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(msado15);
struct stream
{
_Stream Stream_iface;
LONG refs;
ObjectStateEnum state;
StreamTypeEnum type;
_Stream Stream_iface;
LONG refs;
ObjectStateEnum state;
StreamTypeEnum type;
LONG size;
LONG allocated;
LONG pos;
BYTE *buf;
};
static inline struct stream *impl_from_Stream( _Stream *iface )
@ -56,6 +60,7 @@ static ULONG WINAPI stream_Release( _Stream *iface )
if (!refs)
{
TRACE( "destroying %p\n", stream );
heap_free( stream->buf );
heap_free( stream );
}
return refs;
@ -124,6 +129,20 @@ static HRESULT WINAPI stream_get_Position( _Stream *iface, LONG *pos )
return E_NOTIMPL;
}
static HRESULT resize_buffer( struct stream *stream, LONG size )
{
if (stream->allocated < size)
{
BYTE *tmp;
LONG new_size = max( size, stream->allocated * 2 );
if (!(tmp = heap_realloc_zero( stream->buf, new_size ))) return E_OUTOFMEMORY;
stream->buf = tmp;
stream->allocated = new_size;
}
stream->size = size;
return S_OK;
}
static HRESULT WINAPI stream_put_Position( _Stream *iface, LONG pos )
{
FIXME( "%p, %d\n", iface, pos );
@ -193,10 +212,49 @@ static HRESULT WINAPI stream_put_Charset( _Stream *iface, BSTR charset )
return E_NOTIMPL;
}
static HRESULT create_byte_array( BYTE *data, LONG len, VARIANT *ret )
{
SAFEARRAY *vector;
LONG i;
HRESULT hr;
if (!len)
{
V_VT( ret ) = VT_NULL;
return S_OK;
}
if (!(vector = SafeArrayCreateVector( VT_UI1, 0, len ))) return E_OUTOFMEMORY;
for (i = 0; i < len; i++)
{
if ((hr = SafeArrayPutElement( vector, &i, &data[i] )) != S_OK)
{
SafeArrayDestroy( vector );
return hr;
}
}
V_VT( ret ) = VT_ARRAY | VT_UI1;
V_ARRAY( ret ) = vector;
return S_OK;
}
static HRESULT WINAPI stream_Read( _Stream *iface, LONG size, VARIANT *val )
{
FIXME( "%p, %d, %p\n", iface, size, val );
return E_NOTIMPL;
struct stream *stream = impl_from_Stream( iface );
HRESULT hr;
TRACE( "%p, %d, %p\n", stream, size, val );
if (stream->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
if (stream->type != adTypeBinary) return MAKE_ADO_HRESULT( adErrIllegalOperation );
if (size < adReadAll) return MAKE_ADO_HRESULT( adErrInvalidArgument );
if (size == adReadAll) size = stream->size - stream->pos;
else size = min( size, stream->size - stream->pos );
if ((hr = create_byte_array( stream->buf + stream->pos, size, val )) != S_OK) return hr;
stream->pos += size;
return S_OK;
}
static HRESULT WINAPI stream_Open( _Stream *iface, VARIANT src, ConnectModeEnum mode, StreamOpenOptionsEnum options,
@ -219,6 +277,10 @@ static HRESULT WINAPI stream_Close( _Stream *iface )
if (stream->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
heap_free( stream->buf );
stream->buf = NULL;
stream->size = stream->allocated = stream->pos = 0;
stream->state = adStateClosed;
return S_OK;
}
@ -231,8 +293,25 @@ static HRESULT WINAPI stream_SkipLine( _Stream *iface )
static HRESULT WINAPI stream_Write( _Stream *iface, VARIANT buf )
{
FIXME( "%p, %s\n", iface, debugstr_variant(&buf) );
return E_NOTIMPL;
struct stream *stream = impl_from_Stream( iface );
LONG bound, i;
HRESULT hr;
TRACE( "%p, %s\n", stream, debugstr_variant(&buf) );
if (stream->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
if (stream->type != adTypeBinary) return MAKE_ADO_HRESULT( adErrIllegalOperation );
if (V_VT( &buf ) != (VT_ARRAY | VT_UI1)) return MAKE_ADO_HRESULT( adErrInvalidArgument );
if ((hr = SafeArrayGetUBound( V_ARRAY( &buf ), 1, &bound )) != S_OK) return hr;
if ((hr = resize_buffer( stream, stream->size + bound + 1 )) != S_OK) return hr;
for (i = 0; i <= bound; i++)
{
if ((hr = SafeArrayGetElement( V_ARRAY( &buf ), &i, &stream->buf[stream->pos++] )) != S_OK) return hr;
}
return S_OK;
}
static HRESULT WINAPI stream_SetEOS( _Stream *iface )

View File

@ -25,13 +25,34 @@
#define MAKE_ADO_HRESULT( err ) MAKE_HRESULT( SEVERITY_ERROR, FACILITY_CONTROL, err )
static HRESULT str_to_byte_array( const char *data, VARIANT *ret )
{
SAFEARRAY *vector;
LONG i, len = strlen(data);
HRESULT hr;
if (!(vector = SafeArrayCreateVector( VT_UI1, 0, len ))) return E_OUTOFMEMORY;
for (i = 0; i < len; i++)
{
if ((hr = SafeArrayPutElement( vector, &i, (void *)&data[i] )) != S_OK)
{
SafeArrayDestroy( vector );
return hr;
}
}
V_VT( ret ) = VT_ARRAY | VT_UI1;
V_ARRAY( ret ) = vector;
return S_OK;
}
static void test_Stream(void)
{
_Stream *stream;
StreamTypeEnum type;
LONG refs;
ObjectStateEnum state;
VARIANT missing;
VARIANT missing, val;
HRESULT hr;
hr = CoCreateInstance( &CLSID_Stream, NULL, CLSCTX_INPROC_SERVER, &IID__Stream, (void **)&stream );
@ -60,6 +81,9 @@ static void test_Stream(void)
ok( hr == S_OK, "got %08x\n", hr );
ok( state == adStateClosed, "got %u\n", state );
hr = _Stream_Read( stream, 2, &val );
ok( hr == MAKE_ADO_HRESULT( adErrObjectClosed ), "got %08x\n", hr );
V_VT( &missing ) = VT_ERROR;
V_ERROR( &missing ) = DISP_E_PARAMNOTFOUND;
hr = _Stream_Open( stream, missing, adModeUnknown, adOpenStreamUnspecified, NULL, NULL );
@ -73,6 +97,9 @@ static void test_Stream(void)
ok( hr == S_OK, "got %08x\n", hr );
ok( state == adStateOpen, "got %u\n", state );
hr = _Stream_Read( stream, 2, &val );
ok( hr == MAKE_ADO_HRESULT( adErrIllegalOperation ), "got %08x\n", hr );
hr = _Stream_Close( stream );
ok( hr == S_OK, "got %08x\n", hr );
@ -86,6 +113,34 @@ static void test_Stream(void)
refs = _Stream_Release( stream );
ok( !refs, "got %d\n", refs );
/* binary type */
hr = CoCreateInstance( &CLSID_Stream, NULL, CLSCTX_INPROC_SERVER, &IID__Stream, (void **)&stream );
ok( hr == S_OK, "got %08x\n", hr );
hr = _Stream_put_Type( stream, adTypeBinary );
ok( hr == S_OK, "got %08x\n", hr );
hr = _Stream_Open( stream, missing, adModeUnknown, adOpenStreamUnspecified, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
VariantInit( &val );
hr = _Stream_Read( stream, 1, &val );
ok( hr == S_OK, "got %08x\n", hr );
ok( V_VT( &val ) == VT_NULL, "got %u\n", V_VT( &val ) );
VariantInit( &val );
hr = _Stream_Write( stream, val );
ok( hr == MAKE_ADO_HRESULT( adErrInvalidArgument ), "got %08x\n", hr );
hr = str_to_byte_array( "data", &val );
ok( hr == S_OK, "got %08x\n", hr );
hr = _Stream_Write( stream, val );
ok( hr == S_OK, "got %08x\n", hr );
VariantClear( &val );
refs = _Stream_Release( stream );
ok( !refs, "got %d\n", refs );
}
START_TEST(msado15)