home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / oledb / tablecopy / datasource.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-12  |  15.8 KB  |  538 lines

  1. //-----------------------------------------------------------------------------
  2. // Microsoft OLE DB TABLECOPY Sample
  3. // Copyright (C) 1995-1998 Microsoft Corporation
  4. //
  5. // @doc
  6. //
  7. // @module DATASOURCE.CPP
  8. //
  9. //-----------------------------------------------------------------------------
  10.  
  11. /////////////////////////////////////////////////////////////////
  12. // Includes
  13. //
  14. /////////////////////////////////////////////////////////////////
  15. #include "WinMain.h"
  16. #include "Common.h"
  17. #include "DataSource.h"
  18. #include "msdaguid.h"    //CLSID_OLEDB_ENUMERATOR
  19.  
  20.  
  21. /////////////////////////////////////////////////////////////////
  22. // CDataSource::CDataSource
  23. //
  24. /////////////////////////////////////////////////////////////////
  25. CDataSource::CDataSource()
  26. {
  27.     //OLEDB Interfaces
  28.     m_pIDBInitialize        = NULL;    //DataSource
  29.     m_pIOpenRowset            = NULL;    //Session
  30.     m_pIDBSchemaRowset        = NULL;    //Session
  31.     m_pITableDefinition        = NULL;    //Session
  32.     m_pIIndexDefinition        = NULL;    //Session
  33.     m_pICommandText            = NULL;    //Command
  34.  
  35.     //ProviderInfo
  36.     m_pwszProviderName        = NULL;    //Pointer into m_rgProviderInfo.wszName
  37.     m_pwszProviderParseName    = NULL;    //Pointer into m_rgProviderInfo.wszParseName
  38.     m_pwszProviderFileName    = NULL; //DBPROP_PROVIDERNAME
  39.     m_pwszProviderVer        = NULL; //DBPROP_PROVIDERVER
  40.     m_pwszProviderOLEDBVer    = NULL; //DBPROP_PROVIDEROLEDBVER
  41.  
  42.     //Enumerator ProvierInfo
  43.     m_cProviderInfo            = 0;    
  44.     m_rgProviderInfo        = NULL;
  45.     m_pIParseDisplayName    = NULL; //Enumerator
  46.  
  47.     //Properties
  48.     m_fReadOnly                = TRUE;    //DBPROP_DATASOURCEREADONLY
  49.     m_fPrimaryKeysSupported = FALSE;//DBPROP_SQLSUPPORT
  50.     m_fMultipleParamSets    = FALSE;//DBPROP_MULTIPLEPARAMSETS
  51.     m_fIRowsetChange        = FALSE;//DBPROP_IRowsetChange
  52.     m_fIRowsetUpdate        = FALSE;//DBPROP_IRowsetUpdate
  53.     m_dwStorageObjects        = 0;    //DBPROP_STRUCTUREDSTORAGE
  54.  
  55.     m_pwszCatalog            = NULL; //DBPROP_CURRENTCATALOG
  56.     m_pwszCatalogTerm        = NULL; //DBPROP_CATALOGTERM
  57.     m_pwszCatalogLocation    = NULL; //DBPROP_CATALOGLOCATION
  58.     m_pwszSchemaTerm        = NULL; //DBPROP_SCHEMATERM
  59.     m_pwszTableTerm            = NULL; //DBPROP_TABLETERM
  60.  
  61.     //DataSource Info
  62.     m_ulActiveSessions        = 0;    //DBPROP_ACTIVESESSIONS
  63.     m_pwszDataSource        = NULL;    //DBPROP_DATASOURCENAME
  64.     m_pwszDBMS                = NULL; //DBPROP_DBMSNAME
  65.     m_pwszDBMSVer            = NULL; //DBPROP_DBMSVER
  66.  
  67.     m_fConnected = FALSE;
  68. }
  69.  
  70. /////////////////////////////////////////////////////////////////
  71. // CDataSource::~CDataSource
  72. //
  73. /////////////////////////////////////////////////////////////////
  74. CDataSource::~CDataSource()
  75. {
  76.     Disconnect();
  77.  
  78.     //Enumerator ProviderInfo
  79.     m_cProviderInfo            = 0;    
  80.     SAFE_FREE(m_rgProviderInfo);
  81.     SAFE_RELEASE(m_pIParseDisplayName);
  82. }
  83.  
  84.  
  85. /////////////////////////////////////////////////////////////////
  86. // BOOL CDataSource::IsConnected
  87. //
  88. /////////////////////////////////////////////////////////////////
  89. BOOL CDataSource::IsConnected()
  90. {
  91.     return m_fConnected;
  92. }
  93.  
  94.  
  95. /////////////////////////////////////////////////////////////////
  96. // BOOL CDataSource::IsSimilar
  97. //
  98. /////////////////////////////////////////////////////////////////
  99. BOOL CDataSource::IsSimilar(CDataSource* pCDataSource)
  100. {
  101.     ASSERT(pCDataSource);
  102.     
  103.     //Must be Connected to compare
  104.     if(!IsConnected() || !pCDataSource->IsConnected())
  105.         return FALSE;
  106.  
  107.     ASSERT(m_pwszDBMS && pCDataSource->m_pwszDBMS);
  108.     ASSERT(m_pwszDBMSVer && pCDataSource->m_pwszDBMSVer);
  109.     
  110.     //Similiar: Must be the same DBMS and Version
  111.     if(wcscmp(m_pwszDBMS, pCDataSource->m_pwszDBMS)==0 &&
  112.         wcscmp(m_pwszDBMSVer, pCDataSource->m_pwszDBMSVer)==0)
  113.         return TRUE;
  114.  
  115.     return FALSE;
  116. }
  117.  
  118.  
  119. /////////////////////////////////////////////////////////////////
  120. // BOOL CDataSource::IsEqual
  121. //
  122. /////////////////////////////////////////////////////////////////
  123. BOOL CDataSource::IsEqual(CDataSource* pCDataSource)
  124. {
  125.     ASSERT(pCDataSource);
  126.     
  127.     //Must be Connected to compare
  128.     if(!IsConnected() || !pCDataSource->IsConnected())
  129.         return FALSE;
  130.  
  131.     ASSERT(m_pwszCatalog && pCDataSource->m_pwszCatalog);
  132.     ASSERT(m_pwszDBMS && pCDataSource->m_pwszDBMS);
  133.     ASSERT(m_pwszDBMSVer && pCDataSource->m_pwszDBMSVer);
  134.     
  135.     //Equal: 
  136.     //Must have same Catalog, DBMS, Version
  137.     //Note, Don't have to have the same DataSource Name (an access
  138.     //database can have multiple names for the same file)
  139.     if(wcscmp(m_pwszCatalog, pCDataSource->m_pwszCatalog)==0 &&
  140.         wcscmp(m_pwszDBMS, pCDataSource->m_pwszDBMS)==0 &&
  141.         wcscmp(m_pwszDBMSVer, pCDataSource->m_pwszDBMSVer)==0)
  142.         return TRUE;
  143.  
  144.     return FALSE;
  145. }
  146.  
  147.  
  148. /////////////////////////////////////////////////////////////////
  149. // BOOL CDataSource::Disconnect
  150. //
  151. /////////////////////////////////////////////////////////////////
  152. BOOL CDataSource::Disconnect()
  153. {
  154.     //Interfaces
  155.     SAFE_RELEASE(m_pIDBInitialize);
  156.     SAFE_RELEASE(m_pIOpenRowset);
  157.     SAFE_RELEASE(m_pIDBSchemaRowset);
  158.     SAFE_RELEASE(m_pITableDefinition);
  159.     SAFE_RELEASE(m_pIIndexDefinition);
  160.     SAFE_RELEASE(m_pICommandText);
  161.  
  162.     //Properties
  163.     SAFE_FREE(m_pwszCatalog);
  164.     SAFE_FREE(m_pwszCatalogTerm);
  165.     SAFE_FREE(m_pwszCatalogLocation);
  166.     SAFE_FREE(m_pwszSchemaTerm);
  167.     SAFE_FREE(m_pwszTableTerm);
  168.     SAFE_FREE(m_pwszDataSource);
  169.     SAFE_FREE(m_pwszDBMS);
  170.     SAFE_FREE(m_pwszDBMSVer);
  171.  
  172.     SAFE_FREE(m_pwszProviderFileName);
  173.     SAFE_FREE(m_pwszProviderVer);
  174.     SAFE_FREE(m_pwszProviderOLEDBVer);
  175.  
  176.     m_fConnected = FALSE;
  177.     return TRUE;
  178. }
  179.  
  180.  
  181. /////////////////////////////////////////////////////////////////
  182. // BOOL CDataSource::Connect
  183. //
  184. /////////////////////////////////////////////////////////////////
  185. BOOL CDataSource::Connect(HWND hWnd, CDataSource* pCDataSource)
  186. {
  187.     ASSERT(hWnd);
  188.     ASSERT(m_pIParseDisplayName);
  189.  
  190.     HRESULT                hr;
  191.     ULONG               cPropSets = 0;
  192.     DBPROPSET*            rgPropSets = NULL;
  193.     
  194.     IDBProperties*        pIDBProperties = NULL;
  195.     IDBCreateSession*   pIDBCreateSession = NULL;
  196.  
  197.     //Local interface pointers, until we have a connection
  198.     IDBInitialize*        pIDBInitialize = NULL;
  199.     IOpenRowset*        pIOpenRowset = NULL;
  200.     IDBCreateCommand*   pIDBCreateCommand = NULL;
  201.     ICommandText*        pICommandText = NULL;
  202.  
  203.     ULONG chEaten = 0;
  204.     IMoniker* pIMoniker = NULL;
  205.  
  206.     if(pCDataSource == NULL)
  207.     {
  208.         //Get the IDBInitalize interface
  209.         //Could just do a CoCreateInstance on the Provider CLSID, but since were using
  210.         //The enumerator, we can be a more general app by using IParseDisplayName
  211.         ASSERT(m_pwszProviderParseName);
  212.         XTESTC(hr = m_pIParseDisplayName->ParseDisplayName(NULL, m_pwszProviderParseName, &chEaten, &pIMoniker));
  213.         XTESTC(hr = BindMoniker(pIMoniker, 0, IID_IDBInitialize, (void**)&pIDBInitialize));
  214.  
  215.         //DBPROP_INIT_HWND
  216.         if(IsSettableProperty(pIDBInitialize, DBPROP_INIT_HWND, DBPROPSET_DBINIT))
  217.             SetProperty(DBPROP_INIT_HWND, DBPROPSET_DBINIT, &cPropSets, &rgPropSets, DBTYPE_I4, (LONG)hWnd);
  218.         //DBPROP_INIT_PROMPT
  219.         if(IsSettableProperty(pIDBInitialize, DBPROP_INIT_PROMPT, DBPROPSET_DBINIT))
  220.             SetProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT, &cPropSets, &rgPropSets, DBTYPE_I2, DBPROMPT_COMPLETE);
  221.         //DBPROP_INIT_MODE
  222.         if(IsSettableProperty(pIDBInitialize, DBPROP_INIT_MODE, DBPROPSET_DBINIT))
  223.             SetProperty(DBPROP_INIT_MODE, DBPROPSET_DBINIT, &cPropSets, &rgPropSets, DBTYPE_I4, DB_MODE_READWRITE | DB_MODE_SHARE_DENY_WRITE);
  224.  
  225.         //Set the DataSource Properties
  226.         //IDBProperties is a MANDATORY interface, if error try and Initialize anyway
  227.         XTEST(hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties));
  228.         XTEST(hr = pIDBProperties->SetProperties(cPropSets, rgPropSets));
  229.         
  230.         //Initailize
  231.         XTESTC(hr = pIDBInitialize->Initialize());
  232.     }
  233.     else
  234.     {
  235.         //Use exsiting Connection
  236.         pIDBInitialize = pCDataSource->m_pIDBInitialize;
  237.         pIDBInitialize->AddRef();
  238.     }
  239.  
  240.     //Get the Session Object
  241.     XTESTC(hr = pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void **)&pIDBCreateSession));
  242.  
  243.     //Create the SessionObject
  244.     XTESTC(hr = pIDBCreateSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown**)&pIOpenRowset));
  245.  
  246.     //Get the CommandText object - If supported
  247.     if(SUCCEEDED(pIOpenRowset->QueryInterface(IID_IDBCreateCommand, (void**)&pIDBCreateCommand)))
  248.         XTESTC(hr = pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICommandText));
  249.  
  250.     //Do away with any previous connections
  251.     Disconnect();
  252.     
  253.     //If we have made it this far, we are successfully connected, 
  254.     m_fConnected = TRUE;
  255.  
  256.     //Save the new connection interfaces
  257.     SAFE_ADDREF(pIDBInitialize);
  258.     m_pIDBInitialize = pIDBInitialize;
  259.  
  260.     SAFE_ADDREF(pIOpenRowset);
  261.     m_pIOpenRowset    = pIOpenRowset;
  262.  
  263.     SAFE_ADDREF(pICommandText);
  264.     m_pICommandText = pICommandText;
  265.  
  266.     //Obtain ITableDefinition/IIndexDefintion if supported
  267.     pIOpenRowset->QueryInterface(IID_ITableDefinition, (void**)&m_pITableDefinition);
  268.     pIOpenRowset->QueryInterface(IID_IIndexDefinition, (void**)&m_pIIndexDefinition);
  269.     pIOpenRowset->QueryInterface(IID_IDBSchemaRowset,  (void**)&m_pIDBSchemaRowset);
  270.  
  271.     //Now get the connection properties
  272.     QTESTC(hr = GetConnectionProps());
  273.  
  274. CLEANUP:
  275.     FreeProperties(cPropSets, rgPropSets);
  276.  
  277.     //Release Interfaces
  278.     SAFE_RELEASE(pIDBInitialize);
  279.     SAFE_RELEASE(pIDBProperties);
  280.     SAFE_RELEASE(pIDBCreateSession);
  281.     SAFE_RELEASE(pIOpenRowset);
  282.     SAFE_RELEASE(pIDBCreateCommand);
  283.     SAFE_RELEASE(pICommandText);
  284.     SAFE_RELEASE(pIMoniker);
  285.     return SUCCEEDED(hr);
  286. }
  287.  
  288.  
  289.  
  290. /////////////////////////////////////////////////////////////////////////////
  291. // HRESULT CDataSource::GetConnectionProps
  292. //
  293. /////////////////////////////////////////////////////////////////////////////
  294. HRESULT CDataSource::GetConnectionProps()
  295. {
  296.     HRESULT hr = S_OK;
  297.     DWORD dwSqlSupport = 0;
  298.     
  299.     //DBPROP_CURRENTCATALOG
  300.     hr = GetProperty(m_pIDBInitialize, DBPROP_CURRENTCATALOG, 
  301.                             DBPROPSET_DATASOURCE, &m_pwszCatalog); 
  302.  
  303.     //DBPROP_CATALOGTERM
  304.     hr = GetProperty(m_pIDBInitialize, DBPROP_CATALOGTERM, 
  305.                             DBPROPSET_DATASOURCEINFO, &m_pwszCatalogTerm); 
  306.     if(!m_pwszCatalogTerm[0])
  307.     {
  308.         SAFE_FREE(m_pwszCatalogTerm);
  309.         m_pwszCatalogTerm = wcsDuplicate(L"Catalog");
  310.     }
  311.  
  312.  
  313.     //DBPROP_CATALOGLOCATION
  314.     hr = GetProperty(m_pIDBInitialize, DBPROP_CATALOGLOCATION, 
  315.                             DBPROPSET_DATASOURCEINFO, &m_pwszCatalogLocation); 
  316.  
  317.     //DBPROP_SCHEMATERM
  318.     hr = GetProperty(m_pIDBInitialize, DBPROP_SCHEMATERM, 
  319.                             DBPROPSET_DATASOURCEINFO, &m_pwszSchemaTerm); 
  320.     if(!m_pwszSchemaTerm[0])
  321.     {
  322.         SAFE_FREE(m_pwszSchemaTerm);
  323.         m_pwszSchemaTerm = wcsDuplicate(L"Schema");
  324.     }
  325.  
  326.     //DBPROP_TABLETERM
  327.     hr = GetProperty(m_pIDBInitialize, DBPROP_TABLETERM, 
  328.                             DBPROPSET_DATASOURCEINFO, &m_pwszTableTerm); 
  329.     if(!m_pwszTableTerm[0])
  330.     {
  331.         SAFE_FREE(m_pwszTableTerm);
  332.         m_pwszTableTerm = wcsDuplicate(L"Table");
  333.     }
  334.  
  335.     //DBPROP_ACTIVESESSIONS
  336.     hr = GetProperty(m_pIDBInitialize, DBPROP_ACTIVESESSIONS, 
  337.                             DBPROPSET_DATASOURCEINFO, &m_ulActiveSessions);
  338.  
  339.     //DBPROP_DATASOURCENAME
  340.     hr = GetProperty(m_pIDBInitialize, DBPROP_DATASOURCENAME, 
  341.                             DBPROPSET_DATASOURCEINFO, &m_pwszDataSource);
  342.  
  343.     //DBPROP_DBMSNAME
  344.     hr = GetProperty(m_pIDBInitialize, DBPROP_DBMSNAME, 
  345.                             DBPROPSET_DATASOURCEINFO, &m_pwszDBMS);
  346.  
  347.     //DBPROP_DBMSVER
  348.     hr = GetProperty(m_pIDBInitialize, DBPROP_DBMSVER, 
  349.                             DBPROPSET_DATASOURCEINFO, &m_pwszDBMSVer);
  350.  
  351.     //DBPROP_DATASOURCEREADONLY 
  352.     hr = GetProperty(m_pIDBInitialize, DBPROP_DATASOURCEREADONLY, 
  353.                             DBPROPSET_DATASOURCEINFO, &m_fReadOnly);
  354.  
  355.     //DBPROP_PROVIDERNAME
  356.     hr = GetProperty(m_pIDBInitialize, DBPROP_PROVIDERNAME, 
  357.                             DBPROPSET_DATASOURCEINFO, &m_pwszProviderFileName);
  358.  
  359.     //DBPROP_PROVIDERVER 
  360.     hr = GetProperty(m_pIDBInitialize, DBPROP_PROVIDERVER, 
  361.                             DBPROPSET_DATASOURCEINFO, &m_pwszProviderVer);
  362.  
  363.     //DBPROP_PROVIDEROLEDBVER 
  364.     hr = GetProperty(m_pIDBInitialize, DBPROP_PROVIDEROLEDBVER, 
  365.                             DBPROPSET_DATASOURCEINFO, &m_pwszProviderOLEDBVer);
  366.  
  367.     //DBPROP_MULTIPLEPARAMSETS 
  368.     hr = GetProperty(m_pIDBInitialize, DBPROP_MULTIPLEPARAMSETS, 
  369.                             DBPROPSET_DATASOURCEINFO, &m_fMultipleParamSets);
  370.  
  371.     //DBPROP_STRUCTUREDSTORAGE
  372.     hr = GetProperty(m_pIDBInitialize, DBPROP_STRUCTUREDSTORAGE, 
  373.                             DBPROPSET_DATASOURCEINFO, &m_dwStorageObjects);
  374.     
  375.     //DBPROP_SQLSUPPORT 
  376.     hr = GetProperty(m_pIDBInitialize, DBPROP_SQLSUPPORT, 
  377.                             DBPROPSET_DATASOURCEINFO, &dwSqlSupport);
  378.  
  379.     //Are PrimaryKeys supported
  380.     m_fPrimaryKeysSupported = dwSqlSupport & DBPROPVAL_SQL_ANSI89_IEF;
  381.  
  382.     //DBPROP_IRowsetChange
  383.     m_fIRowsetChange = FALSE;
  384.     if(IsSupportedProperty(m_pIDBInitialize, DBPROP_IRowsetChange, DBPROPSET_ROWSET))
  385.         m_fIRowsetChange = TRUE;
  386.  
  387.     //DBPROP_IRowsetUpdate
  388.     m_fIRowsetUpdate = FALSE;
  389.     if(IsSupportedProperty(m_pIDBInitialize, DBPROP_IRowsetUpdate, DBPROPSET_ROWSET))
  390.         m_fIRowsetUpdate = TRUE;
  391.  
  392.     return S_OK;
  393. }
  394.  
  395.  
  396. /////////////////////////////////////////////////////////////////////////////
  397. // HRESULT CDataSource::GetProviders
  398. //
  399. /////////////////////////////////////////////////////////////////////////////
  400. HRESULT CDataSource::GetProviders()
  401. {
  402.     HRESULT hr;
  403.     
  404.     HROW* rghRows = NULL;
  405.     ULONG cRowsObtained = 0;
  406.     IRowset* pIRowset = NULL;
  407.  
  408.     IAccessor* pIAccessor = NULL;
  409.     HACCESSOR hAccessor = DB_NULL_HACCESSOR;
  410.  
  411.     //Release Previous ProviderInfo
  412.     m_cProviderInfo = 0;
  413.     SAFE_FREE(m_rgProviderInfo);
  414.     ISourcesRowset* pISourcesRowset = NULL;
  415.     
  416.     // Bind the user and table name for the list
  417.     const static ULONG cBindings = 4;
  418.     const static DBBINDING rgBindings[cBindings] = 
  419.         {
  420.             1,                 
  421.             offsetof(PROVIDERINFO, wszName),
  422.             0,
  423.             0,    
  424.             NULL,            
  425.             NULL,         
  426.             NULL,        
  427.             DBPART_VALUE,
  428.             DBMEMOWNER_CLIENTOWNED,        
  429.             DBPARAMIO_NOTPARAM, 
  430.             MAX_NAME_LEN,         
  431.             0,                 
  432.             DBTYPE_WSTR,     
  433.             0,    
  434.             0,                 
  435.  
  436.             2,                 
  437.             offsetof(PROVIDERINFO, wszParseName),
  438.             0,
  439.             0,    
  440.             NULL,            
  441.             NULL,         
  442.             NULL,        
  443.             DBPART_VALUE,
  444.             DBMEMOWNER_CLIENTOWNED,        
  445.             DBPARAMIO_NOTPARAM, 
  446.             MAX_NAME_LEN,         
  447.             0,                 
  448.             DBTYPE_WSTR,     
  449.             0,    
  450.             0,                 
  451.  
  452.             3,                 
  453.             offsetof(PROVIDERINFO, wszDescription),
  454.             0,
  455.             0,    
  456.             NULL,            
  457.             NULL,         
  458.             NULL,        
  459.             DBPART_VALUE,
  460.             DBMEMOWNER_CLIENTOWNED,        
  461.             DBPARAMIO_NOTPARAM, 
  462.             MAX_NAME_LEN,         
  463.             0,                 
  464.             DBTYPE_WSTR,     
  465.             0,    
  466.             0,                 
  467.     
  468.             4,                 
  469.             offsetof(PROVIDERINFO, wType),
  470.             0,
  471.             0,    
  472.             NULL,            
  473.             NULL,         
  474.             NULL,        
  475.             DBPART_VALUE,
  476.             DBMEMOWNER_CLIENTOWNED,        
  477.             DBPARAMIO_NOTPARAM, 
  478.             sizeof(DBTYPE),         
  479.             0,                 
  480.             DBTYPE_UI2,     
  481.             0,    
  482.             0,                 
  483.     };
  484.  
  485.  
  486.     //Initialize the OLE DB Enumerator and Obtain rowset
  487.     XTESTC(hr = CoCreateInstance(CLSID_OLEDB_ENUMERATOR, NULL, CLSCTX_INPROC_SERVER, IID_ISourcesRowset, (void**)&pISourcesRowset));
  488.     XTESTC(hr = pISourcesRowset->GetSourcesRowset(NULL, IID_IRowset, 0, NULL, (IUnknown**)&pIRowset));
  489.  
  490.     //Create Accessor
  491.     XTESTC(hr = pIRowset->QueryInterface(IID_IAccessor, (void **)&pIAccessor));
  492.     XTESTC(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBindings, rgBindings, 0, &hAccessor, NULL));
  493.  
  494.     //Obtain IParseDisplayName interface
  495.     XTESTC(hr = pISourcesRowset->QueryInterface(IID_IParseDisplayName, (void**)&m_pIParseDisplayName));
  496.  
  497.     //Loop through the entire returned rowet
  498.     while(TRUE)
  499.     {
  500.         XTESTC(hr = pIRowset->GetNextRows(NULL, 0, MAX_BLOCK_SIZE, &cRowsObtained, &rghRows));
  501.         
  502.         //ENDOFROWSET
  503.         if(cRowsObtained==0) 
  504.             break;
  505.         
  506.         //Alloc room for ProviderInfo (in chunks)
  507.         SAFE_REALLOC(m_rgProviderInfo, PROVIDERINFO, m_cProviderInfo + cRowsObtained);
  508.         memset(&m_rgProviderInfo[m_cProviderInfo], 0, sizeof(PROVIDERINFO)*cRowsObtained);
  509.  
  510.         //Loop over rows obtained and get ProviderInfo
  511.         for(ULONG i=0; i<cRowsObtained; i++) 
  512.         {    
  513.             //Get the Data
  514.             XTESTC(hr = pIRowset->GetData(rghRows[i], hAccessor, (void*)&m_rgProviderInfo[m_cProviderInfo]));
  515.  
  516.             //Only interested in DATASOURCEs, not other ENUMERATORs
  517.             if(m_rgProviderInfo[m_cProviderInfo].wType == DBSOURCETYPE_DATASOURCE)
  518.                 m_cProviderInfo++;
  519.         }
  520.             
  521.         //Release all the rows
  522.         XTESTC(hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL));
  523.         SAFE_FREE(rghRows);
  524.     }
  525.  
  526. CLEANUP:
  527.     if(hAccessor && pIAccessor)
  528.         XTEST(pIAccessor->ReleaseAccessor(hAccessor,NULL));
  529.  
  530.     SAFE_RELEASE(pISourcesRowset);
  531.     SAFE_RELEASE(pIRowset);
  532.     SAFE_RELEASE(pIAccessor);
  533.     SAFE_FREE(rghRows);
  534.     return hr;
  535. }
  536.  
  537.  
  538.