Share via


Setting and Getting Provider Properties

The data source object is the first object created when a consumer instantiates an OLE DB data provider by calling CoCreateInstance or through some other technique.

The data source object provides the starting point for communications between the provider and consumer. For example, a consumer can call CoCreateInstance and request an IDBInitialize interface pointer to instantiate a data source object. The provider's developer must generate a CLSID (class ID) and store the ID in the Microsoft® Windows® Registry. The consumer can use this CLSID with CoCreateInstance to instantiate the data source object. To facilitate this operation, providers should add their application or library information to the Windows Registry upon installation on a new system. The sample provider setup program registers the sample provider in the Windows Registry.

The data source object is also responsible for setting and returning information about the properties supported by the provider and exposing the list of supported keywords and literals. This functionality is supported through the mandatory IDBProperties interface and the optional IDBInfo interface. The IDBProperties interface contains three methods:

  • GetProperties returns the list of properties currently set on the data source object.

  • GetPropertyInfo returns information about supported rowset and data source properties.

  • SetProperties sets the properties on the data source object.

The IDBInfo interface contains two methods:

  • GetKeywords returns a list of supported keywords.

  • GetLiteralInfo returns information about literals used in text commands.

In the sample provider implementation, no command interfaces are implemented, so GetKeywords returns NULL. GetLiteralInfo is not implemented and returns E_NOTIMPL. GetProperties, GetPropertyInfo, and SetProperties are handled by passing the calls to the utility object that manages properties, which is found in UtilProp.cpp. The structure containing the properties known to the sample provider, which is also found in UtilProp.cpp, follows.

// Struct containing the properties we know about. The GUID and string fields are
// initialized in the constructor, because C++ makes it awkward to do so at declaration
// time. So, if you change this table, be sure to make parallel changes in CUtilProp::CUtilProp.
PROPSTRUCT s_rgprop[] =
   {
/* 0 */ {DBPROP_IAccessor,               DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IAccessor"},
/* 1 */ {DBPROP_IColumnsInfo,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IColumnsInfo"},
/* 2 */ {DBPROP_IConvertType,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IConvertType"},
/* 3 */ {DBPROP_IRowset,               DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IRowset"},
/* 4 */ {DBPROP_IRowsetChange,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,  VT_BOOL, TRUE,      0,                     NULL,         L"IRowsetChange"},
/* 5 */ {DBPROP_IRowsetInfo,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IRowsetInfo"},
/* 6 */ {DBPROP_IRowsetIdentity,         DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IRowsetIdentity"},
/* 7 */ {DBPROP_CANHOLDROWS,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,  VT_BOOL, TRUE,      0,                     NULL,         L"Hold Rows"},
/* 8 */ {DBPROP_LITERALIDENTITY,         DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,  VT_BOOL, TRUE,      0,                     NULL,         L"Literal Row Identity"},
/* 9 */ {DBPROP_UPDATABILITY,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_I4,    TRUE,      DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE|DBPROPVAL_UP_INSERT, NULL,L"Updatability"},
/* 10*/ {DBPROP_IRow,                  DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,   VT_BOOL, FALSE,      0,                     NULL,         L"IRow"},
/* 11*/ {DBPROP_IRowChange,               DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,   VT_BOOL, FALSE,      0,                     NULL,         L"IRowChange"},
/* 12*/ {DBPROP_IGetRow,               DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IGetRow"},
/* 13*/ {DBPROP_IGetSession,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, TRUE,      0,                     NULL,         L"IGetSession"},
/* 14*/ {DBPROP_QUICKRESTART,            DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ,                  VT_BOOL, FALSE,      0,                     NULL,         L"Quick Restart"},
/* 15*/ {DBPROP_SESS_AUTOCOMMITISOLEVELS,   DBPROPFLAGS_SESSION | DBPROPFLAGS_READ,                  VT_I4,    FALSE,      0,                     NULL,         L"Autocommit Isolation Levels"},
/* 16*/ {DBPROP_ACTIVESESSIONS,            DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_I4,    FALSE,      1,                     NULL,         L"Active Sessions"},
/* 17*/ {DBPROP_PERSISTENTIDTYPE,         DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_I4,    FALSE,      DBPROPVAL_PT_GUID_PROPID,   NULL,         L"Persistent ID Type"},
/* 18*/ {DBPROP_PROVIDERFILENAME,         DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_BSTR, FALSE,      0,                     L"SAMPPROV.DLL",L"Provider Name"},
/* 19*/ {DBPROP_PROVIDERFRIENDLYNAME,      DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_BSTR, FALSE,      0,                     L"Microsoft OLE DB Sample Provider",   L"Provider Friendly Name"},
/* 20*/ {DBPROP_PROVIDEROLEDBVER,         DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_BSTR, FALSE,      0,                     L"02.00",      L"OLE DB Version"},
/* 21*/ {DBPROP_PROVIDERVER,            DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_BSTR, FALSE,      0,                     _TEXT(VER_PRODUCTVERSION_STR),         L"Provider Version"},
/* 22*/ {DBPROP_ROWSETCONVERSIONSONCOMMAND, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_BOOL, TRUE,      0,                     NULL,         L"Rowset Conversions on Command"},
/* 23*/ {DBPROP_OLEOBJECTS,               DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ,            VT_I4,   FALSE,      DBPROPVAL_OO_DIRECTBIND|DBPROPVAL_OO_ROWOBJECT|DBPROPVAL_OO_SINGLETON,   NULL, L"OLE Object Support"},
/* 24*/ {DBPROP_INIT_DATASOURCE,         DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,   VT_BSTR, FALSE,      0,                     L"",         L"Data Source"},
#ifdef _WIN64
/* 25*/ {DBPROP_INIT_HWND,               DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,   VT_I8,    FALSE,      0,                     NULL,         L"Window Handle"},
#else
/* 25*/ {DBPROP_INIT_HWND,               DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,   VT_I4,    FALSE,      0,                     NULL,         L"Window Handle"},
#endif
/* 26*/ {DBPROP_INIT_PROMPT,            DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE,   VT_I2,   FALSE,      4,                     NULL,         L"Prompt"}
    }; 

The source code for GetPropertyInfo, which passes property information back to the provider, follows.

// Code ----------------------------------------------------------------------

// CUtilProp::CUtilProp ----------------------------------------------------------
//
// @mfunc Constructor for this class
//
// @rdesc NONE
//
CUtilProp::CUtilProp
    (
    void
    )
{
   memcpy(m_rgproperties, s_rgprop, sizeof(s_rgprop));
   memset(m_wszFilePath,0,sizeof(m_wszFilePath));
    return;
}


// CUtilProp::~CUtilProp ---------------------------------------------------------
//
// @mfunc Destructor for this class
//
// @rdesc NONE
//
CUtilProp:: ~CUtilProp
    (
   void
    )
{
   return;
}



// CUtilProp::GetPropIndex ----------------------------------------------------
//
// @mfunc Returns index of the given property in our global table of properties
//
// @rdesc BOOL
//      @flag TRUE      | found match, copied it to pulIndex out-param
//      @flag FALSE     | no match. In this case, pulIndex has no meaning
//
BOOL CUtilProp::GetPropIndex
    (
      DBPROPID dwPropertyID,  //@parm IN  | PROPID of desired property
       ULONG *    pulIndex      //@parm OUT | index of desired property if return was TRUE
    )
{
    //
   // asserts
   //
    assert(pulIndex);

    for (ULONG cNumberOfProperties = 0; 
       cNumberOfProperties < NUMBER_OF_SUPPORTED_PROPERTIES; 
       cNumberOfProperties++)
    {
        if( dwPropertyID == m_rgproperties[cNumberOfProperties].dwPropertyID )
        {
            // found a match
            *pulIndex = cNumberOfProperties;
            return TRUE;
         }
    }
    
   // found no matches
    return FALSE;
}



// CUtilProp::LoadDBPROPINFO  ----------------------------------------------------
//
// @mfunc Helper for GetPropertyInfo. Loads field of DBPROPINFO structure.
//
// @rdesc BOOL
//      @flag TRUE          | Method succeeded
//      @flag FALSE         | Method failed (couldn't allocate memory)
//
void CUtilProp::LoadDBPROPINFO
    (
    PROPSTRUCT * pPropStruct,
    DBPROPINFO * pPropInfo
    )
{
    //
   // asserts
   //
    assert(pPropStruct);
    assert(pPropInfo);

    //
   // set the easy fields..
   //
    pPropInfo->dwPropertyID   = pPropStruct->dwPropertyID;
    pPropInfo->dwFlags      = pPropStruct->dwFlags;
    pPropInfo->vtType      = pPropStruct->vtType;

    //
   // init the variant
   //
    VariantInit(&pPropInfo->vValues);

   //
   // fill in the description
   //
   if( pPropInfo->pwszDescription )
      wcscpy_s(pPropInfo->pwszDescription, _countof(pPropInfo->pwszDescription ), pPropStruct->pwstrDescBuffer);

   return;
}


// CUtilProp::LoadDBPROP  ----------------------------------------------------
//
// @mfunc Helper for GetProperties. Loads field of DBPROP structure.
//
// @rdesc HRESULT
//      @flag TRUE          | Method succeeded
//      @flag FALSE         | Method failed (couldn't allocate memory)
//
HRESULT CUtilProp::LoadDBPROP
    (
    PROPSTRUCT*   pPropStruct,
    DBPROP*      pPropSupport
    )
{
    HRESULT hr = S_OK;

   //
   // asserts
   //
    assert(pPropStruct);
    assert(pPropSupport);

    //
   // set the easy fields..
   //
    pPropSupport->dwPropertyID = pPropStruct->dwPropertyID;
    pPropSupport->colid         = DB_NULLID;
   pPropSupport->dwStatus      = DBPROPSTATUS_OK;

    //
   // init the variant
   //
    VariantInit(&pPropSupport->vValue);

   //
    // set pPropSupport->vValue based on Variant type
   //
    switch (pPropStruct->vtType)
    {
       case VT_BOOL:
         V_VT(&pPropSupport->vValue) = VT_BOOL;
         V_BOOL(&pPropSupport->vValue) = 
              (pPropStruct->boolVal ? VARIANT_TRUE : VARIANT_FALSE);
         break;
        
       case VT_I2:
          V_VT(&pPropSupport->vValue) = VT_I2;
         V_I2(&pPropSupport->vValue) = (SHORT)pPropStruct->longVal;
         break;

      case VT_I4:
          V_VT(&pPropSupport->vValue) = VT_I4;
         V_I4(&pPropSupport->vValue) = (LONG)pPropStruct->longVal;
         break;

#ifdef _WIN64
         case VT_I8:
          V_VT(&pPropSupport->vValue) = VT_I8;
         V_I8(&pPropSupport->vValue) = (LONGLONG)pPropStruct->longVal;
         break;
#endif

       case VT_BSTR:
         V_VT(&pPropSupport->vValue) = VT_BSTR;
         SAFE_SYSALLOC(V_BSTR(&pPropSupport->vValue), pPropStruct->pwstrVal);
         break;
    
      default:
         assert( !"LoadDBPROP unknown variant type!\n\r" );
         hr = E_FAIL;
         break;
    }

CLEANUP:
   
   return hr;
}

The source code for GetProperties, which returns the current settings of all supported properties, follows. Immediately following the creation of the data source object, none of the properties are set. Properties are set by the SetProperties method.

// CUtilProp::GetProperties ----------------------------------------------------
//
// @mfunc Returns current settings of all properties supported by the DSO/rowset
//
// @rdesc HRESULT
//      @flag S_OK          | The method succeeded
//      @flag E_INVALIDARG  | pcProperties or prgPropertyInfo was NULL
//      @flag E_OUTOFMEMORY | Out of memory
//
STDMETHODIMP CUtilProp::GetProperties
    (
      DWORD            dwBitMask,         //@parm IN  | Mask if Initialized
      ULONG            cPropertyIDSets,   //@parm IN | # of restiction property IDs
      const DBPROPIDSET   rgPropertyIDSets[],   //@parm IN | restriction guids
      ULONG*              pcPropertySets,      //@parm OUT | count of properties returned
      DBPROPSET**         prgPropertySets      //@parm OUT | property information returned
    )
{
    HRESULT         hr            = S_OK;
   BOOL         fPropsinError = FALSE;
   BOOL         fPropsSucceed = FALSE;
    ULONG         cProps        = 0;
   ULONG         cCount        = 0;
    ULONG         ulPropertySets= 0;
    DBPROP*         pProp;
    DBPROPSET*      pPropSet;

   // save the count of PropertyIDSets
   cProps = cPropertyIDSets;

   // If the consumer does not restrict the property sets
   // by specify an array of property sets and a cPropertySets
   // greater than 0, then we need to make sure we 
   // have some to return
   if( cPropertyIDSets == 0 )
   {
      // only allow the DBINIT, DATASOURCE and DATASOURCEINFO if Initialized
      if( dwBitMask & PROPSET_INIT )
         cProps = 2;
      else
         cProps = 1;
   }

    // use task memory allocater to alloc a DBPROPSET struct
    SAFE_ALLOC(pPropSet, DBPROPSET, cProps);
    memset(pPropSet, 0, cProps * sizeof(DBPROPSET));

   // For each supported Property Set
   for (ulPropertySets=0; ulPropertySets < cProps; ulPropertySets++)
   {
      BOOL fGetAllProps = FALSE;

      // If no restrictions return all properties from the three supported property sets
      if( cPropertyIDSets == 0 )
      {
            fGetAllProps = TRUE;
            
            // only do this once
            if( ulPropertySets == 0 )
            {
               if( !(dwBitMask & PROPSET_SESSION) )
               {                  
                  if( !(dwBitMask & PROPSET_ROWSET) )
                  {
                        pPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
                        pPropSet[0].cProperties  = NUMBER_OF_SUPPORTED_DBINIT_PROPERTIES;

                     if( dwBitMask & PROPSET_INIT )
                     {
                        pPropSet[1].guidPropertySet = DBPROPSET_DATASOURCEINFO;
                        pPropSet[1].cProperties  = NUMBER_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES;
                     }
                  }
                  else
                  {
                     pPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
                     pPropSet[0].cProperties  = NUMBER_OF_SUPPORTED_ROWSET_PROPERTIES;
                  }
               }
               else
               {
                  pPropSet[0].guidPropertySet = DBPROPSET_SESSION;
                  pPropSet[0].cProperties  = NUMBER_OF_SUPPORTED_SESSION_PROPERTIES;
               }
            }
      }
      else
      {
         pPropSet[ulPropertySets].guidPropertySet = rgPropertyIDSets[ulPropertySets].guidPropertySet;
         pPropSet[ulPropertySets].cProperties  = rgPropertyIDSets[ulPropertySets].cPropertyIDs;

         if( rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0 )
         {
            fGetAllProps = TRUE;

            if( rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT &&
               dwBitMask & PROPSET_DSO )
            {
               pPropSet[ulPropertySets].cProperties  = NUMBER_OF_SUPPORTED_DBINIT_PROPERTIES;
            }
            else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO) &&
                   ((dwBitMask & PROPSET_DSOINIT) == PROPSET_DSOINIT) )
            {
               pPropSet[ulPropertySets].cProperties  = NUMBER_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES;
            }
            else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_SESSION) &&
                   (dwBitMask & PROPSET_SESSION))
            {
               pPropSet[ulPropertySets].cProperties  = NUMBER_OF_SUPPORTED_SESSION_PROPERTIES;
            }
            else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET) &&
                   (dwBitMask & PROPSET_ROWSET))
            {
               pPropSet[ulPropertySets].cProperties  = NUMBER_OF_SUPPORTED_ROWSET_PROPERTIES;
            }
            else if( rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_PROPERTIESINERROR )
            {
               if( dwBitMask & PROPSET_DSO ) {
                  pPropSet[ulPropertySets].guidPropertySet = DBPROPSET_DBINIT;
                  fPropsSucceed = TRUE;
               }
               else if( dwBitMask & PROPSET_ROWSET ) {
                  pPropSet[ulPropertySets].guidPropertySet = DBPROPSET_ROWSET;
                  fPropsSucceed = TRUE;
               }
               else
                  fPropsinError = TRUE;
            }
            else
            {
               fGetAllProps = FALSE;
               fPropsinError = TRUE;
            }
         }
      }
      
      if( pPropSet[ulPropertySets].cProperties )
      {
          // use task memory allocater to alloc array of DBPROP structs
         pProp = (DBPROP*) PROVIDER_ALLOC(sizeof( DBPROP ) *
                               pPropSet[ulPropertySets].cProperties);

         if (!pProp)
         {
            for(ULONG ul=0; ul<ulPropertySets; ul++)
            {
               for(ULONG ul2=0; ul2<pPropSet[ul].cProperties; ul2++)
                  VariantClear( &pPropSet[ul].rgProperties[ul2].vValue );

               SAFE_FREE( pPropSet[ul].rgProperties );
            }
            SAFE_FREE( pPropSet );

            return ResultFromScode( E_OUTOFMEMORY );
         }
      
         pPropSet[ulPropertySets].rgProperties = &pProp[0];

         memset( pProp, 0, 
            (pPropSet[ulPropertySets].cProperties * sizeof( DBPROP )));
      }

       // for each prop in our table..
      for (cCount=0; cCount < pPropSet[ulPropertySets].cProperties; cCount++)
      {
         // init the Variant right up front
         // that way we can VariantClear with no worried (if we need to)
         VariantInit( &pProp[cCount].vValue );

         // Check supported property sets
         if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT &&
             fGetAllProps )
         {
            fPropsSucceed = TRUE;
            // load up their DBPROP from our table
            hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_DBINIT_PROPERTIES + cCount], 
                     &pProp[cCount] );
         }
         else if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO &&
                 fGetAllProps )
         {
            fPropsSucceed = TRUE;
            // load up their DBPROPINFO from our table
            hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES + cCount], 
                     &pProp[cCount] );
         }
         else if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_SESSION &&
                 fGetAllProps )
         {
            fPropsSucceed = TRUE;
            // load up their DBPROPINFO from our table
            hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_SESSION_PROPERTIES + cCount], 
                     &pProp[cCount] );
         }
         else if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET &&
                 fGetAllProps )
         {
            fPropsSucceed = TRUE;
            // load up their DBPROPINFO from our table
            hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_ROWSET_PROPERTIES + cCount], 
                     &pProp[cCount] );
         }
         else
         {
            ULONG ulIndex;

            pProp[cCount].dwPropertyID   = rgPropertyIDSets[ulPropertySets].rgPropertyIDs[cCount];
            pProp[cCount].dwStatus      = DBPROPSTATUS_NOTSUPPORTED;

            if(  (GetPropIndex(rgPropertyIDSets[ulPropertySets].rgPropertyIDs[cCount], &ulIndex)) &&
                (((dwBitMask & PROPSET_DSO) && 
                  (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT)) ||
                 (((dwBitMask & PROPSET_DSOINIT) == PROPSET_DSOINIT) &&
                  ((rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCE) ||
                  (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO))) ||
                 ((dwBitMask & PROPSET_SESSION) && 
                  (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_SESSION)) ||
                 ((dwBitMask & PROPSET_ROWSET) && 
                  (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET))) )
            {
               fPropsSucceed = TRUE;
               hr = LoadDBPROP( &m_rgproperties[ulIndex], &pProp[cCount] );
            }
            else
               fPropsinError = TRUE;
         }
      }
      // Set local back to FALSE
      fGetAllProps = FALSE;
   }

   // set count of properties and property information
    *pcPropertySets    = cProps;
    *prgPropertySets = pPropSet;

CLEANUP:

   if( FAILED(hr) ) 
   {
      // clear all variants used so far..
      for (ULONG ulFor=0; ulFor < cCount; ulFor++)
         VariantClear(&pProp[ulFor].vValue);

      // delete the pProp array, return failure
      SAFE_FREE(pProp);
      SAFE_FREE(pPropSet);
   }

   if ( (!fPropsSucceed && cPropertyIDSets) || (!fPropsSucceed && fPropsinError) )
      return ResultFromScode( DB_E_ERRORSOCCURRED );
   else if ( fPropsSucceed && fPropsinError )
      return ResultFromScode( DB_S_ERRORSOCCURRED );
   else
      return ResultFromScode( hr );
}

The source code for SetProperties, which sets the values of all supported properties, follows. The consumer must set properties on the provider before initializing the data source object. In most providers, these properties provide information such as a database location, database name, user ID, and password. The sample provider requires only one value: a valid directory path to the data file.

// CUtilProp::SetProperties ----------------------------------------------------
//
// @mfunc Set current settings of properties supported by the DSO/rowset
//
// @rdesc HRESULT
//      @flag S_OK          | The method succeeded
//      @flag E_INVALIDARG  | pcProperties or prgPropertyInfo was NULL
//      @flag E_OUTOFMEMORY | Out of memory
//
STDMETHODIMP CUtilProp::SetProperties
    (
      DWORD      dwBitMask,         //@parm IN      Type of PropSet
      ULONG      cPropertyIDSets,   //@parm IN      # of DBPROPSET
      DBPROPSET   rgPropertyIDSets[]   //@parm INOUT   Array of property sets
   )
{
   ULONG cCountProps = 0;
   ULONG cValidProps = 0;
   ULONG ulIndex     = 0;

   // For each supported Property Set
   for (ULONG cPropSets=0; cPropSets < cPropertyIDSets; cPropSets++)
   {
       // for each prop in the propset
      for (ULONG cCnt=0; cCnt < rgPropertyIDSets[cPropSets].cProperties; cCnt++)
      {
         //Keep track of the number
         cCountProps++;

         // Check Check to see if valid
         switch( dwBitMask )
         {
            case PROPSET_DSO:
               if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DBINIT &&
                  GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
                  break;

               rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
               continue;

            case PROPSET_DSOINIT:
               if( (rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DATASOURCEINFO ||
                   rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DATASOURCE)  &&
                  GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
                  break;
               
               if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DBINIT )
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
               else
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
               continue;

            case PROPSET_SESSION:
               if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_SESSION  &&
                  GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
                  break;

               rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
               continue;

            case PROPSET_ROWSET:
               if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_ROWSET  &&
                  GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
                  break;

               rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
               continue;

            default:
               assert("Unsupported dwBitMask");
         }
         
         // arg checking for the prop
         if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions != DBPROPOPTIONS_OPTIONAL &&
            rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions != DBPROPOPTIONS_REQUIRED )
         {
            rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_BADOPTION;
            continue;
         }
         
         if( (V_VT(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) != VT_EMPTY) &&
            (V_VT(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) != m_rgproperties[ulIndex].vtType ||
             IsValidValue(&rgPropertyIDSets[cPropSets].rgProperties[cCnt]) == S_FALSE) ) 
         {
            rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_BADVALUE;
            continue;
         }
         
         switch( V_VT(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) )
         {
            case VT_BOOL:
               if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
                  m_rgproperties[ulIndex].boolVal = !!(V_BOOL(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue));
                  break;
               }

               if( !!(V_BOOL(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue)) == m_rgproperties[ulIndex].boolVal )
                  break;

               if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
               else
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
               continue;

            case VT_I2:
               if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
                  m_rgproperties[ulIndex].longVal = V_I2(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue);
                  break;
               }

               if( V_I2(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) == (SHORT)m_rgproperties[ulIndex].longVal )
                  break;

               if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
               else
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
               continue;

            case VT_I4:
               if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
                  m_rgproperties[ulIndex].longVal = V_I4(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue);
                  break;
               }

               if( (V_I4(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) == (LONG)m_rgproperties[ulIndex].longVal) ||
                  (rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID == DBPROP_UPDATABILITY &&
                   V_I4(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) & m_rgproperties[ulIndex].longVal) )
                  break;

               if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
               else
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
               continue;

#ifdef _WIN64
                case VT_I8:
               if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
                  m_rgproperties[ulIndex].longVal = V_I8(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue);
                  break;
               }

               if( (V_I8(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) == (LONG)m_rgproperties[ulIndex].longVal) ||
                  (rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID == DBPROP_UPDATABILITY &&
                   V_I8(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) & m_rgproperties[ulIndex].longVal) )
                  break;

               if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
               else
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
               continue;
#endif

            case VT_BSTR:
               if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
                  if( m_rgproperties[ulIndex].dwPropertyID == DBPROP_INIT_DATASOURCE ) {
                     wcsncpy_s(m_wszFilePath, _countof(m_wszFilePath), V_BSTR(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue), MAX_PATH -1);
                     m_rgproperties[ulIndex].pwstrVal = m_wszFilePath;
                  }
                  break;
               }

               if( !(wcscmp(V_BSTR(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue), m_rgproperties[ulIndex].pwstrVal)) )
                  break;

               if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
               else
                  rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
               continue;

            case VT_EMPTY:
               if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE )
                  memcpy(&m_rgproperties[ulIndex], &s_rgprop[ulIndex], sizeof(PROPSTRUCT));
               break;
         }

         // Initialize dwStatus
         rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_OK;
         cValidProps++;
      }
   }
   
   // Figure out the retcode
   if( cValidProps == cCountProps )
      return ResultFromScode( S_OK );
   else if( cValidProps )
      return ResultFromScode( DB_S_ERRORSOCCURRED );
   else 
      return ResultFromScode( DB_E_ERRORSOCCURRED );
}

See Also

Tasks

Writing an OLE DB Provider: An Introduction