How to enumerate OLE DB data sources (OLE DB)

How to Install SQL Server 2000

How To

How to enumerate OLE DB data sources (OLE DB)

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

  1. Retrieve the source rowset by calling ISourceRowset::GetSourcesRowset.

  2. Find the description of the enumerators rowset by calling GetColumnInfo::IColumnInfo.

  3. Create the binding structures from the column information.

  4. Create the rowset accessor by calling IAccessor::CreateAccessor.

  5. Fetch the rows by calling IRowset::GetNextRows.

  6. Retrieve data from the rowset's copy of the row by calling IRowset::GetData and process it.
//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;
};