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
25 #include "msado15_backcompat.h"
27 #include "wine/debug.h"
28 #include "wine/heap.h"
30 #include "msado15_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msado15
);
38 ObjectStateEnum state
;
41 LineSeparatorEnum sep
;
49 static inline struct stream
*impl_from_Stream( _Stream
*iface
)
51 return CONTAINING_RECORD( iface
, struct stream
, Stream_iface
);
54 static ULONG WINAPI
stream_AddRef( _Stream
*iface
)
56 struct stream
*stream
= impl_from_Stream( iface
);
57 return InterlockedIncrement( &stream
->refs
);
60 static ULONG WINAPI
stream_Release( _Stream
*iface
)
62 struct stream
*stream
= impl_from_Stream( iface
);
63 LONG refs
= InterlockedDecrement( &stream
->refs
);
66 TRACE( "destroying %p\n", stream
);
67 heap_free( stream
->charset
);
68 heap_free( stream
->buf
);
74 static HRESULT WINAPI
stream_QueryInterface( _Stream
*iface
, REFIID riid
, void **obj
)
76 TRACE( "%p, %s, %p\n", iface
, debugstr_guid(riid
), obj
);
78 if (IsEqualGUID( riid
, &IID__Stream
) || IsEqualGUID( riid
, &IID_IDispatch
) ||
79 IsEqualGUID( riid
, &IID_IUnknown
))
85 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
88 stream_AddRef( iface
);
92 static HRESULT WINAPI
stream_GetTypeInfoCount( _Stream
*iface
, UINT
*count
)
94 struct stream
*stream
= impl_from_Stream( iface
);
95 TRACE( "%p, %p\n", stream
, count
);
100 static HRESULT WINAPI
stream_GetTypeInfo( _Stream
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
102 struct stream
*stream
= impl_from_Stream( iface
);
103 TRACE( "%p, %u, %u, %p\n", stream
, index
, lcid
, info
);
104 return get_typeinfo(Stream_tid
, info
);
107 static HRESULT WINAPI
stream_GetIDsOfNames( _Stream
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
108 LCID lcid
, DISPID
*dispid
)
110 struct stream
*stream
= impl_from_Stream( iface
);
114 TRACE( "%p, %s, %p, %u, %u, %p\n", stream
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
116 hr
= get_typeinfo(Stream_tid
, &typeinfo
);
119 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, dispid
);
120 ITypeInfo_Release(typeinfo
);
126 static HRESULT WINAPI
stream_Invoke( _Stream
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
127 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
129 struct stream
*stream
= impl_from_Stream( iface
);
133 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", stream
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
134 result
, excep_info
, arg_err
);
136 hr
= get_typeinfo(Stream_tid
, &typeinfo
);
139 hr
= ITypeInfo_Invoke(typeinfo
, &stream
->Stream_iface
, member
, flags
, params
,
140 result
, excep_info
, arg_err
);
141 ITypeInfo_Release(typeinfo
);
147 static HRESULT WINAPI
stream_get_Size( _Stream
*iface
, LONG
*size
)
149 struct stream
*stream
= impl_from_Stream( iface
);
150 TRACE( "%p, %p\n", stream
, size
);
152 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
154 *size
= stream
->size
;
158 static HRESULT WINAPI
stream_get_EOS( _Stream
*iface
, VARIANT_BOOL
*eos
)
160 struct stream
*stream
= impl_from_Stream( iface
);
161 TRACE( "%p, %p\n", stream
, eos
);
163 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
165 *eos
= (stream
->pos
>= stream
->size
) ? VARIANT_TRUE
: VARIANT_FALSE
;
169 static HRESULT WINAPI
stream_get_Position( _Stream
*iface
, LONG
*pos
)
171 struct stream
*stream
= impl_from_Stream( iface
);
172 TRACE( "%p, %p\n", stream
, pos
);
174 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
180 static HRESULT
resize_buffer( struct stream
*stream
, LONG size
)
182 if (stream
->allocated
< size
)
185 LONG new_size
= max( size
, stream
->allocated
* 2 );
186 if (!(tmp
= heap_realloc_zero( stream
->buf
, new_size
))) return E_OUTOFMEMORY
;
188 stream
->allocated
= new_size
;
194 static HRESULT WINAPI
stream_put_Position( _Stream
*iface
, LONG pos
)
196 struct stream
*stream
= impl_from_Stream( iface
);
199 TRACE( "%p, %d\n", stream
, pos
);
201 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
202 if (pos
< 0) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
204 if ((hr
= resize_buffer( stream
, stream
->pos
)) != S_OK
) return hr
;
209 static HRESULT WINAPI
stream_get_Type( _Stream
*iface
, StreamTypeEnum
*type
)
211 struct stream
*stream
= impl_from_Stream( iface
);
212 TRACE( "%p, %p\n", stream
, type
);
214 *type
= stream
->type
;
218 static HRESULT WINAPI
stream_put_Type( _Stream
*iface
, StreamTypeEnum type
)
220 struct stream
*stream
= impl_from_Stream( iface
);
221 TRACE( "%p, %u\n", stream
, type
);
227 static HRESULT WINAPI
stream_get_LineSeparator( _Stream
*iface
, LineSeparatorEnum
*sep
)
229 struct stream
*stream
= impl_from_Stream( iface
);
230 TRACE( "%p, %p\n", stream
, sep
);
236 static HRESULT WINAPI
stream_put_LineSeparator( _Stream
*iface
, LineSeparatorEnum sep
)
238 struct stream
*stream
= impl_from_Stream( iface
);
239 TRACE( "%p, %d\n", stream
, sep
);
245 static HRESULT WINAPI
stream_get_State( _Stream
*iface
, ObjectStateEnum
*state
)
247 struct stream
*stream
= impl_from_Stream( iface
);
248 TRACE( "%p, %p\n", stream
, state
);
250 *state
= stream
->state
;
254 static HRESULT WINAPI
stream_get_Mode( _Stream
*iface
, ConnectModeEnum
*mode
)
256 struct stream
*stream
= impl_from_Stream( iface
);
257 TRACE( "%p, %p\n", stream
, mode
);
259 *mode
= stream
->mode
;
263 static HRESULT WINAPI
stream_put_Mode( _Stream
*iface
, ConnectModeEnum mode
)
265 struct stream
*stream
= impl_from_Stream( iface
);
266 TRACE( "%p, %u\n", stream
, mode
);
272 static HRESULT WINAPI
stream_get_Charset( _Stream
*iface
, BSTR
*charset
)
274 struct stream
*stream
= impl_from_Stream( iface
);
275 const WCHAR
*src
= stream
->charset
? stream
->charset
: L
"Unicode";
278 TRACE( "%p, %p\n", stream
, charset
);
280 if (!(dst
= SysAllocString( src
))) return E_OUTOFMEMORY
;
285 static HRESULT WINAPI
stream_put_Charset( _Stream
*iface
, BSTR charset
)
287 struct stream
*stream
= impl_from_Stream( iface
);
290 TRACE( "%p, %s\n", stream
, debugstr_w(charset
) );
292 if (!(str
= strdupW( charset
))) return E_OUTOFMEMORY
;
293 heap_free( stream
->charset
);
294 stream
->charset
= str
;
298 static HRESULT
create_byte_array( BYTE
*data
, LONG len
, VARIANT
*ret
)
306 V_VT( ret
) = VT_NULL
;
309 if (!(vector
= SafeArrayCreateVector( VT_UI1
, 0, len
))) return E_OUTOFMEMORY
;
310 for (i
= 0; i
< len
; i
++)
312 if ((hr
= SafeArrayPutElement( vector
, &i
, &data
[i
] )) != S_OK
)
314 SafeArrayDestroy( vector
);
319 V_VT( ret
) = VT_ARRAY
| VT_UI1
;
320 V_ARRAY( ret
) = vector
;
324 static HRESULT WINAPI
stream_Read( _Stream
*iface
, LONG size
, VARIANT
*val
)
326 struct stream
*stream
= impl_from_Stream( iface
);
329 TRACE( "%p, %d, %p\n", stream
, size
, val
);
331 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
332 if (stream
->type
!= adTypeBinary
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
333 if (size
< adReadAll
) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
335 if (size
== adReadAll
) size
= stream
->size
- stream
->pos
;
336 else size
= min( size
, stream
->size
- stream
->pos
);
338 if ((hr
= create_byte_array( stream
->buf
+ stream
->pos
, size
, val
)) != S_OK
) return hr
;
343 static HRESULT WINAPI
stream_Open( _Stream
*iface
, VARIANT src
, ConnectModeEnum mode
, StreamOpenOptionsEnum options
,
344 BSTR username
, BSTR password
)
346 struct stream
*stream
= impl_from_Stream( iface
);
347 FIXME( "%p, %s, %u, %d, %s, %p\n", stream
, debugstr_variant(&src
), mode
, options
, debugstr_w(username
), password
);
349 if (stream
->state
== adStateOpen
) return MAKE_ADO_HRESULT( adErrObjectOpen
);
351 stream
->state
= adStateOpen
;
355 static HRESULT WINAPI
stream_Close( _Stream
*iface
)
357 struct stream
*stream
= impl_from_Stream( iface
);
359 TRACE( "%p\n", stream
);
361 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
363 heap_free( stream
->buf
);
365 stream
->size
= stream
->allocated
= stream
->pos
= 0;
367 stream
->state
= adStateClosed
;
371 static HRESULT WINAPI
stream_SkipLine( _Stream
*iface
)
373 FIXME( "%p\n", iface
);
377 static HRESULT WINAPI
stream_Write( _Stream
*iface
, VARIANT buf
)
379 struct stream
*stream
= impl_from_Stream( iface
);
383 TRACE( "%p, %s\n", stream
, debugstr_variant(&buf
) );
385 if (stream
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
386 if (stream
->type
!= adTypeBinary
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
387 if (V_VT( &buf
) != (VT_ARRAY
| VT_UI1
)) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
389 if ((hr
= SafeArrayGetUBound( V_ARRAY( &buf
), 1, &bound
)) != S_OK
) return hr
;
390 if ((hr
= resize_buffer( stream
, stream
->size
+ bound
+ 1 )) != S_OK
) return hr
;
392 for (i
= 0; i
<= bound
; i
++)
394 if ((hr
= SafeArrayGetElement( V_ARRAY( &buf
), &i
, &stream
->buf
[stream
->pos
++] )) != S_OK
) return hr
;
400 static HRESULT WINAPI
stream_SetEOS( _Stream
*iface
)
402 struct stream
*stream
= impl_from_Stream( iface
);
404 TRACE( "%p\n", stream
);
406 return resize_buffer( stream
, stream
->pos
);
409 static HRESULT WINAPI
stream_CopyTo( _Stream
*iface
, _Stream
*dst
, LONG size
)
411 FIXME( "%p, %p, %d\n", iface
, dst
, size
);
415 static HRESULT WINAPI
stream_Flush( _Stream
*iface
)
417 FIXME( "%p\n", iface
);
421 static HRESULT WINAPI
stream_SaveToFile( _Stream
*iface
, BSTR filename
, SaveOptionsEnum options
)
423 FIXME( "%p, %s, %u\n", iface
, debugstr_w(filename
), options
);
427 static HRESULT WINAPI
stream_LoadFromFile( _Stream
*iface
, BSTR filename
)
429 FIXME( "%p, %s\n", iface
, debugstr_w(filename
) );
433 static HRESULT WINAPI
stream_ReadText( _Stream
*iface
, LONG len
, BSTR
*ret
)
435 struct stream
*stream
= impl_from_Stream( iface
);
438 TRACE( "%p, %d, %p\n", stream
, len
, ret
);
439 if (len
== adReadLine
)
441 FIXME( "adReadLine not supported\n" );
444 if (stream
->charset
&& wcscmp( stream
->charset
, L
"Unicode" ))
446 FIXME( "charset %s not supported\n", debugstr_w(stream
->charset
) );
450 if (stream
->type
!= adTypeText
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
451 if (len
< adReadLine
) return MAKE_ADO_HRESULT( adErrInvalidArgument
);
453 if (len
== adReadAll
) len
= (stream
->size
- stream
->pos
) / sizeof(WCHAR
);
454 else len
= min( len
, stream
->size
- stream
->pos
/ sizeof(WCHAR
) );
456 if (!(str
= SysAllocStringLen( NULL
, len
))) return E_OUTOFMEMORY
;
457 memcpy( str
, stream
->buf
+ stream
->pos
, len
* sizeof(WCHAR
) );
460 stream
->pos
+= len
* sizeof(WCHAR
);
466 static HRESULT WINAPI
stream_WriteText( _Stream
*iface
, BSTR data
, StreamWriteEnum options
)
468 struct stream
*stream
= impl_from_Stream( iface
);
472 TRACE( "%p, %s, %u\n", stream
, debugstr_w(data
), options
);
473 if (options
!= adWriteChar
)
475 FIXME( "options %u not supported\n", options
);
478 if (stream
->charset
&& wcscmp( stream
->charset
, L
"Unicode" ))
480 FIXME( "charset %s not supported\n", debugstr_w(stream
->charset
) );
484 if (stream
->type
!= adTypeText
) return MAKE_ADO_HRESULT( adErrIllegalOperation
);
486 size
= (lstrlenW( data
) + 1) * sizeof(WCHAR
);
487 if ((hr
= resize_buffer( stream
, stream
->size
+ size
)) != S_OK
) return hr
;
489 memcpy( stream
->buf
+ stream
->pos
, data
, size
);
495 static HRESULT WINAPI
stream_Cancel( _Stream
*iface
)
497 FIXME( "%p\n", iface
);
501 static const struct _StreamVtbl stream_vtbl
=
503 stream_QueryInterface
,
506 stream_GetTypeInfoCount
,
508 stream_GetIDsOfNames
,
516 stream_get_LineSeparator
,
517 stream_put_LineSeparator
,
538 HRESULT
Stream_create( void **obj
)
540 struct stream
*stream
;
542 if (!(stream
= heap_alloc_zero( sizeof(*stream
) ))) return E_OUTOFMEMORY
;
543 stream
->Stream_iface
.lpVtbl
= &stream_vtbl
;
545 stream
->type
= adTypeText
;
546 stream
->sep
= adCRLF
;
548 *obj
= &stream
->Stream_iface
;
549 TRACE( "returning iface %p\n", *obj
);