[PATCH 3/5] msado15: Implement _Stream_Read and _Stream_Write.
Hans Leidekker
hans at codeweavers.com
Mon Dec 9 04:24:31 CST 2019
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/msado15/msado15_private.h | 6 +++
dlls/msado15/stream.c | 95 +++++++++++++++++++++++++++++++---
dlls/msado15/tests/msado15.c | 57 +++++++++++++++++++-
3 files changed, 149 insertions(+), 9 deletions(-)
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
index f901791ea9..1078cbf64e 100644
--- a/dlls/msado15/msado15_private.h
+++ b/dlls/msado15/msado15_private.h
@@ -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_ */
diff --git a/dlls/msado15/stream.c b/dlls/msado15/stream.c
index cc67e930a4..d5a129f869 100644
--- a/dlls/msado15/stream.c
+++ b/dlls/msado15/stream.c
@@ -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 )
diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c
index 9733116151..257d1c26fa 100644
--- a/dlls/msado15/tests/msado15.c
+++ b/dlls/msado15/tests/msado15.c
@@ -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)
--
2.20.1
More information about the wine-devel
mailing list