This bug was corrected in MDAC 2.1 SP2.
To work around this bug, insert the following "GetProperty()" C++ function as a method in a COM object. Essentially, the function returns the requested property of the underlying rowset using the OLE DB IDBProperties::GetPropertyInfo() and IRowsetInfo::GetProperty() methods. The parameters are:
- pADORecordset- [in] IUnknown pointer to the Ado Recordset
- bstrPropertyName - [in] Description of the Property ID**
- pValue - [out] The property value
** Refer to Appendix C in the
OLE DB 2.0 Programmers Reference for a comprehensive list of Property ID descriptions.
#include <COMDEF.H>
#include <oledb.h>
#undef EOF
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace
_COM_SMARTPTR_TYPEDEF(IRowset, __uuidof(IRowset));
_COM_SMARTPTR_TYPEDEF(IRowsetInfo, __uuidof(IRowsetInfo));
_COM_SMARTPTR_TYPEDEF(IDBProperties, __uuidof(IDBProperties));
_COM_SMARTPTR_TYPEDEF(IGetDataSource, __uuidof(IGetDataSource));
_COM_SMARTPTR_TYPEDEF(ICommand, __uuidof(ICommand));
STDMETHODIMP CPropertyHelper::GetProperty(IUnknown *pADORecordset, BSTR bstrPropertyName, VARIANT * pValue)
{
HRESULT hr;
ADORecordsetConstructionPtr pRC;
ADOConnectionConstructionPtr pCC;
IRowsetPtr pRS;
IRowsetInfoPtr pRI;
IDBPropertiesPtr pDBProps;
IGetDataSourcePtr pGetDataSource;
ICommandPtr pCommand;
// Make certain that we are getting an ADORecordset.
pRC = pADORecordset;
// Get the IRowsetInfo interface.
pRI = pRC->GetRowset();
// Get the property ID based on the name supplied.
hr = pRI->GetSpecification(__uuidof(IGetDataSource), (IUnknown **)&pGetDataSource);
// The rowset was probably created with IOpenRowset::OpenRowset,
// but just in case...
if (pGetDataSource.GetInterfacePtr() == NULL)
{
// Need to get command first.
hr = pRI->GetSpecification(__uuidof(ICommand), (IUnknown **)&pCommand);
hr = pCommand->GetDBSession(__uuidof(IGetDataSource), (IUnknown **)&pGetDataSource);
}
if(hr = pGetDataSource.GetInterfacePtr() == NULL)
return E_FAIL;
hr = pGetDataSource->GetDataSource(__uuidof(IDBProperties), (IUnknown **)&pDBProps);
// Want all of the rowset properties.
DBPROPIDSET PropIDSet;
PropIDSet.cPropertyIDs = 0;
PropIDSet.guidPropertySet = DBPROPSET_ROWSETALL;
PropIDSet.rgPropertyIDs = NULL;
DBPROPINFOSET * pPropertyInfoSet;
ULONG ulPropInfoSets;
OLECHAR * pDescBuffer;
pDBProps->GetPropertyInfo(1,&PropIDSet, &ulPropInfoSets, &pPropertyInfoSet, &pDescBuffer);
DBPROPID PropID;
GUID guid;
bool bFoundProperty = false;
// Find the ID associated with the property name.
for(ULONG ulIndex1= 0; ulIndex1 < ulPropInfoSets && bFoundProperty ==false; ulIndex1 ++)
for (ULONG ulIndex = 0; ulIndex < pPropertyInfoSet[ulIndex1].cPropertyInfos; ulIndex++)
{
if (_wcsicmp(pPropertyInfoSet[ulIndex1].rgPropertyInfos[ulIndex].pwszDescription, bstrPropertyName) == 0)
{
PropID = pPropertyInfoSet[ulIndex1].rgPropertyInfos[ulIndex].dwPropertyID;
guid = pPropertyInfoSet[ulIndex1].guidPropertySet;
bFoundProperty = true;
break;
}
}
// Free structures.
CoTaskMemFree(pDescBuffer);
CoTaskMemFree(pPropertyInfoSet->rgPropertyInfos);
CoTaskMemFree(pPropertyInfoSet);
if (bFoundProperty == false)
return E_FAIL; // Might also want to call CreateErrorInfor/SetErrorInfo.
// Now use IRowsetInfo to return the property value.
ULONG ulPropSets;
DBPROPSET * prgPropSets;
DBPROPIDSET rgPropertyIDSets;
rgPropertyIDSets.cPropertyIDs = 1;
rgPropertyIDSets.guidPropertySet = guid;
rgPropertyIDSets.rgPropertyIDs = &PropID;
hr = pRI->GetProperties(1, &rgPropertyIDSets, &ulPropSets, &prgPropSets);
// Copy the property value to the return VARIANT.
VariantCopy(pValue, &prgPropSets->rgProperties->vValue);
CoTaskMemFree(prgPropSets->rgProperties);
CoTaskMemFree(prgPropSets);
return S_OK;
}
The following Visual Basic code accesses the "PropertyHelper.CPropertyHelper.1" COM object that contains the GetProperty method:
Dim rs As New ADODB.Recordset
Dim rsChild As ADODB.Recordset
rs.Open "c:\*.*", "Provider=ChildrsProv.CHildRSProv.1", adOpenForwardOnly, adLockOptimistic
Set rsChild = rs.Fields(5).Value
Dim obj
Set obj = CreateObject("PropertyHelper.CPropertyHelper.1")
Dim propVal As Variant
obj.GetProperty rsChild, "IRowsetInfo", propVal
Debug.Print propVal