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
27 #include "msado15_backcompat.h"
29 #include "wine/debug.h"
30 #include "wine/heap.h"
32 #include "msado15_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msado15
);
38 struct connection_point
40 IConnectionPoint IConnectionPoint_iface
;
41 struct connection
*conn
;
49 _Connection Connection_iface
;
50 ISupportErrorInfo ISupportErrorInfo_iface
;
51 IConnectionPointContainer IConnectionPointContainer_iface
;
53 ObjectStateEnum state
;
58 CursorLocationEnum location
;
59 struct connection_point cp_connev
;
62 static inline struct connection
*impl_from_Connection( _Connection
*iface
)
64 return CONTAINING_RECORD( iface
, struct connection
, Connection_iface
);
67 static inline struct connection
*impl_from_ISupportErrorInfo( ISupportErrorInfo
*iface
)
69 return CONTAINING_RECORD( iface
, struct connection
, ISupportErrorInfo_iface
);
72 static inline struct connection
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
74 return CONTAINING_RECORD( iface
, struct connection
, IConnectionPointContainer_iface
);
77 static inline struct connection_point
*impl_from_IConnectionPoint( IConnectionPoint
*iface
)
79 return CONTAINING_RECORD( iface
, struct connection_point
, IConnectionPoint_iface
);
82 static ULONG WINAPI
connection_AddRef( _Connection
*iface
)
84 struct connection
*connection
= impl_from_Connection( iface
);
85 return InterlockedIncrement( &connection
->refs
);
88 static ULONG WINAPI
connection_Release( _Connection
*iface
)
90 struct connection
*connection
= impl_from_Connection( iface
);
91 LONG refs
= InterlockedDecrement( &connection
->refs
);
95 TRACE( "destroying %p\n", connection
);
96 for (i
= 0; i
< connection
->cp_connev
.sinks_size
; ++i
)
98 if (connection
->cp_connev
.sinks
[i
])
99 IUnknown_Release( connection
->cp_connev
.sinks
[i
] );
101 heap_free( connection
->cp_connev
.sinks
);
102 heap_free( connection
->provider
);
103 heap_free( connection
->datasource
);
104 heap_free( connection
);
109 static HRESULT WINAPI
connection_QueryInterface( _Connection
*iface
, REFIID riid
, void **obj
)
111 struct connection
*connection
= impl_from_Connection( iface
);
112 TRACE( "%p, %s, %p\n", connection
, debugstr_guid(riid
), obj
);
116 if (IsEqualGUID( riid
, &IID__Connection
) || IsEqualGUID( riid
, &IID_IDispatch
) ||
117 IsEqualGUID( riid
, &IID_IUnknown
))
121 else if(IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
123 *obj
= &connection
->ISupportErrorInfo_iface
;
125 else if (IsEqualGUID( riid
, &IID_IConnectionPointContainer
))
127 *obj
= &connection
->IConnectionPointContainer_iface
;
129 else if (IsEqualGUID( riid
, &IID_IRunnableObject
))
131 TRACE("IID_IRunnableObject not supported returning NULL\n");
132 return E_NOINTERFACE
;
136 FIXME( "interface %s not implemented\n", debugstr_guid(riid
) );
137 return E_NOINTERFACE
;
139 connection_AddRef( iface
);
143 static HRESULT WINAPI
connection_GetTypeInfoCount( _Connection
*iface
, UINT
*count
)
145 FIXME( "%p, %p\n", iface
, count
);
149 static HRESULT WINAPI
connection_GetTypeInfo( _Connection
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
151 FIXME( "%p, %u, %u, %p\n", iface
, index
, lcid
, info
);
155 static HRESULT WINAPI
connection_GetIDsOfNames( _Connection
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
,
156 LCID lcid
, DISPID
*dispid
)
158 FIXME( "%p, %s, %p, %u, %u, %p\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
162 static HRESULT WINAPI
connection_Invoke( _Connection
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
163 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
165 FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface
, member
, debugstr_guid(riid
), lcid
, flags
, params
,
166 result
, excep_info
, arg_err
);
170 static HRESULT WINAPI
connection_get_Properties( _Connection
*iface
, Properties
**obj
)
172 FIXME( "%p, %p\n", iface
, obj
);
176 static HRESULT WINAPI
connection_get_ConnectionString( _Connection
*iface
, BSTR
*str
)
178 struct connection
*connection
= impl_from_Connection( iface
);
181 TRACE( "%p, %p\n", connection
, str
);
183 if (connection
->datasource
&& !(source
= SysAllocString( connection
->datasource
))) return E_OUTOFMEMORY
;
188 static HRESULT WINAPI
connection_put_ConnectionString( _Connection
*iface
, BSTR str
)
190 struct connection
*connection
= impl_from_Connection( iface
);
191 WCHAR
*source
= NULL
;
193 TRACE( "%p, %s\n", connection
, debugstr_w( str
&& !wcsstr( str
, L
"Password" ) ? L
"<hidden>" : str
) );
195 if (str
&& !(source
= strdupW( str
))) return E_OUTOFMEMORY
;
196 heap_free( connection
->datasource
);
197 connection
->datasource
= source
;
201 static HRESULT WINAPI
connection_get_CommandTimeout( _Connection
*iface
, LONG
*timeout
)
203 struct connection
*connection
= impl_from_Connection( iface
);
204 TRACE( "%p, %p\n", connection
, timeout
);
205 *timeout
= connection
->timeout
;
209 static HRESULT WINAPI
connection_put_CommandTimeout( _Connection
*iface
, LONG timeout
)
211 struct connection
*connection
= impl_from_Connection( iface
);
212 TRACE( "%p, %d\n", connection
, timeout
);
213 connection
->timeout
= timeout
;
217 static HRESULT WINAPI
connection_get_ConnectionTimeout( _Connection
*iface
, LONG
*timeout
)
219 FIXME( "%p, %p\n", iface
, timeout
);
223 static HRESULT WINAPI
connection_put_ConnectionTimeout( _Connection
*iface
, LONG timeout
)
225 FIXME( "%p, %d\n", iface
, timeout
);
229 static HRESULT WINAPI
connection_get_Version( _Connection
*iface
, BSTR
*str
)
231 FIXME( "%p, %p\n", iface
, str
);
235 static HRESULT WINAPI
connection_Close( _Connection
*iface
)
237 struct connection
*connection
= impl_from_Connection( iface
);
239 TRACE( "%p\n", connection
);
241 if (connection
->state
== adStateClosed
) return MAKE_ADO_HRESULT( adErrObjectClosed
);
243 connection
->state
= adStateClosed
;
247 static HRESULT WINAPI
connection_Execute( _Connection
*iface
, BSTR command
, VARIANT
*records_affected
,
248 LONG options
, _Recordset
**record_set
)
250 FIXME( "%p, %s, %p, %08x, %p\n", iface
, debugstr_w(command
), records_affected
, options
, record_set
);
254 static HRESULT WINAPI
connection_BeginTrans( _Connection
*iface
, LONG
*transaction_level
)
256 FIXME( "%p, %p\n", iface
, transaction_level
);
260 static HRESULT WINAPI
connection_CommitTrans( _Connection
*iface
)
262 FIXME( "%p\n", iface
);
266 static HRESULT WINAPI
connection_RollbackTrans( _Connection
*iface
)
268 FIXME( "%p\n", iface
);
272 static HRESULT WINAPI
connection_Open( _Connection
*iface
, BSTR connect_str
, BSTR userid
, BSTR password
,
275 struct connection
*connection
= impl_from_Connection( iface
);
276 FIXME( "%p, %s, %s, %p, %08x\n", iface
, debugstr_w(connect_str
), debugstr_w(userid
),
279 if (connection
->state
== adStateOpen
) return MAKE_ADO_HRESULT( adErrObjectOpen
);
281 connection
->state
= adStateOpen
;
285 static HRESULT WINAPI
connection_get_Errors( _Connection
*iface
, Errors
**obj
)
287 FIXME( "%p, %p\n", iface
, obj
);
291 static HRESULT WINAPI
connection_get_DefaultDatabase( _Connection
*iface
, BSTR
*str
)
293 FIXME( "%p, %p\n", iface
, str
);
297 static HRESULT WINAPI
connection_put_DefaultDatabase( _Connection
*iface
, BSTR str
)
299 FIXME( "%p, %s\n", iface
, debugstr_w(str
) );
303 static HRESULT WINAPI
connection_get_IsolationLevel( _Connection
*iface
, IsolationLevelEnum
*level
)
305 FIXME( "%p, %p\n", iface
, level
);
309 static HRESULT WINAPI
connection_put_IsolationLevel( _Connection
*iface
, IsolationLevelEnum level
)
311 FIXME( "%p, %d\n", iface
, level
);
315 static HRESULT WINAPI
connection_get_Attributes( _Connection
*iface
, LONG
*attr
)
317 FIXME( "%p, %p\n", iface
, attr
);
321 static HRESULT WINAPI
connection_put_Attributes( _Connection
*iface
, LONG attr
)
323 FIXME( "%p, %d\n", iface
, attr
);
327 static HRESULT WINAPI
connection_get_CursorLocation( _Connection
*iface
, CursorLocationEnum
*cursor_loc
)
329 struct connection
*connection
= impl_from_Connection( iface
);
331 TRACE( "%p, %p\n", iface
, cursor_loc
);
333 *cursor_loc
= connection
->location
;
337 static HRESULT WINAPI
connection_put_CursorLocation( _Connection
*iface
, CursorLocationEnum cursor_loc
)
339 struct connection
*connection
= impl_from_Connection( iface
);
341 TRACE( "%p, %u\n", iface
, cursor_loc
);
343 connection
->location
= cursor_loc
;
347 static HRESULT WINAPI
connection_get_Mode( _Connection
*iface
, ConnectModeEnum
*mode
)
349 struct connection
*connection
= impl_from_Connection( iface
);
351 TRACE( "%p, %p\n", iface
, mode
);
353 *mode
= connection
->mode
;
357 static HRESULT WINAPI
connection_put_Mode( _Connection
*iface
, ConnectModeEnum mode
)
359 struct connection
*connection
= impl_from_Connection( iface
);
361 TRACE( "%p, %u\n", iface
, mode
);
363 connection
->mode
= mode
;
367 static HRESULT WINAPI
connection_get_Provider( _Connection
*iface
, BSTR
*str
)
369 struct connection
*connection
= impl_from_Connection( iface
);
370 BSTR provider
= NULL
;
372 TRACE( "%p, %p\n", iface
, str
);
374 if (connection
->provider
&& !(provider
= SysAllocString( connection
->provider
))) return E_OUTOFMEMORY
;
379 static HRESULT WINAPI
connection_put_Provider( _Connection
*iface
, BSTR str
)
381 struct connection
*connection
= impl_from_Connection( iface
);
382 WCHAR
*provider
= NULL
;
384 TRACE( "%p, %s\n", iface
, debugstr_w(str
) );
386 if (!str
) return MAKE_ADO_HRESULT(adErrInvalidArgument
);
388 if (!(provider
= strdupW( str
))) return E_OUTOFMEMORY
;
389 heap_free( connection
->provider
);
390 connection
->provider
= provider
;
394 static HRESULT WINAPI
connection_get_State( _Connection
*iface
, LONG
*state
)
396 struct connection
*connection
= impl_from_Connection( iface
);
397 TRACE( "%p, %p\n", connection
, state
);
398 *state
= connection
->state
;
402 static HRESULT WINAPI
connection_OpenSchema( _Connection
*iface
, SchemaEnum schema
, VARIANT restrictions
,
403 VARIANT schema_id
, _Recordset
**record_set
)
405 FIXME( "%p, %d, %s, %s, %p\n", iface
, schema
, debugstr_variant(&restrictions
),
406 debugstr_variant(&schema_id
), record_set
);
410 static HRESULT WINAPI
connection_Cancel( _Connection
*iface
)
412 FIXME( "%p\n", iface
);
416 static const struct _ConnectionVtbl connection_vtbl
=
418 connection_QueryInterface
,
421 connection_GetTypeInfoCount
,
422 connection_GetTypeInfo
,
423 connection_GetIDsOfNames
,
425 connection_get_Properties
,
426 connection_get_ConnectionString
,
427 connection_put_ConnectionString
,
428 connection_get_CommandTimeout
,
429 connection_put_CommandTimeout
,
430 connection_get_ConnectionTimeout
,
431 connection_put_ConnectionTimeout
,
432 connection_get_Version
,
435 connection_BeginTrans
,
436 connection_CommitTrans
,
437 connection_RollbackTrans
,
439 connection_get_Errors
,
440 connection_get_DefaultDatabase
,
441 connection_put_DefaultDatabase
,
442 connection_get_IsolationLevel
,
443 connection_put_IsolationLevel
,
444 connection_get_Attributes
,
445 connection_put_Attributes
,
446 connection_get_CursorLocation
,
447 connection_put_CursorLocation
,
450 connection_get_Provider
,
451 connection_put_Provider
,
452 connection_get_State
,
453 connection_OpenSchema
,
457 static HRESULT WINAPI
supporterror_QueryInterface( ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
459 struct connection
*connection
= impl_from_ISupportErrorInfo( iface
);
460 return connection_QueryInterface( &connection
->Connection_iface
, riid
, obj
);
463 static ULONG WINAPI
supporterror_AddRef( ISupportErrorInfo
*iface
)
465 struct connection
*connection
= impl_from_ISupportErrorInfo( iface
);
466 return connection_AddRef( &connection
->Connection_iface
);
469 static ULONG WINAPI
supporterror_Release( ISupportErrorInfo
*iface
)
471 struct connection
*connection
= impl_from_ISupportErrorInfo( iface
);
472 return connection_Release( &connection
->Connection_iface
);
475 static HRESULT WINAPI
supporterror_InterfaceSupportsErrorInfo( ISupportErrorInfo
*iface
, REFIID riid
)
477 struct connection
*connection
= impl_from_ISupportErrorInfo( iface
);
478 FIXME( "%p, %s\n", connection
, debugstr_guid(riid
) );
482 static const struct ISupportErrorInfoVtbl support_error_vtbl
=
484 supporterror_QueryInterface
,
486 supporterror_Release
,
487 supporterror_InterfaceSupportsErrorInfo
490 static HRESULT WINAPI
connpointcontainer_QueryInterface( IConnectionPointContainer
*iface
,
491 REFIID riid
, void **obj
)
493 struct connection
*connection
= impl_from_IConnectionPointContainer( iface
);
494 return connection_QueryInterface( &connection
->Connection_iface
, riid
, obj
);
497 static ULONG WINAPI
connpointcontainer_AddRef( IConnectionPointContainer
*iface
)
499 struct connection
*connection
= impl_from_IConnectionPointContainer( iface
);
500 return connection_AddRef( &connection
->Connection_iface
);
503 static ULONG WINAPI
connpointcontainer_Release( IConnectionPointContainer
*iface
)
505 struct connection
*connection
= impl_from_IConnectionPointContainer( iface
);
506 return connection_Release( &connection
->Connection_iface
);
509 static HRESULT WINAPI
connpointcontainer_EnumConnectionPoints( IConnectionPointContainer
*iface
,
510 IEnumConnectionPoints
**points
)
512 struct connection
*connection
= impl_from_IConnectionPointContainer( iface
);
513 FIXME( "%p, %p\n", connection
, points
);
517 static HRESULT WINAPI
connpointcontainer_FindConnectionPoint( IConnectionPointContainer
*iface
,
518 REFIID riid
, IConnectionPoint
**point
)
520 struct connection
*connection
= impl_from_IConnectionPointContainer( iface
);
522 TRACE( "%p, %s %p\n", connection
, debugstr_guid( riid
), point
);
524 if (!point
) return E_POINTER
;
526 if (IsEqualIID( riid
, connection
->cp_connev
.riid
))
528 *point
= &connection
->cp_connev
.IConnectionPoint_iface
;
529 IConnectionPoint_AddRef( *point
);
533 FIXME( "unsupported connection point %s\n", debugstr_guid( riid
) );
534 return CONNECT_E_NOCONNECTION
;
537 static const struct IConnectionPointContainerVtbl connpointcontainer_vtbl
=
539 connpointcontainer_QueryInterface
,
540 connpointcontainer_AddRef
,
541 connpointcontainer_Release
,
542 connpointcontainer_EnumConnectionPoints
,
543 connpointcontainer_FindConnectionPoint
546 static HRESULT WINAPI
connpoint_QueryInterface( IConnectionPoint
*iface
, REFIID riid
, void **obj
)
548 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
550 if (IsEqualGUID( &IID_IUnknown
, riid
) || IsEqualGUID( &IID_IConnectionPoint
, riid
))
552 *obj
= &connpoint
->IConnectionPoint_iface
;
556 FIXME( "interface %s not implemented\n", debugstr_guid( riid
) );
557 return E_NOINTERFACE
;
560 connection_AddRef( &connpoint
->conn
->Connection_iface
);
564 static ULONG WINAPI
connpoint_AddRef( IConnectionPoint
*iface
)
566 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
567 return IConnectionPointContainer_AddRef( &connpoint
->conn
->IConnectionPointContainer_iface
);
570 static ULONG WINAPI
connpoint_Release( IConnectionPoint
*iface
)
572 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
573 return IConnectionPointContainer_Release( &connpoint
->conn
->IConnectionPointContainer_iface
);
576 static HRESULT WINAPI
connpoint_GetConnectionInterface( IConnectionPoint
*iface
, IID
*iid
)
578 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
579 FIXME( "%p, %p\n", connpoint
, iid
);
583 static HRESULT WINAPI
connpoint_GetConnectionPointContainer( IConnectionPoint
*iface
,
584 IConnectionPointContainer
**container
)
586 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
587 FIXME( "%p, %p\n", connpoint
, container
);
591 static HRESULT WINAPI
connpoint_Advise( IConnectionPoint
*iface
, IUnknown
*unk_sink
,
594 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
595 IUnknown
*sink
, **tmp
;
600 TRACE( "%p, %p, %p\n", iface
, unk_sink
, cookie
);
602 if (!unk_sink
|| !cookie
) return E_FAIL
;
604 if (FAILED(hr
= IUnknown_QueryInterface( unk_sink
, &IID_ConnectionEventsVt
, (void**)&sink
)))
610 if (connpoint
->sinks
)
612 for (i
= 0; i
< connpoint
->sinks_size
; ++i
)
614 if (!connpoint
->sinks
[i
])
618 if (i
== connpoint
->sinks_size
)
620 new_size
= connpoint
->sinks_size
* 2;
621 if (!(tmp
= heap_realloc_zero( connpoint
->sinks
, new_size
* sizeof(*connpoint
->sinks
) )))
622 return E_OUTOFMEMORY
;
623 connpoint
->sinks
= tmp
;
624 connpoint
->sinks_size
= new_size
;
629 if (!(connpoint
->sinks
= heap_alloc_zero( sizeof(*connpoint
->sinks
) ))) return E_OUTOFMEMORY
;
630 connpoint
->sinks_size
= 1;
634 connpoint
->sinks
[i
] = sink
;
639 static HRESULT WINAPI
connpoint_Unadvise( IConnectionPoint
*iface
, DWORD cookie
)
641 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
642 TRACE( "%p, %u\n", connpoint
, cookie
);
644 if (!cookie
|| cookie
> connpoint
->sinks_size
|| !connpoint
->sinks
|| !connpoint
->sinks
[cookie
- 1])
647 IUnknown_Release( connpoint
->sinks
[cookie
- 1] );
648 connpoint
->sinks
[cookie
- 1] = NULL
;
652 static HRESULT WINAPI
connpoint_EnumConnections( IConnectionPoint
*iface
,
653 IEnumConnections
**points
)
655 struct connection_point
*connpoint
= impl_from_IConnectionPoint( iface
);
656 FIXME( "%p, %p\n", connpoint
, points
);
660 static const IConnectionPointVtbl connpoint_vtbl
=
662 connpoint_QueryInterface
,
665 connpoint_GetConnectionInterface
,
666 connpoint_GetConnectionPointContainer
,
669 connpoint_EnumConnections
672 HRESULT
Connection_create( void **obj
)
674 struct connection
*connection
;
676 if (!(connection
= heap_alloc( sizeof(*connection
) ))) return E_OUTOFMEMORY
;
677 connection
->Connection_iface
.lpVtbl
= &connection_vtbl
;
678 connection
->ISupportErrorInfo_iface
.lpVtbl
= &support_error_vtbl
;
679 connection
->IConnectionPointContainer_iface
.lpVtbl
= &connpointcontainer_vtbl
;
680 connection
->refs
= 1;
681 connection
->state
= adStateClosed
;
682 connection
->timeout
= 30;
683 connection
->datasource
= NULL
;
684 if (!(connection
->provider
= strdupW( L
"MSDASQL" )))
686 heap_free( connection
);
687 return E_OUTOFMEMORY
;
689 connection
->mode
= adModeUnknown
;
690 connection
->location
= adUseServer
;
692 connection
->cp_connev
.conn
= connection
;
693 connection
->cp_connev
.riid
= &DIID_ConnectionEvents
;
694 connection
->cp_connev
.IConnectionPoint_iface
.lpVtbl
= &connpoint_vtbl
;
695 connection
->cp_connev
.sinks
= NULL
;
696 connection
->cp_connev
.sinks_size
= 0;
698 *obj
= &connection
->Connection_iface
;
699 TRACE( "returning iface %p\n", *obj
);