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:
parent
6463db0c4b
commit
59c8fb9c3e
|
@ -25,4 +25,10 @@ HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
|
||||||
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
|
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
|
||||||
HRESULT Stream_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_ */
|
#endif /* _WINE_MSADO15_PRIVATE_H_ */
|
||||||
|
|
|
@ -36,6 +36,10 @@ struct stream
|
||||||
LONG refs;
|
LONG refs;
|
||||||
ObjectStateEnum state;
|
ObjectStateEnum state;
|
||||||
StreamTypeEnum type;
|
StreamTypeEnum type;
|
||||||
|
LONG size;
|
||||||
|
LONG allocated;
|
||||||
|
LONG pos;
|
||||||
|
BYTE *buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct stream *impl_from_Stream( _Stream *iface )
|
static inline struct stream *impl_from_Stream( _Stream *iface )
|
||||||
|
@ -56,6 +60,7 @@ static ULONG WINAPI stream_Release( _Stream *iface )
|
||||||
if (!refs)
|
if (!refs)
|
||||||
{
|
{
|
||||||
TRACE( "destroying %p\n", stream );
|
TRACE( "destroying %p\n", stream );
|
||||||
|
heap_free( stream->buf );
|
||||||
heap_free( stream );
|
heap_free( stream );
|
||||||
}
|
}
|
||||||
return refs;
|
return refs;
|
||||||
|
@ -124,6 +129,20 @@ static HRESULT WINAPI stream_get_Position( _Stream *iface, LONG *pos )
|
||||||
return E_NOTIMPL;
|
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 )
|
static HRESULT WINAPI stream_put_Position( _Stream *iface, LONG pos )
|
||||||
{
|
{
|
||||||
FIXME( "%p, %d\n", iface, pos );
|
FIXME( "%p, %d\n", iface, pos );
|
||||||
|
@ -193,10 +212,49 @@ static HRESULT WINAPI stream_put_Charset( _Stream *iface, BSTR charset )
|
||||||
return E_NOTIMPL;
|
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 )
|
static HRESULT WINAPI stream_Read( _Stream *iface, LONG size, VARIANT *val )
|
||||||
{
|
{
|
||||||
FIXME( "%p, %d, %p\n", iface, size, val );
|
struct stream *stream = impl_from_Stream( iface );
|
||||||
return E_NOTIMPL;
|
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,
|
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 );
|
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;
|
stream->state = adStateClosed;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -231,8 +293,25 @@ static HRESULT WINAPI stream_SkipLine( _Stream *iface )
|
||||||
|
|
||||||
static HRESULT WINAPI stream_Write( _Stream *iface, VARIANT buf )
|
static HRESULT WINAPI stream_Write( _Stream *iface, VARIANT buf )
|
||||||
{
|
{
|
||||||
FIXME( "%p, %s\n", iface, debugstr_variant(&buf) );
|
struct stream *stream = impl_from_Stream( iface );
|
||||||
return E_NOTIMPL;
|
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 )
|
static HRESULT WINAPI stream_SetEOS( _Stream *iface )
|
||||||
|
|
|
@ -25,13 +25,34 @@
|
||||||
|
|
||||||
#define MAKE_ADO_HRESULT( err ) MAKE_HRESULT( SEVERITY_ERROR, FACILITY_CONTROL, err )
|
#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)
|
static void test_Stream(void)
|
||||||
{
|
{
|
||||||
_Stream *stream;
|
_Stream *stream;
|
||||||
StreamTypeEnum type;
|
StreamTypeEnum type;
|
||||||
LONG refs;
|
LONG refs;
|
||||||
ObjectStateEnum state;
|
ObjectStateEnum state;
|
||||||
VARIANT missing;
|
VARIANT missing, val;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = CoCreateInstance( &CLSID_Stream, NULL, CLSCTX_INPROC_SERVER, &IID__Stream, (void **)&stream );
|
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( hr == S_OK, "got %08x\n", hr );
|
||||||
ok( state == adStateClosed, "got %u\n", state );
|
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_VT( &missing ) = VT_ERROR;
|
||||||
V_ERROR( &missing ) = DISP_E_PARAMNOTFOUND;
|
V_ERROR( &missing ) = DISP_E_PARAMNOTFOUND;
|
||||||
hr = _Stream_Open( stream, missing, adModeUnknown, adOpenStreamUnspecified, NULL, NULL );
|
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( hr == S_OK, "got %08x\n", hr );
|
||||||
ok( state == adStateOpen, "got %u\n", state );
|
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 );
|
hr = _Stream_Close( stream );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
@ -86,6 +113,34 @@ static void test_Stream(void)
|
||||||
|
|
||||||
refs = _Stream_Release( stream );
|
refs = _Stream_Release( stream );
|
||||||
ok( !refs, "got %d\n", refs );
|
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)
|
START_TEST(msado15)
|
||||||
|
|
Loading…
Reference in New Issue