2025-11-28 00:35:46 +09:00

489 lines
15 KiB
C++

//-----------------------------------------------------------------------------
// Microsoft OLE DB TABLECOPY Sample
// Copyright (C) 1991-2000 Microsoft Corporation
//
// @doc
//
// @module PROPERTY.CPP
//
//-----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
// Includes
//
////////////////////////////////////////////////////////////////////////
#include "WinMain.h"
#include "Property.h"
/////////////////////////////////////////////////////////////////////////////
// HRESULT GetProperty
//
// Get the property information from the data source or object.
// propid specifies the property and propset specifies the property set to which
// propid belongs. The datatype of the property is required for the correct
// coercion of the data
/////////////////////////////////////////////////////////////////////////////
HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet,
DBPROP** ppProperty)
{
ASSERT(pIUnknown && ppProperty);
*ppProperty = NULL;
HRESULT hr = S_OK;
IDBProperties* pIDBProperties = NULL;
ICommandProperties* pICommandProperties = NULL;
IRowsetInfo* pIRowsetInfo = NULL;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
const ULONG cPropertyIDSets = 1;
DBPROPIDSET rgPropertyIDSets[cPropertyIDSets];
//SetUp input DBPROPIDSET struct (all static)
rgPropertyIDSets[0].cPropertyIDs = cPropertyIDSets;
rgPropertyIDSets[0].rgPropertyIDs = &PropertyID;
rgPropertyIDSets[0].guidPropertySet = guidPropertySet;
//Need to figure out which Interface was passed in
//IDBInitialize, or ICommand, or IRowset, all three allow GetProperties
if(SUCCEEDED(hr = pIUnknown->QueryInterface(IID_IDBProperties,(void **)&pIDBProperties)))
{
//GetProperties
//Property might not be supported
hr = pIDBProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
}
else if(SUCCEEDED(hr = pIUnknown->QueryInterface(IID_ICommandProperties,(void **)&pICommandProperties)))
{
//GetProperties
//Property might not be supported
hr = pICommandProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
}
else
{
XTESTC(hr = pIUnknown->QueryInterface(IID_IRowsetInfo, (void **)&pIRowsetInfo));
//GetProperties
//Property might not be supported
hr = pIRowsetInfo->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets);
}
//Check return result
//Can be DB_S_ / DB_E_ERRORSOCCURRED if notsupported property...
if(FAILED(hr) && hr != DB_E_ERRORSOCCURRED)
XTESTC(hr);
//Verify results
CHECKC(cPropSets==1 && rgPropSets!=NULL);
CHECKC(rgPropSets[0].cProperties==1 && rgPropSets[0].rgProperties!=NULL);
CHECKC(rgPropSets[0].rgProperties[0].dwPropertyID == PropertyID);
//Return the property to the user
*ppProperty = rgPropSets[0].rgProperties;
hr = S_OK;
CLEANUP:
//Just Free the outer Struct,
//since we return the inner Property for the user to free
SAFE_FREE(rgPropSets);
SAFE_RELEASE(pIDBProperties);
SAFE_RELEASE(pICommandProperties);
SAFE_RELEASE(pIRowsetInfo);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT GetProperty
//
/////////////////////////////////////////////////////////////////////////////
HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet, WCHAR** ppwszValue)
{
ASSERT(pIUnknown && ppwszValue);
HRESULT hr;
DBPROP* pProperty = NULL;
*ppwszValue = NULL;
//Property might not be supported
hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
//Copy the value
//GetProperty might return VT_EMPTY for no default string
if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_BSTR)
(*ppwszValue) = wcsDuplicate(V_BSTR(&pProperty->vValue));
if(*ppwszValue == NULL)
{
SAFE_ALLOC(*ppwszValue, WCHAR, 1);
(*ppwszValue)[0] = EOL;
}
CLEANUP:
FreeProperties(1, pProperty);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT GetProperty
//
/////////////////////////////////////////////////////////////////////////////
HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet, WCHAR* pwszValue, size_t cwchValue)
{
ASSERT(pIUnknown && pwszValue);
HRESULT hr;
DBPROP* pProperty = NULL;
*pwszValue = EOL;
//Might not be supported
hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
//Copy the value
//GetProperty might return VT_EMPTY for no default string
if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_BSTR)
StringCchCopyW(pwszValue, cwchValue, V_BSTR(&pProperty->vValue));
FreeProperties(1, pProperty);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT GetProperty
//
/////////////////////////////////////////////////////////////////////////////
HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet, ULONG* pcValue)
{
ASSERT(pIUnknown && pcValue);
HRESULT hr;
DBPROP* pProperty = NULL;
*pcValue = 0;
//Might not be supported
hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
//Copy the value
//GetProperty might return VT_EMPTY for no default string
if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_I4)
*pcValue = V_I4(&pProperty->vValue);
FreeProperties(1, pProperty);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT GetProperty
//
/////////////////////////////////////////////////////////////////////////////
HRESULT GetProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet, BOOL* pbValue)
{
ASSERT(pIUnknown && pbValue);
HRESULT hr;
DBPROP* pProperty = NULL;
*pbValue = FALSE;
//Might not be supported
hr = GetProperty(pIUnknown, PropertyID, guidPropertySet, &pProperty);
//Copy the value
//GetProperty might return VT_EMPTY for no default string
if(SUCCEEDED(hr) && pProperty && pProperty->vValue.vt == VT_BOOL)
*pbValue = V_BOOL(&pProperty->vValue) == VARIANT_TRUE;
FreeProperties(1, pProperty);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT GetPropInfo
//
/////////////////////////////////////////////////////////////////////////////
HRESULT GetPropInfo(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet, DBPROPINFO** ppPropInfo)
{
ASSERT(pIUnknown && ppPropInfo);
HRESULT hr;
IDBProperties* pIDBProperties = NULL;
const ULONG cPropIDSets = 1;
DBPROPIDSET rgPropIDSets[cPropIDSets];
ULONG cPropInfoSets = 0;
DBPROPINFOSET* rgPropInfoSets = NULL;
//Construct the DBPROPIDSET structure
rgPropIDSets[0].cPropertyIDs = 1;
rgPropIDSets[0].rgPropertyIDs = &PropertyID;
rgPropIDSets[0].guidPropertySet = guidPropertySet;
//Obtain IDBProperties
XTESTC(hr = pIUnknown->QueryInterface(IID_IDBProperties,(void**)&pIDBProperties));
//Don't display dialog if errors occurred.
//Errors can occur if properties are not supported by the provider
QTESTC(hr = pIDBProperties->GetPropertyInfo(cPropIDSets,rgPropIDSets,&cPropInfoSets,&rgPropInfoSets,NULL));
CLEANUP:
*ppPropInfo = rgPropInfoSets ? rgPropInfoSets[0].rgPropertyInfos : NULL;
SAFE_FREE(rgPropInfoSets);
SAFE_RELEASE(pIDBProperties);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// DBPROPFLAGS GetPropInfoFlags
//
/////////////////////////////////////////////////////////////////////////////
DBPROPFLAGS GetPropInfoFlags(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet)
{
ASSERT(pIUnknown);
DBPROPINFO* pPropInfo = NULL;
DBPROPFLAGS dwFlags = DBPROPFLAGS_NOTSUPPORTED;
//GetPropInfo
QTESTC(GetPropInfo(pIUnknown, PropertyID, guidPropertySet, &pPropInfo))
if(pPropInfo)
dwFlags = pPropInfo->dwFlags;
CLEANUP:
SAFE_FREE(pPropInfo);
return dwFlags;
}
/////////////////////////////////////////////////////////////////////////////
// BOOL IsSupportedProperty
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsSupportedProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet)
{
return GetPropInfoFlags(pIUnknown, PropertyID, guidPropertySet) != DBPROPFLAGS_NOTSUPPORTED;
}
/////////////////////////////////////////////////////////////////////////////
// BOOL IsSettableProperty
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsSettableProperty(IUnknown* pIUnknown, DBPROPID PropertyID, GUID guidPropertySet)
{
return GetPropInfoFlags(pIUnknown, PropertyID, guidPropertySet) & DBPROPFLAGS_WRITE;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT SetProperty
//
/////////////////////////////////////////////////////////////////////////////
HRESULT SetProperty(DBPROPID PropertyID, GUID guidPropertySet, ULONG* pcPropSets, DBPROPSET** prgPropSets, DBTYPE wType, ULONG_PTR ulValue, DBPROPOPTIONS dwOptions, DBID colid)
{
if(wType == DBTYPE_BOOL)
ulValue = ulValue ? VARIANT_TRUE : VARIANT_FALSE;
return SetProperty(PropertyID, guidPropertySet, pcPropSets, prgPropSets, wType, &ulValue, dwOptions, colid);
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT SetProperty
//
/////////////////////////////////////////////////////////////////////////////
HRESULT SetProperty(DBPROPID PropertyID, GUID guidPropertySet, ULONG* pcPropSets, DBPROPSET** prgPropSets, DBTYPE wType, void* pv, DBPROPOPTIONS dwOptions, DBID colid)
{
ASSERT(PropertyID && prgPropSets && pcPropSets && pv);
HRESULT hr = S_OK;
ULONG cProperties = 0;
DBPROP* rgProperties = NULL;
//Make our lives a little easier
ULONG cPropSets = *pcPropSets;
DBPROPSET* rgPropSets = *prgPropSets;
ULONG iPropSet = ULONG_MAX;
//Find the correct PropSet structure to add the property to
for(ULONG i=0; i<cPropSets; i++)
if(guidPropertySet == rgPropSets[i].guidPropertySet)
iPropSet = i;
//Do we need to create another PropSets structure for this property
if(iPropSet==ULONG_MAX)
{
iPropSet = cPropSets;
SAFE_REALLOC(rgPropSets, DBPROPSET, cPropSets+1);
rgPropSets[iPropSet].cProperties = 0;
rgPropSets[iPropSet].rgProperties = NULL;
rgPropSets[iPropSet].guidPropertySet = guidPropertySet;
cPropSets++;
}
//Now make our lives really easy
cProperties = rgPropSets[iPropSet].cProperties;
rgProperties = rgPropSets[iPropSet].rgProperties;
//do we need to enlarge the list
SAFE_REALLOC(rgProperties, DBPROP, cProperties+1);
//Add the new property to the list
rgProperties[cProperties].dwPropertyID = PropertyID;
rgProperties[cProperties].dwOptions = dwOptions;
rgProperties[cProperties].dwStatus = DBPROPSTATUS_OK;
rgProperties[cProperties].colid = colid;
VariantInit(&rgProperties[cProperties].vValue);
switch(wType)
{
case DBTYPE_BOOL:
rgProperties[cProperties].vValue.vt = VT_BOOL;
V_BOOL(&(rgProperties[cProperties].vValue)) = *(VARIANT_BOOL*)pv;
break;
case DBTYPE_I2:
rgProperties[cProperties].vValue.vt = VT_I2;
V_I2(&(rgProperties[cProperties].vValue)) = *(SHORT*)pv;
break;
case DBTYPE_I4:
rgProperties[cProperties].vValue.vt = VT_I4;
V_I4(&(rgProperties[cProperties].vValue)) = *(LONG*)pv;
break;
case DBTYPE_I8:
rgProperties[cProperties].vValue.vt = VT_I8;
V_I8(&(rgProperties[cProperties].vValue)) = *(LONG_PTR*)pv;
break;
case DBTYPE_WSTR:
case DBTYPE_BSTR:
rgProperties[cProperties].vValue.vt = VT_BSTR;
V_BSTR(&(rgProperties[cProperties].vValue)) = SysAllocString((BSTR)pv);
break;
case DBTYPE_VARIANT:
VariantCopy(&rgProperties[cProperties].vValue, (VARIANT*)pv);
break;
default:
ASSERT(FALSE); //Unhandled property type
break;
}
//Increment the number of properties
cProperties++;
CLEANUP:
//Now go back to the rediculous property structures
rgPropSets[iPropSet].cProperties = cProperties;
rgPropSets[iPropSet].rgProperties = rgProperties;
*pcPropSets = cPropSets;
*prgPropSets = rgPropSets;
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT SetRestriction
//
/////////////////////////////////////////////////////////////////////////////
HRESULT SetRestriction(VARIANT* pRestriction, WCHAR* pwszValue)
{
ASSERT(pRestriction);
ASSERT(pwszValue);
//VT_BSTR case
if(pwszValue && pwszValue[0])
{
pRestriction->vt = VT_BSTR;
SAFE_SYSALLOC(V_BSTR(pRestriction), pwszValue);
}
CLEANUP:
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT InitVariants
//
/////////////////////////////////////////////////////////////////////////////
HRESULT InitVariants(ULONG cVariants, VARIANT* rgVariants)
{
HRESULT hr = S_OK;
//Free all variants
for(ULONG i=0; i<cVariants; i++)
VariantInit(&rgVariants[i]);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT FreeVariants
//
/////////////////////////////////////////////////////////////////////////////
HRESULT FreeVariants(ULONG cVariants, VARIANT* rgVariants)
{
HRESULT hr = S_OK;
//Free the inner variants first
for(ULONG i=0; i<cVariants; i++)
XTEST(hr = VariantClear(&rgVariants[i]));
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT FreeProperties
//
/////////////////////////////////////////////////////////////////////////////
HRESULT FreeProperties(ULONG cProperties, DBPROP* rgProperties)
{
HRESULT hr = S_OK;
//no-op case
if(cProperties==0 || rgProperties==NULL)
return S_OK;
//Free the inner variants first
for(ULONG i=0; i<cProperties; i++)
{
//if DBPROPSTATUS_NOTSUPPORTED then vValue is undefined
if(rgProperties[i].dwStatus != DBPROPSTATUS_NOTSUPPORTED)
XTEST(hr = VariantClear(&rgProperties[i].vValue));
}
//Now free the set
SAFE_FREE(rgProperties);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// HRESULT FreeProperties
//
/////////////////////////////////////////////////////////////////////////////
HRESULT FreeProperties(ULONG cPropSets, DBPROPSET* rgPropSets)
{
HRESULT hr = S_OK;
//Loop over all the property sets
for(ULONG i=0; i<cPropSets; i++)
FreeProperties(rgPropSets[i].cProperties, rgPropSets[i].rgProperties);
//Now free the outer set
SAFE_FREE(rgPropSets);
return hr;
}