2 * Copyright 2019 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
20 #define DBINITCONSTANTS
29 #include "wine/debug.h"
38 #include "msdasql_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msdasql
);
42 void dump_sql_diag_records(SQLSMALLINT type
, SQLHANDLE handle
)
44 SQLCHAR state
[6], msg
[SQL_MAX_MESSAGE_LENGTH
];
46 SQLSMALLINT i
= 1, len
;
48 if (!TRACE_ON(msdasql
))
51 while(SQLGetDiagRec(type
, handle
, i
, state
, &native
, msg
, sizeof(msg
), &len
) == SQL_SUCCESS
)
53 WARN("%d: %s: %s\n", i
, state
, msg
);
58 static HRESULT WINAPI
ClassFactory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppv
)
62 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
63 TRACE("(%p)->(IID_IUnknown %p)\n", iface
, ppv
);
65 }else if(IsEqualGUID(&IID_IClassFactory
, riid
)) {
66 TRACE("(%p)->(IID_IClassFactory %p)\n", iface
, ppv
);
71 IUnknown_AddRef((IUnknown
*)*ppv
);
75 WARN("(%p)->(%s %p)\n", iface
, debugstr_guid(riid
), ppv
);
79 static ULONG WINAPI
ClassFactory_AddRef(IClassFactory
*iface
)
81 TRACE("(%p)\n", iface
);
85 static ULONG WINAPI
ClassFactory_Release(IClassFactory
*iface
)
87 TRACE("(%p)\n", iface
);
91 static HRESULT
create_msdasql_provider(REFIID riid
, void **ppv
);
92 static HRESULT
create_msdasql_enumerator(REFIID riid
, void **ppv
);
94 HRESULT WINAPI
msdasql_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
96 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
98 return create_msdasql_provider(riid
, ppv
);
101 static HRESULT WINAPI
ClassFactory_LockServer(IClassFactory
*iface
, BOOL fLock
)
103 TRACE("(%p)->(%x)\n", iface
, fLock
);
107 static const IClassFactoryVtbl cfmsdasqlVtbl
= {
108 ClassFactory_QueryInterface
,
110 ClassFactory_Release
,
111 msdasql_CreateInstance
,
112 ClassFactory_LockServer
115 HRESULT WINAPI
enumerationcf_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
117 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
119 return create_msdasql_enumerator(riid
, ppv
);
122 static const IClassFactoryVtbl enumfactoryVtbl
=
124 ClassFactory_QueryInterface
,
126 ClassFactory_Release
,
127 enumerationcf_CreateInstance
,
128 ClassFactory_LockServer
131 static IClassFactory cfmsdasql
= { &cfmsdasqlVtbl
};
132 static IClassFactory enumfactory
= { &enumfactoryVtbl
};
134 HRESULT WINAPI
DllGetClassObject( REFCLSID rclsid
, REFIID riid
, void **ppv
)
136 TRACE("%s %s %p\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
138 if (IsEqualGUID(&CLSID_MSDASQL
, rclsid
))
139 return IClassFactory_QueryInterface(&cfmsdasql
, riid
, ppv
);
140 else if (IsEqualGUID(&CLSID_MSDASQL_ENUMERATOR
, rclsid
))
141 return IClassFactory_QueryInterface(&enumfactory
, riid
, ppv
);
143 return CLASS_E_CLASSNOTAVAILABLE
;
150 DBPROPOPTIONS options
;
152 HRESULT (*convert_dbproperty
)(const WCHAR
*src
, VARIANT
*dest
);
161 static int __cdecl
dbmodeprop_compare(const void *a
, const void *b
)
163 const WCHAR
*src
= a
;
164 const struct mode_propval
*propval
= b
;
165 return wcsicmp(src
, propval
->name
);
168 static HRESULT
convert_dbproperty_mode(const WCHAR
*src
, VARIANT
*dest
)
170 struct mode_propval mode_propvals
[] =
172 { L
"Read", DB_MODE_READ
},
173 { L
"ReadWrite", DB_MODE_READWRITE
},
174 { L
"Share Deny None", DB_MODE_SHARE_DENY_NONE
},
175 { L
"Share Deny Read", DB_MODE_SHARE_DENY_READ
},
176 { L
"Share Deny Write", DB_MODE_SHARE_DENY_WRITE
},
177 { L
"Share Exclusive", DB_MODE_SHARE_EXCLUSIVE
},
178 { L
"Write", DB_MODE_WRITE
},
180 struct mode_propval
*prop
;
182 if ((prop
= bsearch(src
, mode_propvals
, ARRAY_SIZE(mode_propvals
),
183 sizeof(struct mode_propval
), dbmodeprop_compare
)))
186 V_I4(dest
) = prop
->value
;
187 TRACE("%s = %#lx\n", debugstr_w(src
), prop
->value
);
194 static const struct dbproperty dbproperties
[] =
196 { L
"Password", DBPROP_AUTH_PASSWORD
, DBPROPOPTIONS_OPTIONAL
, VT_BSTR
},
197 { L
"Persist Security Info", DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO
, DBPROPOPTIONS_OPTIONAL
, VT_BOOL
},
198 { L
"User ID", DBPROP_AUTH_USERID
, DBPROPOPTIONS_OPTIONAL
, VT_BSTR
},
199 { L
"Data Source", DBPROP_INIT_DATASOURCE
, DBPROPOPTIONS_REQUIRED
, VT_BSTR
},
200 { L
"Window Handle", DBPROP_INIT_HWND
, DBPROPOPTIONS_OPTIONAL
, sizeof(void *) == 8 ? VT_I8
: VT_I4
},
201 { L
"Location", DBPROP_INIT_LOCATION
, DBPROPOPTIONS_OPTIONAL
, VT_BSTR
},
202 { L
"Mode", DBPROP_INIT_MODE
, DBPROPOPTIONS_OPTIONAL
, VT_I4
, convert_dbproperty_mode
},
203 { L
"Prompt", DBPROP_INIT_PROMPT
, DBPROPOPTIONS_OPTIONAL
, VT_I2
},
204 { L
"Connect Timeout", DBPROP_INIT_TIMEOUT
, DBPROPOPTIONS_OPTIONAL
, VT_I4
},
205 { L
"Extended Properties", DBPROP_INIT_PROVIDERSTRING
, DBPROPOPTIONS_REQUIRED
, VT_BSTR
},
206 { L
"Locale Identifier", DBPROP_INIT_LCID
, DBPROPOPTIONS_OPTIONAL
, VT_I4
},
207 { L
"Initial Catalog", DBPROP_INIT_CATALOG
, DBPROPOPTIONS_OPTIONAL
, VT_BSTR
},
208 { L
"OLE DB Services", DBPROP_INIT_OLEDBSERVICES
, DBPROPOPTIONS_OPTIONAL
, VT_I4
},
209 { L
"General Timeout", DBPROP_INIT_GENERALTIMEOUT
, DBPROPOPTIONS_OPTIONAL
, VT_I4
},
220 IUnknown MSDASQL_iface
;
221 IDBProperties IDBProperties_iface
;
222 IDBInitialize IDBInitialize_iface
;
223 IDBCreateSession IDBCreateSession_iface
;
224 IPersist IPersist_iface
;
227 struct msdasql_prop properties
[14];
234 static inline struct msdasql
*impl_from_IUnknown(IUnknown
*iface
)
236 return CONTAINING_RECORD(iface
, struct msdasql
, MSDASQL_iface
);
239 static inline struct msdasql
*impl_from_IDBProperties(IDBProperties
*iface
)
241 return CONTAINING_RECORD(iface
, struct msdasql
, IDBProperties_iface
);
244 static inline struct msdasql
*impl_from_IDBInitialize(IDBInitialize
*iface
)
246 return CONTAINING_RECORD(iface
, struct msdasql
, IDBInitialize_iface
);
249 static inline struct msdasql
*impl_from_IDBCreateSession(IDBCreateSession
*iface
)
251 return CONTAINING_RECORD(iface
, struct msdasql
, IDBCreateSession_iface
);
254 static inline struct msdasql
*impl_from_IPersist( IPersist
*iface
)
256 return CONTAINING_RECORD( iface
, struct msdasql
, IPersist_iface
);
259 static HRESULT WINAPI
msdsql_QueryInterface(IUnknown
*iface
, REFIID riid
, void **out
)
261 struct msdasql
*provider
= impl_from_IUnknown(iface
);
263 TRACE("(%p)->(%s %p)\n", provider
, debugstr_guid(riid
), out
);
265 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
266 IsEqualGUID(riid
, &CLSID_MSDASQL
))
268 *out
= &provider
->MSDASQL_iface
;
270 else if(IsEqualGUID(riid
, &IID_IDBProperties
))
272 *out
= &provider
->IDBProperties_iface
;
274 else if ( IsEqualGUID(riid
, &IID_IDBInitialize
))
276 *out
= &provider
->IDBInitialize_iface
;
278 else if (IsEqualGUID(riid
, &IID_IDBCreateSession
))
280 *out
= &provider
->IDBCreateSession_iface
;
282 else if(IsEqualGUID(&IID_IPersist
, riid
))
284 *out
= &provider
->IPersist_iface
;
288 FIXME("(%s, %p)\n", debugstr_guid(riid
), out
);
290 return E_NOINTERFACE
;
293 IUnknown_AddRef((IUnknown
*)*out
);
297 static ULONG WINAPI
msdsql_AddRef(IUnknown
*iface
)
299 struct msdasql
*provider
= impl_from_IUnknown(iface
);
300 ULONG ref
= InterlockedIncrement(&provider
->ref
);
302 TRACE("(%p) ref=%lu\n", provider
, ref
);
307 static ULONG WINAPI
msdsql_Release(IUnknown
*iface
)
309 struct msdasql
*provider
= impl_from_IUnknown(iface
);
310 ULONG ref
= InterlockedDecrement(&provider
->ref
);
312 TRACE("(%p) ref=%lu\n", provider
, ref
);
316 SQLDisconnect(provider
->hdbc
);
318 SQLFreeHandle(SQL_HANDLE_DBC
, provider
->hdbc
);
319 SQLFreeHandle(SQL_HANDLE_ENV
, provider
->henv
);
326 static const IUnknownVtbl msdsql_vtbl
=
328 msdsql_QueryInterface
,
333 static HRESULT WINAPI
dbprops_QueryInterface(IDBProperties
*iface
, REFIID riid
, void **ppvObject
)
335 struct msdasql
*provider
= impl_from_IDBProperties(iface
);
337 return IUnknown_QueryInterface(&provider
->MSDASQL_iface
, riid
, ppvObject
);
340 static ULONG WINAPI
dbprops_AddRef(IDBProperties
*iface
)
342 struct msdasql
*provider
= impl_from_IDBProperties(iface
);
344 return IUnknown_AddRef(&provider
->MSDASQL_iface
);
347 static ULONG WINAPI
dbprops_Release(IDBProperties
*iface
)
349 struct msdasql
*provider
= impl_from_IDBProperties(iface
);
351 return IUnknown_Release(&provider
->MSDASQL_iface
);
354 static HRESULT WINAPI
dbprops_GetProperties(IDBProperties
*iface
, ULONG cPropertyIDSets
,
355 const DBPROPIDSET rgPropertyIDSets
[], ULONG
*pcPropertySets
, DBPROPSET
**prgPropertySets
)
357 struct msdasql
*provider
= impl_from_IDBProperties(iface
);
361 TRACE("(%p)->(%ld %p %p %p)\n", provider
, cPropertyIDSets
, rgPropertyIDSets
, pcPropertySets
, prgPropertySets
);
365 if (cPropertyIDSets
!= 1)
367 FIXME("Currently only 1 property set supported.\n");
371 propset
= CoTaskMemAlloc(cPropertyIDSets
* sizeof(DBPROPSET
));
373 if (IsEqualGUID(&rgPropertyIDSets
[0].guidPropertySet
, &DBPROPSET_DATASOURCEINFO
))
375 TRACE("Propertyset DBPROPSET_DATASOURCEINFO not supported\n");
376 propset
->guidPropertySet
= rgPropertyIDSets
[0].guidPropertySet
;
377 propset
->cProperties
= rgPropertyIDSets
[0].cPropertyIDs
;
379 propset
->rgProperties
= CoTaskMemAlloc(propset
->cProperties
* sizeof(DBPROP
));
381 for (j
=0; j
< propset
->cProperties
; j
++)
383 propset
->rgProperties
[j
].dwPropertyID
= rgPropertyIDSets
[0].rgPropertyIDs
[j
];
384 propset
->rgProperties
[j
].dwStatus
= DBPROPSTATUS_NOTSUPPORTED
;
387 *prgPropertySets
= propset
;
389 return DB_E_ERRORSOCCURRED
;
392 propset
->guidPropertySet
= DBPROPSET_DBINIT
;
394 for (i
=0; i
< cPropertyIDSets
; i
++)
396 TRACE("Property id %d (count %ld, set %s)\n", i
, rgPropertyIDSets
[i
].cPropertyIDs
,
397 debugstr_guid(&rgPropertyIDSets
[i
].guidPropertySet
));
399 propset
->cProperties
= rgPropertyIDSets
[i
].cPropertyIDs
;
400 propset
->rgProperties
= CoTaskMemAlloc(propset
->cProperties
* sizeof(DBPROP
));
402 for (j
=0; j
< propset
->cProperties
; j
++)
404 propset
->rgProperties
[j
].dwPropertyID
= rgPropertyIDSets
[i
].rgPropertyIDs
[j
];
406 for(k
= 0; k
< ARRAY_SIZE(provider
->properties
); k
++)
408 if (provider
->properties
[k
].id
== rgPropertyIDSets
[i
].rgPropertyIDs
[j
])
410 V_VT(&propset
->rgProperties
[j
].vValue
) = VT_EMPTY
;
411 VariantCopy(&propset
->rgProperties
[j
].vValue
, &provider
->properties
[k
].value
);
418 *prgPropertySets
= propset
;
423 static HRESULT WINAPI
dbprops_GetPropertyInfo(IDBProperties
*iface
, ULONG cPropertyIDSets
,
424 const DBPROPIDSET rgPropertyIDSets
[], ULONG
*pcPropertyInfoSets
,
425 DBPROPINFOSET
**prgPropertyInfoSets
, OLECHAR
**ppDescBuffer
)
427 struct msdasql
*provider
= impl_from_IDBProperties(iface
);
429 DBPROPINFOSET
*infoset
;
433 TRACE("(%p)->(%ld %p %p %p %p)\n", provider
, cPropertyIDSets
, rgPropertyIDSets
, pcPropertyInfoSets
,
434 prgPropertyInfoSets
, ppDescBuffer
);
436 infoset
= CoTaskMemAlloc(sizeof(DBPROPINFOSET
));
437 memcpy(&infoset
->guidPropertySet
, &DBPROPSET_DBINIT
, sizeof(GUID
));
438 infoset
->cPropertyInfos
= ARRAY_SIZE(dbproperties
);
439 infoset
->rgPropertyInfos
= CoTaskMemAlloc(sizeof(DBPROPINFO
) * ARRAY_SIZE(dbproperties
));
441 for(i
=0; i
< ARRAY_SIZE(dbproperties
); i
++)
443 size
+= lstrlenW(dbproperties
[i
].name
) + 1;
446 ptr
= *ppDescBuffer
= CoTaskMemAlloc(size
* sizeof(WCHAR
));
447 memset(*ppDescBuffer
, 0, size
* sizeof(WCHAR
));
449 for(i
=0; i
< ARRAY_SIZE(dbproperties
); i
++)
451 lstrcpyW(ptr
, dbproperties
[i
].name
);
452 infoset
->rgPropertyInfos
[i
].pwszDescription
= ptr
;
453 infoset
->rgPropertyInfos
[i
].dwPropertyID
= dbproperties
[i
].id
;
454 infoset
->rgPropertyInfos
[i
].dwFlags
= DBPROPFLAGS_DBINIT
| DBPROPFLAGS_READ
| DBPROPFLAGS_WRITE
;
455 infoset
->rgPropertyInfos
[i
].vtType
= dbproperties
[i
].type
;
456 V_VT(&infoset
->rgPropertyInfos
[i
].vValues
) = VT_EMPTY
;
458 ptr
+= lstrlenW(dbproperties
[i
].name
) + 1;
461 *pcPropertyInfoSets
= 1;
462 *prgPropertyInfoSets
= infoset
;
467 static HRESULT WINAPI
dbprops_SetProperties(IDBProperties
*iface
, ULONG cPropertySets
,
468 DBPROPSET rgPropertySets
[])
470 struct msdasql
*provider
= impl_from_IDBProperties(iface
);
473 TRACE("(%p)->(%ld %p)\n", provider
, cPropertySets
, rgPropertySets
);
475 for (i
=0; i
< cPropertySets
; i
++)
477 for (j
=0; j
< rgPropertySets
[i
].cProperties
; j
++)
479 for(k
=0; k
< ARRAY_SIZE(provider
->properties
); k
++)
481 if (provider
->properties
[k
].id
== rgPropertySets
[i
].rgProperties
[j
].dwPropertyID
)
483 TRACE("Found property %d\n", provider
->properties
[k
].id
);
484 VariantCopy(&provider
->properties
[k
].value
, &rgPropertySets
[i
].rgProperties
[j
].vValue
);
494 static const struct IDBPropertiesVtbl dbprops_vtbl
=
496 dbprops_QueryInterface
,
499 dbprops_GetProperties
,
500 dbprops_GetPropertyInfo
,
501 dbprops_SetProperties
504 static HRESULT WINAPI
dbinit_QueryInterface(IDBInitialize
*iface
, REFIID riid
, void **ppvObject
)
506 struct msdasql
*provider
= impl_from_IDBInitialize(iface
);
508 return IUnknown_QueryInterface(&provider
->MSDASQL_iface
, riid
, ppvObject
);
511 static ULONG WINAPI
dbinit_AddRef(IDBInitialize
*iface
)
513 struct msdasql
*provider
= impl_from_IDBInitialize(iface
);
515 return IUnknown_AddRef(&provider
->MSDASQL_iface
);
518 static ULONG WINAPI
dbinit_Release(IDBInitialize
*iface
)
520 struct msdasql
*provider
= impl_from_IDBInitialize(iface
);
522 return IUnknown_Release(&provider
->MSDASQL_iface
);
525 static HRESULT WINAPI
dbinit_Initialize(IDBInitialize
*iface
)
527 struct msdasql
*provider
= impl_from_IDBInitialize(iface
);
530 WCHAR connection
[1024], *p
= connection
, outstr
[1024];
532 FIXME("%p semi-stub\n", provider
);
535 for(i
=0; i
< ARRAY_SIZE(provider
->properties
); i
++)
537 if (provider
->properties
[i
].id
== DBPROP_INIT_DATASOURCE
)
539 len
= swprintf(p
, ARRAY_SIZE(connection
) - (p
- connection
),
540 L
"DSN=%s;", V_BSTR(&provider
->properties
[i
].value
));
543 else if (provider
->properties
[i
].id
== DBPROP_INIT_PROVIDERSTRING
)
545 if (V_VT(&provider
->properties
[i
].value
) == VT_BSTR
&& SysStringLen(V_BSTR(&provider
->properties
[i
].value
)) )
547 len
= swprintf(p
, ARRAY_SIZE(connection
) - (p
- connection
),
548 L
"%s;", V_BSTR(&provider
->properties
[i
].value
));
554 ret
= SQLDriverConnectW( provider
->hdbc
, NULL
, connection
, wcslen(connection
),
555 outstr
, ARRAY_SIZE(outstr
), NULL
, 0);
556 TRACE("SQLDriverConnectW ret %d\n", ret
);
557 if (ret
!= SQL_SUCCESS
)
559 dump_sql_diag_records(SQL_HANDLE_DBC
, provider
->hdbc
);
561 if (ret
!= SQL_SUCCESS_WITH_INFO
)
568 static HRESULT WINAPI
dbinit_Uninitialize(IDBInitialize
*iface
)
570 struct msdasql
*provider
= impl_from_IDBInitialize(iface
);
572 FIXME("%p stub\n", provider
);
578 static const struct IDBInitializeVtbl dbinit_vtbl
=
580 dbinit_QueryInterface
,
587 static HRESULT WINAPI
dbsess_QueryInterface(IDBCreateSession
*iface
, REFIID riid
, void **ppvObject
)
589 struct msdasql
*provider
= impl_from_IDBCreateSession(iface
);
591 return IUnknown_QueryInterface(&provider
->MSDASQL_iface
, riid
, ppvObject
);
594 static ULONG WINAPI
dbsess_AddRef(IDBCreateSession
*iface
)
596 struct msdasql
*provider
= impl_from_IDBCreateSession(iface
);
598 return IUnknown_AddRef(&provider
->MSDASQL_iface
);
601 static ULONG WINAPI
dbsess_Release(IDBCreateSession
*iface
)
603 struct msdasql
*provider
= impl_from_IDBCreateSession(iface
);
605 return IUnknown_Release(&provider
->MSDASQL_iface
);
608 static HRESULT WINAPI
dbsess_CreateSession(IDBCreateSession
*iface
, IUnknown
*outer
, REFIID riid
,
611 struct msdasql
*provider
= impl_from_IDBCreateSession(iface
);
614 TRACE("%p, outer %p, riid %s, session %p stub\n", provider
, outer
, debugstr_guid(riid
), session
);
617 FIXME("outer currently not supported.\n");
619 hr
= create_db_session(riid
, &provider
->MSDASQL_iface
, provider
->hdbc
, (void**)session
);
624 static const struct IDBCreateSessionVtbl dbsess_vtbl
=
626 dbsess_QueryInterface
,
632 static HRESULT WINAPI
persist_QueryInterface(IPersist
*iface
, REFIID riid
, void **ppv
)
634 struct msdasql
*provider
= impl_from_IPersist( iface
);
635 return IUnknown_QueryInterface(&provider
->MSDASQL_iface
, riid
, ppv
);
638 static ULONG WINAPI
persist_AddRef(IPersist
*iface
)
640 struct msdasql
*provider
= impl_from_IPersist( iface
);
641 return IUnknown_AddRef(&provider
->MSDASQL_iface
);
644 static ULONG WINAPI
persist_Release(IPersist
*iface
)
646 struct msdasql
*provider
= impl_from_IPersist( iface
);
647 return IUnknown_Release(&provider
->MSDASQL_iface
);
650 static HRESULT WINAPI
persist_GetClassID(IPersist
*iface
, CLSID
*classid
)
652 struct msdasql
*provider
= impl_from_IPersist( iface
);
654 TRACE("(%p)->(%p)\n", provider
, classid
);
659 *classid
= CLSID_MSDASQL
;
664 static const IPersistVtbl persistVtbl
= {
665 persist_QueryInterface
,
671 static HRESULT
create_msdasql_provider(REFIID riid
, void **ppv
)
673 struct msdasql
*provider
;
677 provider
= malloc(sizeof(struct msdasql
));
679 return E_OUTOFMEMORY
;
681 provider
->MSDASQL_iface
.lpVtbl
= &msdsql_vtbl
;
682 provider
->IDBProperties_iface
.lpVtbl
= &dbprops_vtbl
;
683 provider
->IDBInitialize_iface
.lpVtbl
= &dbinit_vtbl
;
684 provider
->IDBCreateSession_iface
.lpVtbl
= &dbsess_vtbl
;
685 provider
->IPersist_iface
.lpVtbl
= &persistVtbl
;
688 for(i
=0; i
< ARRAY_SIZE(dbproperties
); i
++)
690 provider
->properties
[i
].id
= dbproperties
[i
].id
;
691 VariantInit(&provider
->properties
[i
].value
);
693 /* Only the follow are initialized to a value */
694 switch(dbproperties
[i
].id
)
696 case DBPROP_INIT_PROMPT
:
697 V_VT(&provider
->properties
[i
].value
) = dbproperties
[i
].type
;
698 V_I2(&provider
->properties
[i
].value
) = 4;
700 case DBPROP_INIT_LCID
:
701 V_VT(&provider
->properties
[i
].value
) = dbproperties
[i
].type
;
702 V_I4(&provider
->properties
[i
].value
) = GetUserDefaultLCID();
704 case DBPROP_INIT_OLEDBSERVICES
:
705 V_VT(&provider
->properties
[i
].value
) = dbproperties
[i
].type
;
706 V_I4(&provider
->properties
[i
].value
) = -1;
709 V_VT(&provider
->properties
[i
].value
) = VT_EMPTY
;
713 SQLAllocHandle(SQL_HANDLE_ENV
, NULL
, &provider
->henv
);
714 if (SQLSetEnvAttr(provider
->henv
, SQL_ATTR_ODBC_VERSION
, (void *)SQL_OV_ODBC3_80
, 0) == SQL_ERROR
)
716 WARN("Falling back to SQL_OV_ODBC3\n");
717 SQLSetEnvAttr(provider
->henv
, SQL_ATTR_ODBC_VERSION
, (void *)SQL_OV_ODBC3
, 0);
720 SQLAllocHandle(SQL_HANDLE_DBC
, provider
->henv
, &provider
->hdbc
);
722 hr
= IUnknown_QueryInterface(&provider
->MSDASQL_iface
, riid
, ppv
);
723 IUnknown_Release(&provider
->MSDASQL_iface
);
729 ISourcesRowset ISourcesRowset_iface
;
733 static inline struct msdasql_enum
*msdasql_enum_from_ISourcesRowset(ISourcesRowset
*iface
)
735 return CONTAINING_RECORD(iface
, struct msdasql_enum
, ISourcesRowset_iface
);
738 static HRESULT WINAPI
msdasql_enum_QueryInterface(ISourcesRowset
*iface
, REFIID riid
, void **out
)
740 struct msdasql_enum
*enumerator
= msdasql_enum_from_ISourcesRowset(iface
);
742 TRACE("(%p)->(%s %p)\n", enumerator
, debugstr_guid(riid
), out
);
744 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
745 IsEqualGUID(riid
, &IID_ISourcesRowset
) )
747 *out
= &enumerator
->ISourcesRowset_iface
;
751 FIXME("(%s, %p)\n", debugstr_guid(riid
), out
);
753 return E_NOINTERFACE
;
756 IUnknown_AddRef((IUnknown
*)*out
);
760 static ULONG WINAPI
msdasql_enum_AddRef(ISourcesRowset
*iface
)
762 struct msdasql_enum
*enumerator
= msdasql_enum_from_ISourcesRowset(iface
);
763 ULONG ref
= InterlockedIncrement(&enumerator
->ref
);
765 TRACE("(%p) ref=%lu\n", enumerator
, ref
);
770 static ULONG WINAPI
msdasql_enum_Release(ISourcesRowset
*iface
)
772 struct msdasql_enum
*enumerator
= msdasql_enum_from_ISourcesRowset(iface
);
773 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
775 TRACE("(%p) ref=%lu\n", enumerator
, ref
);
785 struct msdasql_enum_rowset
787 IRowset IRowset_iface
;
788 IAccessor IAccessor_iface
;
792 static inline struct msdasql_enum_rowset
*msdasql_rs_from_IRowset(IRowset
*iface
)
794 return CONTAINING_RECORD(iface
, struct msdasql_enum_rowset
, IRowset_iface
);
797 static inline struct msdasql_enum_rowset
*msdasql_enum_from_IAccessor ( IAccessor
*iface
)
799 return CONTAINING_RECORD( iface
, struct msdasql_enum_rowset
, IAccessor_iface
);
802 static HRESULT WINAPI
enum_rowset_QueryInterface(IRowset
*iface
, REFIID riid
, void **ppv
)
804 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
806 TRACE( "%p, %s, %p\n", rowset
, debugstr_guid(riid
), ppv
);
809 if(IsEqualGUID(&IID_IUnknown
, riid
) ||
810 IsEqualGUID(&IID_IRowset
, riid
))
812 *ppv
= &rowset
->IRowset_iface
;
814 else if(IsEqualGUID(&IID_IAccessor
, riid
))
816 *ppv
= &rowset
->IAccessor_iface
;
821 IUnknown_AddRef((IUnknown
*)*ppv
);
825 FIXME("(%p)->(%s %p)\n", iface
, debugstr_guid(riid
), ppv
);
826 return E_NOINTERFACE
;
829 static ULONG WINAPI
enum_rowset_AddRef(IRowset
*iface
)
831 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
832 LONG refs
= InterlockedIncrement( &rowset
->ref
);
833 TRACE( "%p new refcount %ld\n", rowset
, refs
);
837 static ULONG WINAPI
enum_rowset_Release(IRowset
*iface
)
839 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
840 LONG refs
= InterlockedDecrement( &rowset
->ref
);
841 TRACE( "%p new refcount %ld\n", rowset
, refs
);
844 TRACE( "destroying %p\n", rowset
);
850 static HRESULT WINAPI
enum_rowset_AddRefRows(IRowset
*iface
, DBCOUNTITEM count
,
851 const HROW rows
[], DBREFCOUNT ref_counts
[], DBROWSTATUS status
[])
853 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
855 FIXME("%p, %Iu, %p, %p, %p\n", rowset
, count
, rows
, ref_counts
, status
);
860 static HRESULT WINAPI
enum_rowset_GetData(IRowset
*iface
, HROW row
, HACCESSOR accessor
, void *data
)
862 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
864 FIXME("%p, %Iu, %Iu, %p\n", rowset
, row
, accessor
, data
);
869 static HRESULT WINAPI
enum_rowset_GetNextRows(IRowset
*iface
, HCHAPTER reserved
, DBROWOFFSET offset
,
870 DBROWCOUNT count
, DBCOUNTITEM
*obtained
, HROW
**rows
)
872 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
874 FIXME("%p, %Iu, %Iu, %Iu, %p, %p\n", rowset
, reserved
, offset
, count
, obtained
, rows
);
876 if (!obtained
|| !rows
)
884 return DB_S_ENDOFROWSET
;
887 static HRESULT WINAPI
enum_rowset_ReleaseRows(IRowset
*iface
, DBCOUNTITEM count
,
888 const HROW rows
[], DBROWOPTIONS options
[], DBREFCOUNT ref_counts
[], DBROWSTATUS status
[])
890 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
892 FIXME("%p, %Iu, %p, %p, %p, %p\n", rowset
, count
, rows
, options
, ref_counts
, status
);
897 static HRESULT WINAPI
enum_rowset_RestartPosition(IRowset
*iface
, HCHAPTER reserved
)
899 struct msdasql_enum_rowset
*rowset
= msdasql_rs_from_IRowset( iface
);
901 FIXME("%p, %Iu\n", rowset
, reserved
);
906 static const struct IRowsetVtbl enum_rowset_vtbl
=
908 enum_rowset_QueryInterface
,
911 enum_rowset_AddRefRows
,
913 enum_rowset_GetNextRows
,
914 enum_rowset_ReleaseRows
,
915 enum_rowset_RestartPosition
918 static HRESULT WINAPI
enum_rs_accessor_QueryInterface(IAccessor
*iface
, REFIID riid
, void **out
)
920 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
921 return IRowset_QueryInterface(&rowset
->IRowset_iface
, riid
, out
);
924 static ULONG WINAPI
enum_rs_accessor_AddRef(IAccessor
*iface
)
926 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
927 return IRowset_AddRef(&rowset
->IRowset_iface
);
930 static ULONG WINAPI
enum_rs_accessor_Release(IAccessor
*iface
)
932 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
933 return IRowset_Release(&rowset
->IRowset_iface
);
936 static HRESULT WINAPI
enum_rs_accessor_AddRefAccessor(IAccessor
*iface
, HACCESSOR accessor
, DBREFCOUNT
*count
)
938 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
939 FIXME("%p, %Iu, %p\n", rowset
, accessor
, count
);
943 static HRESULT WINAPI
enum_rs_accessor_CreateAccessor(IAccessor
*iface
, DBACCESSORFLAGS flags
,
944 DBCOUNTITEM count
, const DBBINDING bindings
[], DBLENGTH row_size
, HACCESSOR
*accessor
,
945 DBBINDSTATUS status
[])
947 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
949 FIXME("%p 0x%08lx, %Iu, %p, %Iu, %p, %p\n", rowset
, flags
, count
, bindings
, row_size
, accessor
, status
);
952 *accessor
= 0xdeadbeef;
957 static HRESULT WINAPI
enum_rs_accessor_GetBindings(IAccessor
*iface
, HACCESSOR accessor
,
958 DBACCESSORFLAGS
*flags
, DBCOUNTITEM
*count
, DBBINDING
**bindings
)
960 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
961 FIXME("%p, %Iu, %p, %p, %p\n", rowset
, accessor
, flags
, count
, bindings
);
965 static HRESULT WINAPI
enum_rs_accessor_ReleaseAccessor(IAccessor
*iface
, HACCESSOR accessor
, DBREFCOUNT
*count
)
967 struct msdasql_enum_rowset
*rowset
= msdasql_enum_from_IAccessor( iface
);
969 FIXME("%p, %Iu, %p\n", rowset
, accessor
, count
);
977 struct IAccessorVtbl enum_accessor_vtbl
=
979 enum_rs_accessor_QueryInterface
,
980 enum_rs_accessor_AddRef
,
981 enum_rs_accessor_Release
,
982 enum_rs_accessor_AddRefAccessor
,
983 enum_rs_accessor_CreateAccessor
,
984 enum_rs_accessor_GetBindings
,
985 enum_rs_accessor_ReleaseAccessor
988 static HRESULT WINAPI
msdasql_enum_GetSourcesRowset(ISourcesRowset
*iface
, IUnknown
*outer
, REFIID riid
, ULONG sets
,
989 DBPROPSET properties
[], IUnknown
**rowset
)
991 struct msdasql_enum
*enumerator
= msdasql_enum_from_ISourcesRowset(iface
);
992 struct msdasql_enum_rowset
*enum_rs
;
995 TRACE("(%p) %p, %s, %lu, %p, %p\n", enumerator
, outer
, debugstr_guid(riid
), sets
, properties
, rowset
);
997 enum_rs
= malloc(sizeof(*enum_rs
));
998 enum_rs
->IRowset_iface
.lpVtbl
= &enum_rowset_vtbl
;
999 enum_rs
->IAccessor_iface
.lpVtbl
= &enum_accessor_vtbl
;
1002 hr
= IRowset_QueryInterface(&enum_rs
->IRowset_iface
, riid
, (void**)rowset
);
1003 IRowset_Release(&enum_rs
->IRowset_iface
);
1007 static const ISourcesRowsetVtbl msdsqlenum_vtbl
=
1009 msdasql_enum_QueryInterface
,
1010 msdasql_enum_AddRef
,
1011 msdasql_enum_Release
,
1012 msdasql_enum_GetSourcesRowset
1015 static HRESULT
create_msdasql_enumerator(REFIID riid
, void **ppv
)
1017 struct msdasql_enum
*enumerator
;
1020 enumerator
= malloc(sizeof(*enumerator
));
1022 return E_OUTOFMEMORY
;
1024 enumerator
->ISourcesRowset_iface
.lpVtbl
= &msdsqlenum_vtbl
;
1025 enumerator
->ref
= 1;
1027 hr
= IUnknown_QueryInterface(&enumerator
->ISourcesRowset_iface
, riid
, ppv
);
1028 IUnknown_Release(&enumerator
->ISourcesRowset_iface
);