Connection to a 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:
//
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.
ULONG cBindings = 5;
DBBINDING rgBindings[cBindings] =
{
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;
ULONG cRowsObtained = 0;
ULONG cEnumInfo = 0;
ENUMINFO* rgEnumInfo;
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 (ULONG 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;
}