⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 igetasoledbrowsetimpl.h

📁 The ATL OLE DB Provider templates only seem to support read-only rowsets and making them support upd
💻 H
字号:
#ifndef __I_GET_AS_OLEDB_ROWSET_IMPL__INCLUDED__
#define __I_GET_AS_OLEDB_ROWSET_IMPL__INCLUDED__

#include "IGetAsOLEDBRowset.h"

template <class T>
class ATL_NO_VTABLE IGetAsOLEDBRowsetImpl: public _IGetAsOLEDBRowset
{
public:

   STDMETHOD(GetAsRowset)(
      /* [in] */ IUnknown *pUnkCreator,
      /* [in] */ IUnknown *pUnkOuter,	
	   /* [in] */ REFIID riid,				
      /* [out] */ LONG *pcRowsAffected,					
	   /* [out, iid_is(riid)] */ IUnknown **ppRowset)
   {
      if (!ppRowset || !pcRowsAffected)
      {
         return E_POINTER;
      }

      *ppRowset = 0;
      *pcRowsAffected = 0;

      T *pT = (T*)this;

      return pT->AsRowset(pUnkCreator, pUnkOuter, riid, pcRowsAffected, ppRowset);
   }

   // The following function can be called by the object that implements AsRowset() to
   // create a "standard" rowset object of its choice, it handles all the crap that 
   // needs to be done to get the rowset object created and wired up to the rest of
   // the provider properly.

   template <class RowsetClass> 
   HRESULT CreateRowset(
      IUnknown * pUnkCreator,	
      IUnknown * pUnkOuter,	
	   REFIID riid,				
	   IUnknown **ppRowset,
      RowsetClass *& pRowsetObj)
   {
	   HRESULT hr;
	   
	   if (ppRowset != NULL)
      {
		   *ppRowset = NULL;
      }

	   if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
      {
		   return DB_E_NOAGGREGATION;
      }

	   CComPolyObject<RowsetClass>* pPolyObj;
	   
      if (FAILED(hr = CComPolyObject<RowsetClass>::CreateInstance(pUnkOuter, &pPolyObj)))
      {
		   return hr;
      }
	   
      // Ref the created COM object and Auto release it on failure
	   
      CComPtr<IUnknown> spUnk;
	   
      hr = pPolyObj->QueryInterface(&spUnk);
	   
      if (FAILED(hr))
	   {
		   delete pPolyObj; // must hand delete as it is not ref'd
		   return hr;
	   }
	   
      // Get a pointer to the Rowset instance
	   pRowsetObj = &(pPolyObj->m_contained);


      // Rowsets have their properties initialised from their creators.
      // Unfortunately we can't do that as our creator object could be in a different
      // appartment.
      // Instead we call FInit with a new copy of our creator class, which will get 
      // our rowset's property map set up correctly. We then call get properties on
      // the COM interface to our creator and set the properties in ourself...
      // Long winded, but it should work...

      CComObject<RowsetClass::_RowsetCreatorClass> dummy;   
      
      dummy.InternalAddRef();    // bump ref count to 1
      dummy.FinalConstruct();

	   if (FAILED(hr = pRowsetObj->FInit(&dummy)))
      {
		   return hr;
      }

      CComQIPtr<ICommandProperties> spCommandProps(pUnkCreator);

      // what if our creator isn't a command?

      if (spCommandProps)
      {
         //
         ULONG cPropSets = 0;
         DBPROPSET *pPropSets = 0;
         
         // Passing 0 as the first argument means give us all properties...


         hr = spCommandProps->GetProperties(0, 0, &cPropSets, &pPropSets);

         if (SUCCEEDED(hr))
         {
            const GUID* ppGuid[1];
      		ppGuid[0] = &DBPROPSET_ROWSET;

            // Call SetProperties.  The true in the last parameter indicates
            // the special behavior that takes place on rowset creation (i.e.
            // it succeeds as long as any of the properties were not marked
            // as DBPROPS_REQUIRED.

            hr = pRowsetObj->SetProperties(0, cPropSets, pPropSets, 1, ppGuid, true);

            ReleasePropertyStructures(cPropSets, pPropSets);

            // do a recursive free on all of the data in the pPropSets structure
         }
      }
      else
      {
   		ATLTRACE2(atlTraceDBProvider, 0, "IGetAsOLEDBRowsetImpl::CreateRowset - pUnkCreator isn't a command\n");
      }
   
      if (FAILED(hr))
      {
         return hr;
      }

	   pRowsetObj->SetSite(pUnkCreator);

	   if (InlineIsEqualGUID(riid, IID_NULL) || ppRowset == NULL)
	   {
		   if (ppRowset != NULL)
			   *ppRowset = NULL;
		   return hr;
	   }

      hr = pPolyObj->QueryInterface(riid, (void**)ppRowset);

      // Note: We dont bother to copy the bindings from the command to the rowset. This is
      // against the rules of OLE DB which say that if you set up bindings in the command
      // then they're available in the rowset. We never do that, so it shouldnt matter. 
      // It's a problem for us to copy the bindings as we cant just to the memory copy that
      // the standard templates do as our rowsets and commands are potentially in different
      // appartments...

      // This is the code from the standard templates that does the binding copy, we'd need
      // to concoct some COM way of doing this if we wanted to do it...

      /*

  	   for (iBind = 0; iBind < pT->m_rgBindings.GetSize(); iBind++)
	   {
		   T::_BindType* pBind = NULL;
		   T::_BindType* pBindSrc = NULL;
		   ATLTRY(pBind = new T::_BindType);
		   if (pBind == NULL)
		   {
			   ATLTRACE2(atlTraceDBProvider, 0, "Failed to allocate memory for new Binding\n");
			   return E_OUTOFMEMORY;
		   }
		   // auto cleanup on failure
		   CAutoMemRelease<T::_BindType> amr(pBind);
		   pBindSrc = pT->m_rgBindings.GetValueAt(iBind);
		   if (pBindSrc == NULL)
		   {
			   ATLTRACE2(atlTraceDBProvider, 0, "The map appears to be corrupted, failing!!\n");
			   return E_FAIL;
		   }
		   if (!pRowsetObj->m_rgBindings.Add(pT->m_rgBindings.GetKeyAt(iBind), pBind))
		   {
			   ATLTRACE2(atlTraceDBProvider, 0, "Failed to add hAccessor to Map\n");
			   return E_OUTOFMEMORY;
		   }
		   if (pBindSrc->cBindings)
		   {
			   ATLTRY(pBind->pBindings = new DBBINDING[pBindSrc->cBindings])
			   if (pBind->pBindings == NULL)
			   {
				   ATLTRACE2(atlTraceDBProvider, 0, "Failed to Allocate dbbinding Array\n");
				   // We added it, must now remove on failure
				   pRowsetObj->m_rgBindings.Remove(pT->m_rgBindings.GetKeyAt(iBind));
				   return E_OUTOFMEMORY;
			   }
		   }
		   else
		   {
			   pBind->pBindings = NULL; // NULL Accessor
		   }

		   pBind->dwAccessorFlags = pBindSrc->dwAccessorFlags;
		   pBind->cBindings = pBindSrc->cBindings;
		   pBind->dwRef = 1;
		   memcpy (pBind->pBindings, pBindSrc->pBindings, (pBindSrc->cBindings)*sizeof(DBBINDING));
		   pBind = amr.Detach();
	   }

      */

	   return hr;
   }

   private : 
                  
      void ReleasePropertyStructures(ULONG cPropSets, DBPROPSET* pPropSets)
      {
         DBPROPSET *pPropSet = pPropSets;

         for (size_t setIndex = 0; setIndex < cPropSets; setIndex++)
         {
            if (pPropSet)
            {
               CoTaskMemFree(pPropSet->rgProperties);
            
               DBPROPSET *pLastSet = pPropSet;

               pPropSet++;

               CoTaskMemFree(pLastSet);
            }            
         }
      }


};

#endif // __I_GET_AS_OLEDB_ROWSET_IMPL__INCLUDED__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -