To list the data sources visible to the SQLOLEDB enumerator, the consumer calls the ISourcesRowset::GetSourcesRowset method. This method returns a rowset of information about the currently visible data sources.
Depending on the network library used, the appropriate domain is searched for the data sources. For Named Pipes, it is the domain to which the client is logged on. For AppleTalk, it is the default zone. For SPX/IPX, it is the list of SQL Server installations found in the bindery. For Banyan VINES, it is the SQL Server installations found on the local network. Multiprotocol and TCP/IP sockets are not supported.
When the server is turned off or on, it can take few minutes to update the information in these domains.
To enumerate OLE DB data sources
//How to use the enumerator object to list
//the data sources available.
#define UNICODE
#define _UNICODE
#define DBINITCONSTANTS
#define INITGUID
#include <windows.h>
#include <stddef.h>
#include <oledb.h>
#include <oledberr.h>
#include <SQLOLEDB.h>
#include <stdio.h>
#define NUMROWS_CHUNK 5
//AdjustLen supports binding on four-byte boundaries.
_inline ULONG AdjustLen(ULONG cb)
{
return ((cb + 3) & ~3);
}
// Get the characteristics of the rowset (the IColumnsInfo interface).
HRESULT GetColumnInfo
(
IRowset* pIRowset,
UINT* pnCols,
DBCOLUMNINFO** ppColumnsInfo,
OLECHAR** ppColumnStrings
)
{
IColumnsInfo* pIColumnsInfo;
HRESULT hr;
*pnCols = 0;
if (FAILED(pIRowset->QueryInterface(IID_IColumnsInfo,
(void**) &pIColumnsInfo)))
{
return (E_FAIL);
}
hr = pIColumnsInfo->GetColumnInfo((ULONG*) pnCols,
ppColumnsInfo,
ppColumnStrings);
if (FAILED(hr))
{
//Process error.
}
pIColumnsInfo->Release();
return (hr);
}
// Create binding structures from column information. Binding structures
// will be used to create an accessor that allows row value retrieval.
void CreateDBBindings
(
UINT nCols,
DBCOLUMNINFO* pColumnsInfo,
DBBINDING** ppDBBindings,
BYTE** ppRowValues
)
{
ULONG nCol;
ULONG cbRow = 0;
ULONG cbCol;
DBBINDING* pDBBindings;
BYTE* pRowValues;
pDBBindings = new DBBINDING[nCols];
for (nCol = 0; nCol < nCols; nCol++)
{
pDBBindings[nCol].iOrdinal = nCol+1;
pDBBindings[nCol].pTypeInfo = NULL;
pDBBindings[nCol].pObject = NULL;
pDBBindings[nCol].pBindExt = NULL;
pDBBindings[nCol].dwPart = DBPART_VALUE;
pDBBindings[nCol].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
pDBBindings[nCol].eParamIO = DBPARAMIO_NOTPARAM;
pDBBindings[nCol].dwFlags = 0;
pDBBindings[nCol].wType = pColumnsInfo[nCol].wType;
pDBBindings[nCol].bPrecision = pColumnsInfo[nCol].bPrecision;
pDBBindings[nCol].bScale = pColumnsInfo[nCol].bScale;
cbCol = pColumnsInfo[nCol].ulColumnSize;
switch (pColumnsInfo[nCol].wType)
{
case DBTYPE_STR:
{
cbCol += 1;
break;
}
case DBTYPE_WSTR:
{
cbCol = (cbCol + 1) * sizeof(WCHAR);
break;
}
default:
break;
}
pDBBindings[nCol].obValue = cbRow;
pDBBindings[nCol].cbMaxLen = cbCol;
cbRow += AdjustLen(cbCol);
}
pRowValues = new BYTE[cbRow];
*ppDBBindings = pDBBindings;
*ppRowValues = pRowValues;
return;
}
int main()
{
ISourcesRowset* pISourceRowset = NULL;
IRowset* pIRowset = NULL;
IAccessor* pIAccessor = NULL;
DBBINDING* pDBBindings = NULL;
HROW* pRows = new HROW[500];
BYTE* pData = NULL;
HACCESSOR hAccessorRetrieve = NULL;
ULONG cRows = 0;
ULONG DSSeqNumber = 0;
HRESULT hr;
UINT nCols;
DBCOLUMNINFO* pColumnsInfo = NULL;
OLECHAR* pColumnStrings = NULL;
DBBINDSTATUS* pDBBindStatus = NULL;
BYTE* pRowValues = NULL;
ULONG cRowsObtained;
ULONG iRow;
char* pMultiByte = NULL;
short* psSourceType = NULL;
BYTE* pDatasource = NULL;
//Initialize COM library.
CoInitialize(NULL);
//Initialize the enumerator.
if(FAILED(CoCreateInstance(CLSID_SQLOLEDB_ENUMERATOR,
NULL,
CLSCTX_INPROC_SERVER,
IID_ISourcesRowset,
(void**)&pISourceRowset)))
{
//Process error.
return TRUE;
}
//Retrieve the source rowset.
hr = pISourceRowset->GetSourcesRowset(NULL,
IID_IRowset,
0,
NULL,
(IUnknown**)&pIRowset);
pISourceRowset->Release();
if(FAILED(hr))
{
//Process error.
return TRUE;
}
//Get the description of the enumerator's rowset.
if(FAILED(hr = GetColumnInfo(pIRowset,
&nCols,
&pColumnsInfo,
&pColumnStrings)))
{
//Process error.
goto SAFE_EXIT;
}
//Create the binding structures.
CreateDBBindings(nCols,
pColumnsInfo,
&pDBBindings,
&pRowValues);
pDBBindStatus = new DBBINDSTATUS[nCols];
if (sizeof(TCHAR) != sizeof(WCHAR))
{
pMultiByte = new char[pDBBindings[0].cbMaxLen];
}
if(FAILED(pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor)))
{
//Process error.
goto SAFE_EXIT;
}
//Create the rowset accessor.
if(FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
nCols,
pDBBindings,
0,
&hAccessorRetrieve,
pDBBindStatus)))
{
//Process error.
goto SAFE_EXIT;
}
//Process all the rows, NUMROWS_CHUNK rows at a time.
while (SUCCEEDED(hr))
{
hr=pIRowset->GetNextRows(NULL,
0,
NUMROWS_CHUNK,
&cRowsObtained,
&pRows);
if(FAILED(hr))
{
//process error
}
if(cRowsObtained == 0 || FAILED(hr))
break;
for(iRow = 0; iRow < cRowsObtained; iRow++)
{
//Get the rowset data.
if(SUCCEEDED(hr = pIRowset->GetData(pRows[iRow],
hAccessorRetrieve,
pRowValues)))
{
psSourceType = (short *)(pRowValues +
pDBBindings[3].obValue);
if (*psSourceType == DBSOURCETYPE_DATASOURCE)
{
DSSeqNumber = DSSeqNumber + 1; //Data source counter.
pDatasource = (pRowValues + pDBBindings[0].obValue);
if(sizeof(TCHAR) != sizeof(WCHAR))
{
WideCharToMultiByte(CP_ACP, 0,
(WCHAR*)pDatasource, -1, pMultiByte,
pDBBindings[0].cbMaxLen, NULL, NULL);
printf( "DataSource# %d\tName: %S\n",
DSSeqNumber, (WCHAR *) pMultiByte );
}
else
{
printf( "DataSource# %d\tName: %S\n",
DSSeqNumber, (WCHAR *) pDatasource );
} //if
} //if
} //if
} //for
pIRowset->ReleaseRows(cRowsObtained, pRows, NULL, NULL, NULL);
} //while
//Release COM library.
CoUninitialize();
return(0);
SAFE_EXIT:
//Do the clean-up.
return TRUE;
};