Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2058 lines
50 KiB

//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: ccommand.cxx
//
// Contents: Microsoft OleDB/OleDS Data Source Object for ADSI
//
//
// History: 08-01-96 shanksh Created.
//
//----------------------------------------------------------------------------
#include "oleds.hxx"
#pragma hdrstop
static WCHAR gpszADsPathAttr[] = L"ADsPath";
static BOOL
IsAutomatable(
DBTYPE dbType
);
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::AddRefAccessor
//
// Synopsis:
//
// Arguments:
//
//
// Returns:
//
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::AddRefAccessor(
HACCESSOR hAccessor,
DBREFCOUNT * pcRefCount
)
{
//
// Asserts
//
ADsAssert(_pAccessor);
RRETURN( _pAccessor->AddRefAccessor(
hAccessor,
pcRefCount) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::CreateAccessor
//
// Synopsis:
//
// Arguments:
//
//
// Returns:
//
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::CreateAccessor(
DBACCESSORFLAGS dwAccessorFlags,
DBCOUNTITEM cBindings,
const DBBINDING rgBindings[],
DBLENGTH cbRowSize,
HACCESSOR * phAccessor,
DBBINDSTATUS rgStatus[]
)
{
//
// Asserts
//
ADsAssert(_pAccessor);
RRETURN( _pAccessor->CreateAccessor(
dwAccessorFlags,
cBindings,
rgBindings,
cbRowSize,
phAccessor,
rgStatus) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::ReleaseAccessor
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::ReleaseAccessor(
HACCESSOR hAccessor,
DBREFCOUNT * pcRefCount
)
{
//
// Asserts
//
ADsAssert(_pAccessor);
RRETURN( _pAccessor->ReleaseAccessor(
hAccessor,
pcRefCount) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::GetBindings
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::GetBindings(
HACCESSOR hAccessor,
DBACCESSORFLAGS * pdwAccessorFlags,
DBCOUNTITEM * pcBindings,
DBBINDING ** prgBindings
)
{
//
// Asserts
//
ADsAssert(_pAccessor);
RRETURN( _pAccessor->GetBindings(
hAccessor,
pdwAccessorFlags,
pcBindings, prgBindings) );
}
STDMETHODIMP
CCommandObject::GetColumnInfo2(
DBORDINAL * pcColumns,
DBCOLUMNINFO ** prgInfo,
OLECHAR ** ppStringBuffer,
BOOL ** ppfMultiValued
)
{
HRESULT hr;
ULONG pos, nStringBufLen;
DBCOLUMNINFO *pInfo=NULL;
OLECHAR* pStringBuffer=NULL ;
DWORD i;
DBTYPE wType;
DWORD cAttrsReturned;
LPWSTR *ppszTmpAttrs = NULL;
DWORD cTmpAttrs;
IDirectorySchemaMgmt *pDSAttrMgmt = NULL;
PADS_ATTR_DEF pAttrDefinition = NULL;
ADsAssert(_pIMalloc != NULL);
//
// IMalloc->Alloc is the way we have to allocate memory for out parameters
//
nStringBufLen = 0;
for (i=0; i < _cAttrs; i++) {
nStringBufLen += (wcslen(_ppszAttrs[i]) + 1) * sizeof (WCHAR);
}
nStringBufLen+= sizeof(WCHAR); // For the bookmark column which is a null string
//
// No. of DBCOLUMN structures to be allocated
//
pInfo = (DBCOLUMNINFO *)_pIMalloc->Alloc((_cAttrs+1)*sizeof(DBCOLUMNINFO));
if( !pInfo ) {
hr = E_OUTOFMEMORY;
goto error;
}
memset(pInfo, 0, (_cAttrs*sizeof(DBCOLUMNINFO)));
pStringBuffer = (WCHAR *)_pIMalloc->Alloc(nStringBufLen);
if( !pStringBuffer ) {
hr = E_OUTOFMEMORY;
goto error;
};
memset(pStringBuffer, 0, nStringBufLen);
//
// Get the attribute types by enquiring the DS schema
//
hr = _pDSSearch->QueryInterface(
IID_IDirectorySchemaMgmt,
(void**)&pDSAttrMgmt
);
BAIL_ON_FAILURE( hr );
// Fix for #285757. We should not send the ADsPath attribute to the
// server. So, search for occurences of this attribute and remove them.
ppszTmpAttrs = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * _cAttrs);
if(NULL == ppszTmpAttrs)
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
cTmpAttrs = 0;
for(i = 0; i < _cAttrs; i++)
{
if( _wcsicmp(L"ADsPath", _ppszAttrs[i]) )
{
ppszTmpAttrs[cTmpAttrs] = _ppszAttrs[i];
cTmpAttrs++;
}
}
// Request attributes only if there is some attribute other than ADsPath
if(cTmpAttrs)
hr = pDSAttrMgmt->EnumAttributes(
ppszTmpAttrs,
cTmpAttrs,
&pAttrDefinition,
&cAttrsReturned
);
else
{
cAttrsReturned = 0;
pAttrDefinition = NULL;
}
if(ppszTmpAttrs != NULL)
FreeADsMem(ppszTmpAttrs);
pDSAttrMgmt->Release();
pDSAttrMgmt = NULL;
BAIL_ON_FAILURE( hr );
//fill up the Bookmark column
// bookmark name is empty string
pInfo[0].pwszName = NULL;
pInfo[0].columnid.eKind = DBKIND_GUID_PROPID;
pInfo[0].columnid.uGuid.guid = DBCOL_SPECIALCOL;
pInfo[0].columnid.uName.ulPropid = 2; // Value from note about
// bookmarks in spec.
pInfo[0].pTypeInfo = NULL;
pInfo[0].iOrdinal = 0;
pInfo[0].ulColumnSize = sizeof(ULONG);
pInfo[0].wType = DBTYPE_UI4;
pInfo[0].bPrecision = 10; // Precision for I4.
pInfo[0].bScale = (BYTE) ~ 0;
pInfo[0].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK
| DBCOLUMNFLAGS_ISFIXEDLENGTH;
//
// Fill up the columnsinfo by getting the attribute types
//
pos = 0;
for(i=0; i < _cAttrs; i++) {
wcscpy(&pStringBuffer[pos], _ppszAttrs[i]);
pInfo[i+1].pwszName= &pStringBuffer[pos];
//
// Get the type and size of the attribute
//
// Because of a Temporary bug in TmpTable, ~0 (specifying variable
// size) is replaced by 256. This does not actually put a memory
// restriction on the column size, but done merely to avoid the bug.
//
if( _wcsicmp(_ppszAttrs[i], L"ADsPath") == 0) {
pInfo[i+1].wType = DBTYPE_WSTR|DBTYPE_BYREF;
// pInfo[i+1].ulColumnSize = (ULONG) ~0;
pInfo[i+1].ulColumnSize = (ULONG)256;
}
else {
hr = GetDBType(
pAttrDefinition,
cAttrsReturned,
_ppszAttrs[i],
&pInfo[i+1].wType,
&pInfo[i+1].ulColumnSize
);
if( FAILED(hr) )
BAIL_ON_FAILURE( hr=E_FAIL );
}
wType = pInfo[i+1].wType & ~DBTYPE_BYREF;
// any change made to setting dwFlags below should also be made in
// GetRestrictedColumnInfo in row.cxx, for consistency
if( (wType == DBTYPE_STR) ||
(wType == DBTYPE_WSTR) ||
(wType == DBTYPE_BYTES) )
pInfo[i+1].dwFlags = DBCOLUMNFLAGS_ISNULLABLE;
else {
// Temporary check
// pInfo[i+1].dwFlags = (0);
pInfo[i+1].dwFlags = DBCOLUMNFLAGS_ISNULLABLE |
DBCOLUMNFLAGS_ISFIXEDLENGTH;
}
pInfo[i+1].pTypeInfo = NULL;
pInfo[i+1].iOrdinal = i+1;
pInfo[i+1].bPrecision = SetPrecision(wType);
pInfo[i+1].bScale = (UCHAR) ~0;
pInfo[i+1].columnid.eKind=DBKIND_NAME;
pInfo[i+1].columnid.uGuid.guid=GUID_NULL;
pInfo[i+1].columnid.uName.pwszName=pInfo[i+1].pwszName;
pos += (wcslen(_ppszAttrs[i]) + 1);
}
if( ppfMultiValued ) {
//
// Filling in MultiValue array
//
BOOL * pfMultiValuedTemp;
pfMultiValuedTemp= (BOOL *) AllocADsMem(sizeof(BOOL) * (_cAttrs+1));
if( !(pfMultiValuedTemp) ) {
hr=E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pfMultiValuedTemp[0] = FALSE; // First one is bookmark which is always FALSE
for(ULONG j=0; j < _cAttrs; j++) {
for(ULONG k=0; k < cAttrsReturned; k++) {
if( !_wcsicmp(_ppszAttrs[j], pAttrDefinition[k].pszAttrName) )
break;
}
if( (k != cAttrsReturned) &&
(pAttrDefinition[k].fMultiValued &&
IsAutomatable(g_MapADsTypeToVarType[pAttrDefinition[k].dwADsType]))) {
pfMultiValuedTemp[j+1] = TRUE;
}
else {
pfMultiValuedTemp[j+1] = FALSE;
}
}
*ppfMultiValued = pfMultiValuedTemp;
}
if( pAttrDefinition ) {
FreeADsMem(pAttrDefinition);
}
*pcColumns = _cAttrs + 1;
*prgInfo = pInfo;
*ppStringBuffer = pStringBuffer;
RRETURN( S_OK );
error:
if( pInfo != NULL )
_pIMalloc->Free(pInfo);
if( pStringBuffer != NULL )
_pIMalloc->Free(pStringBuffer);
if( pAttrDefinition ) {
FreeADsMem(pAttrDefinition);
}
if (pDSAttrMgmt) {
pDSAttrMgmt->Release();
}
RRETURN( hr );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::GetColumnInfo
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
//
// Modifies:
//
// History: 10-10-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::GetColumnInfo(
DBORDINAL * pcColumns,
DBCOLUMNINFO ** prgInfo,
OLECHAR ** ppStringBuffer
)
{
if( pcColumns )
*pcColumns = 0;
if( prgInfo )
*prgInfo = NULL;
if( ppStringBuffer )
*ppStringBuffer = NULL;
if( !pcColumns || !prgInfo || !ppStringBuffer )
RRETURN( E_INVALIDARG );
if( !IsCommandSet() )
RRETURN( DB_E_NOCOMMAND );
if( !IsCommandPrepared() )
RRETURN( DB_E_NOTPREPARED );
RRETURN( GetColumnInfo2(
pcColumns,
prgInfo,
ppStringBuffer,
NULL
) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::MapColumnIDs
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::MapColumnIDs(
DBORDINAL cColumnIDs,
const DBID rgColumnIDs[],
DBORDINAL rgColumns[]
)
{
DBORDINAL cValidCols = 0;
//
// No Column IDs are set when GetColumnInfo returns ColumnsInfo structure.
// Hence, any value of ID will not match with any column
//
DBORDINAL iCol;
if( cColumnIDs == 0 )
RRETURN( S_OK );
// Spec-defined checks.
// Note that this guarantees we can access rgColumnIDs[] in loop below.
// (Because we'll just fall through.)
if ( cColumnIDs && (!rgColumnIDs || !rgColumns) )
RRETURN( E_INVALIDARG );
if( !IsCommandSet() )
RRETURN( DB_E_NOCOMMAND );
if( !IsCommandPrepared() )
RRETURN( DB_E_NOTPREPARED );
//
// Set the columns ordinals to invalid values
//
for(iCol=0; iCol < cColumnIDs; iCol++) {
// Initialize
rgColumns[iCol] = DB_INVALIDCOLUMN;
//
// The columnid with the Bookmark ID
//
if( rgColumnIDs[iCol].eKind == DBKIND_GUID_PROPID &&
rgColumnIDs[iCol].uGuid.guid == DBCOL_SPECIALCOL &&
rgColumnIDs[iCol].uName.ulPropid == 2 ) {
rgColumns[iCol] = 0;
cValidCols++;
continue;
}
//
// The columnid with the Column Name
//
if( rgColumnIDs[iCol].eKind == DBKIND_NAME &&
rgColumnIDs[iCol].uName.pwszName ) {
//
// Find the name in the list of Attributes
//
for (ULONG iOrdinal=0; iOrdinal < _cAttrs; iOrdinal++) {
if( !_wcsicmp(_ppszAttrs[iOrdinal],
rgColumnIDs[iCol].uName.pwszName) ) {
rgColumns[iCol] = iOrdinal+1;
cValidCols++;
break;
}
}
}
}
if( cValidCols == 0 )
RRETURN( DB_E_ERRORSOCCURRED );
else if( cValidCols < cColumnIDs )
RRETURN( DB_S_ERRORSOCCURRED );
else
RRETURN( S_OK );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::Cancel
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::Cancel(
void
)
{
//
// Need to protect _dwStatus for mutual exclusion when we support
// multiple threads acting on the same Command object
//
_dwStatus |= CMD_EXEC_CANCELLED;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::Execute
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::Execute(
IUnknown * pUnkOuter,
REFIID riid,
DBPARAMS * pParams,
DBROWCOUNT *pcRowsAffected,
IUnknown ** ppRowset
)
{
HRESULT hr;
DWORD dwFlags = 0;
ULONG cAccessors = 0;
HACCESSOR *prgAccessors = NULL;
BOOL *pbMultiValued = NULL;
CRowProvider *pRowProvider = NULL;
DBORDINAL cColumns = 0;
DBCOLUMNINFO *prgInfo = NULL;
WCHAR *pStringBuffer = NULL;
ULONG cPropertySets = 0;
DBPROPSET *prgPropertySets = NULL;
ULONG i, j;
ADsAssert(_pIMalloc != NULL);
ADsAssert(_pAccessor != NULL);
ADsAssert(_pCSession != NULL);
if( ppRowset )
*ppRowset = NULL;
if( pcRowsAffected )
*pcRowsAffected= -1;
//
// If the IID asked for is IID_NULL, then we can expect
// that this is a non-row returning statement
//
if( riid == IID_NULL )
dwFlags |= EXECUTE_NOROWSET;
//
// Check Arguments - Only check on row returning statements
//
if( !(dwFlags & EXECUTE_NOROWSET) &&
(ppRowset == NULL) )
RRETURN( E_INVALIDARG );
//
// Only 1 ParamSet if ppRowset is non-null
//
if( pParams &&
(pParams->cParamSets > 1) &&
ppRowset )
RRETURN( E_INVALIDARG );
//
// Check that a command has been set
//
if( !IsCommandSet() )
RRETURN( DB_E_NOCOMMAND );
if( pUnkOuter )
RRETURN( DB_E_NOAGGREGATION );
//
// Prepare the Command if not already done
//
if( !IsCommandPrepared() ) {
hr = PrepareHelper();
BAIL_ON_FAILURE( hr );
}
//
// Check for a non row returning statement
//
if( dwFlags & EXECUTE_NOROWSET )
RRETURN( S_OK );
//
// Get ColumnsInfo based on the list of attributes that we want to be
// returned
//
hr = GetColumnInfo2(
&cColumns,
&prgInfo,
&pStringBuffer,
&pbMultiValued
);
BAIL_ON_FAILURE( hr );
//
// Commit the properties in the Command Object as the preferences to the
// search
//
hr = SetSearchPrefs();
BAIL_ON_FAILURE( hr );
//
// Create RowProvider object to pass to rowset code
//
_pDSSearch->AddRef();
hr= CRowProvider::CreateRowProvider(
_pDSSearch,
_pszSearchFilter,
_ppszAttrs,
_cAttrs,
cColumns,
prgInfo,
pStringBuffer,
IID_IRowProvider,
pbMultiValued,
_fADSPathPresent,
NULL,
(void **) &pRowProvider);
BAIL_ON_FAILURE( hr );
pbMultiValued = NULL; // RowProvider responsible for deallocation
//
// We no longer need the ColumnsInfo; Release it
//
if (prgInfo)
{
_pIMalloc->Free(prgInfo);
prgInfo = NULL;
}
if (pStringBuffer)
{
_pIMalloc->Free(pStringBuffer);
pStringBuffer = NULL;
}
if( _pAccessor &&
_pAccessor->_pextbuffer ) {
cAccessors = _pAccessor->_pextbuffer->GetLastHandleCount();
if( cAccessors > 0 ) {
prgAccessors = (HACCESSOR *) AllocADsMem(
sizeof(HACCESSOR) * cAccessors
);
if( !prgAccessors )
cAccessors = 0;
else
for(ULONG i=0; i<cAccessors; i++)
prgAccessors[i] = i+1;
}
}
hr = GetProperties(0, NULL, &cPropertySets, &prgPropertySets);
BAIL_ON_FAILURE( hr );
hr= CRowset::CreateRowset(
pRowProvider,
(LPUNKNOWN)(IAccessor FAR *)this ,
NULL,
this,
cPropertySets,
prgPropertySets,
cAccessors,
prgAccessors,
_fADSPathPresent,
_fAllAttrs,
riid,
ppRowset
);
if (prgAccessors)
{
FreeADsMem(prgAccessors);
prgAccessors = NULL;
}
BAIL_ON_FAILURE( hr );
error:
if (FAILED(hr))
{
//
// Remove the Prepare flag,
//
_dwStatus &= ~(CMD_PREPARED);
}
//
// Free the memory
//
if( pRowProvider )
pRowProvider->Release();
if( prgInfo )
_pIMalloc->Free(prgInfo);
if( pStringBuffer )
_pIMalloc->Free(pStringBuffer);
if( prgAccessors )
FreeADsMem(prgAccessors);
if( pbMultiValued ) {
FreeADsMem(pbMultiValued);
}
// 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);
}
_pIMalloc->Free(prgPropertySets[i].rgProperties);
}
_pIMalloc->Free(prgPropertySets);
RRETURN( hr );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::GetDBSession
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::GetDBSession(
REFIID riid,
IUnknown ** ppSession
)
{
HRESULT hr;
//
// Asserts
//
ADsAssert(_pCSession);
//
// Check Arguments
//
if( ppSession == NULL )
RRETURN( E_INVALIDARG );
//
// Query for the interface on the session object. If failure,
// return the error from QueryInterface.
//
RRETURN( (_pCSession)->QueryInterface(riid, (VOID**)ppSession) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::GetProperties
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::GetProperties(
const 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_COMMAND);
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_COMMAND) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::SetProperties
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::SetProperties(
ULONG cPropertySets,
DBPROPSET rgPropertySets[]
)
{
//
// Asserts
//
ADsAssert(_pUtilProp);
// Don't allow properties to be set if we've got a rowset open
if( IsRowsetOpen() )
RRETURN( DB_E_OBJECTOPEN );
//
// Just pass this call on to the utility object that manages our properties
//
RRETURN( _pUtilProp->SetProperties(
cPropertySets,
rgPropertySets,
PROPSET_COMMAND) );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::GetCommandText
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::GetCommandText(
GUID * pguidDialect,
LPOLESTR * ppwszCommand
)
{
HRESULT hr = S_OK;
ADsAssert(_pIMalloc!= NULL);
//
// Check Function Arguments
//
if( ppwszCommand == NULL ) {
hr = E_INVALIDARG;
goto error;
}
*ppwszCommand = NULL;
//
// If the command has not been set, make sure the buffer
// contains an empty stringt to return to the consumer
//
if( !IsCommandSet() ) {
hr = DB_E_NOCOMMAND;
goto error;
}
//
// Allocate memory for the string we're going to return to the caller
//
*ppwszCommand = (LPWSTR)_pIMalloc->Alloc((wcslen(_pszCommandText)+1) * sizeof(WCHAR));
if( !*ppwszCommand ) {
hr = E_OUTOFMEMORY;
goto error;
}
//
// Copy our saved text into the newly allocated string
//
wcscpy(*ppwszCommand, _pszCommandText);
//
// If the text we're giving back is a different dialect than was
// requested, let the caller know what dialect the text is in
//
if( pguidDialect != NULL && *pguidDialect != _guidCmdDialect)
{
hr = DB_S_DIALECTIGNORED;
*pguidDialect = _guidCmdDialect;
}
error:
if( FAILED(hr) ) {
if( pguidDialect )
memset(pguidDialect, 0, sizeof(GUID));
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::SetCommandText
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::SetCommandText(
REFGUID rguidDialect,
LPCOLESTR pszCommand
)
{
// Don't allow text to be set if we've got a rowset open
if( IsRowsetOpen() )
RRETURN( DB_E_OBJECTOPEN );
// Check Dialect
if( rguidDialect != DBGUID_LDAPDialect &&
rguidDialect != DBGUID_DBSQL &&
rguidDialect != DBGUID_SQL &&
rguidDialect != DBGUID_DEFAULT )
RRETURN( DB_E_DIALECTNOTSUPPORTED );
//
// If a CommandText is set with a Null or an empty string, it effectively
// unsets the CommandText to a null string
//
if( (pszCommand == NULL) ||
(*pszCommand == L'\0') ) {
if( _dwStatus & CMD_TEXT_SET )
FreeADsStr(_pszCommandText);
_pszCommandText = NULL;
_dwStatus &= ~(CMD_TEXT_SET | CMD_PREPARED);
RRETURN( S_OK );
}
//
// Set the CommandText
//
LPWSTR pszSQLCmd = (LPWSTR)AllocADsMem((wcslen(pszCommand)+1) * sizeof(WCHAR));
if( !pszSQLCmd )
RRETURN( E_OUTOFMEMORY );
//
// Free the old memory, and set new text
//
if( _dwStatus & CMD_TEXT_SET )
FreeADsMem(_pszCommandText);
_pszCommandText = pszSQLCmd;
wcscpy(_pszCommandText, pszCommand);
//
// Reset adspath present flag.
//
_fADSPathPresent = FALSE;
//
// Set status flag that we have set text
//
_dwStatus |= CMD_TEXT_SET;
_dwStatus &= ~CMD_PREPARED;
//
// Remember the dialect that was passed in
//
_guidCmdDialect = rguidDialect;
RRETURN( S_OK );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::CanConvert
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::CanConvert(
DBTYPE wFromType,
DBTYPE wToType,
DBCONVERTFLAGS dwConvertFlags
)
{
RRETURN( CanConvertHelper(
wFromType,
wToType,
dwConvertFlags) );
}
//+---------------------------------------------------------------------------
//
// Function: SplitCommandText
//
// Synopsis:
//
//
// Arguments:
//
//
//
//
//
//
// Returns: HRESULT
// S_OK NO ERROR
// E_ADS_BAD_PARAMETER bad parameter
//
// Modifies:
//
// History: 08-15-96 ShankSh Created.
// 11-21-96 Felix Wong modified to get only bind and attr
//----------------------------------------------------------------------------
HRESULT
CCommandObject::SplitCommandText(
LPWSTR pszParsedCmd
)
{
LPWSTR pszAttrs = NULL;
LPWSTR pszFirstAttr = NULL;
LPWSTR pszCurrentAttr = NULL;
LPWSTR pszSearchScope = NULL;
LPWSTR pszTemp = NULL;
HRESULT hr;
LPWSTR ptr;
// Command Text is the concatenation of three components separated by
// semicolons
//
// 1. ADsPathName of the object of the root of the search which contains
// the host name and the context enclosed by '<' and '>'
// 2. The LDAP search string
// 3. The list of names of the attributes to be returned separated by
// commas
//
// If the attributes have any specifiers like Range (for eg.,
// objectclass;Range=0-1, we need to do some special processing to include
// it in the list of attributes
//
// The fourth component is optional
//
// 4. The scope of the search: Either "Base", "Onelevel", "SubTree"
// (case insensitve)
//
// Search defaults to Subtree
//
// White spaces are insignificant
_searchScope = ADS_SCOPE_SUBTREE;
_pszADsContext = NULL;
_pszSearchFilter = NULL;
if( _ppszAttrs ) {
FreeADsMem(_ppszAttrs);
_ppszAttrs = NULL;
}
if( _pszCommandTextCp ) {
FreeADsStr(_pszCommandTextCp);
_pszCommandTextCp = NULL;
}
_pszCommandTextCp = AllocADsStr(pszParsedCmd);
if( !_pszCommandTextCp)
BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
_pszADsContext = RemoveWhiteSpaces(_pszCommandTextCp);
if( _pszADsContext[0] != L'<' ) {
BAIL_ON_FAILURE( hr=DB_E_ERRORSINCOMMAND);
}
_pszADsContext++;
ptr = _pszADsContext;
hr = SeekPastADsPath(ptr, &ptr);
BAIL_ON_FAILURE( hr );
if( *ptr != L'>' || *(ptr+1) != L';') {
BAIL_ON_FAILURE( hr=DB_E_ERRORSINCOMMAND);
}
*ptr = L'\0';
//
// If the command text does not contain a filter, set it to NULL
//
if (*(ptr + 2) == L';') {
_pszSearchFilter = NULL;
ptr+=2;
}
else {
_pszSearchFilter = ptr + 2;
_pszSearchFilter = RemoveWhiteSpaces(_pszSearchFilter);
hr = SeekPastSearchFilter(_pszSearchFilter, &ptr);
BAIL_ON_FAILURE( hr );
}
if (*ptr != L';') {
BAIL_ON_FAILURE( hr=DB_E_ERRORSINCOMMAND);
}
*ptr = L'\0';
ptr++;
//
// The next component is the list of attributes followed by (optionally)
// the scope of the search
//
// Since the attributes themselves can contain a ';' because of some
// attribute specifiers, we need to make sure which ';' we are looking at.
pszAttrs = ptr;
while ((pszTemp = wcschr(ptr, ';')) != NULL)
if ( !_wcsicmp(pszTemp+1, L"Base") ||
!_wcsicmp(pszTemp+1, L"Onelevel") ||
!_wcsicmp(pszTemp+1, L"Subtree") ) {
//
// we have hit the end of the attribute list
//
*pszTemp = L'\0';
pszSearchScope = pszTemp+1;
break;
}
else {
ptr = pszTemp + 1;
}
if( pszSearchScope ) {
if(!_wcsicmp(pszSearchScope, L"Base"))
_searchScope = ADS_SCOPE_BASE;
else if(!_wcsicmp(pszSearchScope, L"Onelevel"))
_searchScope = ADS_SCOPE_ONELEVEL;
else if(!_wcsicmp(pszSearchScope, L"SubTree"))
_searchScope = ADS_SCOPE_SUBTREE;
else
BAIL_ON_FAILURE( hr=DB_E_ERRORSINCOMMAND);
//
// set the search preference property
//
DBPROPSET rgCmdPropSet[1];
DBPROP rgCmdProp[1];
rgCmdPropSet[0].rgProperties = rgCmdProp;
rgCmdPropSet[0].cProperties = 1;
rgCmdPropSet[0].guidPropertySet = DBPROPSET_ADSISEARCH;
rgCmdProp[0].dwPropertyID = ADS_SEARCHPREF_SEARCH_SCOPE;
rgCmdProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[0].vValue.vt = VT_I4;
V_I4(&rgCmdProp[0].vValue) = _searchScope;
hr = SetProperties(
1,
rgCmdPropSet);
BAIL_ON_FAILURE( hr );
}
pszCurrentAttr = pszFirstAttr = wcstok(pszAttrs, L",");
for (_cAttrs=0; pszCurrentAttr != NULL; _cAttrs++ ) {
pszCurrentAttr = wcstok(NULL, L",");
}
if( _cAttrs == 0 ) {
hr=DB_E_ERRORSINCOMMAND;
goto error;
}
pszFirstAttr = RemoveWhiteSpaces(pszFirstAttr);
if( _cAttrs == 1 && !wcscmp( pszFirstAttr, L"*")) {
// _cAttrs=1; Just ADsPath and Class attribute is sent
_ppszAttrs = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * _cAttrs);
if( !_ppszAttrs )
BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
_ppszAttrs[0] = gpszADsPathAttr;
_fADSPathPresent = TRUE;
_fAllAttrs = TRUE;
}
else {
// Allocate memory for all the string pointers
_ppszAttrs = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * (_cAttrs+1));
if( !_ppszAttrs ) {
BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
}
pszCurrentAttr = pszFirstAttr;
// Remember if adspath and rdn are avaialble or not.
for (ULONG i=0 ; i < _cAttrs; i++) {
if( !_wcsicmp(L"ADsPath", pszCurrentAttr) )
_fADSPathPresent = TRUE;
_ppszAttrs[i] = pszCurrentAttr;
pszCurrentAttr += wcslen(pszCurrentAttr) + 1;
_ppszAttrs[i] = RemoveWhiteSpaces(_ppszAttrs[i]);
}
//
// If adspath is not in the list add it
//
if( _fADSPathPresent == FALSE )
_ppszAttrs[i] = L"ADsPath";
_fAllAttrs = FALSE; // not a SELECT * query
}
RRETURN( S_OK );
error:
_pszADsContext = NULL;
if( _ppszAttrs ) {
FreeADsMem(_ppszAttrs);
_ppszAttrs = NULL;
}
if( _pszCommandTextCp ) {
FreeADsStr(_pszCommandTextCp);
_pszCommandTextCp = NULL;
}
RRETURN( hr );
}
//
// Look up for the given attribute name in the list of ADS_ATTR_DEF structures.
// Convert the ADSTYPE to the appropriate OLE DB type.
//
STDMETHODIMP
CCommandObject::GetDBType(
PADS_ATTR_DEF pAttrDefinition,
DWORD dwNumAttrs,
LPWSTR pszAttrName,
WORD * pwType,
DBLENGTH * pulSize
)
{
HRESULT hr = S_OK;
ADsAssert(pwType && pulSize);
for (ULONG i=0; i < dwNumAttrs; i++) {
if( !_wcsicmp(pszAttrName, pAttrDefinition[i].pszAttrName) )
break;
}
if( i == dwNumAttrs )
BAIL_ON_FAILURE( hr=E_ADS_PROPERTY_NOT_FOUND );
if( pAttrDefinition[i].fMultiValued &&
IsAutomatable(g_MapADsTypeToVarType[pAttrDefinition[i].dwADsType])) {
//
// Can be represented it as a variant
//
*pwType = DBTYPE_VARIANT | DBTYPE_BYREF;
*pulSize = sizeof(VARIANT);
}
else if( (ULONG)pAttrDefinition[i].dwADsType >= g_cMapADsTypeToDBType ||
pAttrDefinition[i].dwADsType == ADSTYPE_INVALID ||
pAttrDefinition[i].dwADsType == ADSTYPE_PROV_SPECIFIC) {
BAIL_ON_FAILURE( hr=E_ADS_CANT_CONVERT_DATATYPE );
}
else {
*pwType = g_MapADsTypeToDBType[pAttrDefinition[i].dwADsType].wType;
*pulSize = g_MapADsTypeToDBType[pAttrDefinition[i].dwADsType].ulSize;
}
error:
RRETURN (hr);
}
STDMETHODIMP
CCommandObject::SetSearchPrefs(
void
)
{
PROPSET *pPropSet;
PADS_SEARCHPREF_INFO pSearchPref = NULL;
HRESULT hr = S_OK;
ULONG i = 0;
//
// 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
);
BAIL_ON_FAILURE( hr );
error:
if( pSearchPref )
{
//
// Free the search preferences that have already been obtained.
// If we didn't encounter an error obtaining the preferences
// then i == pPropSet->cProperties
//
_pUtilProp->FreeSearchPrefInfo(pSearchPref, i);
FreeADsMem(pSearchPref);
}
RRETURN( hr );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::CCommandObject
//
// Synopsis: Constructor
//
// Arguments:
// pUnkOuter Outer Unkown Pointer
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
CCommandObject::CCommandObject(
LPUNKNOWN pUnkOuter // Outer Unkown Pointer
)
{
// Initialize simple member vars
_pUnkOuter = pUnkOuter ? pUnkOuter : (IAccessor FAR *) this;
_dwStatus = 0L;
_cRowsetsOpen = 0;
_pAccessor = NULL;
_pUtilProp = NULL;
_pDSSearch = NULL;
_fADSPathPresent = FALSE;
_fAllAttrs = FALSE;
ENLIST_TRACKING(CCommandObject);
return;
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::~CCommandObject
//
// Synopsis: Destructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
CCommandObject::~CCommandObject( )
{
if( _pCSession ) {
_pCSession->DecrementOpenCommands();
_pCSession->Release();
}
delete _pUtilProp;
if( _pszCommandText ) {
FreeADsMem(_pszCommandText);
}
if( _ppszAttrs ) {
FreeADsMem(_ppszAttrs);
}
if( _pszCommandTextCp ) {
FreeADsStr(_pszCommandTextCp);
}
if( _pAccessor )
delete _pAccessor;
if( _pIMalloc )
_pIMalloc->Release();
if( _pDSSearch ) {
_pDSSearch->Release();
}
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::FInit
//
// Synopsis: Initialize the data source Object
//
// Arguments:
//
// Returns:
// Did the Initialization Succeed
// TRUE Initialization succeeded
// FALSE Initialization failed
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
BOOL
CCommandObject::FInit(
CSessionObject * pSession,
CCredentials& Credentials
)
{
HRESULT hr;
//
// Asserts
//
ADsAssert(pSession);
ADsAssert(&Credentials);
_pCSession = pSession;
_pCSession->AddRef();
_pCSession->IncrementOpenCommands();
//
// Allocate properties management object
//
_pUtilProp = new CUtilProp();
if( !_pUtilProp )
return FALSE;
hr = _pUtilProp->FInit(&Credentials);
BAIL_ON_FAILURE(hr);
// IAccessor is always instantiated.
_pAccessor = new CImpIAccessor(this, _pUnkOuter);
if( _pAccessor == NULL || FAILED(_pAccessor->FInit()) )
return FALSE;
hr = CoGetMalloc(MEMCTX_TASK, &_pIMalloc);
if( FAILED(hr) )
return FALSE;
_Credentials = Credentials;
return TRUE;
error:
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::QueryInterface
//
// Synopsis: Returns a pointer to a specified interface. Callers use
// QueryInterface to determine which interfaces the called object
// supports.
//
// Arguments:
// riid Interface ID of the interface being queried for
// ppv Pointer to interface that was instantiated
//
// Returns:
// S_OK Interface is supported and ppvObject is set.
// E_NOINTERFACE Interface is not supported by the object
// E_INVALIDARG One or more arguments are invalid.
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
// Is the pointer bad?
if( ppv == NULL )
RRETURN( E_INVALIDARG );
if( IsEqualIID(iid, IID_IUnknown) ) {
*ppv = (IAccessor FAR *) this;
}
else if( IsEqualIID(iid, IID_IAccessor) ) {
*ppv = (IAccessor FAR *) this;
}
else if( IsEqualIID(iid, IID_IColumnsInfo) ) {
*ppv = (IColumnsInfo FAR *) this;
}
else if( IsEqualIID(iid, IID_ICommand) ) {
*ppv = (ICommand FAR *) this;
}
else if( IsEqualIID(iid, IID_ICommandProperties) ) {
*ppv = (ICommandProperties FAR *) this;
}
else if( IsEqualIID(iid, IID_ICommandText) ) {
*ppv = (ICommandText FAR *) this;
}
else if( IsEqualIID(iid, IID_IConvertType) ) {
*ppv = (IConvertType FAR *) this;
}
else if( IsEqualIID(iid, IID_ICommandPrepare) ) {
*ppv = (ICommandPrepare FAR *) this;
}
else {
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
BOOL
IsAutomatable(
DBTYPE dbType
)
{
if (dbType != DBTYPE_NULL) {
return TRUE;
}
else {
return FALSE;
}
}
HRESULT
CCommandObject::SeekPastADsPath(
IN LPWSTR pszIn,
OUT LPWSTR * ppszOut
)
{
BOOL fEscapeOn = FALSE, fQuotingOn = FALSE;
WCHAR ch = 0;
// No. of LParans '<' over RParans '>'
DWORD dwParanOffset = 1;
ADsAssert(pszIn);
ADsAssert(ppszOut);
while (1) {
ch = *pszIn;
if( ch == TEXT('\0') ) {
break;
}
if( fEscapeOn ) {
fEscapeOn = FALSE;
}
else if( fQuotingOn ) {
if( ch == TEXT('"') ) {
fQuotingOn = FALSE;
}
}
else if( ch == TEXT('\\') ) {
fEscapeOn = TRUE;
}
else if( ch == TEXT('"') ) {
fQuotingOn = TRUE;
}
else if( ch == L'<' ) {
dwParanOffset++;
}
else if( ch == L'>' ) {
if( --dwParanOffset == 0)
break;
}
pszIn++;
}
if( fEscapeOn || fQuotingOn || dwParanOffset != 0 ) {
RRETURN( DB_E_ERRORSINCOMMAND );
}
*ppszOut = pszIn;
RRETURN( S_OK );
}
HRESULT
CCommandObject::SeekPastSearchFilter(
IN LPWSTR pszIn,
OUT LPWSTR * ppszOut
)
{
BOOL fEscapeOn = FALSE, fQuotingOn = FALSE;
DWORD dwParanOffset = 0;
ADsAssert(pszIn);
if( *pszIn != L'(' ) {
RRETURN( DB_E_ERRORSINCOMMAND );
}
//
// No. of LParans over RParans
//
dwParanOffset = 1;
pszIn++;
while (*pszIn && (*pszIn != L')' || dwParanOffset != 1)) {
if( *pszIn == L'(' ) {
dwParanOffset++;
}
if( *pszIn == L')' ) {
dwParanOffset--;
}
pszIn++;
}
if( *pszIn != L')' ) {
RRETURN( DB_E_ERRORSINCOMMAND );
}
*ppszOut = pszIn + 1;
RRETURN( S_OK );
}
HRESULT
CCommandObject::Prepare(
ULONG cExpectedRuns
)
{
//
// If the command has not been set, make sure the buffer
// contains an empty stringt to return to the consumer
//
if( !IsCommandSet() )
RRETURN( DB_E_NOCOMMAND );
//
// Don't allow prepare if we've got a rowset open
//
if( IsRowsetOpen() )
RRETURN( DB_E_OBJECTOPEN );
//
// SQL dialect: Convert to LDAP and save
//
HRESULT hr = PrepareHelper();
//
// Fixup the HRESULT
//
if( hr == DB_E_NOTABLE )
hr = DB_E_ERRORSINCOMMAND;
BAIL_ON_FAILURE( hr );
//
// Set the Prepare state
//
_dwStatus |= CMD_PREPARED;
error:
RRETURN( hr );
}
HRESULT
CCommandObject::Unprepare()
{
//
// Don't allow unprepare if we've got a rowset open
//
if( IsRowsetOpen() )
RRETURN( DB_E_OBJECTOPEN );
//
// Reset the Prepare state
//
_dwStatus &= ~(CMD_PREPARED);
RRETURN( S_OK );
}
//+---------------------------------------------------------------------------
//
// Function: CCommandObject::PrepareHelper
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-28-96 ShankSh Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CCommandObject::PrepareHelper(void)
{
LPWSTR pszOrderList = NULL;
LPWSTR pszSelect = NULL;
LPWSTR pszLocation = NULL;
LPWSTR pszLdapQuery = NULL;
LPWSTR pszParsedCmd = NULL;
//
// SQL dialect: Convert to LDAP and save
// If SQLParse Fails the function cleans up memory
//
HRESULT hr = SQLParse(
(const LPWSTR) _pszCommandText,
&pszLocation,
&pszLdapQuery,
&pszSelect,
&pszOrderList
);
if( FAILED(hr) && hr != E_ADS_INVALID_FILTER)
RRETURN( hr=DB_E_ERRORSINCOMMAND );
if (SUCCEEDED(hr))
{
//
// the ldap query is optional, it can be NULL. When it is NULL, it
// implies a * search.
//
DWORD dwLdapQuery = 0;
if (pszLdapQuery) {
dwLdapQuery = wcslen(pszLdapQuery);
}
pszParsedCmd =(LPWSTR) AllocADsMem((wcslen(pszLocation) +
dwLdapQuery+
wcslen(pszSelect) +
5 + // 2 semicolons and 2 <
1) * sizeof(WCHAR));
if( !pszParsedCmd ) {
_dwStatus &= ~CMD_TEXT_SET;
BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
}
//
// Put the statement together.
//
wcscpy(pszParsedCmd, L"<");
wcscat(pszParsedCmd, pszLocation);
wcscat(pszParsedCmd, L">;");
if (pszLdapQuery)
wcscat(pszParsedCmd, pszLdapQuery);
wcscat(pszParsedCmd, L";");
wcscat(pszParsedCmd, pszSelect);
hr = SplitCommandText(pszParsedCmd);
}
else
{
//
// Assume valid LDAP filter
//
hr = SplitCommandText(_pszCommandText);
}
BAIL_ON_FAILURE( hr )
//
// Set the sort preference property if necessary
//
if( pszOrderList ) {
DBPROPSET rgCmdPropSet[1];
DBPROP rgCmdProp[1];
rgCmdPropSet[0].rgProperties = rgCmdProp;
rgCmdPropSet[0].cProperties = 1;
rgCmdPropSet[0].guidPropertySet = DBPROPSET_ADSISEARCH;
rgCmdProp[0].dwPropertyID = ADSIPROP_SORT_ON;
rgCmdProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgCmdProp[0].vValue.vt = VT_BSTR;
V_BSTR (&rgCmdProp[0].vValue) = pszOrderList;
hr = SetProperties(1, rgCmdPropSet);
BAIL_ON_FAILURE( hr );
}
if( _pDSSearch ) {
_pDSSearch->Release();
_pDSSearch = NULL;
}
//
// If integrated security is being used, impersonate the caller
//
BOOL fImpersonating;
fImpersonating = FALSE;
if(_pCSession->IsIntegratedSecurity())
{
HANDLE ThreadToken = _pCSession->GetThreadToken();
ASSERT(ThreadToken != NULL);
if (ThreadToken)
{
if (!ImpersonateLoggedOnUser(ThreadToken))
RRETURN(E_FAIL);
fImpersonating = TRUE;
}
else
RRETURN(E_FAIL);
}
hr = GetDSInterface(_pszADsContext,
_Credentials,
IID_IDirectorySearch,
(void **)&_pDSSearch);
if (fImpersonating)
{
RevertToSelf();
fImpersonating = FALSE;
}
BAIL_ON_FAILURE( hr );
error:
if( pszLocation )
FreeADsMem(pszLocation);
if( pszLdapQuery )
FreeADsMem(pszLdapQuery);
if( pszSelect )
FreeADsMem(pszSelect);
if( pszOrderList )
FreeADsStr(pszOrderList);
if( pszParsedCmd )
FreeADsStr(pszParsedCmd);
RRETURN( hr );
}