|
|
//---------------------------------------------------------------------------
//
//
// 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;
static HRESULT NdsValueToADsColumn( LPWSTR pszColumnName, DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpValue, ADS_SEARCH_COLUMN * pColumn );
static HRESULT NdsValueToADsColumnAppend( DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpValue, ADS_SEARCH_COLUMN * pColumn );
static HRESULT NdsAddAttributes( IN ADS_SEARCH_HANDLE hSearchHandle, OUT HANDLE *phSearchResult );
//
// 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_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_ONELEVEL: _SearchPref._iScope = 0; break;
case ADS_SCOPE_SUBTREE: _SearchPref._iScope = 1; break;
case ADS_SCOPE_BASE: _SearchPref._iScope = 2; 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 pszNDSContext = NULL, 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);
if (pszSearchFilter) { phSearchInfo->_pszSearchFilter = AllocADsStr(pszSearchFilter); } else { phSearchInfo->_pszSearchFilter = AllocADsStr(L"(object class=*)"); } if(!(phSearchInfo->_pszSearchFilter)) BAIL_ON_FAILURE (hr = E_OUTOFMEMORY);
hr = BuildNDSPathFromADsPath( _ADsPath, &phSearchInfo->_pszBindContext ); BAIL_ON_FAILURE(hr);
hr = AdsNdsGenerateParseTree( phSearchInfo->_pszSearchFilter, phSearchInfo->_pszBindContext, &phSearchInfo->_pQueryNode ); 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; } else { ppszAttrs = (LPWSTR *) AllocADsMem( sizeof(LPWSTR) * (dwNumberAttributes + 1) ); 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++; }
} ppszAttrs[j] = NULL;
phSearchInfo->_ppszAttrs = ppszAttrs; phSearchInfo->_pszAttrNameBuffer = pszAttrNameBuffer; }
phSearchInfo->_hConnection = NULL; phSearchInfo->_dwIterHandle = NDS_INITIAL_SEARCH; phSearchInfo->_pSearchResults = NULL; phSearchInfo->_cSearchResults = 0; phSearchInfo->_dwCurrResult = 0; phSearchInfo->_fResultPrefetched = FALSE; phSearchInfo->_fCheckForDuplicates = TRUE; phSearchInfo->_dwCurrAttr = 0; phSearchInfo->_SearchPref = _SearchPref;
*phSearchHandle = phSearchInfo;
RRETURN(S_OK);
error:
if(phSearchInfo) { if(phSearchInfo->_pszBindContext) FreeADsStr(phSearchInfo->_pszBindContext);
if(phSearchInfo->_pszSearchFilter) FreeADsStr(phSearchInfo->_pszSearchFilter);
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; DWORD dwStatus;
if (!phSearchInfo) RRETURN (E_ADS_BAD_PARAMETER);
if (phSearchInfo->_pQueryNode) { dwStatus = NwNdsDeleteQueryTree(phSearchInfo->_pQueryNode); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); } }
if (phSearchInfo->_hConnection) { dwStatus = NwNdsCloseObject(phSearchInfo->_hConnection); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); } }
if(phSearchInfo->_pszBindContext) FreeADsStr(phSearchInfo->_pszBindContext);
if(phSearchInfo->_pszSearchFilter) FreeADsStr(phSearchInfo->_pszSearchFilter);
if(phSearchInfo->_ppszAttrs) FreeADsMem(phSearchInfo->_ppszAttrs);
if(phSearchInfo->_pszAttrNameBuffer) FreeADsMem(phSearchInfo->_pszAttrNameBuffer);
if (phSearchInfo->_pSearchResults) { for (DWORD i=0; i <= phSearchInfo->_dwCurrResult; i++) { NwNdsFreeBuffer(phSearchInfo->_pSearchResults[i]._hSearchResult); } 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; LPNDS_OBJECT_INFO pObject, pNextObject; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
if (!phSearchInfo) { RRETURN(E_ADS_BAD_PARAMETER); }
if (phSearchInfo->_fCheckForDuplicates) { phSearchInfo->_dwCurrAttr = 0; phSearchInfo->_fADsPathReturned = FALSE; }
if (!phSearchInfo->_hConnection) { dwStatus = ADsNwNdsOpenObject( phSearchInfo->_pszBindContext, _Credentials, &phSearchInfo->_hConnection, NULL, NULL, NULL, NULL ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); RRETURN (hr); } }
if (phSearchInfo->_pSearchResults) { pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if (pResult->_pObjects && ((pResult->_lObjectCurrent+1) < pResult->_lObjects)) { pResult->_lObjectCurrent++; RRETURN(S_OK); } if (pResult->_lObjectCurrent+1 == pResult->_lObjects && phSearchInfo->_fResultPrefetched) { phSearchInfo->_dwCurrResult++; pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]); pNextResult->_lObjectCurrent = 0; phSearchInfo->_fResultPrefetched = FALSE;
if(phSearchInfo->_fCheckForDuplicates) { pObject = pResult->_pObjects + pResult->_lObjectCurrent; pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent; if (!_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// Duplicates; Skip one more result
//
if (pNextResult->_lObjectCurrent+1 < pNextResult->_lObjects) pNextResult->_lObjectCurrent++; else { pNextResult->_lObjectCurrent++; RRETURN(S_ADS_NOMORE_ROWS); } } } if( pNextResult->_lObjectCurrent >= pNextResult->_lObjects && phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS) RRETURN(S_ADS_NOMORE_ROWS); else RRETURN(S_OK); } else if( pResult->_lObjectCurrent+1 >= pResult->_lObjects && phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS) { // Make sure _lObjectCurrent doesn't exceed _lObjects. If the
// result set is empty, _lObjectCurrent should stay at -1
if( ((pResult->_lObjectCurrent+1) == pResult->_lObjects) && (pResult->_lObjectCurrent != -1) ) pResult->_lObjectCurrent++; RRETURN(S_ADS_NOMORE_ROWS); } }
if (!phSearchInfo->_pQueryNode) { //
// 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; } else { phSearchInfo->_dwCurrResult++; if (phSearchInfo->_dwCurrResult >= 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; } phSearchInfo->_cSearchResults += NO_NDS_RESULT_HANDLES;
} }
pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
hr = NdsAddAttributes(phSearchInfo, &pNextResult->_hSearchResult ); BAIL_ON_FAILURE(hr);
pNextResult->_lObjects = 0; pNextResult->_pObjects = NULL; // Set _lObjectCurrent to -1 so that empty result set is handled correctly.
// If it is set to 0 and the result set is empty, then a subsequent call
// to GetNextRow will not return S_ADS_NOMORE_ROWS. Instead, it will try to
// search again (in the process, possibly allocate memory for
// _pSearchResults etc.). Also, setting it to -1 ensures that a call to
// GetColumn returns error if the result set is empty.
// Setting it to -1 also ensures that if an error occurs during the search,
// subsequent calls to GetNextRow and GetColumn are handled correctly.
pNextResult->_lObjectCurrent = -1;
dwStatus = NwNdsSearch( phSearchInfo->_hConnection, _SearchPref._fAttrsOnly ? NDS_INFO_NAMES : NDS_INFO_ATTR_NAMES_VALUES, _SearchPref._iScope, _SearchPref._fDerefAliases, phSearchInfo->_pQueryNode, &phSearchInfo->_dwIterHandle, &pNextResult->_hSearchResult ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); RRETURN (hr); }
DWORD dwType; dwStatus = NwNdsGetObjectListFromBuffer( pNextResult->_hSearchResult, (DWORD *) (&pNextResult->_lObjects), &dwType, &pNextResult->_pObjects ); if (dwStatus) { dwStatus = GetLastError(); if (dwStatus == ERROR_NO_DATA) RRETURN(S_ADS_NOMORE_ROWS); else RRETURN (HRESULT_FROM_WIN32(dwStatus)); }
if (pNextResult->_lObjects > 0) { pNextResult->_lObjectCurrent = 0; if(phSearchInfo->_fCheckForDuplicates && phSearchInfo->_dwCurrResult > 0) { pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult-1]); pObject = pResult->_pObjects + pResult->_lObjectCurrent; pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent; if (!_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) { //
// Duplicates; Skip one more result
//
pNextResult->_lObjectCurrent++; } } if( pNextResult->_lObjectCurrent >= pNextResult->_lObjects && phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS) RRETURN(S_ADS_NOMORE_ROWS);
RRETURN(S_OK); } else RRETURN(E_FAIL);
error: RRETURN(hr); }
HRESULT CNDSGenObject::GetPreviousRow( IN ADS_SEARCH_HANDLE hSearchHandle ) { PNDS_SEARCH_RESULT pResult, pPrevResult; LPNDS_OBJECT_INFO pPrevObject, pObject; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
if(!phSearchInfo || !phSearchInfo->_pSearchResults) RRETURN(E_FAIL);
if (phSearchInfo->_fCheckForDuplicates) { phSearchInfo->_dwCurrAttr = 0; phSearchInfo->_fADsPathReturned = FALSE; }
pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if (pResult->_lObjectCurrent > 0) { pResult->_lObjectCurrent--;
if(phSearchInfo->_fCheckForDuplicates && (phSearchInfo->_dwCurrResult > 0) && (0 == pResult->_lObjectCurrent)) { pPrevResult = &(phSearchInfo->_pSearchResults[ phSearchInfo->_dwCurrResult - 1]); pPrevObject = pPrevResult->_pObjects + pPrevResult->_lObjects - 1; pObject = pResult->_pObjects + pResult->_lObjectCurrent;
if(!_wcsicmp(pObject->szObjectName, pPrevObject->szObjectName)) { // Current row is a duplicate. Go to previous result
phSearchInfo->_dwCurrResult--; pResult = &(phSearchInfo->_pSearchResults[ phSearchInfo->_dwCurrResult]); pResult->_lObjectCurrent = pResult->_lObjects-1; phSearchInfo->_fResultPrefetched = TRUE; } } } else if (phSearchInfo->_dwCurrResult > 0) { phSearchInfo->_dwCurrResult--; pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]); pResult->_lObjectCurrent = pResult->_lObjects-1; phSearchInfo->_fResultPrefetched = TRUE; } else if(0 == pResult->_lObjectCurrent) // we are at the very beginning of the result set
pResult->_lObjectCurrent--; 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; LPNDS_OBJECT_INFO pObject, pNextObject; DWORD cAttr; BOOL fRowAdvanced = FALSE; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
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;
pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if( pResult->_lObjectCurrent < 0 ) RRETURN (E_ADS_BAD_PARAMETER);
pObject = pResult->_pObjects + pResult->_lObjectCurrent;
pColumn->pszAttrName = AllocADsStr(pszColumnName); if (pColumn->pszAttrName) BAIL_ON_FAILURE(hr);
if(!_wcsicmp (pszColumnName, L"ADsPath")) { LPWSTR szNDSPath = pObject->szObjectFullName;
//
// Build the ADsPathName
//
WCHAR szTree[MAX_PATH]; WCHAR szCN[MAX_PATH]; WCHAR szADsPath[MAX_PATH];
// Building the CN and the TreeName
LPWSTR szCurrent = szNDSPath; szCurrent+=2; while ((WCHAR)(*szCurrent) != (WCHAR)'\\') szCurrent++; wcsncpy( szTree, szNDSPath, (UINT) (szCurrent-szNDSPath) );
// Make the first two characters "//" instead of "\\"
szTree[0] = (WCHAR)'/'; szTree[1] = (WCHAR)'/';
szTree[szCurrent-szNDSPath] = (WCHAR)'\0'; szCurrent++; wcscpy( szCN, szCurrent );
// Building the ADsPath
hr = BuildADsPathFromNDSPath( szTree, szCN, 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; } 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->dwNumberOfAttributes;cAttr++,pAttribute++) { if (_wcsicmp( pAttribute->szAttributeName, pszColumnName ) == 0) break; } if (cAttr == pObject->dwNumberOfAttributes) { if(pResult->_lObjectCurrent+1 != pResult->_lObjects || (phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS && !phSearchInfo->_fResultPrefetched)) { //
// 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.
//
phSearchInfo->_fCheckForDuplicates = FALSE; hr = GetNextRow( phSearchInfo ); phSearchInfo->_fCheckForDuplicates = TRUE; 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->_lObjectCurrent; 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->dwNumberOfAttributes;cAttr++,pAttribute++) { if (_wcsicmp( pAttribute->szAttributeName, pszColumnName ) == 0) break; } if (cAttr == pNextObject->dwNumberOfAttributes) { //
// 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, 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->dwNumberOfAttributes - 1))) {
//
// If there is indeed a need to try out an extra packet
//
if(pResult->_lObjectCurrent+1 != pResult->_lObjects || (phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS && !phSearchInfo->_fResultPrefetched)) { //
// 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.
//
phSearchInfo->_fCheckForDuplicates = FALSE; hr = GetNextRow( phSearchInfo ); phSearchInfo->_fCheckForDuplicates = TRUE; 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->_lObjectCurrent; 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->dwNumberOfAttributes;cAttr++,pAttribute++) { if (_wcsicmp( pAttribute->szAttributeName, pszColumnName ) == 0) break; } if (cAttr == pNextObject->dwNumberOfAttributes) { //
// 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, pAttribute->lpValue, pColumn ); BAIL_ON_FAILURE(hr); } done: if (fRowAdvanced) { phSearchInfo->_fCheckForDuplicates = FALSE; GetPreviousRow(phSearchInfo); phSearchInfo->_fCheckForDuplicates = TRUE; }
RRETURN(S_OK);
error:
if (fRowAdvanced) { phSearchInfo->_fCheckForDuplicates = FALSE; GetPreviousRow(phSearchInfo); phSearchInfo->_fCheckForDuplicates = TRUE; }
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; LPNDS_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;
pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
if( pResult->_lObjectCurrent < 0 ) RRETURN (E_ADS_BAD_PARAMETER);
pObject = pResult->_pObjects + pResult->_lObjectCurrent;
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->dwNumberOfAttributes) { if(pResult->_lObjectCurrent+1 != pResult->_lObjects || (phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS && !phSearchInfo->_fResultPrefetched)) { //
// 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.
//
phSearchInfo->_fCheckForDuplicates = FALSE; hr = GetNextRow( phSearchInfo ); phSearchInfo->_fCheckForDuplicates = TRUE; 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->_lObjectCurrent; 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->dwNumberOfAttributes; pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute + phSearchInfo->_dwCurrAttr - pObject->dwNumberOfAttributes; //
// 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->dwNumberOfAttributes) > 0) { pAttributeOld = pAttribute - 1; }
if (phSearchInfo->_dwCurrAttr >= (pObject->dwNumberOfAttributes + pNextObject->dwNumberOfAttributes)) { //
// 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->dwNumberOfAttributes + pNextObject->dwNumberOfAttributes)) { //
// 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->dwNumberOfAttributes; pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute + phSearchInfo->_dwCurrAttr - pObject->dwNumberOfAttributes; } } } } }
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 {
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);
switch(pColumn->dwADsType) { case ADSTYPE_CASE_IGNORE_STRING: if ((PNDSOBJECT)pColumn->hReserved) { //ADsPath does not have hReserved, it is a direct string allocation
if (pColumn->pADsValues) { FreeADsStr(pColumn->pADsValues[0].CaseIgnoreString); } } break;
default: // Nothing to free
break; }
if (pColumn->pADsValues) FreeADsMem(pColumn->pADsValues);
RRETURN(hr); }
HRESULT NdsValueToADsColumn( LPWSTR pszColumnName, DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpValue, ADS_SEARCH_COLUMN * pColumn ) { HRESULT hr = S_OK; LPASN1_TYPE_1 lpASN1_1; LPASN1_TYPE_7 lpASN1_7; LPASN1_TYPE_8 lpASN1_8; LPASN1_TYPE_9 lpASN1_9; LPASN1_TYPE_14 lpASN1_14; LPASN1_TYPE_24 lpASN1_24; DWORD i, j;
if(!pszColumnName || !pColumn) RRETURN(E_ADS_BAD_PARAMETER);
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: case NDS_SYNTAX_ID_11: case NDS_SYNTAX_ID_20: for (i=0; i < dwValues; i++) { lpASN1_1 = (LPASN1_TYPE_1) lpValue + i; pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].CaseIgnoreString = lpASN1_1->DNString; } break;
case NDS_SYNTAX_ID_14 : for (i=0; i < dwValues; i++) { lpASN1_14 = (LPASN1_TYPE_14) lpValue + i; pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].CaseIgnoreString = lpASN1_14->Address; } break;
// BYTE STREAM
case NDS_SYNTAX_ID_9: for (i=0; i < dwValues; i++) { lpASN1_9 = (LPASN1_TYPE_9) lpValue + i; pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].OctetString.dwLength =lpASN1_9->Length; pColumn->pADsValues[i].OctetString.lpValue = lpASN1_9->OctetString; } break;
// BOOLEAN
case NDS_SYNTAX_ID_7: for (i=0; i < dwValues; i++) { lpASN1_7 = (LPASN1_TYPE_7) lpValue + i; pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].Boolean = lpASN1_7->Boolean; } break;
// INTEGER
case NDS_SYNTAX_ID_8: case NDS_SYNTAX_ID_22: case NDS_SYNTAX_ID_27: for (i=0; i < dwValues; i++) { lpASN1_8 = (LPASN1_TYPE_8) lpValue + i; pColumn->pADsValues[i].dwType = pColumn->dwADsType; pColumn->pADsValues[i].Integer = lpASN1_8->Integer; } break;
case NDS_SYNTAX_ID_24 : for (i=0; i < dwValues; i++) { lpASN1_24 = (LPASN1_TYPE_24) lpValue + i; pColumn->pADsValues[i].dwType = pColumn->dwADsType; hr = ConvertDWORDtoSYSTEMTIME( lpASN1_24->Time, &(pColumn->pADsValues[i].UTCTime) ); BAIL_ON_FAILURE(hr); } 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_18 : 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; } break; } RRETURN(hr);
error:
if (pColumn->pADsValues) FreeADsMem(pColumn->pADsValues);
RRETURN(hr);
}
/*++
Routine Description:
Given a column, this function will append more values to the end
Return Value:
S_OK on success, error code otherwise
--*/ HRESULT NdsValueToADsColumnAppend( DWORD dwSyntaxId, DWORD dwValues, LPBYTE lpValue, ADS_SEARCH_COLUMN * pColumn ) { HRESULT hr = S_OK; LPASN1_TYPE_1 lpASN1_1; LPASN1_TYPE_7 lpASN1_7; LPASN1_TYPE_8 lpASN1_8; LPASN1_TYPE_9 lpASN1_9; LPASN1_TYPE_14 lpASN1_14; LPASN1_TYPE_24 lpASN1_24; DWORD i, j; PADSVALUE pADsValuesNew = NULL; DWORD dwValuesBase;
if(!pColumn) RRETURN(E_ADS_BAD_PARAMETER);
dwValuesBase = pColumn->dwNumValues;
//
// 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: case NDS_SYNTAX_ID_11: case NDS_SYNTAX_ID_20: for (i=0; i < dwValues; i++) { lpASN1_1 = (LPASN1_TYPE_1) lpValue + i; pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].CaseIgnoreString = lpASN1_1->DNString; } break;
case NDS_SYNTAX_ID_14 : for (i=0; i < dwValues; i++) { lpASN1_14 = (LPASN1_TYPE_14) lpValue + i; pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].CaseIgnoreString = lpASN1_14->Address; } break;
// BYTE STREAM
case NDS_SYNTAX_ID_9: for (i=0; i < dwValues; i++) { lpASN1_9 = (LPASN1_TYPE_9) lpValue + i; pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].OctetString.dwLength =lpASN1_9->Length; pColumn->pADsValues[dwValuesBase+i].OctetString.lpValue = lpASN1_9->OctetString; } break;
// BOOLEAN
case NDS_SYNTAX_ID_7: for (i=0; i < dwValues; i++) { lpASN1_7 = (LPASN1_TYPE_7) lpValue + i; pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].Boolean = lpASN1_7->Boolean; } break;
// INTEGER
case NDS_SYNTAX_ID_8: case NDS_SYNTAX_ID_22: case NDS_SYNTAX_ID_27: for (i=0; i < dwValues; i++) { lpASN1_8 = (LPASN1_TYPE_8) lpValue + i; pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; pColumn->pADsValues[dwValuesBase+i].Integer = lpASN1_8->Integer; } break;
case NDS_SYNTAX_ID_24 : for (i=0; i < dwValues; i++) { lpASN1_24 = (LPASN1_TYPE_24) lpValue + i; pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType; hr = ConvertDWORDtoSYSTEMTIME( lpASN1_24->Time, &(pColumn->pADsValues[dwValuesBase+i].UTCTime) ); BAIL_ON_FAILURE(hr); } 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_18 : 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; } break; } pColumn->dwNumValues = pColumn->dwNumValues + dwValues; error: //
// We don't need to free memory even in error case because it has been
// put into the column
//
RRETURN(hr); }
HRESULT NdsAddAttributes( IN ADS_SEARCH_HANDLE hSearchHandle, OUT HANDLE *phSearchResult ) { DWORD dwStatus = NO_ERROR; HANDLE hSearchResult = NULL; HRESULT hr; DWORD i; PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
if (!phSearchResult || !phSearchResult) RRETURN( E_FAIL );
*phSearchResult = NULL;
if(!phSearchInfo->_ppszAttrs) RRETURN(S_OK);
dwStatus = NwNdsCreateBuffer( NDS_SEARCH, &hSearchResult );
if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto error; }
for (i=0; phSearchInfo->_ppszAttrs[i]; i++) { dwStatus = NwNdsPutInBuffer( phSearchInfo->_ppszAttrs[i], 0, NULL, 0, 0, hSearchResult ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto error; } }
*phSearchResult = hSearchResult; RRETURN( S_OK );
error: if(hSearchResult) NwNdsFreeBuffer(phSearchInfo);
RRETURN(hr); }
|