include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / msdasql / session.c
blobb42af7f6a02d810972d2d025369adfbb9f59865e
1 /*
2 * Copyright 2020 Alistair Leslie-Hughes
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 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "rpcproxy.h"
27 #include "msdasc.h"
28 #include "wine/debug.h"
30 #include "msdasql.h"
31 #include "oledberr.h"
32 #include "sqlucode.h"
34 #include "msdasql_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
38 struct msdasql_prop
40 DBPROPID property_id;
41 DBPROPFLAGS flags;
42 VARTYPE vartype;
44 LONG value;
47 static struct msdasql_prop msdasql_init_props[] =
49 { DBPROP_ABORTPRESERVE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_DATASOURCEINFO, VT_BOOL, VARIANT_FALSE },
50 { DBPROP_BLOCKINGSTORAGEOBJECTS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
51 { DBPROP_BOOKMARKS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
52 { DBPROP_BOOKMARKSKIPPED, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
53 { DBPROP_BOOKMARKTYPE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 1 },
54 { DBPROP_CANFETCHBACKWARDS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
55 { DBPROP_CANHOLDROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
56 { DBPROP_CANSCROLLBACKWARDS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
57 { DBPROP_COLUMNRESTRICT, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
58 { DBPROP_COMMITPRESERVE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
59 { DBPROP_DELAYSTORAGEOBJECTS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
60 { DBPROP_IMMOBILEROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_TRUE },
61 { DBPROP_LITERALBOOKMARKS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
62 { DBPROP_LITERALIDENTITY, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
63 { DBPROP_MAXOPENROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 0 },
64 { DBPROP_MAXPENDINGROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 0 },
65 { DBPROP_MAXROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 0 },
66 { DBPROP_NOTIFICATIONPHASES, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 31 },
67 { DBPROP_OTHERUPDATEDELETE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
68 { DBPROP_OWNINSERT, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
69 { DBPROP_OWNUPDATEDELETE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
70 { DBPROP_QUICKRESTART , DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
71 { DBPROP_REENTRANTEVENTS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
72 { DBPROP_REMOVEDELETED, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
73 { DBPROP_REPORTMULTIPLECHANGES, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
74 { DBPROP_ROWRESTRICT, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
75 { DBPROP_ROWTHREADMODEL, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 2 },
76 { DBPROP_TRANSACTEDOBJECT, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
77 { DBPROP_UPDATABILITY, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 0 },
78 { DBPROP_STRONGIDENTITY, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
79 { DBPROP_IAccessor, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
80 { DBPROP_IColumnsInfo, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
81 { DBPROP_IColumnsRowset, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
82 { DBPROP_IConnectionPointContainer, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
83 { DBPROP_IRowset, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
84 { DBPROP_IRowsetChange, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
85 { DBPROP_IRowsetIdentity, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
86 { DBPROP_IRowsetInfo, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
87 { DBPROP_IRowsetLocate, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
88 { DBPROP_IRowsetResynch, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
89 { DBPROP_IRowsetUpdate, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
90 { DBPROP_ISupportErrorInfo, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
91 { DBPROP_ISequentialStream, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
92 { DBPROP_NOTIFYCOLUMNSET, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
93 { DBPROP_NOTIFYROWDELETE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
94 { DBPROP_NOTIFYROWFIRSTCHANGE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
95 { DBPROP_NOTIFYROWINSERT, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
96 { DBPROP_NOTIFYROWRESYNCH, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
97 { DBPROP_NOTIFYROWSETRELEASE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
98 { DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
99 { DBPROP_NOTIFYROWUNDOCHANGE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
100 { DBPROP_NOTIFYROWUNDODELETE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
101 { DBPROP_NOTIFYROWUNDOINSERT, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
102 { DBPROP_NOTIFYROWUPDATE, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 3 },
103 { DBPROP_CHANGEINSERTEDROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_TRUE },
104 { DBPROP_RETURNPENDINGINSERTS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
105 { DBPROP_IConvertType, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, VARIANT_TRUE },
106 { DBPROP_NOTIFICATIONGRANULARITY, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 1 },
107 { DBPROP_IMultipleResults, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
108 { DBPROP_ACCESSORDER, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 1 },
109 { DBPROP_BOOKMARKINFO, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 0 },
110 { DBPROP_UNIQUEROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
111 { DBPROP_IRowsetFind, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
112 { DBPROP_IRowsetScroll, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_TRUE },
113 { DBPROP_IRowsetRefresh, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_TRUE },
114 { DBPROP_FINDCOMPAREOPS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, 27 },
115 { DBPROP_ORDEREDBOOKMARKS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_TRUE },
116 { DBPROP_CLIENTCURSOR, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_TRUE },
117 { DBPROP_ABORTPRESERVE, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
118 { DBPROP_ACTIVESESSIONS, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
119 { DBPROP_ASYNCTXNCOMMIT, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BOOL, VARIANT_FALSE },
120 { DBPROP_AUTH_CACHE_AUTHINFO, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
121 { DBPROP_AUTH_ENCRYPT_PASSWORD, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 0 },
122 { DBPROP_AUTH_INTEGRATED, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, 14 },
123 { DBPROP_AUTH_MASK_PASSWORD, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
124 { DBPROP_AUTH_PASSWORD, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
125 { DBPROP_AUTH_PERSIST_ENCRYPTED, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
126 { DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
127 { DBPROP_AUTH_USERID, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
128 { DBPROP_BLOCKINGSTORAGEOBJECTS, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, VARIANT_FALSE },
131 #define SQLTYPE_TO_STR(x) case x: return #x
133 static const char *debugstr_sqltype(SQLSMALLINT type)
135 switch (type)
137 SQLTYPE_TO_STR(SQL_DECIMAL);
138 SQLTYPE_TO_STR(SQL_CHAR);
139 SQLTYPE_TO_STR(SQL_VARCHAR);
140 SQLTYPE_TO_STR(SQL_LONGVARCHAR);
141 SQLTYPE_TO_STR(SQL_NUMERIC);
142 SQLTYPE_TO_STR(SQL_GUID);
143 SQLTYPE_TO_STR(SQL_TINYINT);
144 SQLTYPE_TO_STR(SQL_SMALLINT);
145 SQLTYPE_TO_STR(SQL_INTEGER);
146 SQLTYPE_TO_STR(SQL_REAL);
147 SQLTYPE_TO_STR(SQL_FLOAT);
148 SQLTYPE_TO_STR(SQL_DOUBLE);
149 SQLTYPE_TO_STR(SQL_BINARY);
150 SQLTYPE_TO_STR(SQL_VARBINARY);
151 SQLTYPE_TO_STR(SQL_LONGVARBINARY);
152 SQLTYPE_TO_STR(SQL_TYPE_DATE);
153 SQLTYPE_TO_STR(SQL_DATE);
154 SQLTYPE_TO_STR(SQL_TIME);
155 SQLTYPE_TO_STR(SQL_TYPE_TIMESTAMP);
156 SQLTYPE_TO_STR(SQL_TIMESTAMP);
157 SQLTYPE_TO_STR(SQL_TYPE_TIME);
158 SQLTYPE_TO_STR(SQL_BIGINT);
159 SQLTYPE_TO_STR(SQL_C_SBIGINT);
160 SQLTYPE_TO_STR(SQL_C_SLONG);
161 SQLTYPE_TO_STR(SQL_C_ULONG);
162 SQLTYPE_TO_STR(SQL_WLONGVARCHAR);
163 SQLTYPE_TO_STR(SQL_WCHAR);
164 SQLTYPE_TO_STR(SQL_WVARCHAR);
165 default:
166 return "Unknown";
170 static const char *debugstr_dbtype(DBTYPE type)
172 switch(type)
174 SQLTYPE_TO_STR(DBTYPE_NUMERIC);
175 SQLTYPE_TO_STR(DBTYPE_STR);
176 SQLTYPE_TO_STR(DBTYPE_GUID);
177 SQLTYPE_TO_STR(DBTYPE_I1);
178 SQLTYPE_TO_STR(DBTYPE_I2);
179 SQLTYPE_TO_STR(DBTYPE_UI2);
180 SQLTYPE_TO_STR(DBTYPE_I4);
181 SQLTYPE_TO_STR(DBTYPE_I8);
182 SQLTYPE_TO_STR(DBTYPE_UI4);
183 SQLTYPE_TO_STR(DBTYPE_R4);
184 SQLTYPE_TO_STR(DBTYPE_R8);
185 SQLTYPE_TO_STR(DBTYPE_BYTES);
186 SQLTYPE_TO_STR(DBTYPE_DBDATE);
187 SQLTYPE_TO_STR(DBTYPE_DBTIME);
188 SQLTYPE_TO_STR(DBTYPE_DATE);
189 SQLTYPE_TO_STR(DBTYPE_DBTIMESTAMP);
190 SQLTYPE_TO_STR(DBTYPE_WSTR);
191 default:
192 return "Unknown";
196 static SQLSMALLINT sqltype_to_bindtype(SQLSMALLINT type, BOOL sign)
198 switch (type)
200 case SQL_DECIMAL:
201 return DBTYPE_NUMERIC;
202 case SQL_CHAR:
203 case SQL_VARCHAR:
204 case SQL_LONGVARCHAR:
205 case SQL_NUMERIC:
206 return DBTYPE_STR;
207 case SQL_GUID:
208 return DBTYPE_GUID;
209 case SQL_TINYINT:
210 return DBTYPE_I1;
211 case SQL_SMALLINT:
212 return sign ? DBTYPE_I2 : DBTYPE_UI2;
213 case SQL_INTEGER:
214 return sign ? DBTYPE_I4 : DBTYPE_UI4;
215 case SQL_REAL:
216 return DBTYPE_R4;
217 case SQL_FLOAT:
218 case SQL_DOUBLE:
219 return DBTYPE_R8;
220 case SQL_BINARY:
221 case SQL_VARBINARY:
222 case SQL_LONGVARBINARY:
223 return DBTYPE_BYTES;
224 case SQL_TYPE_DATE:
225 return DBTYPE_DBDATE;
226 case SQL_DATE:
227 return DBTYPE_DBTIME;
228 case SQL_TIME:
229 return DBTYPE_DATE;
230 case SQL_TYPE_TIMESTAMP:
231 case SQL_TIMESTAMP:
232 return DBTYPE_DBTIMESTAMP;
233 case SQL_TYPE_TIME:
234 return DBTYPE_DBTIME;
235 case SQL_BIGINT:
236 case SQL_C_SBIGINT:
237 return DBTYPE_I8;
238 case SQL_C_SLONG:
239 return DBTYPE_I4;
240 case SQL_C_ULONG:
241 return DBTYPE_UI4;
242 case SQL_WLONGVARCHAR:
243 case SQL_WCHAR:
244 case SQL_WVARCHAR:
245 return DBTYPE_WSTR;
246 default:
247 FIXME("Unsupported type %i\n", type);
250 return DBTYPE_I4;
253 static BOOL is_variable_length(SQLSMALLINT type)
255 switch(type)
257 case SQL_LONGVARCHAR:
258 case SQL_WLONGVARCHAR:
259 case SQL_LONGVARBINARY:
260 return TRUE;
262 return FALSE;
265 static BOOL is_fixed_length(SQLSMALLINT type)
267 switch(type)
269 case SQL_LONGVARCHAR:
270 case SQL_WLONGVARCHAR:
271 case SQL_WVARCHAR:
272 case SQL_LONGVARBINARY:
273 case SQL_VARBINARY:
274 return FALSE;
276 return TRUE;
279 struct msdasql_session
281 IUnknown session_iface;
282 IGetDataSource IGetDataSource_iface;
283 IOpenRowset IOpenRowset_iface;
284 ISessionProperties ISessionProperties_iface;
285 IDBCreateCommand IDBCreateCommand_iface;
286 ITransactionJoin ITransactionJoin_iface;
287 ITransaction ITransaction_iface;
288 LONG refs;
290 IUnknown *datasource;
292 HDBC hdbc;
295 static inline struct msdasql_session *impl_from_IUnknown( IUnknown *iface )
297 return CONTAINING_RECORD( iface, struct msdasql_session, session_iface );
300 static inline struct msdasql_session *impl_from_IGetDataSource( IGetDataSource *iface )
302 return CONTAINING_RECORD( iface, struct msdasql_session, IGetDataSource_iface );
305 static inline struct msdasql_session *impl_from_IOpenRowset( IOpenRowset *iface )
307 return CONTAINING_RECORD( iface, struct msdasql_session, IOpenRowset_iface );
310 static inline struct msdasql_session *impl_from_ISessionProperties( ISessionProperties *iface )
312 return CONTAINING_RECORD( iface, struct msdasql_session, ISessionProperties_iface );
315 static inline struct msdasql_session *impl_from_IDBCreateCommand( IDBCreateCommand *iface )
317 return CONTAINING_RECORD( iface, struct msdasql_session, IDBCreateCommand_iface );
320 static inline struct msdasql_session *impl_from_ITransactionJoin( ITransactionJoin *iface )
322 return CONTAINING_RECORD( iface, struct msdasql_session, ITransactionJoin_iface );
325 static inline struct msdasql_session *impl_from_ITransaction( ITransaction *iface )
327 return CONTAINING_RECORD( iface, struct msdasql_session, ITransaction_iface );
330 static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
332 struct msdasql_session *session = impl_from_IUnknown( iface );
334 TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), ppv );
335 *ppv = NULL;
337 if(IsEqualGUID(&IID_IUnknown, riid))
339 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
340 *ppv = &session->session_iface;
342 else if(IsEqualGUID(&IID_IGetDataSource, riid))
344 TRACE("(%p)->(IID_IGetDataSource %p)\n", iface, ppv);
345 *ppv = &session->IGetDataSource_iface;
347 else if(IsEqualGUID(&IID_IOpenRowset, riid))
349 TRACE("(%p)->(IID_IOpenRowset %p)\n", iface, ppv);
350 *ppv = &session->IOpenRowset_iface;
352 else if(IsEqualGUID(&IID_ISessionProperties, riid))
354 TRACE("(%p)->(IID_ISessionProperties %p)\n", iface, ppv);
355 *ppv = &session->ISessionProperties_iface;
357 else if(IsEqualGUID(&IID_IDBCreateCommand, riid))
359 TRACE("(%p)->(IDBCreateCommand_iface %p)\n", iface, ppv);
360 *ppv = &session->IDBCreateCommand_iface;
362 else if(IsEqualGUID(&IID_ITransactionJoin, riid))
364 TRACE("(%p)->(ITransactionJoin %p)\n", iface, ppv);
365 *ppv = &session->ITransactionJoin_iface;
367 else if(IsEqualGUID(&IID_ITransaction, riid))
369 TRACE("(%p)->(ITransaction %p)\n", iface, ppv);
370 *ppv = &session->ITransaction_iface;
372 else if(IsEqualGUID(&IID_IBindResource, riid))
374 TRACE("(%p)->(IID_IBindResource not support)\n", iface);
375 return E_NOINTERFACE;
377 else if(IsEqualGUID(&IID_ICreateRow, riid))
379 TRACE("(%p)->(IID_ICreateRow not support)\n", iface);
380 return E_NOINTERFACE;
383 if(*ppv)
385 IUnknown_AddRef((IUnknown*)*ppv);
386 return S_OK;
389 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
390 return E_NOINTERFACE;
393 static ULONG WINAPI session_AddRef(IUnknown *iface)
395 struct msdasql_session *session = impl_from_IUnknown( iface );
396 LONG refs = InterlockedIncrement( &session->refs );
397 TRACE( "%p new refcount %ld\n", session, refs );
398 return refs;
401 static ULONG WINAPI session_Release(IUnknown *iface)
403 struct msdasql_session *session = impl_from_IUnknown( iface );
404 LONG refs = InterlockedDecrement( &session->refs );
405 TRACE( "%p new refcount %ld\n", session, refs );
406 if (!refs)
408 TRACE( "destroying %p\n", session );
410 IUnknown_Release(session->datasource);
411 free(session);
413 return refs;
416 static const IUnknownVtbl unkfactoryVtbl =
418 session_QueryInterface,
419 session_AddRef,
420 session_Release,
424 HRESULT WINAPI datasource_QueryInterface(IGetDataSource *iface, REFIID riid, void **out)
426 struct msdasql_session *session = impl_from_IGetDataSource( iface );
427 return IUnknown_QueryInterface(&session->session_iface, riid, out);
430 ULONG WINAPI datasource_AddRef(IGetDataSource *iface)
432 struct msdasql_session *session = impl_from_IGetDataSource( iface );
433 return IUnknown_AddRef(&session->session_iface);
436 ULONG WINAPI datasource_Release(IGetDataSource *iface)
438 struct msdasql_session *session = impl_from_IGetDataSource( iface );
439 return IUnknown_Release(&session->session_iface);
442 HRESULT WINAPI datasource_GetDataSource(IGetDataSource *iface, REFIID riid, IUnknown **datasource)
444 struct msdasql_session *session = impl_from_IGetDataSource( iface );
446 TRACE("%p, %s, %p stub\n", session, debugstr_guid(riid), datasource);
448 if (!datasource)
449 return E_INVALIDARG;
451 return IUnknown_QueryInterface(session->datasource, riid, (void**)datasource);
454 static const IGetDataSourceVtbl datasourceVtbl =
456 datasource_QueryInterface,
457 datasource_AddRef,
458 datasource_Release,
459 datasource_GetDataSource
462 HRESULT WINAPI openrowset_QueryInterface(IOpenRowset *iface, REFIID riid, void **out)
464 struct msdasql_session *session = impl_from_IOpenRowset( iface );
465 return IUnknown_QueryInterface(&session->session_iface, riid, out);
468 ULONG WINAPI openrowset_AddRef(IOpenRowset *iface)
470 struct msdasql_session *session = impl_from_IOpenRowset( iface );
471 return IUnknown_AddRef(&session->session_iface);
474 ULONG WINAPI openrowset_Release(IOpenRowset *iface)
476 struct msdasql_session *session = impl_from_IOpenRowset( iface );
477 return IUnknown_Release(&session->session_iface);
480 HRESULT WINAPI openrowset_OpenRowset(IOpenRowset *iface, IUnknown *pUnkOuter, DBID *table,
481 DBID *index, REFIID riid, ULONG count, DBPROPSET propertysets[], IUnknown **rowset)
483 struct msdasql_session *session = impl_from_IOpenRowset( iface );
484 FIXME("%p, %p, %p %p %s, %ld %p %p stub\n", session, pUnkOuter, table, index, debugstr_guid(riid),
485 count, propertysets, rowset);
487 return E_NOTIMPL;
490 static const IOpenRowsetVtbl openrowsetVtbl =
492 openrowset_QueryInterface,
493 openrowset_AddRef,
494 openrowset_Release,
495 openrowset_OpenRowset
498 static HRESULT WINAPI properties_QueryInterface(ISessionProperties *iface, REFIID riid, void **out)
500 struct msdasql_session *session = impl_from_ISessionProperties( iface );
501 return IUnknown_QueryInterface(&session->session_iface, riid, out);
504 static ULONG WINAPI properties_AddRef(ISessionProperties *iface)
506 struct msdasql_session *session = impl_from_ISessionProperties( iface );
507 return IUnknown_AddRef(&session->session_iface);
510 static ULONG WINAPI properties_Release(ISessionProperties *iface)
512 struct msdasql_session *session = impl_from_ISessionProperties( iface );
513 return IUnknown_Release(&session->session_iface);
517 static HRESULT WINAPI properties_GetProperties(ISessionProperties *iface, ULONG set_count,
518 const DBPROPIDSET id_sets[], ULONG *count, DBPROPSET **sets)
520 struct msdasql_session *session = impl_from_ISessionProperties( iface );
521 FIXME("%p %lu %p %p %p\n", session, set_count, id_sets, count, sets);
523 return E_NOTIMPL;
526 static HRESULT WINAPI properties_SetProperties(ISessionProperties *iface, ULONG count,
527 DBPROPSET sets[])
529 struct msdasql_session *session = impl_from_ISessionProperties( iface );
530 FIXME("%p %lu %p\n", session, count, sets);
532 return S_OK;
535 static const ISessionPropertiesVtbl propertiesVtbl =
537 properties_QueryInterface,
538 properties_AddRef,
539 properties_Release,
540 properties_GetProperties,
541 properties_SetProperties
544 static HRESULT WINAPI createcommand_QueryInterface(IDBCreateCommand *iface, REFIID riid, void **out)
546 struct msdasql_session *session = impl_from_IDBCreateCommand( iface );
547 return IUnknown_QueryInterface(&session->session_iface, riid, out);
550 static ULONG WINAPI createcommand_AddRef(IDBCreateCommand *iface)
552 struct msdasql_session *session = impl_from_IDBCreateCommand( iface );
553 return IUnknown_AddRef(&session->session_iface);
556 static ULONG WINAPI createcommand_Release(IDBCreateCommand *iface)
558 struct msdasql_session *session = impl_from_IDBCreateCommand( iface );
559 return IUnknown_Release(&session->session_iface);
562 struct command
564 ICommandText ICommandText_iface;
565 ICommandProperties ICommandProperties_iface;
566 IColumnsInfo IColumnsInfo_iface;
567 IConvertType IConvertType_iface;
568 ICommandPrepare ICommandPrepare_iface;
569 ICommandWithParameters ICommandWithParameters_iface;
570 LONG refs;
571 WCHAR *query;
572 IUnknown *session;
573 HDBC hdbc;
574 SQLHSTMT hstmt;
576 struct msdasql_prop *properties;
577 LONG prop_count;
580 static inline struct command *impl_from_ICommandText( ICommandText *iface )
582 return CONTAINING_RECORD( iface, struct command, ICommandText_iface );
585 static inline struct command *impl_from_ICommandProperties( ICommandProperties *iface )
587 return CONTAINING_RECORD( iface, struct command, ICommandProperties_iface );
590 static inline struct command *impl_from_IColumnsInfo( IColumnsInfo *iface )
592 return CONTAINING_RECORD( iface, struct command, IColumnsInfo_iface );
595 static inline struct command *impl_from_IConvertType( IConvertType *iface )
597 return CONTAINING_RECORD( iface, struct command, IConvertType_iface );
600 static inline struct command *impl_from_ICommandPrepare( ICommandPrepare *iface )
602 return CONTAINING_RECORD( iface, struct command, ICommandPrepare_iface );
605 static inline struct command *impl_from_ICommandWithParameters( ICommandWithParameters *iface )
607 return CONTAINING_RECORD( iface, struct command, ICommandWithParameters_iface );
610 static HRESULT WINAPI command_QueryInterface(ICommandText *iface, REFIID riid, void **ppv)
612 struct command *command = impl_from_ICommandText( iface );
614 TRACE( "%p, %s, %p\n", command, debugstr_guid(riid), ppv );
615 *ppv = NULL;
617 if(IsEqualGUID(&IID_IUnknown, riid) ||
618 IsEqualGUID(&IID_ICommand, riid) ||
619 IsEqualGUID(&IID_ICommandText, riid))
621 *ppv = &command->ICommandText_iface;
623 else if(IsEqualGUID(&IID_ICommandProperties, riid))
625 *ppv = &command->ICommandProperties_iface;
627 else if(IsEqualGUID(&IID_IColumnsInfo, riid))
629 *ppv = &command->IColumnsInfo_iface;
631 else if(IsEqualGUID(&IID_IConvertType, riid))
633 *ppv = &command->IConvertType_iface;
635 else if(IsEqualGUID(&IID_ICommandPrepare, riid))
637 *ppv = &command->ICommandPrepare_iface;
639 else if(IsEqualGUID(&IID_ICommandWithParameters, riid))
641 *ppv = &command->ICommandWithParameters_iface;
644 if(*ppv)
646 IUnknown_AddRef((IUnknown*)*ppv);
647 return S_OK;
649 else if (IsEqualGUID(&IID_IMultipleResults, riid))
651 TRACE("IID_IMultipleResults not supported\n");
652 return E_NOINTERFACE;
654 else if(IsEqualGUID(&IID_ICommandStream, riid))
656 TRACE("ICommandStream not support\n");
657 return E_NOINTERFACE;
659 else if (IsEqualGUID(&IID_IRowsetChange, riid))
661 TRACE("IID_IRowsetChange not supported\n");
662 return E_NOINTERFACE;
664 else if (IsEqualGUID(&IID_IRowsetUpdate, riid))
666 TRACE("IID_IRowsetUpdate not supported\n");
667 return E_NOINTERFACE;
669 else if (IsEqualGUID(&IID_IRowsetLocate, riid))
671 TRACE("IID_IRowsetLocate not supported\n");
672 return E_NOINTERFACE;
675 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
676 return E_NOINTERFACE;
679 static ULONG WINAPI command_AddRef(ICommandText *iface)
681 struct command *command = impl_from_ICommandText( iface );
682 LONG refs = InterlockedIncrement( &command->refs );
683 TRACE( "%p new refcount %ld\n", command, refs );
684 return refs;
687 static ULONG WINAPI command_Release(ICommandText *iface)
689 struct command *command = impl_from_ICommandText( iface );
690 LONG refs = InterlockedDecrement( &command->refs );
691 TRACE( "%p new refcount %ld\n", command, refs );
692 if (!refs)
694 TRACE( "destroying %p\n", command );
695 free(command->properties);
696 if (command->session)
697 IUnknown_Release(command->session);
699 if (command->hstmt)
700 SQLFreeHandle(SQL_HANDLE_STMT, command->hstmt);
702 free(command->query);
703 free(command);
705 return refs;
708 static HRESULT WINAPI command_Cancel(ICommandText *iface)
710 struct command *command = impl_from_ICommandText( iface );
711 FIXME("%p\n", command);
712 return E_NOTIMPL;
715 struct msdasql_rowset
717 IRowset IRowset_iface;
718 IRowsetInfo IRowsetInfo_iface;
719 IColumnsInfo IColumnsInfo_iface;
720 IAccessor IAccessor_iface;
721 IColumnsRowset IColumnsRowset_iface;
722 IUnknown *caller;
723 LONG refs;
724 SQLHSTMT hstmt;
727 static inline struct msdasql_rowset *impl_from_IRowset( IRowset *iface )
729 return CONTAINING_RECORD( iface, struct msdasql_rowset, IRowset_iface );
732 static inline struct msdasql_rowset *impl_from_IRowsetInfo( IRowsetInfo *iface )
734 return CONTAINING_RECORD( iface, struct msdasql_rowset, IRowsetInfo_iface );
737 static inline struct msdasql_rowset *rowset_impl_from_IColumnsInfo( IColumnsInfo *iface )
739 return CONTAINING_RECORD( iface, struct msdasql_rowset, IColumnsInfo_iface );
742 static inline struct msdasql_rowset *impl_from_IAccessor ( IAccessor *iface )
744 return CONTAINING_RECORD( iface, struct msdasql_rowset, IAccessor_iface );
747 static inline struct msdasql_rowset *impl_from_IColumnsRowset ( IColumnsRowset *iface )
749 return CONTAINING_RECORD( iface, struct msdasql_rowset, IColumnsRowset_iface );
752 static HRESULT WINAPI msdasql_rowset_QueryInterface(IRowset *iface, REFIID riid, void **ppv)
754 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
756 TRACE( "%p, %s, %p\n", rowset, debugstr_guid(riid), ppv );
758 *ppv = NULL;
759 if(IsEqualGUID(&IID_IUnknown, riid) ||
760 IsEqualGUID(&IID_IRowset, riid))
762 *ppv = &rowset->IRowset_iface;
764 else if (IsEqualGUID(&IID_IRowsetInfo, riid))
766 *ppv = &rowset->IRowsetInfo_iface;
768 else if (IsEqualGUID(&IID_IColumnsInfo, riid))
770 *ppv = &rowset->IColumnsInfo_iface;
772 else if(IsEqualGUID(&IID_IAccessor, riid))
774 *ppv = &rowset->IAccessor_iface;
776 else if(IsEqualGUID(&IID_IColumnsRowset, riid))
778 *ppv = &rowset->IColumnsRowset_iface;
780 else if (IsEqualGUID(&IID_IRowsetChange, riid))
782 TRACE("IID_IRowsetChange not supported\n");
783 return E_NOINTERFACE;
785 else if (IsEqualGUID(&IID_IRowsetUpdate, riid))
787 TRACE("IID_IRowsetUpdate not supported\n");
788 return E_NOINTERFACE;
790 else if (IsEqualGUID(&IID_IRowsetLocate, riid))
792 TRACE("IID_IRowsetLocate not supported\n");
793 return E_NOINTERFACE;
796 if(*ppv)
798 IUnknown_AddRef((IUnknown*)*ppv);
799 return S_OK;
802 FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
803 return E_NOINTERFACE;
806 static ULONG WINAPI msdasql_rowset_AddRef(IRowset *iface)
808 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
809 LONG refs = InterlockedIncrement( &rowset->refs );
810 TRACE( "%p new refcount %ld\n", rowset, refs );
811 return refs;
814 static ULONG WINAPI msdasql_rowset_Release(IRowset *iface)
816 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
817 LONG refs = InterlockedDecrement( &rowset->refs );
818 TRACE( "%p new refcount %ld\n", rowset, refs );
819 if (!refs)
821 TRACE( "destroying %p\n", rowset );
823 SQLFreeHandle(SQL_HANDLE_STMT, rowset->hstmt);
825 if (rowset->caller)
826 IUnknown_Release(rowset->caller);
828 free(rowset);
830 return refs;
833 static HRESULT WINAPI msdasql_rowset_AddRefRows(IRowset *iface, DBCOUNTITEM count,
834 const HROW rows[], DBREFCOUNT ref_counts[], DBROWSTATUS status[])
836 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
837 FIXME("%p, %Id, %p, %p, %p\n", rowset, count, rows, ref_counts, status);
838 return E_NOTIMPL;
841 static HRESULT WINAPI msdasql_rowset_GetData(IRowset *iface, HROW row, HACCESSOR accessor, void *data)
843 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
844 FIXME("%p, %Id, %Id, %p\n", rowset, row, accessor, data);
845 return E_NOTIMPL;
848 static HRESULT WINAPI msdasql_rowset_GetNextRows(IRowset *iface, HCHAPTER reserved, DBROWOFFSET offset,
849 DBROWCOUNT count, DBCOUNTITEM *obtained, HROW **rows)
851 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
852 FIXME("%p, %Id, %Id, %Id, %p, %p\n", rowset, reserved, offset, count, obtained, rows);
853 return E_NOTIMPL;
856 static HRESULT WINAPI msdasql_rowset_ReleaseRows(IRowset *iface, DBCOUNTITEM count,
857 const HROW rows[], DBROWOPTIONS options[], DBREFCOUNT ref_counts[], DBROWSTATUS status[])
859 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
861 FIXME("%p, %Id, %p, %p, %p, %p\n", rowset, count, rows, options, ref_counts, status);
862 return E_NOTIMPL;
865 static HRESULT WINAPI msdasql_rowset_RestartPosition(IRowset *iface, HCHAPTER reserved)
867 struct msdasql_rowset *rowset = impl_from_IRowset( iface );
868 FIXME("%p, %Id\n", rowset, reserved);
869 return E_NOTIMPL;
872 static const struct IRowsetVtbl msdasql_rowset_vtbl =
874 msdasql_rowset_QueryInterface,
875 msdasql_rowset_AddRef,
876 msdasql_rowset_Release,
877 msdasql_rowset_AddRefRows,
878 msdasql_rowset_GetData,
879 msdasql_rowset_GetNextRows,
880 msdasql_rowset_ReleaseRows,
881 msdasql_rowset_RestartPosition
884 static HRESULT WINAPI rowset_info_QueryInterface(IRowsetInfo *iface, REFIID riid, void **ppv)
886 struct msdasql_rowset *rowset = impl_from_IRowsetInfo( iface );
887 return IRowset_QueryInterface(&rowset->IRowset_iface, riid, ppv);
890 static ULONG WINAPI rowset_info_AddRef(IRowsetInfo *iface)
892 struct msdasql_rowset *rowset = impl_from_IRowsetInfo( iface );
893 return IRowset_AddRef(&rowset->IRowset_iface);
896 static ULONG WINAPI rowset_info_Release(IRowsetInfo *iface)
898 struct msdasql_rowset *rowset = impl_from_IRowsetInfo( iface );
899 return IRowset_Release(&rowset->IRowset_iface);
902 static HRESULT WINAPI rowset_info_GetProperties(IRowsetInfo *iface, const ULONG count,
903 const DBPROPIDSET propertyidsets[], ULONG *out_count, DBPROPSET **propertysets)
905 struct msdasql_rowset *rowset = impl_from_IRowsetInfo( iface );
906 HRESULT hr;
907 ICommandProperties *props;
909 TRACE("%p, %lu, %p, %p, %p\n", rowset, count, propertyidsets, out_count, propertysets);
911 hr = IUnknown_QueryInterface(rowset->caller, &IID_ICommandProperties, (void**)&props);
912 if (FAILED(hr))
913 return hr;
915 hr = ICommandProperties_GetProperties(props, count, propertyidsets, out_count, propertysets);
916 ICommandProperties_Release(props);
918 return hr;
921 static HRESULT WINAPI rowset_info_GetReferencedRowset(IRowsetInfo *iface, DBORDINAL ordinal,
922 REFIID riid, IUnknown **unk)
924 struct msdasql_rowset *rowset = impl_from_IRowsetInfo( iface );
925 FIXME("%p, %Id, %s, %p\n", rowset, ordinal, debugstr_guid(riid), unk);
926 return E_NOTIMPL;
929 static HRESULT WINAPI rowset_info_GetSpecification(IRowsetInfo *iface, REFIID riid,
930 IUnknown **specification)
932 struct msdasql_rowset *rowset = impl_from_IRowsetInfo( iface );
934 TRACE("%p, %s, %p\n", rowset, debugstr_guid(riid), specification);
936 if (!specification)
937 return E_INVALIDARG;
939 if (!rowset->caller)
940 return S_FALSE;
942 return IUnknown_QueryInterface(rowset->caller, riid, (void**)specification);
945 struct IRowsetInfoVtbl rowset_info_vtbl =
947 rowset_info_QueryInterface,
948 rowset_info_AddRef,
949 rowset_info_Release,
950 rowset_info_GetProperties,
951 rowset_info_GetReferencedRowset,
952 rowset_info_GetSpecification
955 static HRESULT WINAPI rowset_colsinfo_QueryInterface(IColumnsInfo *iface, REFIID riid, void **out)
957 struct msdasql_rowset *rowset = rowset_impl_from_IColumnsInfo( iface );
958 return IRowset_QueryInterface(&rowset->IRowset_iface, riid, out);
961 static ULONG WINAPI rowset_colsinfo_AddRef(IColumnsInfo *iface)
963 struct msdasql_rowset *rowset = rowset_impl_from_IColumnsInfo( iface );
964 return IRowset_AddRef(&rowset->IRowset_iface);
967 static ULONG WINAPI rowset_colsinfo_Release(IColumnsInfo *iface)
969 struct msdasql_rowset *rowset = rowset_impl_from_IColumnsInfo( iface );
970 return IRowset_Release(&rowset->IRowset_iface);
973 static HRESULT WINAPI rowset_colsinfo_GetColumnInfo(IColumnsInfo *iface, DBORDINAL *columns,
974 DBCOLUMNINFO **colinfo, OLECHAR **stringsbuffer)
976 #define MAX_COLUMN_LEN 128
978 struct msdasql_rowset *rowset = rowset_impl_from_IColumnsInfo( iface );
979 DBCOLUMNINFO *dbcolumn;
980 RETCODE ret;
981 SQLSMALLINT colcnt;
982 int i;
983 OLECHAR *ptr;
985 TRACE("%p, %p, %p, %p\n", rowset, columns, colinfo, stringsbuffer);
987 if (!columns || !colinfo || !stringsbuffer)
988 return E_INVALIDARG;
990 SQLNumResultCols(rowset->hstmt, &colcnt);
991 TRACE("SQLNumResultCols %d\n", colcnt);
993 *columns = colcnt;
995 ptr = *stringsbuffer = CoTaskMemAlloc(colcnt * MAX_COLUMN_LEN * sizeof(WCHAR));
996 if (!ptr)
997 return E_OUTOFMEMORY;
999 dbcolumn = CoTaskMemAlloc(colcnt * sizeof(DBCOLUMNINFO));
1000 if (!dbcolumn)
1002 CoTaskMemFree(ptr);
1003 return E_OUTOFMEMORY;
1006 for (i = 0; i < colcnt; i++)
1008 SQLWCHAR columnname[MAX_COLUMN_LEN];
1009 SQLSMALLINT ColumnNameLen;
1010 SQLSMALLINT ColumnDataType;
1011 SQLULEN ColumnDataSize;
1012 SQLSMALLINT ColumnDataDigits;
1013 SQLSMALLINT ColumnDataNullable;
1015 ret = SQLDescribeColW(rowset->hstmt, i+1, columnname, MAX_COLUMN_LEN, &ColumnNameLen, &ColumnDataType,
1016 &ColumnDataSize, &ColumnDataDigits, &ColumnDataNullable);
1017 if (SQL_SUCCEEDED(ret))
1019 SQLLEN length;
1021 TRACE("%d: Column Name : %s, Column Name Len : %i, SQL Data Type : %i, Data Size : %i, DecimalDigits : %i, Nullable %i\n",
1022 i, debugstr_w(columnname), (int)ColumnNameLen, (int)ColumnDataType, (int)ColumnDataSize, (int)ColumnDataDigits,
1023 (int)ColumnDataNullable);
1024 lstrcpyW(ptr, columnname);
1026 dbcolumn[i].pwszName = ptr;
1027 dbcolumn[i].pTypeInfo = NULL;
1028 dbcolumn[i].iOrdinal = i+1;
1030 ret = SQLColAttributesW (rowset->hstmt, i+1, SQL_DESC_UNSIGNED, NULL, 0, NULL, &length);
1031 if (!SQL_SUCCEEDED(ret))
1033 dump_sql_diag_records(SQL_HANDLE_STMT, rowset->hstmt);
1034 CoTaskMemFree(ptr);
1035 CoTaskMemFree(dbcolumn);
1036 ERR("Failed to get column %d attribute\n", i+1);
1037 return E_FAIL;
1040 dbcolumn[i].wType = sqltype_to_bindtype(ColumnDataType, length == SQL_FALSE);
1041 TRACE("SQLType %s -> %s\n", debugstr_sqltype(ColumnDataType), debugstr_dbtype(dbcolumn[i].wType));
1043 dbcolumn[i].dwFlags = DBCOLUMNFLAGS_WRITE;
1045 ret = SQLColAttributesW(rowset->hstmt, i+1, SQL_DESC_LENGTH, NULL, 0, NULL, &length);
1046 if (!SQL_SUCCEEDED(ret))
1048 CoTaskMemFree(ptr);
1049 CoTaskMemFree(dbcolumn);
1050 ERR("Failed to get column %d length (%d)\n", i+1, ret);
1051 return E_FAIL;
1053 dbcolumn[i].ulColumnSize = length;
1055 if (dbcolumn[i].ulColumnSize > 1024 && is_variable_length(ColumnDataType))
1056 dbcolumn[i].dwFlags |= DBCOLUMNFLAGS_MAYDEFER | DBCOLUMNFLAGS_ISLONG;
1058 if (ColumnDataNullable)
1059 dbcolumn[i].dwFlags |= DBCOLUMNFLAGS_ISNULLABLE | DBCOLUMNFLAGS_MAYBENULL;
1061 if (is_fixed_length(ColumnDataType))
1062 dbcolumn[i].dwFlags |= DBCOLUMNFLAGS_ISFIXEDLENGTH;
1064 ret = SQLColAttributesW(rowset->hstmt, i+1, SQL_DESC_SCALE, NULL, 0, NULL, &length);
1065 if (!SQL_SUCCEEDED(ret))
1067 CoTaskMemFree(ptr);
1068 CoTaskMemFree(dbcolumn);
1069 ERR("Failed to get column %d scale (%d)\n", i+1, ret);
1070 return E_FAIL;
1072 if (length == 0)
1073 length = 255;
1074 dbcolumn[i].bScale = length;
1076 ret = SQLColAttributesW(rowset->hstmt, i+1, SQL_DESC_PRECISION, NULL, 0, NULL, &length);
1077 if (!SQL_SUCCEEDED(ret))
1079 CoTaskMemFree(ptr);
1080 CoTaskMemFree(dbcolumn);
1081 ERR("Failed to get column %d precision (%d)\n", i+1, ret);
1082 return E_FAIL;
1084 if (length == 0)
1085 length = 255;
1086 dbcolumn[i].bPrecision= length;
1088 dbcolumn[i].columnid.eKind = DBKIND_NAME;
1089 dbcolumn[i].columnid.uName.pwszName = ptr;
1091 ptr += ColumnNameLen + 1;
1093 else
1095 CoTaskMemFree(ptr);
1096 CoTaskMemFree(dbcolumn);
1097 ERR("Failed to get column %d description (%d)\n", i+1, ret);
1098 return E_FAIL;
1102 *colinfo = dbcolumn;
1103 #undef MAX_COLUMN_LEN
1104 return S_OK;
1107 static HRESULT WINAPI rowset_colsinfo_MapColumnIDs(IColumnsInfo *iface, DBORDINAL column_ids,
1108 const DBID *dbids, DBORDINAL *columns)
1110 struct msdasql_rowset *rowset = rowset_impl_from_IColumnsInfo( iface );
1111 FIXME("%p, %Id, %p, %p\n", rowset, column_ids, dbids, columns);
1112 return E_NOTIMPL;
1115 static struct IColumnsInfoVtbl rowset_columninfo_vtbll =
1117 rowset_colsinfo_QueryInterface,
1118 rowset_colsinfo_AddRef,
1119 rowset_colsinfo_Release,
1120 rowset_colsinfo_GetColumnInfo,
1121 rowset_colsinfo_MapColumnIDs
1124 static HRESULT WINAPI rowset_accessor_QueryInterface(IAccessor *iface, REFIID riid, void **out)
1126 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1127 return IRowset_QueryInterface(&rowset->IRowset_iface, riid, out);
1130 static ULONG WINAPI rowset_accessor_AddRef(IAccessor *iface)
1132 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1133 return IRowset_AddRef(&rowset->IRowset_iface);
1136 static ULONG WINAPI rowset_accessor_Release(IAccessor *iface)
1138 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1139 return IRowset_Release(&rowset->IRowset_iface);
1142 static HRESULT WINAPI rowset_accessor_AddRefAccessor(IAccessor *iface, HACCESSOR accessor, DBREFCOUNT *count)
1144 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1145 FIXME("%p, %Id, %p\n", rowset, accessor, count);
1146 return E_NOTIMPL;
1149 static HRESULT WINAPI rowset_accessor_CreateAccessor(IAccessor *iface, DBACCESSORFLAGS flags,
1150 DBCOUNTITEM count, const DBBINDING bindings[], DBLENGTH row_size, HACCESSOR *accessor,
1151 DBBINDSTATUS status[])
1153 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1154 FIXME("%p, 0x%08lx, %Id, %p, %Id, %p, %p\n", rowset, flags, count, bindings, row_size, accessor, status);
1155 return E_NOTIMPL;
1158 static HRESULT WINAPI rowset_accessor_GetBindings(IAccessor *iface, HACCESSOR accessor,
1159 DBACCESSORFLAGS *flags, DBCOUNTITEM *count, DBBINDING **bindings)
1161 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1162 FIXME("%p, %Id, %p, %p, %p\n", rowset, accessor, flags, count, bindings);
1163 return E_NOTIMPL;
1166 static HRESULT WINAPI rowset_accessor_ReleaseAccessor(IAccessor *iface, HACCESSOR accessor, DBREFCOUNT *count)
1168 struct msdasql_rowset *rowset = impl_from_IAccessor( iface );
1169 FIXME("%p, %Id, %p\n", rowset, accessor, count);
1170 return E_NOTIMPL;
1173 struct IAccessorVtbl accessor_vtbl =
1175 rowset_accessor_QueryInterface,
1176 rowset_accessor_AddRef,
1177 rowset_accessor_Release,
1178 rowset_accessor_AddRefAccessor,
1179 rowset_accessor_CreateAccessor,
1180 rowset_accessor_GetBindings,
1181 rowset_accessor_ReleaseAccessor
1184 static HRESULT WINAPI column_rs_QueryInterface(IColumnsRowset *iface, REFIID riid, void **out)
1186 struct msdasql_rowset *rowset = impl_from_IColumnsRowset( iface );
1187 return IRowset_QueryInterface(&rowset->IRowset_iface, riid, out);
1190 static ULONG WINAPI column_rs_AddRef(IColumnsRowset *iface)
1192 struct msdasql_rowset *rowset = impl_from_IColumnsRowset( iface );
1193 return IRowset_AddRef(&rowset->IRowset_iface);
1196 static ULONG WINAPI column_rs_Release(IColumnsRowset *iface)
1198 struct msdasql_rowset *rowset = impl_from_IColumnsRowset( iface );
1199 return IRowset_Release(&rowset->IRowset_iface);
1202 static HRESULT WINAPI column_rs_GetAvailableColumns(IColumnsRowset *iface, DBORDINAL *count, DBID **columns)
1204 struct msdasql_rowset *rowset = impl_from_IColumnsRowset( iface );
1205 const DBORDINAL extra_columns = 3;
1207 TRACE("%p, %p, %p\n", rowset, count, columns);
1209 if (!count || !columns)
1210 return E_INVALIDARG;
1212 *count = 0;
1213 *columns = CoTaskMemAlloc(sizeof(DBID) * extra_columns);
1214 if (!*columns)
1215 return E_OUTOFMEMORY;
1217 *count = extra_columns;
1218 (*columns)[0] = DBCOLUMN_BASETABLENAME;
1219 (*columns)[1] = DBCOLUMN_BASECOLUMNNAME;
1220 (*columns)[2] = DBCOLUMN_KEYCOLUMN;
1222 return S_OK;
1225 static HRESULT WINAPI column_rs_GetColumnsRowset(IColumnsRowset *iface, IUnknown *outer, DBORDINAL count,
1226 const DBID columns[], REFIID riid, ULONG property_cnt, DBPROPSET property_sets[], IUnknown **unk_rs)
1228 struct msdasql_rowset *rowset = impl_from_IColumnsRowset( iface );
1229 FIXME("(%p)->(%p, %Id, %p, %s, %lu, %p, %p): stub\n", rowset, outer, count, columns, debugstr_guid(riid),
1230 property_cnt, property_sets, unk_rs);
1231 return E_NOTIMPL;
1234 struct IColumnsRowsetVtbl columnrs_rs_vtbl =
1236 column_rs_QueryInterface,
1237 column_rs_AddRef,
1238 column_rs_Release,
1239 column_rs_GetAvailableColumns,
1240 column_rs_GetColumnsRowset
1243 static HRESULT WINAPI command_Execute(ICommandText *iface, IUnknown *outer, REFIID riid,
1244 DBPARAMS *params, DBROWCOUNT *affected, IUnknown **rowset)
1246 struct command *command = impl_from_ICommandText( iface );
1247 struct msdasql_rowset *msrowset;
1248 HRESULT hr = S_OK;
1249 RETCODE ret;
1250 SQLHSTMT hstmt = command->hstmt;
1251 SQLLEN results = -1;
1252 BOOL free_hstmt = TRUE;
1254 TRACE("%p, %p, %s, %p %p %p\n", command, outer, debugstr_guid(riid), params, affected, rowset);
1256 if (!hstmt)
1257 SQLAllocHandle(SQL_HANDLE_STMT, command->hdbc, &hstmt);
1259 ret = SQLExecDirectW(hstmt, command->query, SQL_NTS);
1260 if (ret != SQL_SUCCESS)
1262 dump_sql_diag_records(SQL_HANDLE_STMT, hstmt);
1263 return E_FAIL;
1266 if (rowset)
1267 *rowset = NULL;
1268 if (!wcsnicmp( command->query, L"select ", 7 ))
1270 msrowset = malloc(sizeof(*msrowset));
1271 if (!msrowset)
1272 return E_OUTOFMEMORY;
1274 command->hstmt = NULL;
1276 msrowset->IRowset_iface.lpVtbl = &msdasql_rowset_vtbl;
1277 msrowset->IRowsetInfo_iface.lpVtbl = &rowset_info_vtbl;
1278 msrowset->IColumnsInfo_iface.lpVtbl = &rowset_columninfo_vtbll;
1279 msrowset->IAccessor_iface.lpVtbl = &accessor_vtbl;
1280 msrowset->IColumnsRowset_iface.lpVtbl = &columnrs_rs_vtbl;
1281 msrowset->refs = 1;
1282 ICommandText_QueryInterface(iface, &IID_IUnknown, (void**)&msrowset->caller);
1283 msrowset->hstmt = hstmt;
1284 free_hstmt = FALSE;
1286 hr = IRowset_QueryInterface(&msrowset->IRowset_iface, riid, (void**)rowset);
1287 IRowset_Release(&msrowset->IRowset_iface);
1290 if (affected)
1292 ret = SQLRowCount(hstmt, &results);
1293 if (ret != SQL_SUCCESS)
1294 ERR("SQLRowCount failed (%d)\n", ret);
1296 *affected = results;
1299 if (free_hstmt)
1300 SQLFreeStmt(hstmt, SQL_CLOSE);
1302 return hr;
1305 static HRESULT WINAPI command_GetDBSession(ICommandText *iface, REFIID riid, IUnknown **session)
1307 struct command *command = impl_from_ICommandText( iface );
1309 TRACE("%p, %s, %p\n", command, debugstr_guid(riid), session);
1311 if (!session)
1312 return E_INVALIDARG;
1314 *session = NULL;
1316 if (!command->session)
1317 return S_FALSE;
1319 return IUnknown_QueryInterface(command->session, riid, (void**)session);
1322 static HRESULT WINAPI command_GetCommandText(ICommandText *iface, GUID *dialect, LPOLESTR *commandstr)
1324 struct command *command = impl_from_ICommandText( iface );
1325 HRESULT hr = S_OK;
1326 TRACE("%p, %p, %p\n", command, dialect, commandstr);
1328 if (!command->query)
1329 return DB_E_NOCOMMAND;
1331 if (dialect && !IsEqualGUID(&DBGUID_DEFAULT, dialect))
1333 *dialect = DBGUID_DEFAULT;
1334 hr = DB_S_DIALECTIGNORED;
1337 *commandstr = wcsdup(command->query);
1338 return hr;
1341 static HRESULT WINAPI command_SetCommandText(ICommandText *iface, REFGUID dialect, LPCOLESTR commandstr)
1343 struct command *command = impl_from_ICommandText( iface );
1344 TRACE("%p, %s, %s\n", command, debugstr_guid(dialect), debugstr_w(commandstr));
1346 if (!IsEqualGUID(&DBGUID_DEFAULT, dialect))
1347 FIXME("Currently non Default Dialect isn't supported\n");
1349 free(command->query);
1351 if (commandstr)
1353 command->query = wcsdup(commandstr);
1354 if (!command->query)
1355 return E_OUTOFMEMORY;
1357 else
1358 command->query = NULL;
1359 return S_OK;
1362 static const ICommandTextVtbl commandVtbl =
1364 command_QueryInterface,
1365 command_AddRef,
1366 command_Release,
1367 command_Cancel,
1368 command_Execute,
1369 command_GetDBSession,
1370 command_GetCommandText,
1371 command_SetCommandText
1374 static HRESULT WINAPI command_prop_QueryInterface(ICommandProperties *iface, REFIID riid, void **out)
1376 struct command *command = impl_from_ICommandProperties( iface );
1377 return ICommandText_QueryInterface(&command->ICommandText_iface, riid, out);
1380 static ULONG WINAPI command_prop_AddRef(ICommandProperties *iface)
1382 struct command *command = impl_from_ICommandProperties( iface );
1383 return ICommandText_AddRef(&command->ICommandText_iface);
1386 static ULONG WINAPI command_prop_Release(ICommandProperties *iface)
1388 struct command *command = impl_from_ICommandProperties( iface );
1389 return ICommandText_Release(&command->ICommandText_iface);
1392 static ULONG get_property_count(DWORD flag, struct msdasql_prop *properties, int prop_count)
1394 int i, count = 0;
1396 for(i=0; i < prop_count; i++)
1398 if (properties[i].flags & flag)
1399 count++;
1402 return count;
1405 static HRESULT WINAPI command_prop_GetProperties(ICommandProperties *iface, ULONG count,
1406 const DBPROPIDSET propertyidsets[], ULONG *sets_cnt, DBPROPSET **propertyset)
1408 struct command *command = impl_from_ICommandProperties( iface );
1409 DBPROPSET *propset = NULL;
1410 int i, j, k;
1412 TRACE("%p %ld %p %p %p\n", command, count, propertyidsets, sets_cnt, propertyset);
1414 /* All Properties */
1415 if (count == 0)
1417 int idx;
1418 propset = CoTaskMemAlloc(2 * sizeof(DBPROPSET));
1419 if (!propset)
1420 return E_OUTOFMEMORY;
1422 propset[0].guidPropertySet = DBPROPSET_ROWSET;
1423 propset[0].cProperties = get_property_count(DBPROPFLAGS_ROWSET, command->properties, command->prop_count);
1424 propset[0].rgProperties = CoTaskMemAlloc(propset[0].cProperties * sizeof(DBPROP));
1425 if (!propset[0].rgProperties)
1427 CoTaskMemFree(propset);
1428 return E_OUTOFMEMORY;
1431 idx = 0;
1432 for (j=0; j < command->prop_count; j++)
1434 if (!(command->properties[j].flags & DBPROPFLAGS_ROWSET))
1435 continue;
1436 propset[0].rgProperties[idx].dwPropertyID = command->properties[j].property_id;
1438 V_VT(&propset[0].rgProperties[idx].vValue) = command->properties[j].vartype;
1439 if (command->properties[j].vartype == VT_BOOL)
1441 V_BOOL(&propset[0].rgProperties[idx].vValue) = command->properties[j].value;
1443 else if (command->properties[j].vartype == VT_I4)
1445 V_I4(&propset[0].rgProperties[idx].vValue) = command->properties[j].value;
1447 else
1448 ERR("Unknown variant type %d\n", command->properties[j].vartype);
1450 idx++;
1453 propset[1].guidPropertySet = DBPROPSET_PROVIDERROWSET;
1454 propset[1].cProperties = get_property_count(DBPROPFLAGS_DATASOURCEINFO, command->properties, command->prop_count);
1455 propset[1].rgProperties = CoTaskMemAlloc(propset[1].cProperties * sizeof(DBPROP));
1456 if (!propset[1].rgProperties)
1458 CoTaskMemFree(propset[0].rgProperties);
1459 CoTaskMemFree(propset);
1460 return E_OUTOFMEMORY;
1463 idx = 0;
1464 for (j=0; j < command->prop_count; j++)
1466 if (!(command->properties[j].flags & DBPROPFLAGS_DATASOURCEINFO))
1467 continue;
1468 propset[1].rgProperties[idx].dwPropertyID = command->properties[j].property_id;
1470 V_VT(&propset[1].rgProperties[idx].vValue) = command->properties[j].vartype;
1471 if (command->properties[j].vartype == VT_BOOL)
1473 V_BOOL(&propset[1].rgProperties[idx].vValue) = command->properties[j].value;
1475 else if (command->properties[j].vartype == VT_I4)
1477 V_I4(&propset[1].rgProperties[idx].vValue) = command->properties[j].value;
1479 else
1480 ERR("Unknown variant type %d\n", command->properties[j].vartype);
1482 idx++;
1485 *sets_cnt = 2;
1487 else
1489 propset = CoTaskMemAlloc(count * sizeof(DBPROPSET));
1490 if (!propset)
1491 return E_OUTOFMEMORY;
1493 for (i=0; i < count; i++)
1495 TRACE("Property id %d (count %ld, set %s)\n", i, propertyidsets[i].cPropertyIDs,
1496 debugstr_guid(&propertyidsets[i].guidPropertySet));
1498 propset[i].cProperties = propertyidsets[i].cPropertyIDs;
1499 propset[i].rgProperties = CoTaskMemAlloc(propset[i].cProperties * sizeof(DBPROP));
1501 for (j=0; j < propset[i].cProperties; j++)
1503 propset[i].rgProperties[j].dwPropertyID = propertyidsets[i].rgPropertyIDs[j];
1505 for(k = 0; k < command->prop_count; k++)
1507 if (command->properties[k].property_id == propertyidsets[i].rgPropertyIDs[j])
1509 V_VT(&propset[i].rgProperties[i].vValue) = command->properties[j].vartype;
1510 if (command->properties[j].vartype == VT_BOOL)
1512 V_BOOL(&propset[i].rgProperties[i].vValue) = command->properties[j].value;
1514 else if (command->properties[j].vartype == VT_I4)
1516 V_I4(&propset[i].rgProperties[i].vValue) = command->properties[j].value;
1518 else
1519 ERR("Unknown variant type %d\n", command->properties[j].vartype);
1520 break;
1526 *sets_cnt = count;
1529 *propertyset = propset;
1531 return S_OK;
1534 static HRESULT WINAPI command_prop_SetProperties(ICommandProperties *iface, ULONG count,
1535 DBPROPSET propertyset[])
1537 struct command *command = impl_from_ICommandProperties( iface );
1538 int i, j, k;
1540 TRACE("%p %lu, %p\n", command, count, propertyset);
1542 for(i=0; i < count; i++)
1544 TRACE("set %s, count %ld\n", debugstr_guid(&propertyset[i].guidPropertySet), propertyset[i].cProperties);
1545 for(j=0; j < propertyset[i].cProperties; j++)
1547 for(k=0; k < command->prop_count; k++)
1549 if (command->properties[k].property_id == propertyset[i].rgProperties[j].dwPropertyID)
1551 TRACE("Found property 0x%08lx\n", command->properties[k].property_id);
1552 if (command->properties[k].flags & DBPROPFLAGS_WRITE)
1554 if (command->properties[k].vartype == VT_BOOL)
1556 command->properties[k].value = V_BOOL(&propertyset[i].rgProperties[j].vValue);
1558 else if (command->properties[k].vartype == VT_I4)
1560 command->properties[k].value = V_I4(&propertyset[i].rgProperties[j].vValue);
1562 else
1563 ERR("Unknown variant type %d\n", command->properties[j].vartype);
1565 else
1566 WARN("Attempting to set Readonly property\n");
1568 break;
1573 return S_OK;
1576 static const ICommandPropertiesVtbl commonpropsVtbl =
1578 command_prop_QueryInterface,
1579 command_prop_AddRef,
1580 command_prop_Release,
1581 command_prop_GetProperties,
1582 command_prop_SetProperties
1585 static HRESULT WINAPI colsinfo_QueryInterface(IColumnsInfo *iface, REFIID riid, void **out)
1587 struct command *command = impl_from_IColumnsInfo( iface );
1588 return ICommandText_QueryInterface(&command->ICommandText_iface, riid, out);
1591 static ULONG WINAPI colsinfo_AddRef(IColumnsInfo *iface)
1593 struct command *command = impl_from_IColumnsInfo( iface );
1594 return ICommandText_AddRef(&command->ICommandText_iface);
1597 static ULONG WINAPI colsinfo_Release(IColumnsInfo *iface)
1599 struct command *command = impl_from_IColumnsInfo( iface );
1600 return ICommandText_Release(&command->ICommandText_iface);
1603 static HRESULT WINAPI colsinfo_GetColumnInfo(IColumnsInfo *iface, DBORDINAL *columns,
1604 DBCOLUMNINFO **colinfo, OLECHAR **stringsbuffer)
1606 struct command *command = impl_from_IColumnsInfo( iface );
1607 FIXME("%p, %p, %p, %p\n", command, columns, colinfo, stringsbuffer);
1608 return E_NOTIMPL;
1611 static HRESULT WINAPI colsinfo_MapColumnIDs(IColumnsInfo *iface, DBORDINAL column_ids,
1612 const DBID *dbids, DBORDINAL *columns)
1614 struct command *command = impl_from_IColumnsInfo( iface );
1615 FIXME("%p, %Iu, %p, %p\n", command, column_ids, dbids, columns);
1616 return E_NOTIMPL;
1619 static struct IColumnsInfoVtbl columninfoVtbl =
1621 colsinfo_QueryInterface,
1622 colsinfo_AddRef,
1623 colsinfo_Release,
1624 colsinfo_GetColumnInfo,
1625 colsinfo_MapColumnIDs
1628 static HRESULT WINAPI converttype_QueryInterface(IConvertType *iface, REFIID riid, void **out)
1630 struct command *command = impl_from_IConvertType( iface );
1631 return ICommandText_QueryInterface(&command->ICommandText_iface, riid, out);
1634 static ULONG WINAPI converttype_AddRef(IConvertType *iface)
1636 struct command *command = impl_from_IConvertType( iface );
1637 return ICommandText_AddRef(&command->ICommandText_iface);
1640 static ULONG WINAPI converttype_Release(IConvertType *iface)
1642 struct command *command = impl_from_IConvertType( iface );
1643 return ICommandText_Release(&command->ICommandText_iface);
1646 static HRESULT WINAPI converttype_CanConvert(IConvertType *iface, DBTYPE from, DBTYPE to, DBCONVERTFLAGS flags)
1648 struct command *command = impl_from_IConvertType( iface );
1649 FIXME("%p, %u, %d, 0x%08lx\n", command, from, to, flags);
1650 return E_NOTIMPL;
1653 static struct IConvertTypeVtbl converttypeVtbl =
1655 converttype_QueryInterface,
1656 converttype_AddRef,
1657 converttype_Release,
1658 converttype_CanConvert
1661 static HRESULT WINAPI commandprepare_QueryInterface(ICommandPrepare *iface, REFIID riid, void **out)
1663 struct command *command = impl_from_ICommandPrepare( iface );
1664 return ICommandText_QueryInterface(&command->ICommandText_iface, riid, out);
1667 static ULONG WINAPI commandprepare_AddRef(ICommandPrepare *iface)
1669 struct command *command = impl_from_ICommandPrepare( iface );
1670 return ICommandText_AddRef(&command->ICommandText_iface);
1673 static ULONG WINAPI commandprepare_Release(ICommandPrepare *iface)
1675 struct command *command = impl_from_ICommandPrepare( iface );
1676 return ICommandText_Release(&command->ICommandText_iface);
1679 static HRESULT WINAPI commandprepare_Prepare(ICommandPrepare *iface, ULONG runs)
1681 struct command *command = impl_from_ICommandPrepare( iface );
1682 RETCODE ret;
1684 TRACE("%p, %lu\n", command, runs);
1686 if (!command->query)
1687 return DB_E_NOCOMMAND;
1689 if (command->hstmt)
1690 SQLFreeHandle(SQL_HANDLE_STMT, command->hstmt);
1692 SQLAllocHandle(SQL_HANDLE_STMT, command->hdbc, &command->hstmt);
1694 ret = SQLPrepareW(command->hstmt, command->query, SQL_NTS);
1695 if (ret != SQL_SUCCESS)
1697 dump_sql_diag_records(SQL_HANDLE_STMT, command->hstmt);
1698 return E_FAIL;
1700 return S_OK;
1703 static HRESULT WINAPI commandprepare_Unprepare(ICommandPrepare *iface)
1705 struct command *command = impl_from_ICommandPrepare( iface );
1706 TRACE("%p\n", command);
1707 return S_OK;
1710 struct ICommandPrepareVtbl commandprepareVtbl =
1712 commandprepare_QueryInterface,
1713 commandprepare_AddRef,
1714 commandprepare_Release,
1715 commandprepare_Prepare,
1716 commandprepare_Unprepare
1719 static HRESULT WINAPI cmd_with_params_QueryInterface(ICommandWithParameters *iface, REFIID riid, void **out)
1721 struct command *command = impl_from_ICommandWithParameters( iface );
1722 return ICommandText_QueryInterface(&command->ICommandText_iface, riid, out);
1725 static ULONG WINAPI cmd_with_params_AddRef(ICommandWithParameters *iface)
1727 struct command *command = impl_from_ICommandWithParameters( iface );
1728 return ICommandText_AddRef(&command->ICommandText_iface);
1731 static ULONG WINAPI cmd_with_params_Release(ICommandWithParameters *iface)
1733 struct command *command = impl_from_ICommandWithParameters( iface );
1734 return ICommandText_Release(&command->ICommandText_iface);
1737 static HRESULT WINAPI cmd_with_params_GetParameterInfo(ICommandWithParameters *iface, DB_UPARAMS *uparams,
1738 DBPARAMINFO **info, OLECHAR **buffer)
1740 struct command *command = impl_from_ICommandWithParameters( iface );
1741 FIXME("%p, %p, %p, %p\n", command, uparams, info, buffer);
1742 return E_NOTIMPL;
1745 static HRESULT WINAPI cmd_with_params_MapParameterNames(ICommandWithParameters *iface, DB_UPARAMS uparams,
1746 LPCWSTR names[], DB_LPARAMS ordinals[])
1748 struct command *command = impl_from_ICommandWithParameters( iface );
1749 FIXME("%p, %Iu, %p, %p\n", command, uparams, names, ordinals);
1750 return E_NOTIMPL;
1753 static HRESULT WINAPI cmd_with_params_SetParameterInfo(ICommandWithParameters *iface, DB_UPARAMS uparams,
1754 const DB_UPARAMS ordinals[], const DBPARAMBINDINFO bindinfo[])
1756 struct command *command = impl_from_ICommandWithParameters( iface );
1757 FIXME("%p, %Iu, %p, %p\n", command, uparams, ordinals, bindinfo);
1758 return E_NOTIMPL;
1761 struct ICommandWithParametersVtbl command_with_params_vtbl =
1763 cmd_with_params_QueryInterface,
1764 cmd_with_params_AddRef,
1765 cmd_with_params_Release,
1766 cmd_with_params_GetParameterInfo,
1767 cmd_with_params_MapParameterNames,
1768 cmd_with_params_SetParameterInfo
1771 static HRESULT WINAPI createcommand_CreateCommand(IDBCreateCommand *iface, IUnknown *outer, REFIID riid,
1772 IUnknown **out)
1774 struct msdasql_session *session = impl_from_IDBCreateCommand( iface );
1775 struct command *command;
1776 HRESULT hr;
1778 TRACE("%p, %p, %s, %p\n", session, outer, debugstr_guid(riid), out);
1780 if (outer)
1781 FIXME("Outer not currently supported\n");
1783 command = malloc(sizeof(*command));
1784 if (!command)
1785 return E_OUTOFMEMORY;
1787 command->ICommandText_iface.lpVtbl = &commandVtbl;
1788 command->ICommandProperties_iface.lpVtbl = &commonpropsVtbl;
1789 command->IColumnsInfo_iface.lpVtbl = &columninfoVtbl;
1790 command->IConvertType_iface.lpVtbl = &converttypeVtbl;
1791 command->ICommandPrepare_iface.lpVtbl = &commandprepareVtbl;
1792 command->ICommandWithParameters_iface.lpVtbl = &command_with_params_vtbl;
1793 command->refs = 1;
1794 command->query = NULL;
1795 command->hdbc = session->hdbc;
1796 command->hstmt = NULL;
1798 command->prop_count = ARRAY_SIZE(msdasql_init_props);
1799 command->properties = malloc(sizeof(msdasql_init_props));
1800 memcpy(command->properties, msdasql_init_props, sizeof(msdasql_init_props));
1802 IUnknown_QueryInterface(&session->session_iface, &IID_IUnknown, (void**)&command->session);
1804 hr = ICommandText_QueryInterface(&command->ICommandText_iface, riid, (void**)out);
1805 ICommandText_Release(&command->ICommandText_iface);
1806 return hr;
1809 static const IDBCreateCommandVtbl createcommandVtbl =
1811 createcommand_QueryInterface,
1812 createcommand_AddRef,
1813 createcommand_Release,
1814 createcommand_CreateCommand
1817 static HRESULT WINAPI transjoin_QueryInterface(ITransactionJoin *iface, REFIID riid, void **out)
1819 struct msdasql_session *session = impl_from_ITransactionJoin( iface );
1820 return IUnknown_QueryInterface(&session->session_iface, riid, out);
1823 static ULONG WINAPI transjoin_AddRef(ITransactionJoin *iface)
1825 struct msdasql_session *session = impl_from_ITransactionJoin( iface );
1826 return IUnknown_AddRef(&session->session_iface);
1829 static ULONG WINAPI transjoin_Release(ITransactionJoin *iface)
1831 struct msdasql_session *session = impl_from_ITransactionJoin( iface );
1832 return IUnknown_Release(&session->session_iface);
1835 static HRESULT WINAPI transjoin_GetOptionsObject(ITransactionJoin *iface, ITransactionOptions **options)
1837 struct msdasql_session *session = impl_from_ITransactionJoin( iface );
1839 FIXME("%p, %p\n", session, options);
1841 return E_NOTIMPL;
1844 static HRESULT WINAPI transjoin_JoinTransaction(ITransactionJoin *iface, IUnknown *unk, ISOLEVEL level,
1845 ULONG flags, ITransactionOptions *options)
1847 struct msdasql_session *session = impl_from_ITransactionJoin( iface );
1849 FIXME("%p, %p, %lu, 0x%08lx, %p\n", session, unk, level, flags, options);
1851 return E_NOTIMPL;
1854 static const ITransactionJoinVtbl transactionjoinVtbl =
1856 transjoin_QueryInterface,
1857 transjoin_AddRef,
1858 transjoin_Release,
1859 transjoin_GetOptionsObject,
1860 transjoin_JoinTransaction
1863 static HRESULT WINAPI transaction_QueryInterface(ITransaction *iface, REFIID riid, void **out)
1865 struct msdasql_session *session = impl_from_ITransaction( iface );
1866 return IUnknown_QueryInterface(&session->session_iface, riid, out);
1869 static ULONG WINAPI transaction_AddRef(ITransaction *iface)
1871 struct msdasql_session *session = impl_from_ITransaction( iface );
1872 return IUnknown_AddRef(&session->session_iface);
1875 static ULONG WINAPI transaction_Release(ITransaction *iface)
1877 struct msdasql_session *session = impl_from_ITransaction( iface );
1878 return IUnknown_Release(&session->session_iface);
1881 static HRESULT WINAPI transaction_Commit(ITransaction *iface, BOOL retaining, DWORD tc, DWORD rm)
1883 struct msdasql_session *session = impl_from_ITransaction( iface );
1885 FIXME("%p, %d, %ld, %ld\n", session, retaining, tc, rm);
1887 return E_NOTIMPL;
1890 static HRESULT WINAPI transaction_Abort(ITransaction *iface, BOID *reason, BOOL retaining, BOOL async)
1892 struct msdasql_session *session = impl_from_ITransaction( iface );
1894 FIXME("%p, %p, %d, %d\n", session, reason, retaining, async);
1896 return E_NOTIMPL;
1899 static HRESULT WINAPI transaction_GetTransactionInfo(ITransaction *iface, XACTTRANSINFO *info)
1901 struct msdasql_session *session = impl_from_ITransaction( iface );
1903 FIXME("%p, %p\n", session, info);
1905 return E_NOTIMPL;
1908 static const ITransactionVtbl transactionVtbl =
1910 transaction_QueryInterface,
1911 transaction_AddRef,
1912 transaction_Release,
1913 transaction_Commit,
1914 transaction_Abort,
1915 transaction_GetTransactionInfo
1918 HRESULT create_db_session(REFIID riid, IUnknown *datasource, HDBC hdbc, void **unk)
1920 struct msdasql_session *session;
1921 HRESULT hr;
1923 session = malloc(sizeof(*session));
1924 if (!session)
1925 return E_OUTOFMEMORY;
1927 session->session_iface.lpVtbl = &unkfactoryVtbl;
1928 session->IGetDataSource_iface.lpVtbl = &datasourceVtbl;
1929 session->IOpenRowset_iface.lpVtbl = &openrowsetVtbl;
1930 session->ISessionProperties_iface.lpVtbl = &propertiesVtbl;
1931 session->IDBCreateCommand_iface.lpVtbl = &createcommandVtbl;
1932 session->ITransactionJoin_iface.lpVtbl = &transactionjoinVtbl;
1933 session->ITransaction_iface.lpVtbl = &transactionVtbl;
1935 IUnknown_QueryInterface(datasource, &IID_IUnknown, (void**)&session->datasource);
1936 session->refs = 1;
1937 session->hdbc = hdbc;
1939 hr = IUnknown_QueryInterface(&session->session_iface, riid, unk);
1940 IUnknown_Release(&session->session_iface);
1941 return hr;