mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1315 lines
58 KiB
1315 lines
58 KiB
// 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
|