d3dcompiler: Allow D3DCompile2() to succeed with null output shader blob pointer.
[wine.git] / dlls / msado15 / stream.c
blob50833aecf34b4942331350b3470533abba072dec
1 /*
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
19 #include <stdarg.h>
20 #include "windef.h"
21 #include "winbase.h"
22 #define COBJMACROS
23 #include "objbase.h"
24 #include "msdasc.h"
25 #include "msado15_backcompat.h"
27 #include "wine/debug.h"
29 #include "msado15_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msado15);
33 struct stream
35 _Stream Stream_iface;
36 LONG refs;
37 ObjectStateEnum state;
38 ConnectModeEnum mode;
39 StreamTypeEnum type;
40 LineSeparatorEnum sep;
41 WCHAR *charset;
42 LONG size;
43 LONG allocated;
44 LONG pos;
45 BYTE *buf;
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 );
63 if (!refs)
65 TRACE( "destroying %p\n", stream );
66 free( stream->charset );
67 free( stream->buf );
68 free( stream );
70 return refs;
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 ))
80 *obj = iface;
82 else
84 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
85 return E_NOINTERFACE;
87 stream_AddRef( iface );
88 return S_OK;
91 static HRESULT WINAPI stream_GetTypeInfoCount( _Stream *iface, UINT *count )
93 struct stream *stream = impl_from_Stream( iface );
94 TRACE( "%p, %p\n", stream, count );
95 *count = 1;
96 return S_OK;
99 static HRESULT WINAPI stream_GetTypeInfo( _Stream *iface, UINT index, LCID lcid, ITypeInfo **info )
101 struct stream *stream = impl_from_Stream( iface );
102 TRACE( "%p, %u, %lu, %p\n", stream, index, lcid, info );
103 return get_typeinfo(Stream_tid, info);
106 static HRESULT WINAPI stream_GetIDsOfNames( _Stream *iface, REFIID riid, LPOLESTR *names, UINT count,
107 LCID lcid, DISPID *dispid )
109 struct stream *stream = impl_from_Stream( iface );
110 HRESULT hr;
111 ITypeInfo *typeinfo;
113 TRACE( "%p, %s, %p, %u, %lu, %p\n", stream, debugstr_guid(riid), names, count, lcid, dispid );
115 hr = get_typeinfo(Stream_tid, &typeinfo);
116 if(SUCCEEDED(hr))
118 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
119 ITypeInfo_Release(typeinfo);
122 return hr;
125 static HRESULT WINAPI stream_Invoke( _Stream *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
126 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
128 struct stream *stream = impl_from_Stream( iface );
129 HRESULT hr;
130 ITypeInfo *typeinfo;
132 TRACE( "%p, %ld, %s, %ld, %d, %p, %p, %p, %p\n", stream, member, debugstr_guid(riid), lcid, flags, params,
133 result, excep_info, arg_err );
135 hr = get_typeinfo(Stream_tid, &typeinfo);
136 if(SUCCEEDED(hr))
138 hr = ITypeInfo_Invoke(typeinfo, &stream->Stream_iface, member, flags, params,
139 result, excep_info, arg_err);
140 ITypeInfo_Release(typeinfo);
143 return hr;
146 static HRESULT WINAPI stream_get_Size( _Stream *iface, ADO_LONGPTR *size )
148 struct stream *stream = impl_from_Stream( iface );
149 TRACE( "%p, %p\n", stream, size );
151 if (stream->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
153 *size = stream->size;
154 return S_OK;
157 static HRESULT WINAPI stream_get_EOS( _Stream *iface, VARIANT_BOOL *eos )
159 struct stream *stream = impl_from_Stream( iface );
160 TRACE( "%p, %p\n", stream, eos );
162 if (stream->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
164 *eos = (stream->pos >= stream->size) ? VARIANT_TRUE : VARIANT_FALSE;
165 return S_OK;
168 static HRESULT WINAPI stream_get_Position( _Stream *iface, ADO_LONGPTR *pos )
170 struct stream *stream = impl_from_Stream( iface );
171 TRACE( "%p, %p\n", stream, pos );
173 if (stream->state == adStateClosed) return MAKE_ADO_HRESULT( adErrObjectClosed );
175 *pos = stream->pos;
176 return S_OK;
179 static HRESULT resize_buffer( struct stream *stream, LONG size )
181 if (stream->allocated < size)
183 BYTE *tmp;
184 LONG new_size = max( size, stream->allocated * 2 );
185 if (!(tmp = realloc( stream->buf, new_size ))) return E_OUTOFMEMORY;
186 memset( tmp + stream->allocated, 0, new_size - stream->allocated );
187 stream->buf = tmp;
188 stream->allocated = new_size;
190 stream->size = size;
191 return S_OK;
194 static HRESULT WINAPI stream_put_Position( _Stream *iface, ADO_LONGPTR pos )
196 struct stream *stream = impl_from_Stream( iface );
197 HRESULT hr;
199 TRACE( "%p, %Id\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;
205 stream->pos = pos;
206 return S_OK;
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;
215 return S_OK;
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 );
223 stream->type = type;
224 return S_OK;
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 );
232 *sep = stream->sep;
233 return S_OK;
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 );
241 stream->sep = sep;
242 return S_OK;
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;
251 return S_OK;
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;
260 return S_OK;
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 );
268 stream->mode = mode;
269 return S_OK;
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";
276 BSTR dst;
278 TRACE( "%p, %p\n", stream, charset );
280 if (!(dst = SysAllocString( src ))) return E_OUTOFMEMORY;
281 *charset = dst;
282 return S_OK;
285 static HRESULT WINAPI stream_put_Charset( _Stream *iface, BSTR charset )
287 struct stream *stream = impl_from_Stream( iface );
288 WCHAR *str;
290 TRACE( "%p, %s\n", stream, debugstr_w(charset) );
292 if (!(str = wcsdup( charset ))) return E_OUTOFMEMORY;
293 free( stream->charset );
294 stream->charset = str;
295 return S_OK;
298 static HRESULT create_byte_array( BYTE *data, LONG len, VARIANT *ret )
300 SAFEARRAY *vector;
301 LONG i;
302 HRESULT hr;
304 if (!len)
306 V_VT( ret ) = VT_NULL;
307 return S_OK;
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 );
315 return hr;
319 V_VT( ret ) = VT_ARRAY | VT_UI1;
320 V_ARRAY( ret ) = vector;
321 return S_OK;
324 static HRESULT WINAPI stream_Read( _Stream *iface, LONG size, VARIANT *val )
326 struct stream *stream = impl_from_Stream( iface );
327 HRESULT hr;
329 TRACE( "%p, %ld, %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;
339 stream->pos += size;
340 return S_OK;
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;
352 return S_OK;
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 free( stream->buf );
364 stream->buf = NULL;
365 stream->size = stream->allocated = stream->pos = 0;
367 stream->state = adStateClosed;
368 return S_OK;
371 static HRESULT WINAPI stream_SkipLine( _Stream *iface )
373 FIXME( "%p\n", iface );
374 return E_NOTIMPL;
377 static HRESULT WINAPI stream_Write( _Stream *iface, VARIANT buf )
379 struct stream *stream = impl_from_Stream( iface );
380 LONG bound, i;
381 HRESULT hr;
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;
397 return S_OK;
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, ADO_LONGPTR size )
411 FIXME( "%p, %p, %Id\n", iface, dst, size );
412 return E_NOTIMPL;
415 static HRESULT WINAPI stream_Flush( _Stream *iface )
417 FIXME( "%p\n", iface );
418 return E_NOTIMPL;
421 static HRESULT WINAPI stream_SaveToFile( _Stream *iface, BSTR filename, SaveOptionsEnum options )
423 FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), options );
424 return E_NOTIMPL;
427 static HRESULT WINAPI stream_LoadFromFile( _Stream *iface, BSTR filename )
429 FIXME( "%p, %s\n", iface, debugstr_w(filename) );
430 return E_NOTIMPL;
433 static HRESULT WINAPI stream_ReadText( _Stream *iface, LONG len, BSTR *ret )
435 struct stream *stream = impl_from_Stream( iface );
436 BSTR str;
438 TRACE( "%p, %ld, %p\n", stream, len, ret );
439 if (len == adReadLine)
441 FIXME( "adReadLine not supported\n" );
442 return E_NOTIMPL;
444 if (stream->charset && wcscmp( stream->charset, L"Unicode" ))
446 FIXME( "charset %s not supported\n", debugstr_w(stream->charset) );
447 return E_NOTIMPL;
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) );
458 str[len] = 0;
460 stream->pos += len * sizeof(WCHAR);
462 *ret = str;
463 return S_OK;
466 static HRESULT WINAPI stream_WriteText( _Stream *iface, BSTR data, StreamWriteEnum options )
468 struct stream *stream = impl_from_Stream( iface );
469 HRESULT hr;
470 LONG size;
472 TRACE( "%p, %s, %u\n", stream, debugstr_w(data), options );
473 if (options != adWriteChar)
475 FIXME( "options %u not supported\n", options );
476 return E_NOTIMPL;
478 if (stream->charset && wcscmp( stream->charset, L"Unicode" ))
480 FIXME( "charset %s not supported\n", debugstr_w(stream->charset) );
481 return E_NOTIMPL;
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 );
490 stream->pos += size;
492 return S_OK;
495 static HRESULT WINAPI stream_Cancel( _Stream *iface )
497 FIXME( "%p\n", iface );
498 return E_NOTIMPL;
501 static const struct _StreamVtbl stream_vtbl =
503 stream_QueryInterface,
504 stream_AddRef,
505 stream_Release,
506 stream_GetTypeInfoCount,
507 stream_GetTypeInfo,
508 stream_GetIDsOfNames,
509 stream_Invoke,
510 stream_get_Size,
511 stream_get_EOS,
512 stream_get_Position,
513 stream_put_Position,
514 stream_get_Type,
515 stream_put_Type,
516 stream_get_LineSeparator,
517 stream_put_LineSeparator,
518 stream_get_State,
519 stream_get_Mode,
520 stream_put_Mode,
521 stream_get_Charset,
522 stream_put_Charset,
523 stream_Read,
524 stream_Open,
525 stream_Close,
526 stream_SkipLine,
527 stream_Write,
528 stream_SetEOS,
529 stream_CopyTo,
530 stream_Flush,
531 stream_SaveToFile,
532 stream_LoadFromFile,
533 stream_ReadText,
534 stream_WriteText,
535 stream_Cancel
538 HRESULT Stream_create( void **obj )
540 struct stream *stream;
542 if (!(stream = calloc( 1, sizeof(*stream) ))) return E_OUTOFMEMORY;
543 stream->Stream_iface.lpVtbl = &stream_vtbl;
544 stream->refs = 1;
545 stream->type = adTypeText;
546 stream->sep = adCRLF;
548 *obj = &stream->Stream_iface;
549 TRACE( "returning iface %p\n", *obj );
550 return S_OK;