|
|
//-----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: CRSInfo.cxx
//
// Contents: IRowsetInfo and IGetRow methods
//
// Functions:
//
// Notes:
//
//
// History: 08/30/96 | RenatoB | Created
//----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// @class CRowsetInfo | embedding of Rowset,
// to give our IrowsetInfo interface
//
//
//-----------------------------------------------------------------------------
// Includes
#include "oleds.hxx"
#include "atl.h"
#include "row.hxx"
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::QueryInterface
//
// Synopsis: @mfunc QueryInterface.
//
// Update: This function should never be called as RowsetInfo is now contained
// in CRowset.
//
//-----------------------------------------------------------------------.
HRESULT CRowsetInfo::QueryInterface( REFIID riid, LPVOID * ppv ) { ADsAssert(FALSE);
RRETURN( E_INVALIDARG ); }
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::CRowsetInfo
//
// Synopsis: @mfunc Ctor
//
// Arguments:
//
//
// Returns: @rdesc NONE
//
// Modifies:
//
// History: 08/30/96 RenatoB Created
//
//----------------------------------------------------------------------------
CRowsetInfo::CRowsetInfo( IUnknown * pUnkOuter, // controlling unknown)
IUnknown * pParentObject, // RowProvider
CSessionObject * pCSession, // Session that created rowset
CCommandObject * pCCommand, // Command object that created rowset
CRowProvider * pRowProvider // Row provider pointer
) { //
// Asserts
//
ADsAssert(pRowProvider);
_pUnkOuter = (pUnkOuter == NULL) ? (IRowsetInfo FAR *)this : pUnkOuter; _pRowset = NULL; _pParentObject = pParentObject; _pCSession = pCSession; _pCCommand = pCCommand;
// AddRef twice - once for command/session object, once for parent object
if( NULL == _pCCommand ) { _pCSession->AddRef(); _pCSession->AddRef(); } else if( NULL == _pCSession ) { _pCCommand->AddRef(); _pCCommand->AddRef(); } else // shouldn't get here
ADsAssert(FALSE);
_pRowProvider = pRowProvider; _pRowProvider->AddRef();
_pMalloc = NULL;
if( _pCCommand != NULL ) _pCCommand->IncrementOpenRowsets();
_fCriticalSectionInitialized = FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::~CRowsetInfo
//
// Synopsis: @mfunc Dtor
//
// Arguments:
//
//
// Returns: @rdesc NONE
//
// Modifies:
//
// History: 08/30/96 RenatoB Created
//
//----------------------------------------------------------------------------
CRowsetInfo::~CRowsetInfo() { if( _pMalloc != NULL ) _pMalloc->Release();
if( _pCCommand != NULL ) { _pCCommand->DecrementOpenRowsets(); _pCCommand->Release(); }
if( _pCSession != NULL ) { _pCSession->Release(); }
if( _pParentObject != NULL ) { _pParentObject->Release(); }
if( _pRowProvider != NULL ) { _pRowProvider->Release(); }
if (_fCriticalSectionInitialized) { DeleteCriticalSection(&_csRowsetInfo); } }
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::FInit
//
// Synopsis: @mfunc Initializer
//
// Synopsis: @mfunc Initializer
//
// Arguments:
//
//
// Returns: @rdesc NONE
// @flag S_OK | Interface is supported
// @flag E_OUTOFMEMORY | Not enough memory
// @flag E_INVALIDARG | One or more arguments are invalid.
//
// Modifies:
//
// History: 08/30/96 RenatoB Created
//
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::FInit( IUnknown * pRowset) // rowset interface
{ HRESULT hr; hr = S_OK;
//
// InitializeCriticalSection can throw exceptions under low memory conditions.
// Catch any exceptions and handle them.
//
try { //this section is for IRowsetInfo and IUnknown methods.
InitializeCriticalSection(&_csRowsetInfo); _fCriticalSectionInitialized = TRUE; } catch(...) { RRETURN( E_FAIL ); }
if( FAILED(CoGetMalloc(MEMCTX_TASK, &_pMalloc)) ) RRETURN( E_OUTOFMEMORY );
// Should not AddRef here because RowsetInfo is contained in CRowset
_pRowset = pRowset;
RRETURN( hr ); }
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetReferencedRowset
//
// Synopsis: @mfunc Returns an interface pointer to the rowset to which a bookmark applies
//
// Called by: Client
// Called when: Any time
//
// Arguments:
// iOrdinal [in] Bookmark column for which to get related rowset. Must be 0 in this impl.
// riid [in] IID of the interface pointer to return in *ppReferencedRowset.
// ppReferencedRowset[out] pointer to Rowset object referenced by Bookmark
//
//
// Returns: @rdesc NONE
// S_OK | Interface is supported
// E_INVALIDARG | ppReferencedRowset was a NULL pointer
// E_FAIL | provider specific error
// E_NOINTERFACE | Rowset does not support interface
// DB_E_NOTAREFENCEDCOLUMN | iOrdinal was not 0
//
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::GetReferencedRowset( DBORDINAL iOrdinal, REFIID riid, IUnknown ** ppReferencedRowset ) { CAutoBlock cab (&_csRowsetInfo);
//
// Asserts
//
ADsAssert(_pRowProvider); ADsAssert(_pRowset);
if( ppReferencedRowset == NULL ) RRETURN( E_INVALIDARG );
*ppReferencedRowset = NULL;
if( iOrdinal >= _pRowProvider->GetColumnCount() ) RRETURN( DB_E_BADORDINAL );
if( iOrdinal != 0 ) RRETURN( DB_E_NOTAREFERENCECOLUMN );
RRETURN(_pRowset->QueryInterface( riid, (void**)ppReferencedRowset) ); };
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetSpecificaton
//
// Synopsis: @mfunc Returns an interface pointer to the command that created the rowset
//
// Called by: Client
// Called when: Any time
//
// Arguments:
// riid [in] IID of the interface pointer to return in *ppSpecification.
// ppSpecification [out] pointer to command
//
//
// Returns: @rdesc NONE
// S_OK | Interface is supported
// E_INVALIDARG | ppSpecification was a NULL pointer
// E_FAIL | provider specific error
// E_NOINTERFACE | Command does not support interface
// S_FALSE | Rowset does not have command that created it
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::GetSpecification( REFIID riid, IUnknown ** ppSpecification ) { CAutoBlock cab(&_csRowsetInfo);
if( ppSpecification == NULL ) RRETURN( E_INVALIDARG );
*ppSpecification = NULL;
if( _pParentObject == NULL ) RRETURN( S_FALSE );
RRETURN( _pParentObject->QueryInterface(riid, (void**)ppSpecification) ); };
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetProperties
//
// Synopsis: @mfunc GetProperties
// Called by: Client.
// Called when: Any time.
//
// Arguments:
// cPropertyIDSets[in] The number of DBPROPIDSET structures in rgProperttySets
// rgPropertyIDSets[in] Array of cPropertyIDSets of DBPROIDSET structs.
// pcPropertySets[out] number of DBPROPSET returned in *prgPropertySets
// prgPropertySets[out] pointer to array of DBPROPSET structures, having the
// value and status of requested properties
//
// Returns: @rdesc HRESULT
// S_OK Success
// DB_S_ERRORSOCCURRED Values were not supported for some properties
// E_FAIL A provider-specific error occurred
// E_INVALIDARG cPropertyIDSets > 0 and rgPropertyIdSEts = NULL
// pcPropertySets or prgPropertySets was NULL pointer
// In al element of rgPropertyIDSets, cPropertyIDs was not zero
// and rgPropertyIDs was a Null pointer
// E_OUTOFMEMORY Provider could not allocate memory
// DB_E_ERRORSOCCURRED Values were not returned for any properties
//-----------------------------------------------------------------------.
HRESULT CRowsetInfo::GetProperties( const ULONG cPropertyIDSets, const DBPROPIDSET rgPropertyIDSets[], ULONG * pcPropertySets, DBPROPSET ** prgPropertySets ) { // should never get here because this call is handled by CRowset
ADsAssert(FALSE);
RRETURN( E_FAIL ); };
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetRowFromHROW
//
// Synopsis: @mfunc Returns an interface pointer to a row in the rowset.
//
// Called by: Client
// Called when: Any time
//
// Arguments:
// IUnknown *pUnkOuter Outer unknown.
// HROW hRow Handle to row.
// REFIID riid, Interface requested.
// [out]IUnknown **ppUnk returned interface
//
//
// Returns: HRESULT
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::GetRowFromHROW( IUnknown *pUnkOuter, HROW hRow, REFIID riid, IUnknown * *ppUnk, BOOL fIsTearOff, BOOL fAllAttrs ) { #if (!defined(BUILD_FOR_NT40))
HRESULT hr = S_OK; CAutoBlock cab(&_csRowsetInfo); auto_tm<WCHAR> lpwszURL; auto_rel<IGetDataSource> pGetDataSource; auto_rel<ICommand> pCommand; auto_rel<IRowset> pRowset; auto_rel<IRowset> pRealRowset; CComObject<CRow> *pRow = NULL; auto_rel<IRow> pRowDelete; CCredentials creds; CCredentials *pCreds; PWSTR pwszUserID = NULL, pwszPassword = NULL;
//Initialize return arguments
if (ppUnk) *ppUnk = NULL;
//We currently don't support aggregation.
if (pUnkOuter != NULL) RRETURN(DB_E_NOAGGREGATION);
if (ppUnk == NULL) RRETURN(E_INVALIDARG);
if ( _pParentObject == NULL) RRETURN(S_FALSE);
TRYBLOCK PWSTR pURL; ADsAssert(_pRowset != NULL); hr = _pRowset->QueryInterface(__uuidof(IRowset), (void **)&pRealRowset); BAIL_ON_FAILURE(hr); hr = _pRowProvider->GetURLFromHROW( hRow,&pURL, pRealRowset); BAIL_ON_FAILURE(hr);
//assign returned ptr to auto_tm class for auto deletion.
lpwszURL = pURL;
*ppUnk = NULL;
//
// Get the session and QI for any mandatory interface -
// we query for IGetDataSource.
//
hr = _pParentObject->QueryInterface( IID_IGetDataSource, (void**)&pGetDataSource);
if (FAILED(hr)) { hr = _pParentObject->QueryInterface( IID_ICommand, (void**)&pCommand); BAIL_ON_FAILURE(hr);
hr = pCommand->GetDBSession ( IID_IGetDataSource, (LPUNKNOWN *)&pGetDataSource); BAIL_ON_FAILURE(hr); }
//Get user id and password properties for authentication
//If the RowProvider has cached special credentials, we use them,
//Otherwise we use the DBPROP_AUTH_USERID and DBPROP_AUTH_PASSWORD
//properties in the originating DataSource object.
if ((pCreds = _pRowProvider->GetCredentials()) == NULL) { hr = GetCredentials(pGetDataSource, creds); BAIL_ON_FAILURE(hr); pCreds = &creds; }
hr = pCreds->GetUserName(&pwszUserID); BAIL_ON_FAILURE(hr); hr = pCreds->GetPassword(&pwszPassword); BAIL_ON_FAILURE(hr);
//Instantiate a row object.
hr = CComObject<CRow>::CreateInstance(&pRow); if (FAILED(hr)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
//To make sure we delete the row object in case
//we encounter errors after this point.
pRow->AddRef(); pRowDelete = pRow;
//Initialize the row object.
hr = pRow->Initialize( lpwszURL, (IUnknown *)pGetDataSource, (IUnknown *)_pRowset, hRow, pwszUserID, pwszPassword, DBBINDURLFLAG_READ, //we are currently a read-only provider.
fIsTearOff, // see comment at beginning of row.cxx
!fAllAttrs, // see comment at beginning of row.cxx
_pRowProvider );
if (FAILED(hr)) { if (INVALID_CREDENTIALS_ERROR(hr)) { BAIL_ON_FAILURE(hr = DB_SEC_E_PERMISSIONDENIED); } else if (hr == E_NOINTERFACE) { BAIL_ON_FAILURE(hr); } else { BAIL_ON_FAILURE(hr = DB_E_NOTFOUND); } }
//Get the requested interface on the Row.
hr = pRow->QueryInterface(riid, (void**)ppUnk); if (FAILED(hr)) BAIL_ON_FAILURE(hr = E_NOINTERFACE);
CATCHBLOCKBAIL(hr)
if (pwszUserID) FreeADsStr(pwszUserID); if (pwszPassword) { SecureZeroMemory(pwszPassword, wcslen(pwszPassword) * sizeof(WCHAR)); FreeADsStr(pwszPassword); }
RRETURN(S_OK);
error: if (pwszUserID) FreeADsStr(pwszUserID); if (pwszPassword) { SecureZeroMemory(pwszPassword, wcslen(pwszPassword) * sizeof(WCHAR)); FreeADsStr(pwszPassword); }
RRETURN(hr);
#else
RRETURN(E_FAIL); #endif
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetURLFromHROW
//
// Synopsis: @mfunc Returns an interface pointer to a row in the rowset.
//
// Called by: Client
// Called when: Any time
//
// Arguments:
// HROW hRow Handle to row.
// LPOLESTR ppwszURL, URL name for the row.
//
//
// Returns: HRESULT
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::GetURLFromHROW( HROW hRow, LPOLESTR *ppwszURL ) { #if (!defined(BUILD_FOR_NT40))
CAutoBlock cab(&_csRowsetInfo); LPWSTR lpwszURL = NULL; auto_rel<IRowset> pRealRowset; HRESULT hr = S_OK;
if (ppwszURL == NULL) RRETURN(E_INVALIDARG);
ADsAssert(_pRowset != NULL); hr = _pRowset->QueryInterface(__uuidof(IRowset), (void **)&pRealRowset); BAIL_ON_FAILURE(hr);
// Call row provider to get the URL.
hr = _pRowProvider->GetURLFromHROW( hRow,ppwszURL, pRealRowset); BAIL_ON_FAILURE(hr);
error:
RRETURN(hr); #else
RRETURN(E_FAIL); #endif
};
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetCredentials
//
// Synopsis: @mfunc Gets credentials stored in INIT properties.
//
// Arguments:
// pSession [in] IGetDataSource interface ptr on Session.
// refCredentials [in] CCredentials containing user id and password.
//
// Returns: HRESULT
//
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::GetCredentials( IGetDataSource *pSession, CCredentials &refCredentials ) { #if (!defined(BUILD_FOR_NT40))
HRESULT hr = S_OK; auto_rel<IDBProperties> pDBProp; ULONG i, j, cPropertySets = 0;
Assert(pSession);
hr = pSession->GetDataSource( __uuidof(IDBProperties), (IUnknown **)&pDBProp);
BAIL_ON_FAILURE(hr);
DBPROPID propids[2]; propids[0] = DBPROP_AUTH_USERID; propids[1] = DBPROP_AUTH_PASSWORD;
DBPROPIDSET rgPropertyIDSets[1]; rgPropertyIDSets[0].rgPropertyIDs = propids; rgPropertyIDSets[0].cPropertyIDs = 2; rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
DBPROPSET *prgPropertySets;
hr = pDBProp->GetProperties( 1, rgPropertyIDSets, &cPropertySets, &prgPropertySets);
if (hr == DB_E_ERRORSOCCURRED) BAIL_ON_FAILURE(hr);
for (i = 0; i < cPropertySets; i++) { for (j = 0; j < prgPropertySets[i].cProperties; j++) { DBPROP *pProp = &prgPropertySets[i].rgProperties[j]; Assert(pProp); if (pProp->dwStatus == S_OK && pProp->dwPropertyID == DBPROP_AUTH_USERID) refCredentials.SetUserName(V_BSTR(&pProp->vValue)); else if (pProp->dwStatus == S_OK && pProp->dwPropertyID == DBPROP_AUTH_PASSWORD) refCredentials.SetPassword(V_BSTR(&pProp->vValue)); else continue; } }
error: for (i = 0; i < cPropertySets; i++) { for (j = 0; j < prgPropertySets[i].cProperties; j++) { DBPROP *pProp = &(prgPropertySets[i].rgProperties[j]); Assert(pProp); FreeDBID(&pProp->colid); VariantClear(&pProp->vValue); }
CoTaskMemFree(prgPropertySets[i].rgProperties); } CoTaskMemFree(prgPropertySets);
RRETURN ( hr ); #else
RRETURN(E_FAIL); #endif
}
|