2 * Copyright 2019 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "msado15_backcompat.h"
26 #include "wine/debug.h"
27 #include "wine/heap.h"
29 #include "msado15_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msado15
);
37 ObjectStateEnum state
;
40 LineSeparatorEnum sep
;
48 static inline struct stream
*impl_from_Stream( _Stream
*iface
)
50 return CONTAINING_RECORD( iface
, struct stream
, Stream_iface
);
53 static ULONG WINAPI
stream_AddRef( _Stream
*iface
)
55 struct stream
*stream
= impl_from_Stream( iface
);
56 return InterlockedIncrement( &stream
->refs
);
59 static ULONG WINAPI
stream_Release( _Stream
*iface
)
61 struct stream
*stream
= impl_from_Stream( iface
);
62 LONG refs
= InterlockedDecrement( &stream
->refs
);
65 TRACE( "destroying %p\n", stream
);
66 heap_free( stream
->charset
);
67 heap_free( stream
->buf
);
73 static HRESULT WINAPI
stream_QueryInterface( _Stream
*iface
, REFIID riid
, void **obj
)
75 TRACE( "%p, %s, %p\n", iface
, debugstr_guid(riid
), obj
);
77 if (IsEqualGUID( riid
, &IID__Stream
) || IsEqualGUID( riid
, &IID_IDispatch
) ||
78 IsEqualGUID( riid
, &IID_IUnknown
))
84 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
87 stream_AddRef( iface
);
91 static HRESULT WINAPI
stream_GetTypeInfoCount( _Stream
*iface
, UINT
*count
)
93 FIXME( "%p, %p\n", iface
, count
);
97 static HRESULT WINAPI
stream_GetTypeInfo( _Stream
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
99 FIXME( "%p, %u, %u, %p\n", iface
, index
, lcid
, info
);
103 static HRESULT WINAPI
stream_GetIDsOfNames( _Stream
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
104 LCID lcid
, DISPID
*dispid
)
106 FIXME( "%p, %s, %p, %u, %u, %p\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
110 static HRESULT WINAPI
stream_Invoke( _Stream
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
111 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
113 FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
114 result
, excep_info
, arg_err
);
118 static HRESULT WINAPI
stream_get_Size( _Stream
*iface
, LONG
*size
)
120 struct stream
*stream
= impl_from_Stream( iface
);
121 TRACE( "%p, %p\n", stream
, size
);
123 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
125 *size
= stream
->size
;
129 static HRESULT WINAPI
stream_get_EOS( _Stream
*iface
, VARIANT_BOOL
*eos
)
131 struct stream
*stream
= impl_from_Stream( iface
);
132 TRACE( "%p, %p\n", stream
, eos
);
134 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
136 *eos
= (stream
->pos
>= stream
->size
) ? VARIANT_TRUE
: VARIANT_FALSE
;
140 static HRESULT WINAPI
stream_get_Position( _Stream
*iface
, LONG
*pos
)
142 struct stream
*stream
= impl_from_Stream( iface
);
143 TRACE( "%p, %p\n", stream
, pos
);
145 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
151 static HRESULT
resize_buffer( struct stream
*stream
, LONG size
)
153 if (stream
->allocated
< size
)
156 LONG new_size
= max( size
, stream
->allocated
* 2 );
157 if (!(tmp
= heap_realloc_zero( stream
->buf
, new_size
))) return E_OUTOFMEMORY
;
159 stream
->allocated
= new_size
;
165 static HRESULT WINAPI
stream_put_Position( _Stream
*iface
, LONG pos
)
167 struct stream
*stream
= impl_from_Stream( iface
);
170 TRACE( "%p, %d\n", stream
, pos
);
172 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
173 if (pos
< 0) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
175 if ((hr
= resize_buffer( stream
, stream
->pos
)) != S_OK
) return hr
;
180 static HRESULT WINAPI
stream_get_Type( _Stream
*iface
, StreamTypeEnum
*type
)
182 struct stream
*stream
= impl_from_Stream( iface
);
183 TRACE( "%p, %p\n", stream
, type
);
185 *type
= stream
->type
;
189 static HRESULT WINAPI
stream_put_Type( _Stream
*iface
, StreamTypeEnum type
)
191 struct stream
*stream
= impl_from_Stream( iface
);
192 TRACE( "%p, %u\n", stream
, type
);
198 static HRESULT WINAPI
stream_get_LineSeparator( _Stream
*iface
, LineSeparatorEnum
*sep
)
200 struct stream
*stream
= impl_from_Stream( iface
);
201 TRACE( "%p, %p\n", stream
, sep
);
207 static HRESULT WINAPI
stream_put_LineSeparator( _Stream
*iface
, LineSeparatorEnum sep
)
209 struct stream
*stream
= impl_from_Stream( iface
);
210 TRACE( "%p, %d\n", stream
, sep
);
216 static HRESULT WINAPI
stream_get_State( _Stream
*iface
, ObjectStateEnum
*state
)
218 struct stream
*stream
= impl_from_Stream( iface
);
219 TRACE( "%p, %p\n", stream
, state
);
221 *state
= stream
->state
;
225 static HRESULT WINAPI
stream_get_Mode( _Stream
*iface
, ConnectModeEnum
*mode
)
227 struct stream
*stream
= impl_from_Stream( iface
);
228 TRACE( "%p, %p\n", stream
, mode
);
230 *mode
= stream
->mode
;
234 static HRESULT WINAPI
stream_put_Mode( _Stream
*iface
, ConnectModeEnum mode
)
236 struct stream
*stream
= impl_from_Stream( iface
);
237 TRACE( "%p, %u\n", stream
, mode
);
243 static HRESULT WINAPI
stream_get_Charset( _Stream
*iface
, BSTR
*charset
)
245 struct stream
*stream
= impl_from_Stream( iface
);
246 const WCHAR
*src
= stream
->charset
? stream
->charset
: L
"Unicode";
249 TRACE( "%p, %p\n", stream
, charset
);
251 if (!(dst
= SysAllocString( src
))) return E_OUTOFMEMORY
;
256 static HRESULT WINAPI
stream_put_Charset( _Stream
*iface
, BSTR charset
)
258 struct stream
*stream
= impl_from_Stream( iface
);
261 TRACE( "%p, %s\n", stream
, debugstr_w(charset
) );
263 if (!(str
= strdupW( charset
))) return E_OUTOFMEMORY
;
264 heap_free( stream
->charset
);
265 stream
->charset
= str
;
269 static HRESULT
create_byte_array( BYTE
*data
, LONG len
, VARIANT
*ret
)
277 V_VT( ret
) = VT_NULL
;
280 if (!(vector
= SafeArrayCreateVector( VT_UI1
, 0, len
))) return E_OUTOFMEMORY
;
281 for (i
= 0; i
< len
; i
++)
283 if ((hr
= SafeArrayPutElement( vector
, &i
, &data
[i
] )) != S_OK
)
285 SafeArrayDestroy( vector
);
290 V_VT( ret
) = VT_ARRAY
| VT_UI1
;
291 V_ARRAY( ret
) = vector
;
295 static HRESULT WINAPI
stream_Read( _Stream
*iface
, LONG size
, VARIANT
*val
)
297 struct stream
*stream
= impl_from_Stream( iface
);
300 TRACE( "%p, %d, %p\n", stream
, size
, val
);
302 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
303 if (stream
->type
!= adTypeBinary
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
304 if (size
< adReadAll
) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
306 if (size
== adReadAll
) size
= stream
->size
- stream
->pos
;
307 else size
= min( size
, stream
->size
- stream
->pos
);
309 if ((hr
= create_byte_array( stream
->buf
+ stream
->pos
, size
, val
)) != S_OK
) return hr
;
314 static HRESULT WINAPI
stream_Open( _Stream
*iface
, VARIANT src
, ConnectModeEnum mode
, StreamOpenOptionsEnum options
,
315 BSTR username
, BSTR password
)
317 struct stream
*stream
= impl_from_Stream( iface
);
318 FIXME( "%p, %s, %u, %d, %s, %p\n", stream
, debugstr_variant(&src
), mode
, options
, debugstr_w(username
), password
);
320 if (stream
->state
== adStateOpen
) return MAKE_ADO_HRESULT( adErrObjectOpen
);
322 stream
->state
= adStateOpen
;
326 static HRESULT WINAPI
stream_Close( _Stream
*iface
)
328 struct stream
*stream
= impl_from_Stream( iface
);
330 TRACE( "%p\n", stream
);
332 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
334 heap_free( stream
->buf
);
336 stream
->size
= stream
->allocated
= stream
->pos
= 0;
338 stream
->state
= adStateClosed
;
342 static HRESULT WINAPI
stream_SkipLine( _Stream
*iface
)
344 FIXME( "%p\n", iface
);
348 static HRESULT WINAPI
stream_Write( _Stream
*iface
, VARIANT buf
)
350 struct stream
*stream
= impl_from_Stream( iface
);
354 TRACE( "%p, %s\n", stream
, debugstr_variant(&buf
) );
356 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
357 if (stream
->type
!= adTypeBinary
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
358 if (V_VT( &buf
) != (VT_ARRAY
| VT_UI1
)) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
360 if ((hr
= SafeArrayGetUBound( V_ARRAY( &buf
), 1, &bound
)) != S_OK
) return hr
;
361 if ((hr
= resize_buffer( stream
, stream
->size
+ bound
+ 1 )) != S_OK
) return hr
;
363 for (i
= 0; i
<= bound
; i
++)
365 if ((hr
= SafeArrayGetElement( V_ARRAY( &buf
), &i
, &stream
->buf
[stream
->pos
++] )) != S_OK
) return hr
;
371 static HRESULT WINAPI
stream_SetEOS( _Stream
*iface
)
373 struct stream
*stream
= impl_from_Stream( iface
);
375 TRACE( "%p\n", stream
);
377 return resize_buffer( stream
, stream
->pos
);
380 static HRESULT WINAPI
stream_CopyTo( _Stream
*iface
, _Stream
*dst
, LONG size
)
382 FIXME( "%p, %p, %d\n", iface
, dst
, size
);
386 static HRESULT WINAPI
stream_Flush( _Stream
*iface
)
388 FIXME( "%p\n", iface
);
392 static HRESULT WINAPI
stream_SaveToFile( _Stream
*iface
, BSTR filename
, SaveOptionsEnum options
)
394 FIXME( "%p, %s, %u\n", iface
, debugstr_w(filename
), options
);
398 static HRESULT WINAPI
stream_LoadFromFile( _Stream
*iface
, BSTR filename
)
400 FIXME( "%p, %s\n", iface
, debugstr_w(filename
) );
404 static HRESULT WINAPI
stream_ReadText( _Stream
*iface
, LONG len
, BSTR
*ret
)
406 struct stream
*stream
= impl_from_Stream( iface
);
409 TRACE( "%p, %d, %p\n", stream
, len
, ret
);
410 if (len
== adReadLine
)
412 FIXME( "adReadLine not supported\n" );
415 if (stream
->charset
&& wcscmp( stream
->charset
, L
"Unicode" ))
417 FIXME( "charset %s not supported\n", debugstr_w(stream
->charset
) );
421 if (stream
->type
!= adTypeText
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
422 if (len
< adReadLine
) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
424 if (len
== adReadAll
) len
= (stream
->size
- stream
->pos
) / sizeof(WCHAR
);
425 else len
= min( len
, stream
->size
- stream
->pos
/ sizeof(WCHAR
) );
427 if (!(str
= SysAllocStringLen( NULL
, len
))) return E_OUTOFMEMORY
;
428 memcpy( str
, stream
->buf
+ stream
->pos
, len
* sizeof(WCHAR
) );
431 stream
->pos
+= len
* sizeof(WCHAR
);
437 static HRESULT WINAPI
stream_WriteText( _Stream
*iface
, BSTR data
, StreamWriteEnum options
)
439 struct stream
*stream
= impl_from_Stream( iface
);
443 TRACE( "%p, %s, %u\n", stream
, debugstr_w(data
), options
);
444 if (options
!= adWriteChar
)
446 FIXME( "options %u not supported\n", options
);
449 if (stream
->charset
&& wcscmp( stream
->charset
, L
"Unicode" ))
451 FIXME( "charset %s not supported\n", debugstr_w(stream
->charset
) );
455 if (stream
->type
!= adTypeText
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
457 size
= (lstrlenW( data
) + 1) * sizeof(WCHAR
);
458 if ((hr
= resize_buffer( stream
, stream
->size
+ size
)) != S_OK
) return hr
;
460 memcpy( stream
->buf
+ stream
->pos
, data
, size
);
466 static HRESULT WINAPI
stream_Cancel( _Stream
*iface
)
468 FIXME( "%p\n", iface
);
472 static const struct _StreamVtbl stream_vtbl
=
474 stream_QueryInterface
,
477 stream_GetTypeInfoCount
,
479 stream_GetIDsOfNames
,
487 stream_get_LineSeparator
,
488 stream_put_LineSeparator
,
509 HRESULT
Stream_create( void **obj
)
511 struct stream
*stream
;
513 if (!(stream
= heap_alloc_zero( sizeof(*stream
) ))) return E_OUTOFMEMORY
;
514 stream
->Stream_iface
.lpVtbl
= &stream_vtbl
;
516 stream
->type
= adTypeText
;
517 stream
->sep
= adCRLF
;
519 *obj
= &stream
->Stream_iface
;
520 TRACE( "returning iface %p\n", *obj
);