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 / property.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-12  |  14.5 KB  |  484 lines

  1. //-----------------------------------------------------------------------------
  2. // Microsoft OLE DB TABLECOPY Sample
  3. // Copyright (C) 1995-1998 Microsoft Corporation
  4. //
  5. // @doc
  6. //
  7. // @module PROPERTY.CPP
  8. //
  9. //-----------------------------------------------------------------------------
  10.  
  11. ////////////////////////////////////////////////////////////////////////
  12. // Includes
  13. //
  14. ////////////////////////////////////////////////////////////////////////
  15. #include "WinMain.h"
  16. #include "Property.h"
  17.  
  18.  
  19.  
  20. /////////////////////////////////////////////////////////////////////////////
  21. // HRESULT GetProperty
  22. //
  23. // Get the property information from the data source or object.
  24. // propid specifies the property and propset specifies the property set to which
  25. // propid belongs. The datatype of the property is required for the correct 
  26. // coercion of the data
  27. /////////////////////////////////////////////////////////////////////////////
  28. HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet,
  29.                    DBPROP** ppProperty)
  30. {
  31.     ASSERT(pIUnknown && ppProperty);
  32.     *ppProperty = NULL;
  33.  
  34.     HRESULT hr = S_OK;
  35.     
  36.     IDBProperties* pIDBProperties = NULL;
  37.     ICommandProperties* pICommandProperties = NULL;
  38.     IRowsetInfo* pIRowsetInfo = NULL;
  39.  
  40.     ULONG        cPropSets = 0;
  41.     DBPROPSET*    rgPropSets = NULL;
  42.         
  43.     const ULONG        cPropertyIDSets = 1;
  44.     DBPROPIDSET        rgPropertyIDSets[cPropertyIDSets];
  45.     
  46.     //SetUp input DBPROPIDSET struct (all static)
  47.     rgPropertyIDSets[0].cPropertyIDs = cPropertyIDSets;
  48.     rgPropertyIDSets[0].rgPropertyIDs = &PropertyID;
  49.     rgPropertyIDSets[0].guidPropertySet = guidPropertySet;
  50.     
  51.     //Need to figure out which Interface was passed in
  52.     //IDBInitialize, or ICommand, or IRowset, all three allow GetProperties
  53.     if(SUCCEEDED(hr = pIUnknown->QueryInterface(IID_IDBProperties,(void **)&pIDBProperties)))
  54.     {
  55.         //GetProperties    
  56.         //Property might not be supported
  57.         hr = pIDBProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
  58.     }
  59.     else if(SUCCEEDED(hr = pIUnknown->QueryInterface(IID_ICommandProperties,(void **)&pICommandProperties)))
  60.     {
  61.         //GetProperties    
  62.         //Property might not be supported
  63.         hr = pICommandProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
  64.     }
  65.     else
  66.     {
  67.         XTESTC(hr = pIUnknown->QueryInterface(IID_IRowsetInfo, (void **)&pIRowsetInfo));
  68.                     
  69.         //GetProperties    
  70.         //Property might not be supported
  71.         hr = pIRowsetInfo->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
  72.     }
  73.         
  74.     //Check return result
  75.     //Can be DB_S_ / DB_E_ERRORSOCCURRED if notsupported property...
  76.     if(FAILED(hr) && hr != DB_E_ERRORSOCCURRED)
  77.         XTESTC(hr);
  78.  
  79.     //Verify results
  80.     CHECKC(cPropSets==1 && rgPropSets!=NULL);
  81.     CHECKC(rgPropSets[0].cProperties==1 && rgPropSets[0].rgProperties!=NULL);
  82.     CHECKC(rgPropSets[0].rgProperties[0].dwPropertyID == PropertyID);
  83.  
  84.     //Return the property to the user
  85.     *ppProperty = rgPropSets[0].rgProperties;
  86.     hr = S_OK;
  87.  
  88. CLEANUP:    
  89.     //Just Free the outer Struct, 
  90.     //since we return the inner Property for the user to free
  91.     SAFE_FREE(rgPropSets);
  92.     
  93.     SAFE_RELEASE(pIDBProperties);
  94.     SAFE_RELEASE(pICommandProperties);
  95.     SAFE_RELEASE(pIRowsetInfo);
  96.     return hr;
  97. }
  98.  
  99. /////////////////////////////////////////////////////////////////////////////
  100. // HRESULT GetProperty
  101. //
  102. /////////////////////////////////////////////////////////////////////////////
  103. HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet,    WCHAR** ppwszValue)
  104. {
  105.     ASSERT(pIUnknown && ppwszValue);
  106.     HRESULT hr;
  107.  
  108.     DBPROP* pProperty = NULL;
  109.     *ppwszValue = NULL;
  110.  
  111.     //Property might not be supported
  112.     hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
  113.  
  114.     //Copy the value
  115.     //GetProperty might return VT_EMPTY for no default string
  116.     if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_BSTR)
  117.         (*ppwszValue) = wcsDuplicate(V_BSTR(&pProperty->vValue));
  118.  
  119.     if(*ppwszValue == NULL)
  120.     {
  121.         SAFE_ALLOC(*ppwszValue, WCHAR, 1);
  122.         (*ppwszValue)[0] = EOL;
  123.     }
  124.  
  125. CLEANUP:
  126.     FreeProperties(1, pProperty);
  127.     return hr;
  128. }
  129.  
  130. /////////////////////////////////////////////////////////////////////////////
  131. // HRESULT GetProperty
  132. //
  133. /////////////////////////////////////////////////////////////////////////////
  134. HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet,    WCHAR* pwszValue)
  135. {
  136.     ASSERT(pIUnknown && pwszValue);
  137.     HRESULT hr;
  138.  
  139.     DBPROP* pProperty = NULL;
  140.     *pwszValue = EOL;
  141.  
  142.     //Might not be supported
  143.     hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
  144.     
  145.     //Copy the value
  146.     //GetProperty might return VT_EMPTY for no default string
  147.     if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_BSTR)
  148.         wcscpy(pwszValue, V_BSTR(&pProperty->vValue));
  149.  
  150.     FreeProperties(1, pProperty);
  151.     return hr;
  152. }
  153.  
  154. /////////////////////////////////////////////////////////////////////////////
  155. // HRESULT GetProperty
  156. //
  157. /////////////////////////////////////////////////////////////////////////////
  158. HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet,    ULONG* pcValue)
  159. {
  160.     ASSERT(pIUnknown && pcValue);
  161.     HRESULT hr;
  162.  
  163.     DBPROP* pProperty = NULL;
  164.     *pcValue = 0;
  165.  
  166.     //Might not be supported
  167.     hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
  168.  
  169.     //Copy the value
  170.     //GetProperty might return VT_EMPTY for no default string
  171.     if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_I4)
  172.         *pcValue = V_I4(&pProperty->vValue);
  173.  
  174.     FreeProperties(1, pProperty);
  175.     return hr;
  176. }
  177.                    
  178. /////////////////////////////////////////////////////////////////////////////
  179. // HRESULT GetProperty
  180. //
  181. /////////////////////////////////////////////////////////////////////////////
  182. HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet,    BOOL* pbValue)
  183. {
  184.     ASSERT(pIUnknown && pbValue);
  185.     HRESULT hr;
  186.  
  187.     DBPROP* pProperty = NULL;
  188.     *pbValue = FALSE;
  189.  
  190.     //Might not be supported
  191.     hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
  192.  
  193.     //Copy the value
  194.     //GetProperty might return VT_EMPTY for no default string
  195.     if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_BOOL)
  196.         *pbValue = V_BOOL(&pProperty->vValue) == VARIANT_TRUE;
  197.  
  198.     FreeProperties(1, pProperty);
  199.     return hr;
  200. }
  201.  
  202.  
  203. /////////////////////////////////////////////////////////////////////////////
  204. // HRESULT GetPropInfo
  205. //
  206. /////////////////////////////////////////////////////////////////////////////
  207. HRESULT GetPropInfo(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet, DBPROPINFO** ppPropInfo)
  208. {
  209.     ASSERT(pIUnknown && ppPropInfo);
  210.     HRESULT hr;
  211.     IDBProperties* pIDBProperties = NULL;
  212.  
  213.     const ULONG cPropIDSets = 1;
  214.     DBPROPIDSET rgPropIDSets[cPropIDSets];
  215.  
  216.     ULONG cPropInfoSets = 0;
  217.     DBPROPINFOSET* rgPropInfoSets = NULL;
  218.     
  219.     //Construct the DBPROPIDSET structure
  220.     rgPropIDSets[0].cPropertyIDs = 1;
  221.     rgPropIDSets[0].rgPropertyIDs = &PropertyID;
  222.     rgPropIDSets[0].guidPropertySet = guidPropertySet;
  223.         
  224.     //Obtain IDBProperties
  225.     XTESTC(hr = pIUnknown->QueryInterface(IID_IDBProperties,(void**)&pIDBProperties));
  226.     
  227.     //Don't display dialog if errors occurred.
  228.     //Errors can occur if properties are not supported by the provider
  229.     QTESTC(hr = pIDBProperties->GetPropertyInfo(cPropIDSets,rgPropIDSets,&cPropInfoSets,&rgPropInfoSets,NULL));
  230.     
  231. CLEANUP:
  232.     *ppPropInfo = rgPropInfoSets ? rgPropInfoSets[0].rgPropertyInfos  : NULL;
  233.      SAFE_FREE(rgPropInfoSets);
  234.     SAFE_RELEASE(pIDBProperties);
  235.     return hr;
  236. }
  237.  
  238.  
  239. /////////////////////////////////////////////////////////////////////////////
  240. // DBPROPFLAGS GetPropInfoFlags
  241. //
  242. /////////////////////////////////////////////////////////////////////////////
  243. DBPROPFLAGS GetPropInfoFlags(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet)
  244. {
  245.     ASSERT(pIUnknown);
  246.     DBPROPINFO* pPropInfo = NULL;
  247.     DBPROPFLAGS dwFlags = DBPROPFLAGS_NOTSUPPORTED;
  248.  
  249.     //GetPropInfo
  250.     QTESTC(GetPropInfo(pIUnknown, PropertyID, guidPropertySet, &pPropInfo))
  251.     if(pPropInfo)
  252.         dwFlags = pPropInfo->dwFlags;
  253.     
  254. CLEANUP:
  255.     SAFE_FREE(pPropInfo);
  256.     return dwFlags; 
  257. }
  258.  
  259.  
  260. /////////////////////////////////////////////////////////////////////////////
  261. // BOOL IsSupportedProperty
  262. //
  263. /////////////////////////////////////////////////////////////////////////////
  264. BOOL IsSupportedProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet)
  265. {
  266.     return GetPropInfoFlags(pIUnknown, PropertyID, guidPropertySet) != DBPROPFLAGS_NOTSUPPORTED;
  267. }
  268.  
  269.  
  270. /////////////////////////////////////////////////////////////////////////////
  271. // BOOL IsSettableProperty
  272. //
  273. /////////////////////////////////////////////////////////////////////////////
  274. BOOL IsSettableProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet)
  275. {
  276.     return GetPropInfoFlags(pIUnknown, PropertyID, guidPropertySet) & DBPROPFLAGS_WRITE;
  277. }
  278.  
  279.  
  280. /////////////////////////////////////////////////////////////////////////////
  281. // HRESULT SetProperty
  282. //
  283. /////////////////////////////////////////////////////////////////////////////
  284. HRESULT SetProperty(DBPROPID PropertyID, GUID guidPropertySet, ULONG* pcPropSets, DBPROPSET** prgPropSets, DBTYPE wType, ULONG ulValue, DBPROPOPTIONS dwOptions, DBID colid)
  285. {
  286.     if(wType == DBTYPE_BOOL)
  287.         ulValue = ulValue ? VARIANT_TRUE : VARIANT_FALSE;
  288.     return SetProperty(PropertyID, guidPropertySet, pcPropSets, prgPropSets, wType, &ulValue, dwOptions, colid);
  289. }
  290.  
  291.  
  292. /////////////////////////////////////////////////////////////////////////////
  293. // HRESULT SetProperty
  294. //
  295. /////////////////////////////////////////////////////////////////////////////
  296. HRESULT SetProperty(DBPROPID PropertyID, GUID guidPropertySet, ULONG* pcPropSets, DBPROPSET** prgPropSets, DBTYPE wType, void* pv, DBPROPOPTIONS dwOptions, DBID colid)
  297. {
  298.     ASSERT(PropertyID && prgPropSets && pcPropSets && pv);
  299.     HRESULT hr = S_OK;
  300.  
  301.     ULONG cProperties = 0;
  302.     DBPROP* rgProperties = NULL;
  303.  
  304.     //Make our lives a little easier
  305.     ULONG cPropSets = *pcPropSets;
  306.     DBPROPSET* rgPropSets = *prgPropSets;
  307.     
  308.     ULONG iPropSet = ULONG_MAX;
  309.     
  310.     //Find the correct PropSet structure to add the property to
  311.     for(ULONG i=0; i<cPropSets; i++)
  312.         if(guidPropertySet == rgPropSets[i].guidPropertySet)
  313.             iPropSet = i;
  314.  
  315.     //Do we need to create another PropSets structure for this property
  316.     if(iPropSet==ULONG_MAX)
  317.     {
  318.         iPropSet = cPropSets;
  319.         SAFE_REALLOC(rgPropSets, DBPROPSET, cPropSets+1);
  320.         rgPropSets[iPropSet].cProperties = 0;
  321.         rgPropSets[iPropSet].rgProperties = NULL;
  322.         rgPropSets[iPropSet].guidPropertySet = guidPropertySet;
  323.         cPropSets++;
  324.     }
  325.  
  326.     //Now make our lives really easy
  327.     cProperties = rgPropSets[iPropSet].cProperties;
  328.     rgProperties = rgPropSets[iPropSet].rgProperties;
  329.  
  330.     //do we need to enlarge the list
  331.     SAFE_REALLOC(rgProperties, DBPROP, cProperties+1);
  332.     
  333.     //Add the new property to the list
  334.     rgProperties[cProperties].dwPropertyID = PropertyID;
  335.     rgProperties[cProperties].dwOptions    = dwOptions;
  336.     rgProperties[cProperties].dwStatus     = DBPROPSTATUS_OK;
  337.     rgProperties[cProperties].colid        = colid;
  338.     VariantInit(&rgProperties[cProperties].vValue);
  339.  
  340.     switch(wType)
  341.     {
  342.         case DBTYPE_BOOL:
  343.             rgProperties[cProperties].vValue.vt          = VT_BOOL;
  344.             V_BOOL(&(rgProperties[cProperties].vValue))  = *(VARIANT_BOOL*)pv;
  345.             break;
  346.         
  347.         case DBTYPE_I2:
  348.             rgProperties[cProperties].vValue.vt            = VT_I2;
  349.             V_I2(&(rgProperties[cProperties].vValue))    = *(SHORT*)pv;
  350.             break;
  351.  
  352.         case DBTYPE_I4:
  353.             rgProperties[cProperties].vValue.vt            = VT_I4;
  354.             V_I4(&(rgProperties[cProperties].vValue))    = *(LONG*)pv;
  355.             break;
  356.     
  357.         case DBTYPE_WSTR:
  358.         case DBTYPE_BSTR:
  359.             rgProperties[cProperties].vValue.vt          = VT_BSTR;
  360.             V_BSTR(&(rgProperties[cProperties].vValue))  = SysAllocString((BSTR)pv);
  361.             break;
  362.  
  363.         case DBTYPE_VARIANT:
  364.             VariantCopy(&rgProperties[cProperties].vValue, (VARIANT*)pv);
  365.             break;
  366.  
  367.         default:
  368.             ASSERT(FALSE); //Unhandled property type
  369.             break;
  370.     }
  371.  
  372.     //Increment the number of properties
  373.     cProperties++;
  374.  
  375. CLEANUP:
  376.     //Now go back to the rediculous property structures
  377.     rgPropSets[iPropSet].cProperties  = cProperties;
  378.     rgPropSets[iPropSet].rgProperties = rgProperties;
  379.     *pcPropSets = cPropSets;
  380.     *prgPropSets = rgPropSets;
  381.     return hr;
  382. }
  383.  
  384.  
  385. /////////////////////////////////////////////////////////////////////////////
  386. // HRESULT SetRestriction
  387. //
  388. /////////////////////////////////////////////////////////////////////////////
  389. HRESULT SetRestriction(VARIANT* pRestriction, WCHAR* pwszValue)
  390. {
  391.     ASSERT(pRestriction);
  392.     ASSERT(pwszValue);
  393.     
  394.     //VT_BSTR case
  395.     if(pwszValue && pwszValue[0])
  396.     {
  397.         pRestriction->vt = VT_BSTR;
  398.         SAFE_SYSALLOC(V_BSTR(pRestriction), pwszValue);
  399.     }
  400.  
  401. CLEANUP:
  402.     return S_OK;
  403. }
  404.     
  405.  
  406. /////////////////////////////////////////////////////////////////////////////
  407. // HRESULT InitVariants
  408. //
  409. /////////////////////////////////////////////////////////////////////////////
  410. HRESULT InitVariants(ULONG cVariants, VARIANT* rgVariants)
  411. {
  412.     HRESULT hr = S_OK;
  413.  
  414.     //Free all variants
  415.     for(ULONG i=0; i<cVariants; i++)
  416.         VariantInit(&rgVariants[i]);
  417.     
  418.     return hr;
  419. }
  420.  
  421.  
  422. /////////////////////////////////////////////////////////////////////////////
  423. // HRESULT FreeVariants
  424. //
  425. /////////////////////////////////////////////////////////////////////////////
  426. HRESULT FreeVariants(ULONG cVariants, VARIANT* rgVariants)
  427. {
  428.     HRESULT hr = S_OK;
  429.  
  430.     //Free the inner variants first
  431.     for(ULONG i=0; i<cVariants; i++)
  432.         XTEST(hr = VariantClear(&rgVariants[i]));
  433.     
  434.     return hr;
  435. }
  436.  
  437.  
  438. /////////////////////////////////////////////////////////////////////////////
  439. // HRESULT FreeProperties
  440. //
  441. /////////////////////////////////////////////////////////////////////////////
  442. HRESULT FreeProperties(ULONG cProperties, DBPROP* rgProperties)
  443. {
  444.     HRESULT hr = S_OK;
  445.     
  446.     //no-op case
  447.     if(cProperties==0 || rgProperties==NULL)
  448.         return S_OK;
  449.     
  450.     //Free the inner variants first
  451.     for(ULONG i=0; i<cProperties; i++)
  452.     {
  453.         //if DBPROPSTATUS_NOTSUPPORTED then vValue is undefined
  454.         if(rgProperties[i].dwStatus != DBPROPSTATUS_NOTSUPPORTED)
  455.             XTEST(hr = VariantClear(&rgProperties[i].vValue));
  456.     }
  457.     
  458.     //Now free the set
  459.     SAFE_FREE(rgProperties);
  460.     return hr;
  461. }
  462.  
  463. /////////////////////////////////////////////////////////////////////////////
  464. // HRESULT FreeProperties
  465. //
  466. /////////////////////////////////////////////////////////////////////////////
  467. HRESULT FreeProperties(ULONG cPropSets, DBPROPSET* rgPropSets)
  468. {
  469.     HRESULT hr = S_OK;
  470.     
  471.     //Loop over all the property sets
  472.     for(ULONG i=0; i<cPropSets; i++)
  473.         FreeProperties(rgPropSets[i].cProperties, rgPropSets[i].rgProperties);
  474.         
  475.     //Now free the outer set
  476.     SAFE_FREE(rgPropSets);
  477.     return hr;
  478. }
  479.  
  480.  
  481.  
  482.  
  483.  
  484.