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 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_ */
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue