|
|
//---------------------------------------------------------------------------
//
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cdssrch.cxx
//
// Contents: Microsoft ADs NDS Provider Generic Object
//
//
// History: 03-02-97 ShankSh Created.
//
//----------------------------------------------------------------------------
#include "nds.hxx"
#pragma hdrstop
const int NO_NDS_RESULT_HANDLES = 32; const int NO_UNCACHED_RESULTS_TO_KEEP = 3;
static HRESULT NdsValueToADsColumn( LPWSTR pszColumnName, DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpValue, ADS_SEARCH_COLUMN * pColumn );
static HRESULT NdsValueToADsColumnAppend( DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpObject, ADS_SEARCH_COLUMN * pColumn );
//
// Sets the appropriate search preferences.
//
HRESULT CNDSGenObject::SetSearchPreference( IN PADS_SEARCHPREF_INFO pSearchPrefs, IN DWORD dwNumPrefs ) { HRESULT hr = S_OK; BOOL fWarning = FALSE; DWORD i;
if (!pSearchPrefs && dwNumPrefs > 0) { RRETURN (E_ADS_BAD_PARAMETER); }
for (i=0; i<dwNumPrefs; i++) {
pSearchPrefs[i].dwStatus = ADS_STATUS_S_OK;
switch(pSearchPrefs[i].dwSearchPref) { case ADS_SEARCHPREF_ASYNCHRONOUS: case ADS_SEARCHPREF_SIZE_LIMIT: case ADS_SEARCHPREF_TIME_LIMIT: case ADS_SEARCHPREF_TIMEOUT: case ADS_SEARCHPREF_PAGESIZE: case ADS_SEARCHPREF_PAGED_TIME_LIMIT: case ADS_SEARCHPREF_CHASE_REFERRALS: //
// Can't be set
//
pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF; fWarning = TRUE; continue; case ADS_SEARCHPREF_DEREF_ALIASES: if (pSearchPrefs[i].vValue.dwType != ADSTYPE_INTEGER) { pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; fWarning = TRUE; continue; } switch (pSearchPrefs[i].vValue.Integer) { case ADS_DEREF_NEVER: _SearchPref._fDerefAliases = FALSE; break; case ADS_DEREF_ALWAYS: _SearchPref._fDerefAliases = TRUE; break; default: pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; fWarning = TRUE; continue; } break; case ADS_SEARCHPREF_ATTRIBTYPES_ONLY: if (pSearchPrefs[i].vValue.dwType != ADSTYPE_BOOLEAN) { pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; fWarning = TRUE; continue; } _SearchPref._fAttrsOnly = pSearchPrefs[i].vValue.Boolean; break; case ADS_SEARCHPREF_CACHE_RESULTS: if (pSearchPrefs[i].vValue.dwType != ADSTYPE_BOOLEAN) { pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; fWarning = TRUE; continue; } _SearchPref._fCacheResults = pSearchPrefs[i].vValue.Boolean; break;
case ADS_SEARCHPREF_SEARCH_SCOPE: if (pSearchPrefs[i].vValue.dwType != ADSTYPE_INTEGER) { pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; fWarning = TRUE; continue; } switch (pSearchPrefs[i].vValue.Integer) { case ADS_SCOPE_BASE: _SearchPref._dwSearchScope = DS_SEARCH_ENTRY; break; case ADS_SCOPE_ONELEVEL: _SearchPref._dwSearchScope = DS_SEARCH_SUBORDINATES; break; case ADS_SCOPE_SUBTREE: _SearchPref._dwSearchScope = DS_SEARCH_SUBTREE; break; default: pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE; fWarning = TRUE; continue; } break;
default: pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF; fWarning = TRUE; continue;
} }
RRETURN (fWarning ? S_ADS_ERRORSOCCURRED : S_OK);
}
HRESULT CNDSGenObject::ExecuteSearch( IN LPWSTR pszSearchFilter, IN LPWSTR * pAttributeNames, IN DWORD dwNumberAttributes, OUT PADS_SEARCH_HANDLE phSearchHandle ) { PNDS_SEARCHINFO phSearchInfo = NULL; LPWSTR szCurrAttr = NULL; DWORD dwAttrNamesLen = 0; HRESULT hr = S_OK; ULONG i, j; LPWSTR pszAttrNameBuffer = NULL, *ppszAttrs = NULL;
if (!phSearchHandle) { RRETURN (E_ADS_BAD_PARAMETER); }
//
// Allocate search handle
//
phSearchInfo = (PNDS_SEARCHINFO) AllocADsMem(sizeof(NDS_SEARCHINFO)); if(!phSearchInfo) BAIL_ON_FAILURE (hr = E_OUTOFMEMORY);
hr = AdsNdsGenerateFilterBuffer( _hADsContext, pszSearchFilter, &phSearchInfo->_pFilterBuf ); BAIL_ON_FAILURE(hr);
phSearchInfo->_fADsPathPresent = FALSE; phSearchInfo->_fADsPathReturned = FALSE;
if (dwNumberAttributes == -1) { //
// Specifies returning all attributes
//
phSearchInfo->_ppszAttrs = NULL; phSearchInfo->_pszAttrNameBuffer = NULL; phSearchInfo->_fADsPathPresent = TRUE; phSearchInfo->_nAttrs = (DWORD) -1;
} else { ppszAttrs = (LPWSTR *) AllocADsMem( sizeof(LPWSTR) * (dwNumberAttributes) ); if (!ppszAttrs) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
for (i = 0; i < dwNumberAttributes; i++) dwAttrNamesLen+= (wcslen(pAttributeNames[i]) + 1) * sizeof(WCHAR);
pszAttrNameBuffer = (LPWSTR) AllocADsMem( dwAttrNamesLen ); if (!pszAttrNameBuffer) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
szCurrAttr = pszAttrNameBuffer; for (i = 0, j = 0; i < dwNumberAttributes; i++) { wcscpy(szCurrAttr, pAttributeNames[i]); ppszAttrs[j] = szCurrAttr; szCurrAttr += wcslen(ppszAttrs[j]) + 1;
if(_wcsicmp(ppszAttrs[j], L"ADsPath") == 0) { //
// ADsPath need not be sent
//
phSearchInfo->_fADsPathPresent = TRUE; } else {
j++; }
}
phSearchInfo->_ppszAttrs = ppszAttrs; phSearchInfo->_nAttrs = j; phSearchInfo->_pszAttrNameBuffer = pszAttrNameBuffer; }
phSearchInfo->_lIterationHandle = NO_MORE_ITERATIONS; phSearchInfo->_pSearchResults = NULL; phSearchInfo->_cSearchResults = 0; phSearchInfo->_dwCurrResult = 0; phSearchInfo->_cResultPrefetched = 0; phSearchInfo->_fCheckForDuplicates = TRUE; phSearchInfo->_dwCurrAttr = 0; phSearchInfo->_SearchPref = _SearchPref;
*phSearchHandle = phSearchInfo;
RRETURN(S_OK);
error:
if(phSearchInfo) {
if(phSearchInfo->_ppszAttrs) FreeADsMem(phSearchInfo->_ppszAttrs);
if(phSearchInfo->_pszAttrNameBuffer) FreeADsMem(phSearchInfo->_pszAttrNameBuffer);
FreeADsMem(phSearchInfo); }
RRETURN (hr);
}
HRESULT CNDSGenObject::AbandonSearch( IN ADS_SEARCH_HANDLE hSearchHandle ) { RRETURN(E_NOTIMPL); }
HRESULT CNDSGenObject::CloseSearchHandle ( IN ADS_SEARCH_HANDLE hSearchHandle ) { HRESULT hr = S_OK; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
if (!phSearchInfo) RRETURN (E_ADS_BAD_PARAMETER);
if (phSearchInfo->_pFilterBuf) { ADsNdsFreeBuffer(phSearchInfo->_pFilterBuf); }
if(phSearchInfo->_ppszAttrs) FreeADsMem(phSearchInfo->_ppszAttrs);
if(phSearchInfo->_pszAttrNameBuffer) FreeADsMem(phSearchInfo->_pszAttrNameBuffer);
if (phSearchInfo->_pSearchResults) {
for (DWORD i=0; i < phSearchInfo->_cSearchResults; i++) {
// If we're not caching all results, these may already have been freed
// and set to NULL, but this is okay --- ADsNdsFreeBuffer and
// ADsNdsFreeNdsObjInfoList will catch this.
ADsNdsFreeBuffer(phSearchInfo->_pSearchResults[i]._hSearchResult); ADsNdsFreeNdsObjInfoList(phSearchInfo->_pSearchResults[i]._pObjects, phSearchInfo->_pSearchResults[i]._dwObjects); } FreeADsMem(phSearchInfo->_pSearchResults); }
FreeADsMem(phSearchInfo); RRETURN (hr); }
HRESULT CNDSGenObject::GetFirstRow( IN ADS_SEARCH_HANDLE hSearchHandle ) { RRETURN(E_NOTIMPL); }
HRESULT CNDSGenObject::GetNextRow( IN ADS_SEARCH_HANDLE hSearchHandle ) { HRESULT hr; DWORD dwStatus = NO_ERROR; PNDS_SEARCH_RESULT pResult, pNextResult, pEvictedResult; PADSNDS_OBJECT_INFO pObject, pNextObject; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle; DWORD dwType; DWORD nObjectsSearched; DWORD i;
if (!phSearchInfo) { RRETURN(E_ADS_BAD_PARAMETER); } if (phSearchInfo->_fCheckForDuplicates) { phSearchInfo->_dwCurrAttr = 0; }
//
// dwCurrResult indexes the location of the array where we have already got
// information from. If it is < 0, it indicates that there is no information
// in this searchinfo at all
//
if (phSearchInfo->_dwCurrResult < 0) RRETURN(S_ADS_NOMORE_ROWS);
if (phSearchInfo->_pSearchResults) { pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
//
// If next object is available in current result
//
if (pResult->_pObjects && ((pResult->_dwObjectCurrent+1) < pResult->_dwObjects)) { pResult->_dwObjectCurrent++; RRETURN(S_OK); } if (pResult->_dwObjectCurrent+1 == pResult->_dwObjects && (phSearchInfo->_cResultPrefetched > 0)) { pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult+1]); pNextResult->_dwObjectCurrent = 0; phSearchInfo->_cResultPrefetched--;
//
// If next object points to NULL, it means we have no objects in
// the next row
//
if (!pNextResult->_pObjects) RRETURN(S_ADS_NOMORE_ROWS);
if(phSearchInfo->_fCheckForDuplicates) { pObject = pResult->_pObjects + pResult->_dwObjectCurrent; pNextObject = pNextResult->_pObjects + pNextResult->_dwObjectCurrent; if (!_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// Duplicates; Skip one more result
//
//if (pNextResult->_dwObjectCurrent+1 < pNextResult->_dwObjects)
pNextResult->_dwObjectCurrent++; //else
// RRETURN(S_ADS_NOMORE_ROWS);
} } if( pNextResult->_dwObjectCurrent >= pNextResult->_dwObjects && phSearchInfo->_lIterationHandle == NO_MORE_ITERATIONS) { RRETURN(S_ADS_NOMORE_ROWS); } else { //
// We have successfully moved onto the next value in the array
//
phSearchInfo->_dwCurrResult++;
if ( (phSearchInfo->_dwCurrResult >= NO_UNCACHED_RESULTS_TO_KEEP) && !phSearchInfo->_SearchPref._fCacheResults ) { // Not caching --- evict the old result
pEvictedResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult-NO_UNCACHED_RESULTS_TO_KEEP]);
ADsNdsFreeBuffer(pEvictedResult->_hSearchResult); ADsNdsFreeNdsObjInfoList(pEvictedResult->_pObjects, pEvictedResult->_dwObjects);
pEvictedResult->_hSearchResult = NULL; pEvictedResult->_pObjects = NULL; pEvictedResult->_dwObjects = 0; pEvictedResult->_fInUse = FALSE; }
if ( pNextResult->_dwObjectCurrent >= pNextResult->_dwObjects) { // phSearchInfo->_lIterationHandle != NO_MORE_ITERATIONS
// We have incremented pNextResult->_dwObjectCurrent past the number
// of objects in pNextResult, but there are more iterations left to go.
// This can occur if there was exactly one object in pNextResult, that
// object is a duplicate of the last object in pResult, and there are
// more objects left to retrieve. (This same case can also occur later
// in this function, after calling AdsNdsSearch to get a new result set,
// and code was added there as well to handle it.)
//
// We make it look like we've exhausted the results in pNextResult (which
// we have) and recursively get the next row to get the next
// result set (which may either be prefetched or retrieved from the server
// via AdsNdsSearch). Since _dwCurrResult has already been
// incremented, our pNextResult will be the recursive call's pResult,
// it will look like we've exhausted the objects in the result,
// and it will fetch the next result.
//
// We do this here, after the cache eviction code, so that we evict the
// _dwCurrentResult-NO_UNCACHED_RESULTS_TO_KEEP result before going on
// to _dwCurrentResult+1
pNextResult->_dwObjectCurrent = pNextResult->_dwObjects-1; RRETURN(GetNextRow(hSearchHandle)); } else { // We haven't exhausted pNextResult, so we're done
RRETURN(S_OK); } } } else if( pResult->_dwObjectCurrent+1 == pResult->_dwObjects && phSearchInfo->_lIterationHandle == NO_MORE_ITERATIONS) RRETURN(S_ADS_NOMORE_ROWS); }
if (!phSearchInfo->_pFilterBuf) { //
// querynode not setup yet
//
RRETURN (E_FAIL); }
if(!phSearchInfo->_pSearchResults) { //
// Allocate an array of handles to Search Handles
//
phSearchInfo->_pSearchResults = (PNDS_SEARCH_RESULT) AllocADsMem( sizeof(NDS_SEARCH_RESULT) * NO_NDS_RESULT_HANDLES); if(!phSearchInfo->_pSearchResults) { hr = E_OUTOFMEMORY; goto error; } phSearchInfo->_dwCurrResult = 0; phSearchInfo->_cSearchResults = NO_NDS_RESULT_HANDLES;
for (i=0; i < phSearchInfo->_cSearchResults; i++) { phSearchInfo->_pSearchResults[i]._fInUse = 0; phSearchInfo->_pSearchResults[i]._hSearchResult = NULL; phSearchInfo->_pSearchResults[i]._pObjects = NULL; phSearchInfo->_pSearchResults[i]._dwObjects = 0; }
} else { phSearchInfo->_dwCurrResult++; if (phSearchInfo->_dwCurrResult >= (LONG) phSearchInfo->_cSearchResults) { //
// Need to allocate more memory for handles
//
phSearchInfo->_pSearchResults = (PNDS_SEARCH_RESULT) ReallocADsMem( (void *) phSearchInfo->_pSearchResults, sizeof(NDS_SEARCH_RESULT) * phSearchInfo->_cSearchResults, sizeof(NDS_SEARCH_RESULT) * (phSearchInfo->_cSearchResults + NO_NDS_RESULT_HANDLES) ); if(!phSearchInfo->_pSearchResults) { hr = E_OUTOFMEMORY; goto error; }
for (i=phSearchInfo->_cSearchResults; i < phSearchInfo->_cSearchResults + NO_NDS_RESULT_HANDLES; i++) { phSearchInfo->_pSearchResults[i]._fInUse = 0; phSearchInfo->_pSearchResults[i]._hSearchResult = NULL; phSearchInfo->_pSearchResults[i]._pObjects = NULL; phSearchInfo->_pSearchResults[i]._dwObjects = 0; }
phSearchInfo->_cSearchResults += NO_NDS_RESULT_HANDLES;
} }
pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]); ADsNdsFreeNdsObjInfoList(pNextResult->_pObjects, pNextResult->_dwObjects); pNextResult->_dwObjects = 0; pNextResult->_pObjects = NULL; pNextResult->_dwObjectCurrent = 0; pNextResult->_hSearchResult = NULL; pNextResult->_fInUse = TRUE;
hr = ADsNdsSearch( _hADsContext, _pszNDSDn, _SearchPref._dwSearchScope, _SearchPref._fDerefAliases, phSearchInfo->_pFilterBuf, 0, _SearchPref._fAttrsOnly ? DS_ATTRIBUTE_NAMES : DS_ATTRIBUTE_VALUES, phSearchInfo->_ppszAttrs, phSearchInfo->_nAttrs, 0, &nObjectsSearched, &pNextResult->_hSearchResult, &phSearchInfo->_lIterationHandle ); BAIL_ON_FAILURE(hr);
hr = ADsNdsGetObjectListFromBuffer( _hADsContext, pNextResult->_hSearchResult, (PDWORD)&pNextResult->_dwObjects, &pNextResult->_pObjects ); BAIL_ON_FAILURE(hr);
if (pNextResult->_dwObjects > 0) { pNextResult->_dwObjectCurrent = 0; if(phSearchInfo->_fCheckForDuplicates && phSearchInfo->_dwCurrResult > 0) { pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult-1]); pObject = pResult->_pObjects + pResult->_dwObjectCurrent; pNextObject = pNextResult->_pObjects + pNextResult->_dwObjectCurrent; if (!_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// Duplicates; Skip one more result
//
pNextResult->_dwObjectCurrent++; } } if( pNextResult->_dwObjectCurrent >= pNextResult->_dwObjects && phSearchInfo->_lIterationHandle == NO_MORE_ITERATIONS) { phSearchInfo->_dwCurrResult--; RRETURN(S_ADS_NOMORE_ROWS); }
if ( !phSearchInfo->_SearchPref._fCacheResults && (phSearchInfo->_dwCurrResult >= NO_UNCACHED_RESULTS_TO_KEEP) ) { // Not caching --- evict the old result
pEvictedResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult-NO_UNCACHED_RESULTS_TO_KEEP]);
ADsNdsFreeBuffer(pEvictedResult->_hSearchResult); ADsNdsFreeNdsObjInfoList(pEvictedResult->_pObjects, pEvictedResult->_dwObjects);
pEvictedResult->_hSearchResult = NULL; pEvictedResult->_pObjects = NULL; pEvictedResult->_dwObjects = 0; pEvictedResult->_fInUse = FALSE; }
// Above, we test if we have incremented _dwObjectCurrent past the last
// object in the result AND there are no more iterations. This would happen
// if there is exactly one object in this result, and that object is a duplicate
// of the last object in the previous result (i.e., the _wcsicmp above is executed
// and returns 0), and there are no more results (no more iterations to go).
//
// But, suppose the above conditions are true, EXCEPT that there are still more
// iterations to go. Then the above test wouldn't succeed, and we'd return with
// _dwObjectCurrent == _dwObjects, an invalid condition.
//
// In this case, we've exhausted the result and must fetch the next one.
// We do this by calling GetNextRow again. Since _dwCurrResult has already been
// incremented, our pNextResult will be the recursive call's pResult, it will look
// like we've exhausted the objects in the result, and it will fetch the next result.
//
// Note that we do this recursive call after the caching code so that we evict the
// _dwCurrResult-NO_UNCACHED_RESULTS_TO_KEEP entry before going on to _dwCurrResult+1.
if( pNextResult->_dwObjectCurrent >= pNextResult->_dwObjects) { // phSearchInfo->_lIterationHandle != NO_MORE_ITERATIONS
pNextResult->_dwObjectCurrent = pNextResult->_dwObjects-1; RRETURN(GetNextRow(hSearchHandle)); }
RRETURN(S_OK); } else { phSearchInfo->_dwCurrResult--; RRETURN(S_ADS_NOMORE_ROWS); }
error: RRETURN(hr); }
HRESULT CNDSGenObject::GetPreviousRow( IN ADS_SEARCH_HANDLE hSearchHandle ) { PNDS_SEARCH_RESULT pResult, pPrevResult; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
if(!phSearchInfo || !phSearchInfo->_pSearchResults) RRETURN(E_FAIL);
if (phSearchInfo->_fCheckForDuplicates) { phSearchInfo->_dwCurrAttr = 0; }
if (phSearchInfo->_dwCurrResult < 0) RRETURN(S_ADS_NOMORE_ROWS);
pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if (pResult->_dwObjectCurrent > 0) pResult->_dwObjectCurrent--; else if (phSearchInfo->_dwCurrResult > 0) { pPrevResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult-1]);
// Make sure the previous result hasn't been evicted from the cache
if (!pPrevResult->_fInUse) RRETURN(S_ADS_NOMORE_ROWS);
pPrevResult->_dwObjectCurrent = pPrevResult->_dwObjects-1; phSearchInfo->_cResultPrefetched++; phSearchInfo->_dwCurrResult--;
// Check for duplicates
if (phSearchInfo->_fCheckForDuplicates) {
PADSNDS_OBJECT_INFO pObject, pPrevObject;
pPrevObject = pPrevResult->_pObjects + pPrevResult->_dwObjectCurrent; pObject = pResult->_pObjects + pResult->_dwObjectCurrent;
if (!_wcsicmp(pPrevObject->szObjectName, pObject->szObjectName)) { // dupe
RRETURN(GetPreviousRow(hSearchHandle)); } }
} else if(0 == pResult->_dwObjectCurrent) // we are at the very beginning of the result set
pResult->_dwObjectCurrent--; else RRETURN(S_ADS_NOMORE_ROWS);
RRETURN(S_OK);
}
HRESULT CNDSGenObject::GetColumn( IN ADS_SEARCH_HANDLE hSearchHandle, IN LPWSTR pszColumnName, OUT PADS_SEARCH_COLUMN pColumn ) { HRESULT hr = S_OK; DWORD dwStatus; DWORD dwSyntaxId = 0; DWORD dwNumValues = 0; LPNDS_ATTR_INFO pAttribute; PNDS_SEARCH_RESULT pResult, pNextResult; PADSNDS_OBJECT_INFO pObject, pNextObject; DWORD cAttr; BOOL fRowAdvanced = FALSE; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
LPWSTR pszNDSDn = NULL; LPWSTR pszNDSTreeName = NULL; LPWSTR szADsPath = NULL;
if( !pColumn || !phSearchInfo || !phSearchInfo->_pSearchResults ) RRETURN (E_ADS_BAD_PARAMETER);
pColumn->pszAttrName = NULL; pColumn->dwADsType = ADSTYPE_INVALID; pColumn->pADsValues = NULL; pColumn->dwNumValues = 0; pColumn->hReserved = NULL;
if (phSearchInfo->_dwCurrResult < 0) RRETURN(S_ADS_NOMORE_ROWS);
pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if( pResult->_dwObjectCurrent < 0 ) RRETURN (E_ADS_BAD_PARAMETER);
if ((pResult->_dwObjects == 0) || (!pResult->_pObjects)) RRETURN (S_ADS_NOMORE_COLUMNS);
pObject = pResult->_pObjects + pResult->_dwObjectCurrent;
pColumn->pszAttrName = AllocADsStr(pszColumnName); if (!pColumn->pszAttrName) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
if(!_wcsicmp (pszColumnName, L"ADsPath")) {
//
// Build the ADsPathName
//
hr = BuildNDSPathFromADsPath2( _ADsPath, &pszNDSTreeName, &pszNDSDn ); BAIL_ON_FAILURE(hr);
hr = BuildADsPathFromNDSPath( pszNDSTreeName, pObject->szObjectName, &szADsPath ); BAIL_ON_FAILURE(hr);
if(*szADsPath) { pColumn->pADsValues = (PADSVALUE) AllocADsMem(sizeof(ADSVALUE)); if (!pColumn->pADsValues) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
pColumn->dwADsType = ADSTYPE_CASE_IGNORE_STRING; pColumn->dwNumValues = 1; pColumn->pADsValues[0].dwType = ADSTYPE_CASE_IGNORE_STRING;
pColumn->pADsValues[0].CaseIgnoreString = AllocADsStr(szADsPath); if (!pColumn->pADsValues[0].CaseIgnoreString) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
pColumn->hReserved = pColumn->pADsValues[0].CaseIgnoreString; }
if (szADsPath) { FreeADsMem(szADsPath); } if (pszNDSDn) { FreeADsMem(pszNDSDn); } if (pszNDSTreeName) { FreeADsMem(pszNDSTreeName); }
RRETURN(S_OK); }
if (phSearchInfo->_SearchPref._fAttrsOnly) { //
// Only Names got. So, don't return any values
//
RRETURN (S_OK); }
pAttribute = (LPNDS_ATTR_INFO)pObject->lpAttribute;
for (cAttr=0;cAttr<pObject->dwNumAttributes;cAttr++,pAttribute++) { if (_wcsicmp( pAttribute->szAttributeName, pszColumnName ) == 0) break; } if (cAttr == pObject->dwNumAttributes) { if(pResult->_dwObjectCurrent+1 != pResult->_dwObjects || (phSearchInfo->_lIterationHandle == NO_MORE_ITERATIONS && (phSearchInfo->_cResultPrefetched == 0))) { //
// No need to look in the next result set;
//
BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET); } else { //
// There is a chance that the column may come in the next
// result set. So, fetch the next set of results.
//
// Since this isn't actually the user causing the row to be advanced,
// we don't want to do any cache evictions
phSearchInfo->_fCheckForDuplicates = FALSE; BOOL fCurrentCachingStatus = phSearchInfo->_SearchPref._fCacheResults; phSearchInfo->_SearchPref._fCacheResults = TRUE; hr = GetNextRow( phSearchInfo ); phSearchInfo->_fCheckForDuplicates = TRUE; phSearchInfo->_SearchPref._fCacheResults = fCurrentCachingStatus; BAIL_ON_FAILURE(hr);
if (hr == S_ADS_NOMORE_ROWS) { BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET); }
fRowAdvanced = TRUE;
pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]); pNextObject = pNextResult->_pObjects + pNextResult->_dwObjectCurrent; if (_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// No need to look in the next object;
//
BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET); } else { //
// Look in the next object
//
pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute; for (cAttr=0;cAttr<pNextObject->dwNumAttributes;cAttr++,pAttribute++) { if (_wcsicmp( pAttribute->szAttributeName, pszColumnName ) == 0) break; } if (cAttr == pNextObject->dwNumAttributes) { //
// Didn't find in the next result set containing the row too
//
BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET); } } } }
hr = NdsValueToADsColumn( pszColumnName, pAttribute->dwSyntaxId, pAttribute->dwNumberOfValues, (LPBYTE) pAttribute->lpValue, pColumn ); BAIL_ON_FAILURE(hr);
//
// Added in to support the case when one multivalue attribute is split into 2 packets. The
// following case checks
// 1) if we haven't advanced the row, if we have advanced already, the whole
// Attribute will already be completely residing in the second packet
// 2) the attribute was the last attribute from the last packet, thus
// the next attribute, (the first attribute of the next row) might be
// the same.
//
if ((!fRowAdvanced) && (cAttr == (pObject->dwNumAttributes - 1))) {
//
// If there is indeed a need to try out an extra packet
//
if(pResult->_dwObjectCurrent+1 != pResult->_dwObjects || (phSearchInfo->_lIterationHandle == NDS_NO_MORE_ITERATIONS && (phSearchInfo->_cResultPrefetched == 0))) { //
// No need to look in the next result set;
//
hr = S_OK; goto done; } else { //
// There is a chance that the column may come in the next
// result set. So, fetch the next set of results.
//
// Since this isn't actually the user causing the row to be advanced,
// we don't want to do any cache evictions
phSearchInfo->_fCheckForDuplicates = FALSE; BOOL fCurrentCachingStatus = phSearchInfo->_SearchPref._fCacheResults; phSearchInfo->_SearchPref._fCacheResults = TRUE; hr = GetNextRow( phSearchInfo ); phSearchInfo->_fCheckForDuplicates = TRUE; phSearchInfo->_SearchPref._fCacheResults = fCurrentCachingStatus; BAIL_ON_FAILURE(hr);
if (hr == S_ADS_NOMORE_ROWS) { hr = S_OK; goto done; }
fRowAdvanced = TRUE;
pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]); pNextObject = pNextResult->_pObjects + pNextResult->_dwObjectCurrent; if (_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// No need to look in the next object, since objname is different
//
hr = S_OK; goto done; } else { //
// Look in the next object, look for the same attribute
//
pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute; for (cAttr=0;cAttr<pNextObject->dwNumAttributes;cAttr++,pAttribute++) { if (_wcsicmp( pAttribute->szAttributeName, pszColumnName ) == 0) break; } if (cAttr == pNextObject->dwNumAttributes) { //
// Didn't find in the next result set containing the row too
//
hr = S_OK; goto done; } } }
//
// If found, we'll append it to the last column
//
hr = NdsValueToADsColumnAppend( pAttribute->dwSyntaxId, pAttribute->dwNumberOfValues, (LPBYTE) pAttribute->lpValue, pColumn ); BAIL_ON_FAILURE(hr); } done:
if (fRowAdvanced) { phSearchInfo->_fCheckForDuplicates = FALSE; GetPreviousRow(phSearchInfo); phSearchInfo->_fCheckForDuplicates = TRUE; }
if (szADsPath) { FreeADsMem(szADsPath); } if (pszNDSDn) { FreeADsMem(pszNDSDn); } if (pszNDSTreeName) { FreeADsMem(pszNDSTreeName); }
RRETURN(S_OK);
error:
if (fRowAdvanced) { phSearchInfo->_fCheckForDuplicates = FALSE; GetPreviousRow(phSearchInfo); phSearchInfo->_fCheckForDuplicates = TRUE; }
if (szADsPath) { FreeADsMem(szADsPath); } if (pszNDSDn) { FreeADsMem(pszNDSDn); } if (pszNDSTreeName) { FreeADsMem(pszNDSTreeName); }
FreeColumn(pColumn);
RRETURN (hr); }
HRESULT CNDSGenObject::GetNextColumnName( IN ADS_SEARCH_HANDLE hSearchHandle, OUT LPWSTR * ppszColumnName ) { HRESULT hr = S_OK; LPNDS_ATTR_INFO pAttribute; LPNDS_ATTR_INFO pAttributeOld = NULL; LPNDS_NAME_ONLY pNameOnlyAttr; PNDS_SEARCH_RESULT pResult, pNextResult; PADSNDS_OBJECT_INFO pObject, pNextObject; BOOL fRowAdvanced = FALSE; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
if( !phSearchInfo || !phSearchInfo->_pSearchResults || !ppszColumnName) RRETURN (E_ADS_BAD_PARAMETER);
*ppszColumnName = NULL;
if (phSearchInfo->_dwCurrResult < 0) RRETURN(S_ADS_NOMORE_ROWS);
pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if( pResult->_dwObjectCurrent < 0 ) RRETURN (E_ADS_BAD_PARAMETER);
if ((pResult->_dwObjects == 0) || (!pResult->_pObjects)) RRETURN (S_ADS_NOMORE_COLUMNS);
pObject = pResult->_pObjects + pResult->_dwObjectCurrent;
pNameOnlyAttr = (LPNDS_NAME_ONLY)pObject->lpAttribute + phSearchInfo->_dwCurrAttr; pAttribute = (LPNDS_ATTR_INFO)pObject->lpAttribute + phSearchInfo->_dwCurrAttr;
//
// Get the last attribute's name to test it to avoid getting duplicate
// column names. This will happen if a multi-value got divided into two
// packets. In that case, both attribute names would be the same.
// We are only getting the last attribute if this object has greater than
// 1 object, or else if this attribute is the first attribute, there would
// not be a one before
//
if (phSearchInfo->_dwCurrAttr > 0) { pAttributeOld = pAttribute - 1; }
if (phSearchInfo->_dwCurrAttr >= pObject->dwNumAttributes) { if(pResult->_dwObjectCurrent+1 != pResult->_dwObjects || (phSearchInfo->_lIterationHandle == NO_MORE_ITERATIONS && (phSearchInfo->_cResultPrefetched == 0))) { //
// No need to look in the next result set;
//
hr = S_ADS_NOMORE_COLUMNS; goto error; } else { //
// There is a chance that the column may come in the next
// result set. So, fetch the next set of results.
//
// Since this isn't actually the user causing the row to be advanced,
// we don't want to do any cache evictions
phSearchInfo->_fCheckForDuplicates = FALSE; BOOL fCurrentCachingStatus = phSearchInfo->_SearchPref._fCacheResults; phSearchInfo->_SearchPref._fCacheResults = TRUE; hr = GetNextRow( phSearchInfo ); phSearchInfo->_fCheckForDuplicates = TRUE; phSearchInfo->_SearchPref._fCacheResults = fCurrentCachingStatus;
BAIL_ON_FAILURE(hr);
if (hr == S_ADS_NOMORE_ROWS) { hr = S_ADS_NOMORE_COLUMNS; goto error; } fRowAdvanced = TRUE; pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]); pNextObject = pNextResult->_pObjects + pNextResult->_dwObjectCurrent; if (_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// No need to look in the next object;
//
hr = S_ADS_NOMORE_COLUMNS; goto error; } else { //
// Look in the next object
//
pNameOnlyAttr = (LPNDS_NAME_ONLY)pNextObject->lpAttribute + phSearchInfo->_dwCurrAttr - pObject->dwNumAttributes; pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute + phSearchInfo->_dwCurrAttr - pObject->dwNumAttributes; //
// If the new attribute is after the first attribute in the new object,
// we'll reset AttributeOld to point to the attribute before this.
// Because the old attribute will be the one before the current one
// in this case.
//
if ((phSearchInfo->_dwCurrAttr - pObject->dwNumAttributes) > 0) { pAttributeOld = pAttribute - 1; }
if (phSearchInfo->_dwCurrAttr >= (pObject->dwNumAttributes + pNextObject->dwNumAttributes)) { //
// Didn't find in the next result set
// containing the row too
//
hr = S_ADS_NOMORE_COLUMNS; goto error; }
//
// If it is a duplicate column, go on to the next one
//
if (pAttributeOld) { if(wcscmp(pAttribute->szAttributeName, pAttributeOld->szAttributeName) == 0) { phSearchInfo->_dwCurrAttr++; if (phSearchInfo->_dwCurrAttr >= (pObject->dwNumAttributes + pNextObject->dwNumAttributes)) { //
// Didn't find in the next result set
// containing the row too
//
hr = S_ADS_NOMORE_COLUMNS; goto error; } pNameOnlyAttr = (LPNDS_NAME_ONLY)pNextObject->lpAttribute + phSearchInfo->_dwCurrAttr - pObject->dwNumAttributes; pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute + phSearchInfo->_dwCurrAttr - pObject->dwNumAttributes; } }
} } }
if (phSearchInfo->_SearchPref._fAttrsOnly) *ppszColumnName = AllocADsStr( pNameOnlyAttr->szName ); else *ppszColumnName = AllocADsStr( pAttribute->szAttributeName );
phSearchInfo->_dwCurrAttr++;
if (fRowAdvanced) { phSearchInfo->_fCheckForDuplicates = FALSE; GetPreviousRow(phSearchInfo); phSearchInfo->_fCheckForDuplicates = TRUE; }
RRETURN(S_OK);
error:
if (fRowAdvanced) { phSearchInfo->_fCheckForDuplicates = FALSE; GetPreviousRow(phSearchInfo); phSearchInfo->_fCheckForDuplicates = TRUE; }
if (*ppszColumnName) FreeADsStr(*ppszColumnName);
if (hr == S_ADS_NOMORE_COLUMNS && phSearchInfo->_fADsPathPresent) {
//
// If ADsPath was specified, return it as the last column in the row
//
if (!phSearchInfo->_fADsPathReturned) {
*ppszColumnName = AllocADsStr(L"ADsPath"); phSearchInfo->_fADsPathReturned = TRUE; hr = S_OK; } else {
//
// We need to reset it back so that we return it for the next
// row
//
phSearchInfo->_fADsPathReturned = FALSE; hr = S_ADS_NOMORE_COLUMNS; }
}
RRETURN (hr); }
HRESULT CNDSGenObject::FreeColumn( IN PADS_SEARCH_COLUMN pColumn ) { HRESULT hr = S_OK;
if(!pColumn) RRETURN (E_ADS_BAD_PARAMETER);
if (pColumn->pszAttrName) FreeADsStr(pColumn->pszAttrName); if (pColumn->pADsValues) { AdsFreeAdsValues(pColumn->pADsValues, pColumn->dwNumValues); FreeADsMem(pColumn->pADsValues); }
RRETURN(hr); }
HRESULT NdsValueToADsColumn( LPWSTR pszColumnName, DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpObject, ADS_SEARCH_COLUMN * pColumn ) { HRESULT hr = S_OK; LPNDS_ASN1_TYPE_1 lpNDS_ASN1_1; LPNDS_ASN1_TYPE_7 lpNDS_ASN1_7; LPNDS_ASN1_TYPE_8 lpNDS_ASN1_8; LPNDS_ASN1_TYPE_9 lpNDS_ASN1_9; LPNDS_ASN1_TYPE_11 lpNDS_ASN1_11; LPNDS_ASN1_TYPE_14 lpNDS_ASN1_14; LPNDS_ASN1_TYPE_18 lpNDS_ASN1_18; LPNDS_ASN1_TYPE_20 lpNDS_ASN1_20; LPNDS_ASN1_TYPE_24 lpNDS_ASN1_24; DWORD i, j, dwValuesAllocated = 0; LPBYTE lpValue = NULL; PNDSOBJECT lpNdsObject = NULL;
if(!pszColumnName || !pColumn || !lpObject) RRETURN(E_ADS_BAD_PARAMETER);
lpNdsObject = (PNDSOBJECT) lpObject;
pColumn->hReserved = NULL; pColumn->dwNumValues = dwValues; pColumn->pADsValues = (PADSVALUE) AllocADsMem( sizeof(ADSVALUE) * dwValues ); if (!pColumn->pADsValues) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
if (dwSyntaxId >= g_cMapNdsTypeToADsType) pColumn->dwADsType = ADSTYPE_INVALID; else pColumn->dwADsType = g_MapNdsTypeToADsType[dwSyntaxId];
switch (dwSyntaxId) { // WIDE STRING
case NDS_SYNTAX_ID_1: case NDS_SYNTAX_ID_2: case NDS_SYNTAX_ID_3: case NDS_SYNTAX_ID_4: case NDS_SYNTAX_ID_5: case NDS_SYNTAX_ID_10: for (i=0; i < dwValues; i++) { lpNDS_ASN1_1 = (LPNDS_ASN1_TYPE_1) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].CaseIgnoreString = AllocADsStr(lpNDS_ASN1_1->DNString); if (!(pColumn->pADsValues[i].CaseIgnoreString)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
dwValuesAllocated++; } break; case NDS_SYNTAX_ID_20: for (i=0; i < dwValues; i++) { lpNDS_ASN1_20 = (LPNDS_ASN1_TYPE_20) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].ClassName = AllocADsStr(lpNDS_ASN1_20->ClassName); if (!(pColumn->pADsValues[i].ClassName)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
dwValuesAllocated++; } break;
// EMAIL
case NDS_SYNTAX_ID_14 : for (i=0; i < dwValues; i++) { lpNDS_ASN1_14 = (LPNDS_ASN1_TYPE_14) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].Email.Address = AllocADsStr(lpNDS_ASN1_14->Address); pColumn->pADsValues[i].Email.Type = lpNDS_ASN1_14->Type; if (!(pColumn->pADsValues[i].Email.Address)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
dwValuesAllocated++; } break; // BYTE STREAM
case NDS_SYNTAX_ID_9: for (i=0; i < dwValues; i++) { lpNDS_ASN1_9 = (LPNDS_ASN1_TYPE_9) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; if (lpNDS_ASN1_9->Length) { LPBYTE lpByte = (LPBYTE)AllocADsMem(lpNDS_ASN1_9->Length); if (!lpByte) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); if (lpNDS_ASN1_9->OctetString) memcpy(lpByte, lpNDS_ASN1_9->OctetString, lpNDS_ASN1_9->Length); pColumn->pADsValues[i].OctetString.dwLength =lpNDS_ASN1_9->Length; pColumn->pADsValues[i].OctetString.lpValue = lpByte; } else { pColumn->pADsValues[i].OctetString.dwLength = 0; pColumn->pADsValues[i].OctetString.lpValue = NULL; }
dwValuesAllocated++; } break; // BOOLEAN
case NDS_SYNTAX_ID_7: for (i=0; i < dwValues; i++) { lpNDS_ASN1_7 = (LPNDS_ASN1_TYPE_7) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].Boolean = lpNDS_ASN1_7->Boolean; }
dwValuesAllocated = dwValues; // no intermediate failures possible
break; // INTEGER
case NDS_SYNTAX_ID_8: case NDS_SYNTAX_ID_22: case NDS_SYNTAX_ID_27: for (i=0; i < dwValues; i++) { lpNDS_ASN1_8 = (LPNDS_ASN1_TYPE_8) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].Integer = lpNDS_ASN1_8->Integer; }
dwValuesAllocated = dwValues; // no intermediate failures possible
break; // TIME
case NDS_SYNTAX_ID_24 : for (i=0; i < dwValues; i++) { lpNDS_ASN1_24 = (LPNDS_ASN1_TYPE_24) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; hr = ConvertDWORDtoSYSTEMTIME( lpNDS_ASN1_24->Time, &(pColumn->pADsValues[i].UTCTime) ); BAIL_ON_FAILURE(hr);
dwValuesAllocated++; } break;
// FAX NUMBER
case NDS_SYNTAX_ID_11 : for (i=0; i < dwValues; i++) { lpNDS_ASN1_11 = (LPNDS_ASN1_TYPE_11) &((lpNdsObject + i)->NdsValue);
pColumn->pADsValues[i].dwType = pColumn->dwADsType;
pColumn->pADsValues[i].pFaxNumber = (PADS_FAXNUMBER)AllocADsMem(sizeof(ADS_FAXNUMBER)); if (!pColumn->pADsValues[i].pFaxNumber) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
pColumn->pADsValues[i].pFaxNumber->TelephoneNumber = AllocADsStr(lpNDS_ASN1_11->TelephoneNumber);
if (!pColumn->pADsValues[i].pFaxNumber->TelephoneNumber) { FreeADsMem(pColumn->pADsValues[i].pFaxNumber); hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
hr = CopyOctetString(lpNDS_ASN1_11->NumberOfBits, lpNDS_ASN1_11->Parameters, &pColumn->pADsValues[i].pFaxNumber->NumberOfBits, &pColumn->pADsValues[i].pFaxNumber->Parameters); if (FAILED(hr)) { FreeADsStr(pColumn->pADsValues[i].pFaxNumber->TelephoneNumber); FreeADsMem(pColumn->pADsValues[i].pFaxNumber); BAIL_ON_FAILURE(hr); }
dwValuesAllocated++; } break;
// POSTAL ADDRESS
case NDS_SYNTAX_ID_18 : for (i=0; i<dwValues; i++) { lpNDS_ASN1_18 = (LPNDS_ASN1_TYPE_18) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].pPostalAddress = (PADS_POSTALADDRESS)AllocADsMem(sizeof(ADS_POSTALADDRESS)); if (!pColumn->pADsValues[i].pPostalAddress) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } for (j=0;j<6;j++) { if (lpNDS_ASN1_18->PostalAddress[j]) { pColumn->pADsValues[i].pPostalAddress->PostalAddress[j] = AllocADsStr( lpNDS_ASN1_18->PostalAddress[j] ); } else { pColumn->pADsValues[i].pPostalAddress->PostalAddress[j] = AllocADsStr( L"" ); } if (!pColumn->pADsValues[i].pPostalAddress->PostalAddress[j]) { hr = E_OUTOFMEMORY; while (j>0) { FreeADsStr(pColumn->pADsValues[i].pPostalAddress->PostalAddress[j-1]); j--; } FreeADsMem(pColumn->pADsValues[i].pPostalAddress); BAIL_ON_FAILURE(hr); } }
dwValuesAllocated++; } break;
case NDS_SYNTAX_ID_6 : case NDS_SYNTAX_ID_12 : case NDS_SYNTAX_ID_13 : case NDS_SYNTAX_ID_15 : case NDS_SYNTAX_ID_16 : case NDS_SYNTAX_ID_17 : case NDS_SYNTAX_ID_19 : case NDS_SYNTAX_ID_21 : case NDS_SYNTAX_ID_23 : case NDS_SYNTAX_ID_25 : case NDS_SYNTAX_ID_26 : default: for (i=0; i < dwValues; i++) { pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].ProviderSpecific.dwLength =0; pColumn->pADsValues[i].ProviderSpecific.lpValue = NULL; }
dwValuesAllocated = dwValues; // no intermediate failures possible
break; } RRETURN(hr);
error:
if (pColumn->pADsValues) { AdsFreeAdsValues(pColumn->pADsValues, dwValuesAllocated);
FreeADsMem(pColumn->pADsValues); pColumn->pADsValues = NULL; pColumn->dwNumValues = 0; }
RRETURN(hr); }
HRESULT NdsValueToADsColumnAppend( DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpObject, ADS_SEARCH_COLUMN * pColumn ) { HRESULT hr = S_OK; LPNDS_ASN1_TYPE_1 lpNDS_ASN1_1; LPNDS_ASN1_TYPE_7 lpNDS_ASN1_7; LPNDS_ASN1_TYPE_8 lpNDS_ASN1_8; LPNDS_ASN1_TYPE_9 lpNDS_ASN1_9; LPNDS_ASN1_TYPE_11 lpNDS_ASN1_11; LPNDS_ASN1_TYPE_14 lpNDS_ASN1_14; LPNDS_ASN1_TYPE_18 lpNDS_ASN1_18; LPNDS_ASN1_TYPE_20 lpNDS_ASN1_20; LPNDS_ASN1_TYPE_24 lpNDS_ASN1_24; DWORD i, j, dwValuesAllocated; PNDSOBJECT lpNdsObject = NULL; PADSVALUE pADsValuesNew = NULL; DWORD dwValuesBase;
if(!pColumn || !lpObject) RRETURN(E_ADS_BAD_PARAMETER);
dwValuesBase = pColumn->dwNumValues; dwValuesAllocated = pColumn->dwNumValues; lpNdsObject = (PNDSOBJECT) lpObject;
//
// Allocate memory for new values + old values
//
pADsValuesNew = (PADSVALUE) AllocADsMem( sizeof(ADSVALUE) * (pColumn->dwNumValues + dwValues) ); if (!pADsValuesNew) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Copy old values into new array, and free the old one
//
memcpy(pADsValuesNew, pColumn->pADsValues, sizeof(ADSVALUE) * dwValuesBase); FreeADsMem(pColumn->pADsValues); pColumn->pADsValues = pADsValuesNew;
switch (dwSyntaxId) { // WIDE STRING
case NDS_SYNTAX_ID_1: case NDS_SYNTAX_ID_2: case NDS_SYNTAX_ID_3: case NDS_SYNTAX_ID_4: case NDS_SYNTAX_ID_5: case NDS_SYNTAX_ID_10: for (i=0; i < dwValues; i++) { lpNDS_ASN1_1 = (LPNDS_ASN1_TYPE_1) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].CaseIgnoreString = AllocADsStr(lpNDS_ASN1_1->DNString);
if (!(pColumn->pADsValues[dwValuesBase+i].CaseIgnoreString)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
dwValuesAllocated++; } break;
case NDS_SYNTAX_ID_20: for (i=0; i < dwValues; i++) { lpNDS_ASN1_20 = (LPNDS_ASN1_TYPE_20) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].ClassName = AllocADsStr(lpNDS_ASN1_20->ClassName); if (!(pColumn->pADsValues[dwValuesBase+i].ClassName)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); dwValuesAllocated++; } break; // EMAIL
case NDS_SYNTAX_ID_14 : for (i=0; i < dwValues; i++) { lpNDS_ASN1_14 = (LPNDS_ASN1_TYPE_14) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].Email.Address = AllocADsStr(lpNDS_ASN1_14->Address); pColumn->pADsValues[dwValuesBase+i].Email.Type = lpNDS_ASN1_14->Type; if (!(pColumn->pADsValues[dwValuesBase+i].Email.Address)) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); dwValuesAllocated++; } break;
// BYTE STREAM
case NDS_SYNTAX_ID_9: for (i=0; i < dwValues; i++) { lpNDS_ASN1_9 = (LPNDS_ASN1_TYPE_9) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
if (lpNDS_ASN1_9->Length) { LPBYTE lpByte = (LPBYTE)AllocADsMem(lpNDS_ASN1_9->Length); if (!lpByte) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
if (lpNDS_ASN1_9->OctetString) memcpy(lpByte, lpNDS_ASN1_9->OctetString, lpNDS_ASN1_9->Length);
pColumn->pADsValues[dwValuesBase+i].OctetString.dwLength =lpNDS_ASN1_9->Length; pColumn->pADsValues[dwValuesBase+i].OctetString.lpValue = lpByte; } else { pColumn->pADsValues[dwValuesBase+i].OctetString.dwLength = 0; pColumn->pADsValues[dwValuesBase+i].OctetString.lpValue = NULL; }
dwValuesAllocated++; } break;
// BOOLEAN
case NDS_SYNTAX_ID_7: for (i=0; i < dwValues; i++) { lpNDS_ASN1_7 = (LPNDS_ASN1_TYPE_7) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].Boolean = lpNDS_ASN1_7->Boolean; }
dwValuesAllocated += dwValues; // no intermediate failures possible
break;
// INTEGER
case NDS_SYNTAX_ID_8: case NDS_SYNTAX_ID_22: case NDS_SYNTAX_ID_27: for (i=0; i < dwValues; i++) { lpNDS_ASN1_8 = (LPNDS_ASN1_TYPE_8) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].Integer = lpNDS_ASN1_8->Integer; }
dwValuesAllocated += dwValues; // no intermediate failures possible
break;
// TIME
case NDS_SYNTAX_ID_24 : for (i=0; i < dwValues; i++) { lpNDS_ASN1_24 = (LPNDS_ASN1_TYPE_24) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[i].dwType = pColumn->dwADsType; hr = ConvertDWORDtoSYSTEMTIME( lpNDS_ASN1_24->Time, &(pColumn->pADsValues[dwValuesBase+i].UTCTime) ); BAIL_ON_FAILURE(hr);
dwValuesAllocated++; } break;
// FAX NUMBER
case NDS_SYNTAX_ID_11 : for (i=0; i < dwValues; i++) { lpNDS_ASN1_11 = (LPNDS_ASN1_TYPE_11) &((lpNdsObject + i)->NdsValue);
pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
pColumn->pADsValues[dwValuesBase+i].pFaxNumber = (PADS_FAXNUMBER)AllocADsMem(sizeof(ADS_FAXNUMBER)); if (!pColumn->pADsValues[dwValuesBase+i].pFaxNumber) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
pColumn->pADsValues[dwValuesBase+i].pFaxNumber->TelephoneNumber = AllocADsStr(lpNDS_ASN1_11->TelephoneNumber);
if (!pColumn->pADsValues[dwValuesBase+i].pFaxNumber->TelephoneNumber) { FreeADsMem(pColumn->pADsValues[dwValuesBase+i].pFaxNumber); hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
hr = CopyOctetString(lpNDS_ASN1_11->NumberOfBits, lpNDS_ASN1_11->Parameters, &pColumn->pADsValues[dwValuesBase+i].pFaxNumber->NumberOfBits, &pColumn->pADsValues[dwValuesBase+i].pFaxNumber->Parameters); if (FAILED(hr)) { FreeADsStr(pColumn->pADsValues[dwValuesBase+i].pFaxNumber->TelephoneNumber); FreeADsMem(pColumn->pADsValues[dwValuesBase+i].pFaxNumber); BAIL_ON_FAILURE(hr); }
dwValuesAllocated++; } break;
// POSTAL ADDRESS
case NDS_SYNTAX_ID_18 : for (i=0; i<dwValues; i++) { lpNDS_ASN1_18 = (LPNDS_ASN1_TYPE_18) &((lpNdsObject + i)->NdsValue); pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].pPostalAddress = (PADS_POSTALADDRESS)AllocADsMem(sizeof(ADS_POSTALADDRESS)); if (!pColumn->pADsValues[dwValuesBase+i].pPostalAddress) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } for (j=0;j<6;j++) { if (lpNDS_ASN1_18->PostalAddress[j]) { pColumn->pADsValues[dwValuesBase+i].pPostalAddress->PostalAddress[j] = AllocADsStr( lpNDS_ASN1_18->PostalAddress[j] ); } else { pColumn->pADsValues[dwValuesBase+i].pPostalAddress->PostalAddress[j] = AllocADsStr( L"" ); } if (!pColumn->pADsValues[dwValuesBase+i].pPostalAddress->PostalAddress[j]) { hr = E_OUTOFMEMORY; while (j>0) { FreeADsStr(pColumn->pADsValues[dwValuesBase+i].pPostalAddress->PostalAddress[j-1]); j--; } FreeADsMem(pColumn->pADsValues[dwValuesBase+i].pPostalAddress); BAIL_ON_FAILURE(hr); } }
dwValuesAllocated++; } break;
case NDS_SYNTAX_ID_6 : case NDS_SYNTAX_ID_12 : case NDS_SYNTAX_ID_13 : case NDS_SYNTAX_ID_15 : case NDS_SYNTAX_ID_16 : case NDS_SYNTAX_ID_17 : case NDS_SYNTAX_ID_19 : case NDS_SYNTAX_ID_21 : case NDS_SYNTAX_ID_23 : case NDS_SYNTAX_ID_25 : case NDS_SYNTAX_ID_26 : default: for (i=0; i < dwValues; i++) { pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].ProviderSpecific.dwLength =0; pColumn->pADsValues[dwValuesBase+i].ProviderSpecific.lpValue = NULL; }
dwValuesAllocated += dwValues; break; } pColumn->dwNumValues = pColumn->dwNumValues + dwValues; RRETURN(hr);
error:
if (pColumn->pADsValues) { AdsFreeAdsValues(pColumn->pADsValues, dwValuesAllocated);
FreeADsMem(pColumn->pADsValues); pColumn->pADsValues = NULL; pColumn->dwNumValues = 0; }
RRETURN(hr); }
|