|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: csession.cxx
//
// Contents: Microsoft OleDB/OleDS Session object for ADSI
//
//
// History: 08-01-96 shanksh Created.
//
//----------------------------------------------------------------------------
#include "oleds.hxx"
#pragma hdrstop
#include "atl.h"
#include "row.hxx"
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::GetDataSource
//
// Synopsis: Retrieve an interface pointer on the session object
//
// Arguments:
// riid, IID desired
// ppDSO ptr to interface
//
//
// Returns:
// S_OK Session Object Interface returned
// E_INVALIDARG ppDSO was NULL
// E_NOINTERFACE IID not supported
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::GetDataSource ( REFIID riid, IUnknown ** ppDSO ) { //
// Asserts
//
ADsAssert(_pDSO);
if( ppDSO == NULL ) RRETURN( E_INVALIDARG );
RRETURN( _pDSO->QueryInterface(riid, (LPVOID*)ppDSO) ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::GetDataSource
//
// Synopsis: Retrieve an interface pointer on the session object
//
// Arguments:
// riid, IID desired
// ppDSO ptr to interface
//
//
// Returns:
// S_OK Session Object Interface returned
// E_INVALIDARG ppDSO was NULL
// E_NOINTERFACE IID not supported
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::OpenRowset( IUnknown * pUnkOuter, DBID * pTableID, DBID * pIndexID, REFIID riid, ULONG cPropertySets, DBPROPSET rgPropertySets[], IUnknown ** ppRowset ) { // Don't pass any credentials (NULL)
RRETURN( OpenRowsetWithCredentials( pUnkOuter, pTableID, pIndexID, riid, cPropertySets, rgPropertySets, NULL, ppRowset) ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::OpenRowsetWithCredentials
//
// Synopsis: Opens a rowset. Similar to OpenRowset but takes extra argument
// CCredentials. This function is used when consumer calls
// IBindResource::Bind requesting a rowset.
//
// Returns : HRESULT
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::OpenRowsetWithCredentials ( IUnknown * pUnkOuter, DBID * pTableID, DBID * pIndexID, REFIID riid, ULONG cPropertySets, DBPROPSET rgPropertySets[], CCredentials * pCredentials, IUnknown ** ppRowset ) { BOOL fWarning = FALSE; CRowProvider *pRowProvider = NULL; DWORD cAttrs = 1; BOOL *pbMultiValue = NULL; LPWSTR *pAttrs = NULL;
//
// Check in-params and NULL out-params in case of error
//
if( ppRowset ) *ppRowset = NULL;
if( !pTableID && !pIndexID ) RRETURN( E_INVALIDARG );
if( pIndexID ) RRETURN( DB_E_NOINDEX );
//
// Check the PropertySets
//
if( cPropertySets > 0 && !rgPropertySets ) RRETURN ( E_INVALIDARG );
for(ULONG i=0; i<cPropertySets; i++) { if( rgPropertySets[i].cProperties && !rgPropertySets[i].rgProperties ) RRETURN ( E_INVALIDARG ); }
//
// pwszName field represents the ADsPath of the Directory we have to open;
// Make sure pwszName is meaningful
//
if( !pTableID || pTableID->eKind != DBKIND_NAME || !pTableID->uName.pwszName || !(*(pTableID->uName.pwszName)) ) RRETURN( DB_E_NOTABLE );
if( pUnkOuter )//&& !InlineIsEqualGUID(riid, IID_IUnknown) )
RRETURN( DB_E_NOAGGREGATION );
if( riid == IID_NULL ) RRETURN( E_NOINTERFACE );
//
// By default, we use credentials stored in member variable _Credentials
// for binding. Buf if caller passed any credentials through pCredentials,
// these take precedence. This also means that we need to store these
// credentials in the CRowProvider object for future use -
// e.g. GetRowFromHRow will use these credentials.
//
CCredentials * pCreds = &_Credentials; if( pCredentials ) pCreds = pCredentials;
//
// If integrated security is being used, impersonate the caller
//
BOOL fImpersonating;
fImpersonating = FALSE; if(_pDSO->IsIntegratedSecurity()) { HANDLE ThreadToken = _pDSO->GetThreadToken();
ASSERT(ThreadToken != NULL); if (ThreadToken) { if (!ImpersonateLoggedOnUser(ThreadToken)) RRETURN(E_FAIL); fImpersonating = TRUE; } else RRETURN(E_FAIL); }
HRESULT hr = GetDSInterface( pTableID->uName.pwszName, *pCreds, IID_IDirectorySearch, (void **)&_pDSSearch);
if (fImpersonating) { RevertToSelf(); fImpersonating = FALSE; }
if( FAILED(hr) ) RRETURN( hr );
//
// Get ColumnsInfo based on the list of attributes that we want to be
// returned. GetDefaultColumnInfo cleansup memory on failure.
//
ULONG cColumns = 0; DBCOLUMNINFO * prgInfo = NULL; WCHAR * pStringBuffer = NULL;
hr = GetDefaultColumnInfo(&cColumns, &prgInfo, &pStringBuffer); if( FAILED(hr) ) RRETURN( hr );
// Store the properties (which must be in the rowset property group) in
// the property object. OpenRowset is different from methods like
// ICOmmand::SetProperties and ISessionProperties::SetProperties in that
// it returns DB_E_ERROSOCCURRED if any property which is REQUIRED could
// not be set and DB_S_ERROROCCURRED if any property that is OPTIONAL
// could not be set. ICommand::SetProperties returns DB_E_ERROSOCCURRED
// if all properties could not be set and DB_S_ERROSOCCURRED if some
// property could not be set i.e, DBPROPOPTIONS (REQUIRED or OPTIONAL) is
// ignored.
// Use PROPSET_COMMAND as the bitmask below since the properties that are
// going to be set are in the rowset property group. These properties that
// are stored in the property object cannot be retrieved by the client
// since GetProperties on a session object will only return properties in
// the session property group.
hr = _pUtilProp->SetProperties( cPropertySets, rgPropertySets, PROPSET_COMMAND ); if( (DB_E_ERRORSOCCURRED == hr) || (DB_S_ERRORSOCCURRED == hr) ) // check if a required property could not be set
{ ULONG i, j;
for(i = 0; i < cPropertySets; i++) for(j = 0; j < rgPropertySets[i].cProperties; j++) if( rgPropertySets[i].rgProperties[j].dwStatus != DBPROPSTATUS_OK ) if( rgPropertySets[i].rgProperties[j].dwOptions != DBPROPOPTIONS_OPTIONAL ) { BAIL_ON_FAILURE( hr = DB_E_ERRORSOCCURRED ); } else fWarning = TRUE;
// if we get here, then there was all required properties were set
// successfully. However, hr could still be DB_ERRORSOCCURRED if all
// properties were optional and all of them could not be set. This
// condition is not an error for OpenRowset as noted in the comment
// above. Hence reset hr to S_OK.
hr = S_OK; }
// we still need to catch other errors like E_INAVLIDARG
BAIL_ON_FAILURE(hr);
hr = SetSearchPrefs(); BAIL_ON_FAILURE( hr );
//
// Create RowProvider object to pass to rowset code
//
pbMultiValue = (BOOL *)AllocADsMem(sizeof(BOOL)); pAttrs = (LPWSTR *)AllocADsMem(cAttrs * sizeof(LPWSTR)); if( pAttrs ) pAttrs[0] = AllocADsStr(L"ADsPath");
if( !pAttrs || !pAttrs[0] || !pbMultiValue ) BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
*pbMultiValue = FALSE;
// Is this an NDS path? If so, set filter appropriately. Fix for #286560.
WCHAR lpszProgId[MAX_PATH]; BOOL fIsNds;
hr = CopyADsProgId(pTableID->uName.pwszName, lpszProgId); BAIL_ON_FAILURE( hr ); if( !wcscmp(L"NDS", lpszProgId) ) fIsNds = TRUE; else fIsNds = FALSE;
//
// AddRef the DSSearch interface. If the CreateRowProvider function fails
// then it releases the interface, otherwise it just stores it.
//
_pDSSearch->AddRef(); hr = CRowProvider::CreateRowProvider( _pDSSearch, NULL, pAttrs, cAttrs, cColumns, prgInfo, pStringBuffer, IID_IRowProvider, pbMultiValue, TRUE, pCreds, (void **) &pRowProvider );
BAIL_ON_FAILURE( hr );
//
// RowProvider responsible for deallocation
//
pbMultiValue = NULL;
hr= CRowset::CreateRowset( pRowProvider, (LPUNKNOWN)(IAccessor FAR *)this , this, NULL, cPropertySets, rgPropertySets, 0, NULL, TRUE, // ADsPath is requested
FALSE, // not all attributes are requested
riid, ppRowset );
BAIL_ON_FAILURE( hr );
error:
if( _pDSSearch ) { _pDSSearch->Release(); _pDSSearch = NULL; }
if( pRowProvider ) pRowProvider->Release();
if( prgInfo ) _pIMalloc->Free(prgInfo);
if( pStringBuffer ) _pIMalloc->Free(pStringBuffer);
if( pbMultiValue ) FreeADsMem(pbMultiValue);
if (pAttrs) { for (i = 0; i < cAttrs; i++) { if (pAttrs[i]) FreeADsStr(pAttrs[0]); } FreeADsMem(pAttrs); }
if( FAILED(hr) ) RRETURN( hr ); else if( fWarning ) RRETURN( DB_S_ERRORSOCCURRED ); else RRETURN( hr ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::GetProperties
//
// Synopsis: Returns current settings of all properties in the DBPROPFLAGS_SESSION property
// group
//
// Arguments:
// cPropertySets count of restiction guids
// rgPropertySets restriction guids
// pcProperties count of properties returned
// prgProperties property information returned
//
// Returns:
// S_OK Session Object Interface returned
// E_INVALIDARG pcProperties or prgPropertyInfo was NULL
// E_OUTOFMEMORY Out of memory
//
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::GetProperties( ULONG cPropIDSets, const DBPROPIDSET rgPropIDSets[], ULONG * pcPropSets, DBPROPSET ** pprgPropSets ) { //
// Asserts
//
ADsAssert(_pUtilProp);
//
// Check in-params and NULL out-params in case of error
//
HRESULT hr = _pUtilProp->GetPropertiesArgChk( cPropIDSets, rgPropIDSets, pcPropSets, pprgPropSets, PROPSET_SESSION); if( FAILED(hr) ) RRETURN( hr );
//
// Just pass this call on to the utility object that manages our properties
//
RRETURN( _pUtilProp->GetProperties( cPropIDSets, rgPropIDSets, pcPropSets, pprgPropSets, PROPSET_SESSION) ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::SetProperties
//
// Synopsis: Set properties in the DBPROPFLAGS_SESSION property group
//
// Arguments:
// cProperties
// rgProperties
//
// Returns:
// S_OK Session Object Interface returned
// E_INVALIDARG pcProperties or prgPropertyInfo was NULL
// E_OUTOFMEMORY Out of memory
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::SetProperties( ULONG cPropertySets, DBPROPSET rgPropertySets[] ) { //
// Asserts
//
ADsAssert(_pUtilProp);
//
// Just pass this call on to the utility object that manages our properties
//
RRETURN( _pUtilProp->SetProperties( cPropertySets, rgPropertySets, PROPSET_SESSION) ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::CreateCommand
//
// Synopsis: Creates a brand new command and returns requested interface
//
// Arguments:
// pUnkOuter outer Unknown
// riid, IID desired
// ppCommand ptr to interface
//
//
// Returns:
// S_OK Command Object Interface returned
// E_INVALIDARG ppCommand was NULL
// E_NOINTERFACE IID not supported
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::CreateCommand( IUnknown * pUnkOuter, REFIID riid, IUnknown ** ppCommand ) { CCommandObject* pCommand = NULL; HRESULT hr;
//
// check in-params and NULL out-params in case of error
//
if( ppCommand ) *ppCommand = NULL; else RRETURN( E_INVALIDARG );
if( pUnkOuter )//&& !InlineIsEqualGUID(riid, IID_IUnknown) )
RRETURN( DB_E_NOAGGREGATION );
//
// open a CCommand object
//
pCommand = new CCommandObject(pUnkOuter); if( !pCommand ) RRETURN( E_OUTOFMEMORY );
//
// initialize the object
//
if( !pCommand->FInit(this, _Credentials) ) { delete pCommand; RRETURN( E_OUTOFMEMORY ); }
//
// get requested interface pointer on DBSession
//
hr = pCommand->QueryInterface(riid, (void **)ppCommand); if( FAILED( hr ) ) { delete pCommand; RRETURN( hr ); }
pCommand->Release();
//
// all went well
//
RRETURN( S_OK ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::GetDefaultColumnInfo
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::GetDefaultColumnInfo( ULONG * pcColumns, DBCOLUMNINFO ** prgInfo, OLECHAR ** ppStringBuffer ) { //
// Asserts
//
ADsAssert(_pIMalloc); ADsAssert(pcColumns); ADsAssert(prgInfo); ADsAssert(ppStringBuffer);
//
// Allcoate memory for the Bookmark and ADsPath column
//
*prgInfo = (DBCOLUMNINFO*)_pIMalloc->Alloc(2 * sizeof(DBCOLUMNINFO)); *ppStringBuffer = (WCHAR*)_pIMalloc->Alloc((wcslen(L"ADsPath") + 1) * sizeof(WCHAR));
//
// Free memory on a failure
//
if( !(*prgInfo) || !(*ppStringBuffer)) { if (*prgInfo) { _pIMalloc->Free(*prgInfo); *prgInfo = NULL; } if (*ppStringBuffer) { _pIMalloc->Free(*ppStringBuffer); *ppStringBuffer = NULL; }
RRETURN( E_OUTOFMEMORY ); }
//
// Initialize the memory
//
ZeroMemory(*prgInfo, 2 * sizeof(DBCOLUMNINFO)); ZeroMemory(*ppStringBuffer, (wcslen(L"ADsPath") + 1) * sizeof(WCHAR)); wcscpy(*ppStringBuffer, OLESTR("ADsPath"));
//
// Fill up the Bookmark column
//
*pcColumns = 2;
(*prgInfo)[0].pwszName = NULL; (*prgInfo)[0].pTypeInfo = NULL; (*prgInfo)[0].iOrdinal = 0; (*prgInfo)[0].ulColumnSize = sizeof(ULONG); (*prgInfo)[0].wType = DBTYPE_UI4; (*prgInfo)[0].bPrecision = 10; (*prgInfo)[0].bScale = (BYTE) ~ 0; (*prgInfo)[0].columnid.eKind = DBKIND_GUID_PROPID; (*prgInfo)[0].columnid.uGuid.guid = DBCOL_SPECIALCOL; (*prgInfo)[0].columnid.uName.ulPropid = 2; (*prgInfo)[0].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK | DBCOLUMNFLAGS_ISFIXEDLENGTH; //
// Fill up the ADsPath column
//
(*prgInfo)[1].pwszName = *ppStringBuffer; (*prgInfo)[1].pTypeInfo = NULL; (*prgInfo)[1].iOrdinal = 1; (*prgInfo)[1].ulColumnSize = (ULONG)256; (*prgInfo)[1].wType = DBTYPE_WSTR|DBTYPE_BYREF; (*prgInfo)[1].bPrecision = (BYTE) ~ 0; (*prgInfo)[1].bScale = (BYTE) ~ 0; (*prgInfo)[1].columnid.eKind = DBKIND_NAME; (*prgInfo)[1].columnid.uName.pwszName = *ppStringBuffer; (*prgInfo)[1].columnid.uGuid.guid = GUID_NULL; (*prgInfo)[1].dwFlags = DBCOLUMNFLAGS_ISNULLABLE;
RRETURN( S_OK ); }
#if (!defined(BUILD_FOR_NT40))
//IBindResource::Bind
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::CSessionObject
//
// Synopsis: Constructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 09-17-1998 mgorti Created.
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::Bind( IUnknown * punkOuter, LPCOLESTR pwszURL, DBBINDURLFLAG dwBindFlags, REFGUID rguid, REFIID riid, IAuthenticate * pAuthenticate, DBIMPLICITSESSION * pImplSession, DWORD * pdwBindStatus, IUnknown ** ppUnk ) { HRESULT hr = S_OK; CComBSTR bstrNewURL;
TRYBLOCK //Initialize return arguments
if (pdwBindStatus) *pdwBindStatus = 0;
if (ppUnk) *ppUnk = NULL;
if (pImplSession) pImplSession->pSession = NULL;
//if caller passed a null value for dwBindFlags,
//get them from initialization properties.
if (dwBindFlags == 0) dwBindFlags = BindFlagsFromDbProps();
//Generic argument validation
hr = ValidateBindArgs(punkOuter, pwszURL, dwBindFlags, rguid, riid, pAuthenticate, pImplSession, pdwBindStatus, ppUnk);
BAIL_ON_FAILURE(hr);
//Fill in the pImplSession struct.
if (pImplSession) { // Our session doesn't support aggregation.
if (pImplSession->pUnkOuter != NULL) BAIL_ON_FAILURE(hr = DB_E_NOAGGREGATION);
hr = QueryInterface(*pImplSession->piid, (void**)&(pImplSession->pSession)); if (FAILED(hr)) BAIL_ON_FAILURE(hr = E_NOINTERFACE ); }
//Specific validation checks
//We are currently a read-only provider
if (dwBindFlags & DBBINDURLFLAG_WRITE) BAIL_ON_FAILURE(hr = DB_E_READONLY);
//We currently don't support aggregation
if (punkOuter != NULL) BAIL_ON_FAILURE (hr = DB_E_NOAGGREGATION);
//We don't support the following flags
if (dwBindFlags & DBBINDURLFLAG_ASYNCHRONOUS) BAIL_ON_FAILURE(hr = DB_E_ASYNCNOTSUPPORTED);
if (dwBindFlags & DBBINDURLFLAG_OUTPUT || dwBindFlags & DBBINDURLFLAG_RECURSIVE || dwBindFlags & DBBINDURLFLAG_DELAYFETCHSTREAM || dwBindFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) BAIL_ON_FAILURE(hr = E_INVALIDARG);
//Now Try to Bind.
if (InlineIsEqualGUID(rguid, DBGUID_ROW) || InlineIsEqualGUID(rguid, DBGUID_ROWSET)) { //If the URL is not absolute, build the absolute URL
//using the DBPROP_INIT_PROVIDERSTRING.
if (! bIsAbsoluteURL(pwszURL)) { hr = BuildAbsoluteURL (pwszURL, bstrNewURL); if (FAILED(hr)) BAIL_ON_FAILURE(hr = E_INVALIDARG); } else bstrNewURL = pwszURL;
if ( InlineIsEqualGUID(rguid, DBGUID_ROW) ) { hr = BindToRow(punkOuter, (PWCHAR)bstrNewURL, pAuthenticate, dwBindFlags, riid, ppUnk); } else { hr = BindToRowset(punkOuter, (PWCHAR)bstrNewURL, pAuthenticate, dwBindFlags, riid, ppUnk); }
BAIL_ON_FAILURE(hr); } else if (InlineIsEqualGUID(rguid, DBGUID_DSO)) { ADsAssert(_pDSO); hr = BindToDataSource( punkOuter, pwszURL, pAuthenticate, dwBindFlags, riid, ppUnk ); BAIL_ON_FAILURE (hr); } else if (InlineIsEqualGUID(rguid, DBGUID_SESSION)) { hr = QueryInterface(riid, (void**)ppUnk); BAIL_ON_FAILURE (hr); } else BAIL_ON_FAILURE(hr = E_INVALIDARG);
//Fix for bug Raid-X5#83386 - spec change
//If caller specified any DENY semantics,
//set warning status and return value, since
//we don't support these.
if (dwBindFlags & DBBINDURLFLAG_SHARE_DENY_READ || dwBindFlags & DBBINDURLFLAG_SHARE_DENY_WRITE || dwBindFlags & DBBINDURLFLAG_SHARE_EXCLUSIVE) { if (pdwBindStatus) *pdwBindStatus = DBBINDURLSTATUS_S_DENYNOTSUPPORTED; BAIL_ON_FAILURE (hr = DB_S_ERRORSOCCURRED); } CATCHBLOCKBAIL(hr)
error:
RRETURN(hr); }
#endif
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::CSessionObject
//
// Synopsis: Constructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
CSessionObject::CSessionObject( LPUNKNOWN pUnkOuter ) { //
// Initialize simple member vars
//
_pUnkOuter = pUnkOuter ? pUnkOuter : (IGetDataSource FAR *)this; _cCommandsOpen = 0; _pUtilProp = NULL; _pDSSearch = NULL; _pIMalloc = NULL; _pDSO = NULL;
ENLIST_TRACKING(CSessionObject); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::~CSessionObject
//
// Synopsis: Destructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
CSessionObject::~CSessionObject( ) { //
// Free properties management object
//
delete _pUtilProp;
if( _pIMalloc ) _pIMalloc->Release();
if( _pDSO ) { _pDSO->DecrementOpenSessions(); _pDSO->Release(); } }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::FInit
//
// Synopsis: Initialize the session Object
//
// Arguments:
//
// Returns:
// TRUE Initialization succeeded
// FALSE Initialization failed
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
BOOL CSessionObject::FInit( CDSOObject * pDSO, CCredentials & Credentials ) { HRESULT hr;
//
// Asserts
//
ADsAssert(pDSO); ADsAssert(&Credentials);
//
// Allocate properties management object
//
_pUtilProp = new CUtilProp(); if( !_pUtilProp ) return FALSE;
hr = _pUtilProp->FInit(&Credentials); BAIL_ON_FAILURE(hr);
//
// IMalloc->Alloc is the way we have to allocate memory for out parameters
//
hr = CoGetMalloc(MEMCTX_TASK, &_pIMalloc); BAIL_ON_FAILURE(hr);
//
// Establish parent object pointer
//
_pDSO = pDSO; _Credentials = Credentials; _pDSO->AddRef(); _pDSO->IncrementOpenSessions();
return( TRUE );
error:
RRETURN( FALSE ); }
STDMETHODIMP CSessionObject::QueryInterface(REFIID iid, LPVOID FAR* ppv) { if( ppv == NULL ) RRETURN( E_INVALIDARG );
if( IsEqualIID(iid, IID_IUnknown) ) { *ppv = (IGetDataSource FAR *) this; } else if( IsEqualIID(iid, IID_IGetDataSource) ) { *ppv = (IGetDataSource FAR *) this; } else if( IsEqualIID(iid, IID_IOpenRowset) ) { *ppv = (IOpenRowset FAR *) this; } else if( IsEqualIID(iid, IID_ISessionProperties) ) { *ppv = (ISessionProperties FAR *) this; } else if( IsEqualIID(iid, IID_IDBCreateCommand) ) { *ppv = (IDBCreateCommand FAR *) this; } #if (!defined(BUILD_FOR_NT40))
else if( IsEqualIID(iid, IID_IBindResource) ) { *ppv = (IBindResource FAR *) this; } #endif
else { *ppv = NULL; return E_NOINTERFACE; }
AddRef(); return NOERROR; }
#if (!defined(BUILD_FOR_NT40))
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::ValidateBindArgs
//
// Synopsis: Validates IBindResource::Bind function arguments.
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::ValidateBindArgs( IUnknown * punkOuter, LPCOLESTR pwszURL, DBBINDURLFLAG dwBindFlags, REFGUID rguid, REFIID riid, IAuthenticate * pAuthenticate, DBIMPLICITSESSION * pImplSession, DWORD * pdwBindStatus, IUnknown ** ppUnk ) { //General validation checks.
if (pwszURL == NULL || InlineIsEqualGUID(rguid,GUID_NULL) || InlineIsEqualGUID(riid, GUID_NULL) || ppUnk == NULL ) RRETURN(E_INVALIDARG);
if (pImplSession && (pImplSession->pUnkOuter == NULL || pImplSession->piid == NULL)) RRETURN(E_INVALIDARG);
if (punkOuter && !InlineIsEqualGUID(riid, IID_IUnknown)) RRETURN(DB_E_NOAGGREGATION);
if (pImplSession && pImplSession->pUnkOuter && pImplSession->piid && !InlineIsEqualGUID(*pImplSession->piid, IID_IUnknown)) RRETURN(DB_E_NOAGGREGATION);
if (dwBindFlags & DBBINDURLFLAG_RECURSIVE) { //if DBBINDURLFLAG_RECURSIVE is set, at least one of the SHARE_DENY
//flags must have been set.
if (! ( (dwBindFlags & DBBINDURLFLAG_SHARE_DENY_READ) || (dwBindFlags & DBBINDURLFLAG_SHARE_DENY_WRITE) || (dwBindFlags & DBBINDURLFLAG_SHARE_EXCLUSIVE) ) ) RRETURN(E_INVALIDARG); }
if (!(dwBindFlags & DBBINDURLFLAG_READ) && !(dwBindFlags & DBBINDURLFLAG_WRITE) ) { // Must have either read or write access:
RRETURN(E_INVALIDARG); }
if (InlineIsEqualGUID(rguid, DBGUID_DSO) && !((dwBindFlags & DBBINDURLFLAG_READ) || (dwBindFlags & DBBINDURLFLAG_ASYNCHRONOUS) || (dwBindFlags & DBBINDURLFLAG_WAITFORINIT) ) ) //if object type is DataSource, only the above flags are allowed
RRETURN(E_INVALIDARG);
if (InlineIsEqualGUID(rguid, DBGUID_SESSION) && ! (dwBindFlags == DBBINDURLFLAG_READ)) //if object type is Session, only DBBINDURLFLAG_READ is allowed
RRETURN(E_INVALIDARG);
if (InlineIsEqualGUID(rguid, DBGUID_ROWSET) && ((dwBindFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) || (dwBindFlags & DBBINDURLFLAG_DELAYFETCHSTREAM) ) ) //if object type is Rowset, DELAYFETCHCOLUMNS and DELAYFETCHSTREAM
//flags are disallowed.
RRETURN ( E_INVALIDARG );
if (InlineIsEqualGUID(rguid, DBGUID_STREAM) && ((dwBindFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) || (dwBindFlags & DBBINDURLFLAG_DELAYFETCHSTREAM) ) ) //if object type is Stream, DELAYFETCHCOLUMNS and
//DELAYFETCHSTREAM flags are disallowed.
RRETURN(E_INVALIDARG);
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::BindToRow
//
// Synopsis: Given a URL, binds to that row object and returns the requested
// interface.
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::BindToRow( IUnknown *punkOuter, LPCOLESTR pwszURL, IAuthenticate *pAuthenticate, DWORD dwBindFlags, REFIID riid, IUnknown** ppUnk ) { CComObject<CRow> *pRow = NULL; auto_rel<IUnknown> pSession; auto_rel<IRow> pRowDelete; HRESULT hr = S_OK;
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.
//Note: this version of auto_rel doesn't addref on assignment.
pRowDelete = pRow; pRowDelete->AddRef();
hr = QueryInterface(__uuidof(IUnknown), (void **)&pSession); if (FAILED(hr)) BAIL_ON_FAILURE(hr = E_FAIL);
//Initialize row and bind it to a Directory Object.
hr = pRow->Initialize((PWSTR)pwszURL, (IUnknown *)pSession, pAuthenticate, dwBindFlags, FALSE, // not a tearoff
FALSE, // don't get column info. from rowset
&_Credentials, true);
if (FAILED(hr)) { if (INVALID_CREDENTIALS_ERROR(hr)) { BAIL_ON_FAILURE(hr = DB_SEC_E_PERMISSIONDENIED); } else { BAIL_ON_FAILURE(hr = DB_E_NOTFOUND); } }
hr = pRow->QueryInterface(riid, (void**)ppUnk); if (FAILED(hr)) BAIL_ON_FAILURE (hr = E_NOINTERFACE);
error:
RRETURN ( hr ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::BindToRowset
//
// Synopsis: Given a URL, binds to a rowset object that has all its child
// nodes as rows and returns the requested interface on the rowset.
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::BindToRowset( IUnknown *pUnkOuter, LPCOLESTR pwszURL, IAuthenticate *pAuthenticate, DWORD dwBindFlags, REFIID riid, IUnknown** ppUnk ) { HRESULT hr; DWORD fAuthFlags;
DBID tableID; tableID.eKind = DBKIND_NAME; tableID.uName.pwszName = (LPWSTR) pwszURL;
//Create the rowset.
// Fix for 351040. First try explicit credentials, then session object's
// credentials, then default credentials.
if(pAuthenticate) { CCredentials creds;
hr = GetCredentialsFromIAuthenticate(pAuthenticate, creds); if (FAILED(hr)) BAIL_ON_FAILURE(hr = E_INVALIDARG);
fAuthFlags = creds.GetAuthFlags(); creds.SetAuthFlags(fAuthFlags | ADS_SECURE_AUTHENTICATION);
hr = OpenRowsetWithCredentials(pUnkOuter, &tableID, NULL, riid, 0, NULL, &creds, ppUnk); }
if( (!pAuthenticate) || (INVALID_CREDENTIALS_ERROR(hr)) ) // try credentials in session object
hr = OpenRowset(pUnkOuter, &tableID, NULL, riid, 0, NULL, ppUnk);
if(INVALID_CREDENTIALS_ERROR(hr)) // try default credentials
{ CCredentials creds; // default credentials
fAuthFlags = creds.GetAuthFlags(); creds.SetAuthFlags(fAuthFlags | ADS_SECURE_AUTHENTICATION);
hr = OpenRowsetWithCredentials(pUnkOuter, &tableID, NULL, riid, 0, NULL, &creds, ppUnk); }
BAIL_ON_FAILURE(hr);
RRETURN ( S_OK );
error: RRETURN ( hr ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::BindFlagsFromDbProps
//
// Synopsis: Synthesizes bind flags from initialization properties
// DBPROP_INIT_MODE and DBPROP_INIT_BINDFLAGS
//
//----------------------------------------------------------------------------
DWORD CSessionObject::BindFlagsFromDbProps() { HRESULT hr = S_OK; auto_rel<IDBProperties> pDBProp; ULONG i, j, cPropertySets = 0; DWORD dwMode = 0, dwBindFlags = 0, dwBindFlagProp = 0; DWORD dwResult = 0;
hr = GetDataSource(__uuidof(IDBProperties), (IUnknown **)&pDBProp); BAIL_ON_FAILURE(hr);
DBPROPID propids[2]; propids[0] = DBPROP_INIT_MODE; propids[1] = DBPROP_INIT_BINDFLAGS;
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]; ADsAssert(pProp); if (pProp->dwStatus == S_OK && pProp->dwPropertyID == DBPROP_INIT_MODE) dwMode = V_I4(&pProp->vValue); else if (pProp->dwStatus == S_OK && pProp->dwPropertyID == DBPROP_INIT_BINDFLAGS) dwBindFlagProp = V_I4(&pProp->vValue); else continue; } }
//Now extract bind flags from dwMode and dwBindFlagProp
{ 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 |= dwMode & dwModeMask;
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 |= dwBindFlagProp | dwBindFlags; }
error: for (i = 0; i < cPropertySets; i++) { for (j = 0; j < prgPropertySets[i].cProperties; j++) { DBPROP *pProp = &(prgPropertySets[i].rgProperties[j]); ADsAssert(pProp); FreeDBID(&pProp->colid); VariantClear(&pProp->vValue); }
CoTaskMemFree(prgPropertySets[i].rgProperties); } CoTaskMemFree(prgPropertySets);
RRETURN ( dwResult ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::BindToDataSource
//
// Synopsis: Initializes the DataSource object if necessary, Sets
// DBPROP_INIT_PROVIDERSTRING property and returns the requested
// interface on the datasource.
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::BindToDataSource( IUnknown *pUnkOuter, LPCOLESTR pwszURL, IAuthenticate *pAuthenticate, DWORD dwBindFlags, REFIID riid, IUnknown** ppUnk ) { HRESULT hr = S_OK; auto_rel<IDBProperties> pDBProperties; DBPROP props[1]; DBPROPSET rgPropertySets[1]; CComBSTR bstrURL(pwszURL);
//Initialize DBPROP_INIT_PROVIDERSTRING only if the
//URL is absolute.
if (bIsAbsoluteURL (pwszURL)) { // Check if the datasource has already been initialized.
if (_pDSO->IsInitialized()) BAIL_ON_FAILURE(hr = DB_E_ALREADYINITIALIZED); props[0].dwPropertyID = DBPROP_INIT_PROVIDERSTRING; props[0].dwOptions = DBPROPOPTIONS_OPTIONAL; props[0].vValue.vt = VT_BSTR; props[0].vValue.bstrVal = (PWCHAR)bstrURL;
rgPropertySets[0].rgProperties = props; rgPropertySets[0].cProperties = 1; rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
hr = GetDataSource( __uuidof(IDBProperties), (IUnknown **)&pDBProperties ); BAIL_ON_FAILURE(hr);
hr = pDBProperties->SetProperties(1, rgPropertySets); BAIL_ON_FAILURE(hr); } // If consumer doesn't specify DBBINDURLFLAG_WAITFORINIT, it
// means consumer wants an initialized DSO
//
if (! (dwBindFlags & DBBINDURLFLAG_WAITFORINIT)) { auto_rel<IDBInitialize> pDBInitialize;
hr = GetDataSource(__uuidof(IDBInitialize), (IUnknown **)&pDBInitialize); BAIL_ON_FAILURE(hr);
hr = pDBInitialize->Initialize(); BAIL_ON_FAILURE(hr); }
//Return the requested interface on the DSO.
hr = GetDataSource(riid, ppUnk); BAIL_ON_FAILURE(hr);
error:
RRETURN ( hr ); }
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::BuildAbsoluteURL
//
// Synopsis: Given a relative URL, builds absolute URL using the relative URL
// and the property DBPROP_INIT_PROVIDERSTRING.
//
//----------------------------------------------------------------------------
HRESULT CSessionObject::BuildAbsoluteURL( CComBSTR bstrLeaf, CComBSTR& bstrAbsoluteURL ) { HRESULT hr = S_OK; auto_rel<IDBProperties> pDBProp; auto_rel<IADsPathname> pPathParent; auto_rel<IADsPathname> pPathLeaf; ULONG cPropertySets = 0; long i, j, cElements = 0; CComBSTR bstrParent; DBPROPSET* prgPropertySets = NULL; DBPROPID propids[1]; DBPROPIDSET rgPropertyIDSets[1];
hr = GetDataSource(__uuidof(IDBProperties), (IUnknown **)&pDBProp); BAIL_ON_FAILURE(hr);
propids[0] = DBPROP_INIT_PROVIDERSTRING;
rgPropertyIDSets[0].rgPropertyIDs = propids; rgPropertyIDSets[0].cPropertyIDs = 1; rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
hr = pDBProp->GetProperties( 1, rgPropertyIDSets, &cPropertySets, &prgPropertySets);
if (SUCCEEDED(hr) && cPropertySets == 1) { ADsAssert(prgPropertySets != NULL); ADsAssert(prgPropertySets[0].rgProperties != NULL);
DBPROP* pProp = & (prgPropertySets[0].rgProperties[0]);
bstrParent = pProp->vValue.bstrVal; }
// Build Absolute Path from Parent and leaf.
hr = CPathname::CreatePathname( __uuidof(IADsPathname), (void **)&pPathParent ); BAIL_ON_FAILURE(hr);
hr = pPathParent->Set(bstrParent, ADS_SETTYPE_FULL); BAIL_ON_FAILURE(hr);
if (bstrLeaf.Length() > 0) { hr = CPathname::CreatePathname( __uuidof(IADsPathname), (void **)&pPathLeaf ); BAIL_ON_FAILURE(hr);
hr = pPathLeaf->Set(bstrLeaf, ADS_SETTYPE_DN); BAIL_ON_FAILURE(hr);
hr = pPathLeaf->GetNumElements(&cElements); BAIL_ON_FAILURE(hr);
//Add leaf elements in reverse order.
//Ex: if bstrLeaf = "CN=Administrator,CN=Users",
//we add CN=Users first.
for (i = cElements-1; i >= 0; i--) { CComBSTR bstrElement; hr = pPathLeaf->GetElement(i, &bstrElement); BAIL_ON_FAILURE(hr);
hr = pPathParent->AddLeafElement(bstrElement); BAIL_ON_FAILURE(hr); } } //Read back the fully built path name
hr = pPathParent->Retrieve(ADS_FORMAT_X500, &bstrAbsoluteURL); BAIL_ON_FAILURE(hr);
error: // Free memory allocated by GetProperties
for (i = 0; i < cPropertySets; i++) { for (j = 0; j < prgPropertySets[i].cProperties; j++) { DBPROP *pProp = &(prgPropertySets[i].rgProperties[j]); ADsAssert(pProp);
// We should free the DBID in pProp, but we know that
// GetProperties always returns DB_NULLID and FreeDBID doesn't
// handle DB_NULLID. So, DBID is not freed here.
VariantClear(&pProp->vValue); }
CoTaskMemFree(prgPropertySets[i].rgProperties); } CoTaskMemFree(prgPropertySets);
RRETURN(hr); }
extern PROUTER_ENTRY g_pRouterHead; extern CRITICAL_SECTION g_csRouterHeadCritSect;
//+---------------------------------------------------------------------------
//
// Function: CSessionObject::bIsAbsoluteURL
//
// Synopsis: If the given URL starts with any of the ADS provider prefixes,
// returns true. Returns false otherwise.
//
//----------------------------------------------------------------------------
bool CSessionObject::bIsAbsoluteURL( LPCOLESTR pwszURL) { if (pwszURL == NULL) return false;
//
// Make sure the router has been initialized
//
EnterCriticalSection(&g_csRouterHeadCritSect); if (!g_pRouterHead) { g_pRouterHead = InitializeRouter(); } LeaveCriticalSection(&g_csRouterHeadCritSect);
for (PROUTER_ENTRY pProvider = g_pRouterHead; pProvider != NULL; pProvider = pProvider->pNext) { if (pProvider->szProviderProgId == NULL) continue;
size_t strSize = wcslen(pProvider->szProviderProgId); if ( _wcsnicmp(pwszURL, pProvider->szProviderProgId, strSize) == 0 ) return true; }
// Given URL doesn't start with any of the ADSI provider prefixes.
return false; }
#endif
//-----------------------------------------------------------------------------
// SetSearchPrefs
//
// Sets ADSI search preferences on the property object.
//
//-----------------------------------------------------------------------------
STDMETHODIMP CSessionObject::SetSearchPrefs( void ) { PROPSET *pPropSet; PADS_SEARCHPREF_INFO pSearchPref = NULL; HRESULT hr = S_OK; ULONG i;
//
// Asserts
//
ADsAssert(_pUtilProp); ADsAssert(_pDSSearch);
pPropSet = _pUtilProp->GetPropSetFromGuid(DBPROPSET_ADSISEARCH);
if( !pPropSet || !pPropSet->cProperties ) RRETURN( S_OK );
pSearchPref = (PADS_SEARCHPREF_INFO) AllocADsMem( pPropSet->cProperties * sizeof(ADS_SEARCHPREF_INFO) ); if( !pSearchPref ) BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
for (i=0; i<pPropSet->cProperties; i++) { hr = _pUtilProp->GetSearchPrefInfo( pPropSet->pUPropInfo[i].dwPropertyID, &pSearchPref[i] ); BAIL_ON_FAILURE( hr ); }
hr = _pDSSearch->SetSearchPreference( pSearchPref, pPropSet->cProperties );
_pUtilProp->FreeSearchPrefInfo(pSearchPref, pPropSet->cProperties);
BAIL_ON_FAILURE( hr );
error:
if( pSearchPref ) FreeADsMem(pSearchPref);
RRETURN( hr ); }
|