1480 lines
45 KiB
C++
1480 lines
45 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|