windows-nt/Source/XPSP1/NT/ds/adsi/router/binder.cxx

1316 lines
58 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// Binder.cpp : Implementation of CBinder
#include "oleds.hxx"
#if (!defined(BUILD_FOR_NT40))
#include "atl.h"
#include "binder.hxx"
#include "row.hxx"
//property description constants
const PWSTR DESC_DBPROP_INIT_LCID = L"Location ID";
const PWSTR DESC_DBPROP_INIT_MODE = L"Mode";
const PWSTR DESC_DBPROP_INIT_BINDFLAGS = L"Bind Flags";
const PWSTR DESC_DBPROP_INIT_LOCKOWNER = L"Lock Owner";
const PWSTR DESC_DBPROP_USERID = L"User ID";
const PWSTR DESC_DBPROP_PASSWORD = L"Password";
const PWSTR DESC_DBPROP_ENCRYPT_PASSWORD = L"Encrypt Password";
#define DEFAULT_DBPROP_INIT_MODE DB_MODE_READ
/////////////////////////////////////////////////////////////////////////////
// CBinder
//ISupportErrorInfo methods
//+---------------------------------------------------------------------------
//
// Function: CBinder::InterfaceSupportsErrorInfo
//
// Synopsis: Given an interface ID, tells if that interface supports
// the interface ISupportErrorInfo
//
// Arguments:
// REFIID riid
//
// Returns:
// S_OK yes, the interface supports ISupportErrorInfo
// S_FALSE no, the interface doesn't support it.
//----------------------------------------------------------------------------
STDMETHODIMP CBinder::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IBindResource, &IID_IDBBinderProperties
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
RRETURN(S_OK);
}
RRETURN(S_FALSE);
}
//IBindResource methods
//+---------------------------------------------------------------------------
//
// Function: CBinder::Bind
//
// Synopsis: Binds to a row or rowset object given a URL.
//
// For more info see OLE DB 2.5 spec.
//----------------------------------------------------------------------------
STDMETHODIMP CBinder::Bind(
IUnknown * punkOuter,
LPCOLESTR pwszURL,
DBBINDURLFLAG dwBindFlags,
REFGUID rguid,
REFIID riid,
IAuthenticate * pAuthenticate,
DBIMPLICITSESSION * pImplSession,
DWORD * pdwBindStatus,
IUnknown ** ppUnk
)
{
HRESULT hr = S_OK;
TRYBLOCK
//if caller passed a null value for dwBindFlags,
//get them from initialization properties.
if (dwBindFlags == 0)
dwBindFlags = BindFlagsFromDbProps();
//Forward the Bind call to CSessionObject for actual binding
ADsAssert(m_pSession);
hr = m_pSession->Bind(punkOuter, pwszURL, dwBindFlags, rguid, riid,
pAuthenticate, pImplSession, pdwBindStatus, ppUnk);
if (FAILED(hr))
RRETURN(hr);
CATCHBLOCKRETURN
RRETURN(hr);
}
//IDBBinderProperties : IDBProperties
//(most of this code has been copied form exoledb and reorganized).
//IDBProperties
//+---------------------------------------------------------------------------
//
// Function: CBinder::GetProperties
//
// Synopsis: Gets the requested Binder properties
//
// For more info see OLE DB 2.1 spec.
//----------------------------------------------------------------------------
STDMETHODIMP CBinder::GetProperties(
ULONG cPropertySets,
const DBPROPIDSET rgPropertySets[ ],
ULONG *pcPropertySets,
DBPROPSET **prgPropertySets)
{
BOOL fPropInError, fSpecialSets, fCopy = FALSE;
HRESULT hr = S_OK;
LONG ipropset =0, iprop =0;
ULONG cprop = 0, cpropError =0, ipropT;
DBPROPSET *rgPropertySetsOutput = NULL, *ppropset = NULL;
DBPROP *pprop;
auto_leave cs_auto_leave(m_autocs);
TRYBLOCK
//Let property manager object check and init the arguments
hr = m_dbProperties.CheckAndInitPropArgs(cPropertySets,
rgPropertySets,
pcPropertySets,
(void **)prgPropertySets,
&fPropInError,
&fSpecialSets);
//if all the requested sets are special,
//we just return error because this method
//doesn't support special sets. Otherwise,
//we attempt to return information about other
//non-special sets.
if(fSpecialSets && SUCCEEDED(hr))
RRETURN(DB_E_ERRORSOCCURRED);
else if(!fSpecialSets && FAILED(hr))
RRETURN(hr);
cs_auto_leave.EnterCriticalSection();
//if cPropertySets is zero, return INIT property set.
if(cPropertySets == 0)
{
cPropertySets = 1;
fCopy = TRUE;
}
//or if DBPROPSET_PROPERTIESINERROR is requested,
//check for invalid status values
else if(fPropInError)
{
ppropset = m_dbProperties.GetPropertySet(DBPROPSET_DBINIT);
for(iprop = 0, cpropError = 0;
(ULONG)iprop < ppropset->cProperties;
iprop++)
if( ppropset->rgProperties[iprop].dwStatus != DBPROPSTATUS_OK )
cpropError++;
}
//Allocate memory for returning property sets.
rgPropertySetsOutput =
(DBPROPSET *)CoTaskMemAlloc(cPropertySets *sizeof(DBPROPSET));
if (!rgPropertySetsOutput)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
//If properties in error were requested, look for all properties
//with invalid status values and return the info.
if(fPropInError)
{
if(cpropError)
{
rgPropertySetsOutput[0].rgProperties
=(DBPROP *)CoTaskMemAlloc(cpropError *sizeof(DBPROP));
if(rgPropertySetsOutput[0].rgProperties == NULL)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
rgPropertySetsOutput[0].guidPropertySet = DBPROPSET_DBINIT;
for(ipropT =0, iprop =0;
ipropT <ppropset->cProperties;
ipropT++)
if( ppropset->rgProperties[ipropT].dwStatus
!= DBPROPSTATUS_OK )
{
memcpy(&(rgPropertySetsOutput[0].rgProperties[iprop]),
&(ppropset->rgProperties[ipropT]),
sizeof(DBPROP));
VariantInit(
&(rgPropertySetsOutput[0].rgProperties[iprop].vValue));
hr = VariantCopy(
&(rgPropertySetsOutput[0].rgProperties[iprop].vValue),
&(ppropset->rgProperties[ipropT].vValue));
BAIL_ON_FAILURE(hr);
iprop++;
}
}
else
rgPropertySetsOutput[0].rgProperties = NULL;
rgPropertySetsOutput[0].cProperties = cpropError;
cpropError =0;
}
//if fCopy is set, copy the init property set to the return array
else if(fCopy)
{
for (ipropset=0; (ULONG)ipropset<cPropertySets; ++ipropset)
{
hr = m_dbProperties.CopyPropertySet(
ipropset, &rgPropertySetsOutput[ipropset]);
BAIL_ON_FAILURE(hr);
}
}
//caller requested for some regular property sets
//return the info.
else
{
//copy passed in information from rgPropertySets
//to output array.
memcpy(rgPropertySetsOutput,
rgPropertySets,
cPropertySets *sizeof(DBPROPSET));
//cycle thru each property set, get properties
//allocate necessary memory and assign values.
for(ipropset = 0, cprop = 0, cpropError =0;
(ULONG)ipropset<cPropertySets;
ipropset++)
{
ppropset = m_dbProperties.GetPropertySet(
rgPropertySets[ipropset].guidPropertySet);
if(rgPropertySets[ipropset].cPropertyIDs)
{
iprop =0;
cprop += rgPropertySets[ipropset].cPropertyIDs;
//Allocate memory for all the propertyIDs in this set.
rgPropertySetsOutput[ipropset].rgProperties =
(DBPROP *) CoTaskMemAlloc(
rgPropertySets[ipropset].cPropertyIDs *sizeof(DBPROP));
if(rgPropertySetsOutput[ipropset].rgProperties == NULL)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
//zero memory
memset( rgPropertySetsOutput[ipropset].rgProperties,
0x00,
rgPropertySets[ipropset].cPropertyIDs *sizeof(DBPROP));
//DBPROPSET_DATASOURCEINFO is not valid on this object.
if( ppropset == NULL ||
(rgPropertySets[ipropset].guidPropertySet ==
DBPROPSET_DATASOURCEINFO)
)
{
cpropError += rgPropertySets[ipropset].cPropertyIDs;
for(;
(ULONG)iprop<rgPropertySets[ipropset].cPropertyIDs;
iprop++
)
{
rgPropertySetsOutput[ipropset].
rgProperties[iprop].dwPropertyID
= rgPropertySets[ipropset].rgPropertyIDs[iprop];
rgPropertySetsOutput[ipropset].
rgProperties[iprop].dwStatus =
DBPROPSTATUS_NOTSUPPORTED;
}
continue; //continue with next property set.
}
//we have a valid property set. Cycle thru each
//property and assign values in output array.
for(;
(ULONG)iprop < rgPropertySets[ipropset].cPropertyIDs;
iprop++
)
{
pprop = (DBPROP *)m_dbProperties.GetProperty(
rgPropertySets[ipropset].guidPropertySet,
rgPropertySets[ipropset].rgPropertyIDs[iprop]);
if(pprop)
{
rgPropertySetsOutput[ipropset].rgProperties[iprop]
= *pprop;
VariantInit(
&(rgPropertySetsOutput[ipropset].
rgProperties[iprop].vValue));
hr = VariantCopy(
&(rgPropertySetsOutput[ipropset].
rgProperties[iprop].vValue),
&(pprop->vValue));
BAIL_ON_FAILURE(hr);
}
//If unable to get property, set dwStatus
else
{
cpropError++;
rgPropertySetsOutput[ipropset].
rgProperties[iprop].dwPropertyID =
rgPropertySets[ipropset].rgPropertyIDs[iprop];
rgPropertySetsOutput[ipropset].
rgProperties[iprop].dwStatus =
DBPROPSTATUS_NOTSUPPORTED;
}
}
}
else //no propertyIDs requested for this set
{
rgPropertySetsOutput[ipropset].rgProperties = NULL;
//DBPROPSET_DATASOURCEINFO is invalid for this object.
//Return error if it is the one requested.
if(ppropset == NULL ||
(rgPropertySets[ipropset].guidPropertySet ==
DBPROPSET_DATASOURCEINFO)
)
{
cprop++;
cpropError++;
}
else //otherwise, copy all propertyIDs
{
hr = m_dbProperties.CopyPropertySet(
rgPropertySets[ipropset].guidPropertySet,
&rgPropertySetsOutput[ipropset]);
BAIL_ON_FAILURE(hr);
}
}
} //for (ipropset = 0....
}
CATCHBLOCKBAIL(hr)
ADsAssert(pcPropertySets && prgPropertySets);
*pcPropertySets = cPropertySets;
*prgPropertySets = rgPropertySetsOutput;
hr = cpropError ?
((cpropError < cprop) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED)
: S_OK;
RRETURN(hr);
error:
while(ipropset >= 0)
{
while(--iprop >= 0)
VariantClear(
&(rgPropertySetsOutput[ipropset].rgProperties[iprop].vValue));
if( rgPropertySetsOutput
&& rgPropertySetsOutput[ipropset].cProperties
&& rgPropertySetsOutput[ipropset].rgProperties)
CoTaskMemFree(rgPropertySetsOutput[ipropset].rgProperties);
ipropset--;
}
if(rgPropertySetsOutput)
CoTaskMemFree(rgPropertySetsOutput);
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CBinder::GetPropertyInfo
//
// Synopsis: Gets information about requested properties
//
// For more info see OLE DB 2.1 spec.
//----------------------------------------------------------------------------
STDMETHODIMP CBinder::GetPropertyInfo(
ULONG cPropertySets,
const DBPROPIDSET rgPropertySets[ ],
ULONG *pcPropertyInfoSets,
DBPROPINFOSET **prgPropertyInfoSets,
OLECHAR **ppDescBuffer)
{
HRESULT hr;
BOOL fPropInError, fSpecialSets, fCopy =FALSE;
ULONG ipropset = 0, iprop, cProperty, cprop = 0, cpropError=0;
ULONG_PTR cchDescBuffer, ichDescBuffer;
DBPROPINFOSET *rgPropertyInfoSetsOutput = NULL, *ppropinfoset;
const DBPROPINFO UNALIGNED *pdbpropinfoSrc;
PDBPROPINFO pdbpropinfo;
auto_leave cs_auto_leave(m_autocs);
TRYBLOCK
if(ppDescBuffer)
{
*ppDescBuffer = NULL;
cchDescBuffer = 0;
ichDescBuffer = 0;
}
//Let the property manager object check and init arguments
hr = m_dbProperties.CheckAndInitPropArgs(cPropertySets,
rgPropertySets,
pcPropertyInfoSets,
(void **)prgPropertyInfoSets,
&fPropInError,
&fSpecialSets);
if(FAILED(hr))
RRETURN(hr);
else if(fPropInError)
RRETURN(E_INVALIDARG);
cs_auto_leave.EnterCriticalSection();
//if cPropertySets is zero, return INIT property set info
if(cPropertySets == 0)
{
cPropertySets = 1;
fCopy = TRUE;
}
rgPropertyInfoSetsOutput = (DBPROPINFOSET *)
CoTaskMemAlloc(cPropertySets*sizeof(DBPROPINFOSET));
if (!rgPropertyInfoSetsOutput)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
if(fCopy)
{
for (ipropset=0; ipropset <cPropertySets; ++ipropset)
{
hr = m_dbProperties.CopyPropertyInfoSet(
ipropset,
&rgPropertyInfoSetsOutput[ipropset],
ppDescBuffer,
&cchDescBuffer,
&ichDescBuffer);
if (FAILED(hr))
break;
}
BAIL_ON_FAILURE(hr);
}
else
{
//copy passed in property set info to output array.
memcpy( rgPropertyInfoSetsOutput,
rgPropertySets,
cPropertySets *sizeof(DBPROPSET));
//Cycle thru each requested property set
for(ipropset=0, cprop =0; ipropset<cPropertySets; ipropset++)
{
iprop =0;
//Handle each special set
if( rgPropertySets[ipropset].guidPropertySet ==
DBPROPSET_DBINITALL)
{
cprop++;
hr = m_dbProperties.CopyPropertyInfoSet(DBPROPSET_DBINIT,
&rgPropertyInfoSetsOutput[ipropset],
ppDescBuffer,
&cchDescBuffer,
&ichDescBuffer);
BAIL_ON_FAILURE(hr);
}
else if(fSpecialSets)
{
if(rgPropertySets[ipropset].guidPropertySet ==
DBPROPSET_DATASOURCEALL)
rgPropertyInfoSetsOutput[ipropset].guidPropertySet =
DBPROPSET_DATASOURCE;
else if (rgPropertyInfoSetsOutput[ipropset].guidPropertySet ==
DBPROPSET_SESSIONALL)
rgPropertyInfoSetsOutput[ipropset].guidPropertySet =
DBPROPSET_SESSION;
else if(rgPropertyInfoSetsOutput[ipropset].guidPropertySet ==
DBPROPSET_ROWSETALL)
rgPropertyInfoSetsOutput[ipropset].guidPropertySet =
DBPROPSET_ROWSET;
else
rgPropertyInfoSetsOutput[ipropset].guidPropertySet =
DBPROPSET_DATASOURCEINFO;
rgPropertyInfoSetsOutput[ipropset].rgPropertyInfos = NULL;
rgPropertyInfoSetsOutput[ipropset].cPropertyInfos = 0;
cprop++;
cpropError++;
}
else //Now the regular property sets
{
ppropinfoset =
m_dbProperties.GetPropertyInfoSet(
rgPropertySets[ipropset].guidPropertySet);
cProperty = rgPropertySets[ipropset].cPropertyIDs;
if(cProperty)
{
cprop += cProperty;
//allocate memory for each property info
rgPropertyInfoSetsOutput[ipropset].rgPropertyInfos
= (DBPROPINFO *)
CoTaskMemAlloc(cProperty *sizeof(DBPROPINFO));
if( rgPropertyInfoSetsOutput[ipropset].rgPropertyInfos
== NULL)
{
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
//zero memory
memset(rgPropertyInfoSetsOutput[ipropset].rgPropertyInfos,
0x00,
cProperty*sizeof(DBPROPINFO));
//if the requested property info set is empty,
//store error information into the output array.
if(ppropinfoset == 0)
{
cpropError += cProperty;
for(iprop =0; iprop <cProperty; iprop++)
{
rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].dwPropertyID =
rgPropertySets[ipropset].rgPropertyIDs[iprop];
rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].dwFlags =
DBPROPFLAGS_NOTSUPPORTED;
}
}
//otherwise, try to get property info for each property.
else
{
pdbpropinfo =
rgPropertyInfoSetsOutput[ipropset].rgPropertyInfos;
for(; iprop <cProperty; iprop++, pdbpropinfo++)
{
pdbpropinfoSrc = m_dbProperties.GetPropertyInfo(
rgPropertySets[ipropset].guidPropertySet,
rgPropertySets[ipropset].rgPropertyIDs[iprop]);
if(pdbpropinfoSrc)
*pdbpropinfo = *pdbpropinfoSrc;
else
{
//unable to get property info
//for this property. Store error info.
pdbpropinfo->dwPropertyID =
rgPropertySets[ipropset].
rgPropertyIDs[iprop];
pdbpropinfo->dwFlags =
DBPROPFLAGS_NOTSUPPORTED;
cpropError++;
}
}
//Now copy property descriptions
//for all properties in this set
hr = m_dbProperties.CopyPropertyDescriptions(
&rgPropertyInfoSetsOutput[ipropset],
ppDescBuffer,
&cchDescBuffer,
&ichDescBuffer);
BAIL_ON_FAILURE(hr);
}
}
else //no properties stored in this set.
{
cprop++;
//if the returned set itself is NULL, nothing
//to copy.
if(ppropinfoset == NULL)
{
cpropError++;
rgPropertyInfoSetsOutput[ipropset].rgPropertyInfos =
NULL;
}
//otherwise, just copy whatever info we have
//in the set.
else
{
hr = m_dbProperties.CopyPropertyInfoSet(
rgPropertySets[ipropset].guidPropertySet,
&rgPropertyInfoSetsOutput[ipropset],
ppDescBuffer,
&cchDescBuffer,
&ichDescBuffer);
BAIL_ON_FAILURE(hr);
}
}
}
} //for (ipropset = 0 ....
} //if (fcopy) ... else ...
CATCHBLOCKBAIL(hr)
*pcPropertyInfoSets = cPropertySets;
*prgPropertyInfoSets = rgPropertyInfoSetsOutput;
// So far we have put relative offsets into pointers to property
// descriptions. They have to be rebased on the beginning of the
// desription strings buffer.
if(ppDescBuffer && *ppDescBuffer)
{
for(ipropset=0; ipropset < cPropertySets; ipropset++)
for(iprop =0;
iprop <rgPropertyInfoSetsOutput[ipropset].cPropertyInfos;
iprop++)
{
// Only do this if we really support the property:
//
if ( rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].dwFlags !=
DBPROPFLAGS_NOTSUPPORTED )
{
rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].pwszDescription =
(WCHAR *)(*ppDescBuffer) +
(ULONG_PTR)(rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].pwszDescription);
}
else {
ADsAssert ( rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].pwszDescription
== NULL );
}
}
}
else
{
// Assert that we're not passing back any strings:
//
for(ipropset=0; ipropset < cPropertySets; ipropset++)
{
for(iprop =0;
iprop < rgPropertyInfoSetsOutput[ipropset].cPropertyInfos;
iprop++)
{
ADsAssert ( rgPropertyInfoSetsOutput[ipropset].
rgPropertyInfos[iprop].pwszDescription == NULL );
}
}
}
hr = cpropError ?
((cpropError <cprop) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED)
: S_OK;
RRETURN(hr);
error:
ULONG i;
for ( i = 0; i < ipropset; i++ )
{
if( rgPropertyInfoSetsOutput
&& rgPropertyInfoSetsOutput[i].cPropertyInfos
&& rgPropertyInfoSetsOutput[i].rgPropertyInfos)
CoTaskMemFree(rgPropertyInfoSetsOutput[i].rgPropertyInfos);
}
if(rgPropertyInfoSetsOutput)
CoTaskMemFree(rgPropertyInfoSetsOutput);
if(ppDescBuffer && *ppDescBuffer)
{
CoTaskMemFree(*ppDescBuffer);
*ppDescBuffer = NULL;
}
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CBinder::GetProperties
//
// Synopsis: Sets Binder properties
//
// For more info see OLE DB 2.1 spec.
//----------------------------------------------------------------------------
STDMETHODIMP CBinder::SetProperties(
ULONG cPropertySets,
DBPROPSET rgPropertySets[ ])
{
ULONG ipropset, cprop, cpropError;
DBPROPSTATUS dbpropstat;
DBPROP *ppropNew, *ppropEnd, *ppropStored;
BOOL fEqualOnly, fRestore;
HRESULT hr;
DBPROPSET *ppropset;
auto_leave cs_auto_leave(m_autocs);
TRYBLOCK
//Let the property manager object verify the args.
hr = m_dbProperties.VerifySetPropertiesArgs(cPropertySets,
rgPropertySets);
if (FAILED(hr))
RRETURN(hr);
cs_auto_leave.EnterCriticalSection();
//Cycle thru each property set.
for(ipropset =0, cprop =0,
cpropError =0; ipropset < cPropertySets;
ipropset++)
{
dbpropstat = DBPROPSTATUS_OK;
fEqualOnly = FALSE;
cprop += rgPropertySets[ipropset].cProperties;
//Get the property set.
ppropset = m_dbProperties.GetPropertySet(
rgPropertySets[ipropset].guidPropertySet);
//Error if this is NOT init property set,
if(rgPropertySets[ipropset].guidPropertySet != DBPROPSET_DBINIT)
{
dbpropstat = DBPROPSTATUS_NOTSUPPORTED;
}
//ppropnew is beginning of property struct in memory
//and ppropEnd is the end.
ppropNew = rgPropertySets[ipropset].rgProperties;
ppropEnd = ppropNew +rgPropertySets[ipropset].cProperties;
if(fEqualOnly || dbpropstat == DBPROPSTATUS_OK)
{
//Cycle thru each property
for(; ppropNew !=ppropEnd; ppropNew++)
{
ppropStored = (DBPROP *)m_dbProperties.GetProperty(
rgPropertySets[ipropset].guidPropertySet,
ppropNew->dwPropertyID);
//if property is already there....
if(ppropStored)
{
ppropNew->dwStatus = DBPROPSTATUS_OK;
//Set error status if validation fails or
//if type doesn't match
//or if bad option or fEqualOnly is set
//but new and existing values aren't the same.
if (ppropNew->dwPropertyID == DBPROP_INIT_MODE && (V_VT(&(ppropNew->vValue)) == VT_I4) &&
V_I4(&ppropNew->vValue) != DB_MODE_READ)
ppropNew->dwStatus = DBPROPSTATUS_BADVALUE;
else if(V_VT(&(ppropNew->vValue)) !=
(m_dbProperties.GetPropertyInfo(
rgPropertySets[ipropset].guidPropertySet,
ppropNew->dwPropertyID))->vtType)
{
if(V_VT(&(ppropNew->vValue)) != VT_EMPTY)
ppropNew->dwStatus = DBPROPSTATUS_BADVALUE;
else if(fEqualOnly)
ppropNew->dwStatus = DBPROPSTATUS_NOTSETTABLE;
}
else if(!GoodPropOption(ppropNew->dwOptions))
ppropNew->dwStatus = DBPROPSTATUS_BADOPTION;
else if(fEqualOnly && !VariantsEqual(
&(ppropNew->vValue),
&(ppropStored->vValue)))
ppropNew->dwStatus = DBPROPSTATUS_NOTSETTABLE;
//fEqualOnly was not set
if(!fEqualOnly && ppropNew->dwStatus ==
DBPROPSTATUS_OK)
{
// If VT_EMPTY we need to reset the default.
if(V_VT(&(ppropNew->vValue)) == VT_EMPTY)
{
// Reset our initialization properties
// to the default:
if(ppropNew->dwPropertyID == DBPROP_INIT_LCID)
{
V_VT(&(ppropNew->vValue)) = VT_I4;
V_I4(&(ppropNew->vValue)) =
GetUserDefaultLCID();
}
else if ( ppropNew->dwPropertyID ==
DBPROP_INIT_MODE)
{
V_VT(&(ppropNew->vValue)) = VT_I4;
V_I4(&(ppropNew->vValue)) = DEFAULT_DBPROP_INIT_MODE;
}
else if ( ppropNew->dwPropertyID ==
DBPROP_INIT_BINDFLAGS)
{
V_VT(&(ppropNew->vValue)) = VT_I4;
V_I4(&(ppropNew->vValue)) = 0;
}
else if ( ppropNew->dwPropertyID ==
DBPROP_INIT_LOCKOWNER)
{
V_VT(&(ppropNew->vValue)) = VT_BSTR;
V_BSTR(&(ppropNew->vValue)) = NULL;
}
else if ( ppropNew->dwPropertyID ==
DBPROP_AUTH_USERID)
{
V_VT(&(ppropNew->vValue)) = VT_BSTR;
V_BSTR(&(ppropNew->vValue)) = NULL;
}
else if ( ppropNew->dwPropertyID ==
DBPROP_AUTH_PASSWORD)
{
V_VT(&(ppropNew->vValue)) = VT_BSTR;
V_BSTR(&(ppropNew->vValue)) = NULL;
}
else if ( ppropNew->dwPropertyID ==
DBPROP_AUTH_ENCRYPT_PASSWORD)
{
V_VT(&(ppropNew->vValue)) = VT_BOOL;
V_BOOL(&(ppropNew->vValue)) = VARIANT_FALSE;
}
fRestore = TRUE;
}
else
fRestore = FALSE;
//copy new value into the property variant.
if(FAILED(VariantCopy(
&(ppropStored->vValue),
&(ppropNew->vValue))))
ppropNew->dwStatus = DBPROPSTATUS_NOTSET;
else if( ppropNew->dwPropertyID == DBPROP_AUTH_USERID ) {
if(S_OK != m_pSession->SetUserName(V_BSTR(&(ppropNew->vValue))))
ppropNew->dwStatus = DBPROPSTATUS_NOTSET;
}
else if( ppropNew->dwPropertyID == DBPROP_AUTH_PASSWORD ) {
if(S_OK != m_pSession->SetPassword(V_BSTR(&(ppropNew->vValue))))
ppropNew->dwStatus = DBPROPSTATUS_NOTSET;
}
else if( ppropNew->dwPropertyID == DBPROP_AUTH_ENCRYPT_PASSWORD ) {
if(V_BOOL(&(ppropNew->vValue)) == VARIANT_TRUE)
m_pSession->SetAuthFlag(ADS_SECURE_AUTHENTICATION);
}
if(fRestore)
VariantInit(&(ppropNew->vValue));
}
}
else
ppropNew->dwStatus = DBPROPSTATUS_NOTSUPPORTED;
if(ppropNew->dwStatus != DBPROPSTATUS_OK)
cpropError++;
}
}
else
{
cpropError += rgPropertySets[ipropset].cProperties;
for(; ppropNew !=ppropEnd; ppropNew++)
ppropNew->dwStatus = dbpropstat;
}
} //for (ipropset = 0 ...
CATCHBLOCKRETURN
hr = cpropError ?
((cpropError <cprop) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED)
: S_OK;
RRETURN(hr);
}
//IDBBinderProperties
//+---------------------------------------------------------------------------
//
// Function: CBinder::Reset
//
// Synopsis: Resets binder properties to default values.
//
// For more info see OLE DB 2.5 spec.
//----------------------------------------------------------------------------
STDMETHODIMP CBinder::Reset( void)
{
HRESULT hr = NOERROR;
DBPROP * pprop;
auto_leave cs_auto_leave(m_autocs);
TRYBLOCK
cs_auto_leave.EnterCriticalSection();
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_INIT_LCID );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_I4;
V_I4(&pprop->vValue) = GetUserDefaultLCID();
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_INIT_MODE );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_I4;
V_I4(&pprop->vValue) = DEFAULT_DBPROP_INIT_MODE;
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_INIT_BINDFLAGS );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_I4;
V_I4(&pprop->vValue) = 0;
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_INIT_LOCKOWNER );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_BSTR;
V_BSTR(&pprop->vValue) = NULL;
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_AUTH_USERID );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_BSTR;
V_BSTR(&pprop->vValue) = NULL;
m_pSession->SetUserName(NULL);
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_AUTH_PASSWORD );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_BSTR;
V_BSTR(&pprop->vValue) = NULL;
m_pSession->SetPassword(NULL);
pprop = (DBPROP *) m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_AUTH_ENCRYPT_PASSWORD );
ADsAssert ( pprop );
VariantClear ( &pprop->vValue );
V_VT(&pprop->vValue) = VT_BOOL;
V_BOOL(&pprop->vValue) = VARIANT_FALSE;
m_pSession->SetAuthFlag(0);
CATCHBLOCKRETURN
RRETURN(hr);
}
//Helper functions
//+---------------------------------------------------------------------------
//
// Function: CBinder::InitializeProperties
//
// Synopsis: Initializes binder init property group to default values.
//
//----------------------------------------------------------------------------
HRESULT CBinder::InitializeProperties()
{
HRESULT hr;
DBPROP prop;
DBPROPINFO * ppropinfo;
// Initialize the DBPROP structure:
//
ZeroMemory ( &prop, sizeof (prop) );
prop.dwOptions = DBPROPOPTIONS_OPTIONAL;
prop.dwStatus = DBPROPSTATUS_OK;
// Add the LCID:
//
prop.dwPropertyID = DBPROP_INIT_LCID;
V_VT(&prop.vValue) = VT_I4;
V_I4(&prop.vValue) = GetUserDefaultLCID ();
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_INIT_LCID
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *)m_dbProperties.GetPropertyInfo(
DBPROPSET_DBINIT,
DBPROP_INIT_LCID);
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
// Add the DB_MODE:
//
prop.dwPropertyID = DBPROP_INIT_MODE;
V_VT(&prop.vValue) = VT_I4;
V_I4(&prop.vValue) = DEFAULT_DBPROP_INIT_MODE;
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_INIT_MODE
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *) m_dbProperties.GetPropertyInfo (
DBPROPSET_DBINIT,
DBPROP_INIT_MODE );
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
// Add the BindFlags property:
//
prop.dwPropertyID = DBPROP_INIT_BINDFLAGS;
V_VT(&prop.vValue) = VT_I4;
V_I4(&prop.vValue) = 0;
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_INIT_BINDFLAGS
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *) m_dbProperties.GetPropertyInfo (
DBPROPSET_DBINIT,
DBPROP_INIT_BINDFLAGS );
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
// Add the LOCKOWNER property:
//
prop.dwPropertyID = DBPROP_INIT_LOCKOWNER;
V_VT(&prop.vValue) = VT_BSTR;
V_BSTR(&prop.vValue) = NULL;
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_INIT_LOCKOWNER
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *) m_dbProperties.GetPropertyInfo (
DBPROPSET_DBINIT,
DBPROP_INIT_LOCKOWNER );
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
// Add the USERID property:
//
prop.dwPropertyID = DBPROP_AUTH_USERID;
V_VT(&prop.vValue) = VT_BSTR;
V_BSTR(&prop.vValue) = NULL;
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_USERID
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *) m_dbProperties.GetPropertyInfo (
DBPROPSET_DBINIT,
DBPROP_AUTH_USERID );
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
// Add the PASSWORD property:
//
prop.dwPropertyID = DBPROP_AUTH_PASSWORD;
V_VT(&prop.vValue) = VT_BSTR;
V_BSTR(&prop.vValue) = NULL;
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_PASSWORD
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *) m_dbProperties.GetPropertyInfo (
DBPROPSET_DBINIT,
DBPROP_AUTH_PASSWORD );
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
// Add the ENCRYPT_PASSWORD property:
//
prop.dwPropertyID = DBPROP_AUTH_ENCRYPT_PASSWORD;
V_VT(&prop.vValue) = VT_BOOL;
V_BOOL(&prop.vValue) = VARIANT_FALSE;
hr = m_dbProperties.SetProperty (
DBPROPSET_DBINIT,
prop,
TRUE,
DESC_DBPROP_ENCRYPT_PASSWORD
);
BAIL_ON_FAILURE(hr);
// Make it writable:
ppropinfo = (DBPROPINFO *) m_dbProperties.GetPropertyInfo (
DBPROPSET_DBINIT,
DBPROP_AUTH_ENCRYPT_PASSWORD );
ADsAssert ( ppropinfo );
ppropinfo->dwFlags |= DBPROPFLAGS_WRITE;
error:
RRETURN ( hr );
}
//+---------------------------------------------------------------------------
//
// Function: CBinder::BindFlagsFromDbProps
//
// Synopsis: extracts bind flags from initialization properties.
//
//----------------------------------------------------------------------------
DWORD CBinder::BindFlagsFromDbProps ( )
{
const DBPROP * ppropMode;
const DBPROP * ppropBindFlags;
ppropMode = m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_INIT_MODE );
ADsAssert ( ppropMode );
ppropBindFlags = m_dbProperties.GetProperty (
DBPROPSET_DBINIT,
DBPROP_INIT_BINDFLAGS );
ADsAssert ( ppropBindFlags );
const VARIANT * pvarMode = &ppropMode->vValue;
const VARIANT * pvarBindFlags = &ppropBindFlags->vValue;
DWORD dwResult = 0;
if ( V_VT(pvarMode) == VT_I4 ) {
DWORD dwModeMask =
DB_MODE_READ |
DB_MODE_WRITE |
DB_MODE_READWRITE |
DB_MODE_SHARE_DENY_READ |
DB_MODE_SHARE_DENY_WRITE |
DB_MODE_SHARE_EXCLUSIVE |
DB_MODE_SHARE_DENY_NONE;
dwResult |= V_I4(pvarMode) & dwModeMask;
}
if ( V_VT(pvarBindFlags) == VT_I4 ) {
DWORD dwBindFlagProp = V_I4(pvarBindFlags);
DWORD dwBindFlags = 0;
if ( dwBindFlagProp & DB_BINDFLAGS_DELAYFETCHCOLUMNS ) {
dwBindFlags |= DBBINDURLFLAG_DELAYFETCHCOLUMNS;
}
if ( dwBindFlagProp & DB_BINDFLAGS_DELAYFETCHSTREAM ) {
dwBindFlags |= DBBINDURLFLAG_DELAYFETCHSTREAM;
}
if ( dwBindFlagProp & DB_BINDFLAGS_RECURSIVE ) {
dwBindFlags |= DBBINDURLFLAG_RECURSIVE;
}
if ( dwBindFlagProp & DB_BINDFLAGS_OUTPUT ) {
dwBindFlags |= DBBINDURLFLAG_OUTPUT;
}
dwResult |= V_I4(pvarBindFlags) | dwBindFlags;
}
RRETURN (dwResult);
}
//+---------------------------------------------------------------------------
//
// Function: CBinder::CreateDataSource
//
// Synopsis: Creates an implicit DataSource object for this binder object.
//
//----------------------------------------------------------------------------
HRESULT CBinder::CreateDataSource()
{
//Call this function only at creation time.
ADsAssert(m_pDataSource == NULL && m_pDBInitialize.get() == NULL);
HRESULT hr = S_OK;
//Create a DataSource object. Note: starts with refcount = 1.
m_pDataSource = new CDSOObject( NULL );
if (m_pDataSource == NULL)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
//Initialize the object
if (!m_pDataSource->FInit())
{
delete m_pDataSource;
m_pDataSource = NULL;
BAIL_ON_FAILURE(hr = E_FAIL);
}
//Get IDBInitialize interface and store it in (auto)member variable.
//This will also make sure the DataSource object stays alive during
//the lifetime of binder object.
hr = m_pDataSource->QueryInterface(__uuidof(IDBInitialize),
(void**)&m_pDBInitialize);
BAIL_ON_FAILURE(hr);
//We already stored datasource object reference in auto_rel object,
//Now release once, since datasource object is created with refcount = 1.
m_pDataSource->Release();
error:
RRETURN ( hr );
}
//+---------------------------------------------------------------------------
//
// Function: CBinder::CreateSession
//
// Synopsis: Creates an implicit Session object for this binder object.
//
//----------------------------------------------------------------------------
HRESULT CBinder::CreateSession()
{
//Call this function only at creation time.
ADsAssert(m_pSession == NULL && m_pOpenRowset.get() == NULL);
HRESULT hr = S_OK;
CCredentials creds;
//create a session object. Note: starts with refcount = 1
m_pSession = new CSessionObject( NULL );
if (m_pSession == NULL)
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
//Initialize session object passing null credentials.
//Note: This increments refcount on DataSource object.
if (!m_pSession->FInit(m_pDataSource, creds))
BAIL_ON_FAILURE(hr = E_FAIL);
hr = m_pSession->QueryInterface(__uuidof(IOpenRowset),
(void **)&m_pOpenRowset);
BAIL_ON_FAILURE(hr);
//We already stored session reference in auto_rel object.
//Now release once, since session object is created
//with refcount = 1
m_pSession->Release();
RRETURN ( S_OK );
error:
//if we're here, the Session object is no good.
if (m_pSession)
{
delete m_pSession;
m_pSession = NULL;
}
RRETURN ( hr );
}
#endif