Connecting to an MDP by Using the Root Enumerator
Connection to an MDP requires using the root enumerator to create a rowset representing all OLE DB providers. This function returns a pointer to the IDBInitialize interface for an MDP data source object:
//
HRESULT MDPConnectUsingRootEnum(IDBInitialize** ppIDBInitialize)
{
HRESULT hr;
assert(*ppIDBInitialize == NULL);
// The ENUMINFO structure is used to bind data source
// rowset data for the provider list.
struct ENUMINFO
{
WCHAR wszName[MAX_NAME_LEN];
WCHAR wszParseName[MAX_NAME_LEN];
WCHAR wszDescription[MAX_NAME_LEN];
DBTYPE wType;
VARIANT_BOOL fIsParent;
};
// Initialize the OLE DB enumerator and obtain rowset.
ISourcesRowset* pISourcesRowset = NULL;
hr = CoCreateInstance(CLSID_OLEDB_ENUMERATOR, NULL,
CLSCTX_INPROC_SERVER, IID_ISourcesRowset,
(void**)&pISourcesRowset);
IRowset* pIRowset = NULL;
hr = pISourcesRowset->GetSourcesRowset(NULL,
IID_IRowset, 0, NULL, (IUnknown**)&pIRowset);
// Create accessor.
IAccessor* pIAccessor = NULL;
hr = pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);
// rgBindings array defines column data to be bound
// to the ENUMINFO data structure.
DBCOUNTITEM cBindings = 5;
DBBINDING rgBindings[5] =
{
1, offsetof(ENUMINFO, wszName), 0, 0, NULL, NULL, NULL,
DBPART_VALUE, DBMEMOWNER_CLIENTOWNED, DBPARAMIO_NOTPARAM,
MAX_NAME_LEN, 0, DBTYPE_WSTR, 0, 0,
2, offsetof(ENUMINFO, wszParseName), 0, 0, NULL, NULL, NULL,
DBPART_VALUE, DBMEMOWNER_CLIENTOWNED, DBPARAMIO_NOTPARAM,
MAX_NAME_LEN, 0, DBTYPE_WSTR, 0, 0,
3, offsetof(ENUMINFO, wszDescription), 0, 0, NULL, NULL, NULL,
DBPART_VALUE, DBMEMOWNER_CLIENTOWNED, DBPARAMIO_NOTPARAM,
MAX_NAME_LEN, 0, DBTYPE_WSTR, 0, 0,
4, offsetof(ENUMINFO, wType), 0, 0, NULL, NULL, NULL, DBPART_VALUE,
DBMEMOWNER_CLIENTOWNED, DBPARAMIO_NOTPARAM, sizeof(DBTYPE), 0,
DBTYPE_UI2, 0, 0,
5, offsetof(ENUMINFO, fIsParent), 0, 0, NULL, NULL, NULL,
DBPART_VALUE, DBMEMOWNER_CLIENTOWNED, DBPARAMIO_NOTPARAM,
sizeof(VARIANT_BOOL), 0, DBTYPE_BOOL, 0, 0,
};
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
cBindings, rgBindings, 0, &hAccessor, NULL);
// Obtain IParseDisplayName interface.
IParseDisplayName* pIParseDisplayName = NULL;
hr = pISourcesRowset->QueryInterface(IID_IParseDisplayName,
(void**)&pIParseDisplayName);
// Loop through the entire returned rowset.
HROW* rghRows = NULL;
DBRCOUNTITEM cRowsObtained = 0;
ULONG cEnumInfo = 0;
ENUMINFO* rgEnumInfo = NULL;
while (SUCCEEDED(hr))
{
hr = pIRowset->GetNextRows(NULL, 0, 20, &cRowsObtained, &rghRows);
if (FAILED(hr)) break;
if (cRowsObtained == 0)
{
// ENDOFROWSET
break;
}
// Alloc room for ProviderInfo (in chunks).
rgEnumInfo =
(ENUMINFO*)CoTaskMemRealloc(rgEnumInfo,
(cEnumInfo+cRowsObtained) * sizeof(ENUMINFO));
memset(&rgEnumInfo[cEnumInfo], 0,
sizeof(ENUMINFO)*cRowsObtained);
// Loop over rows obtained and get ProviderInfo.
for (DBCOUNTITEM i=0; i<cRowsObtained; i++)
{
// Get the data.
hr = pIRowset->GetData(rghRows[i], hAccessor,
(void*)&rgEnumInfo[cEnumInfo]);
if (FAILED(hr)) break;
cEnumInfo++;
}
// Release all the rows.
hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL,
NULL);
CoTaskMemFree(rghRows);
rghRows = NULL;
}
// If successfully obtained a set of providers...
if (SUCCEEDED(hr) && cEnumInfo)
{
// rgEnumInfo[cEnumInfo] contains enumerated info
// for all providers.
for (ULONG i=0; i<cEnumInfo; i++)
{
// Find multidimensional provider and connect
// with IParseDisplayName.
if (rgEnumInfo[i].wType == DBSOURCETYPE_DATASOURCE_MDP)
{
// Connect to MDP provider using IMoniker.
// Create binding context; use default options.
IBindCtx* pIBindCtx = NULL;
hr = CreateBindCtx(0, &pIBindCtx);
if (SUCCEEDED(hr))
{
ULONG chEaten = 0;
IMoniker* pIMoniker = NULL;
hr = pIParseDisplayName->ParseDisplayName(pIBindCtx,
rgEnumInfo[i].wszParseName, &chEaten, &pIMoniker);
}
if (SUCCEEDED(hr))
{
hr = BindMoniker(pIMoniker, 0, IID_IUnknown,
(void**)&pIDBInitialize);
}
if (pIBindCtx) pIBindCtx->Release();
if (pIMoniker) pIMoniker->Release();
if (SUCCEEDED(hr))
{
// If ParseDisplayName() and BindMoniker() have
// succeeded, pIDBInitialize is a valid
// interface pointer to the MDP data source.
break;
}
}
}
}
// Free enum info and rowset handles.
CoTaskMemFree(rgEnumInfo);
CoTaskMemFree(rghRows);
hr = pIParseDisplayName->Release();
hr = pIAccessor->ReleaseAccessor(hAccessor,NULL);
hr = pIAccessor->Release();
hr = pIRowset->Release();
hr = pISourcesRowset->Release();
return hr;
}