|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
qryparse.cxx
Abstract:
Author:
Felix Wong [t-FelixW] 05-Nov-1996 ++*/ #include "nds.hxx"
#pragma hdrstop
//#define DEBUG_DUMPSTACK
//#define DEBUG_DUMPRULE
#if (defined(DEBUG_DUMPSTACK) || defined (DEBUG_DUMPRULE))
#include "stdio.h"
#endif
#define MAPHEXTODIGIT(x) ( x >= '0' && x <= '9' ? (x-'0') : \
x >= 'A' && x <= 'F' ? (x-'A'+10) : \ x >= 'a' && x <= 'f' ? (x-'a'+10) : 0 )
// Action Table
typedef struct _action{ DWORD type; DWORD dwState; }action;
// Rule Table
typedef struct _rule{ DWORD dwNumber; DWORD dwA; }rule;
enum types { N, S, R, A };
#define X 99
action g_action[28][14] = { // ERROR ,LPARAN,RPARAN,OR, AND, NOT, APPROX,EQ, LE, GE, PRESNT,ATYPE, VAL, END,
/*00*/ { {N,X },{S,2 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*01*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{A,X } }, /*02*/ { {N,X },{N,X },{N,X },{S,12},{S,11},{S,13},{N,X },{N,X },{N,X },{N,X },{N,X },{S,14},{N,X },{N,X } }, /*03*/ { {N,X },{N,X },{R,2 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*04*/ { {N,X },{N,X },{R,3 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*05*/ { {N,X },{N,X },{R,4 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*06*/ { {N,X },{N,X },{R,5 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*07*/ { {N,X },{N,X },{S,15},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*08*/ { {N,X },{N,X },{R,11},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*09*/ { {N,X },{N,X },{R,12},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*10*/ { {N,X },{N,X },{R,13},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*11*/ { {N,X },{S,2 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*12*/ { {N,X },{S,2 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*13*/ { {N,X },{S,2 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*14*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{S,20},{S,26},{S,22},{S,21},{S,23},{N,X },{N,X },{N,X } }, /*15*/ { {N,X },{R,1 },{R,1 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{R,1 } }, /*16*/ { {N,X },{N,X },{R,6 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*17*/ { {N,X },{S,2 },{R,9 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*18*/ { {N,X },{N,X },{R,7 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*19*/ { {N,X },{N,X },{R,8 },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*20*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{R,15},{N,X } }, /*21*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{R,16},{N,X } }, /*22*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{R,17},{N,X } }, /*23*/ { {N,X },{N,X },{R,18},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*24*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{S,25},{N,X } }, /*25*/ { {N,X },{N,X },{R,14},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } }, /*26*/ { {N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{R,19},{N,X } }, /*27*/ { {N,X },{N,X },{R,10},{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X },{N,X } } };
enum non_terminals { NONTERM_F, NONTERM_FC, NONTERM_AND, NONTERM_OR, NONTERM_NOT, NONTERM_FL, NONTERM_ITM, NONTERM_SMP, NONTERM_FT, NONTERM_PRS };
rule g_rule[] = { // 1)No. of non-terminals and terminals on the right hand side
// 2)The Parent
/*00*/ {0, 0, }, /*01*/ {3, NONTERM_F, }, /*02*/ {1, NONTERM_FC, }, /*03*/ {1, NONTERM_FC, }, /*04*/ {1, NONTERM_FC, }, /*05*/ {1, NONTERM_FC, }, /*06*/ {2, NONTERM_AND, }, /*07*/ {2, NONTERM_OR, }, /*08*/ {2, NONTERM_NOT, }, /*09*/ {1, NONTERM_FL, }, /*10*/ {2, NONTERM_FL, }, /*11*/ {1, NONTERM_ITM, }, /*12*/ {1, NONTERM_ITM, }, /*13*/ {1, NONTERM_ITM, }, /*14*/ {3, NONTERM_SMP, }, /*15*/ {1, NONTERM_FT, }, /*16*/ {1, NONTERM_FT, }, /*17*/ {1, NONTERM_FT, }, /*18*/ {2, NONTERM_PRS, }, /*19*/ {1, NONTERM_FT, } };
#ifdef DEBUG_DUMPRULE
LPWSTR g_rgszRule[] = { /*00*/ L"", /*01*/ L"F->(FC)", /*02*/ L"FC->AND", /*03*/ L"FC->OR", /*04*/ L"FC->NOT", /*05*/ L"FC->ITM", /*06*/ L"AND->&FL", /*07*/ L"OR->|FL", /*08*/ L"NOT->!F", /*09*/ L"FL->F", /*10*/ L"FL->F FL", /*11*/ L"ITM->SMP", /*12*/ L"ITM->PRS", /*13*/ L"ITM->STR", /*14*/ L"SMP->ATR FT VAL", /*15*/ L"FT->~=", /*16*/ L"FT->>=", /*17*/ L"FT-><=", /*18*/ L"PRS->ATR=*", /*19*/ L"FT->=" }; #endif
DWORD g_goto[28][10] = { // F, FC, AND, OR, NOT, FL, ITM, SMP, FT, PRS,
/*00*/ {1, X, X, X, X, X, X, X, X, X }, /*01*/ {X, X, X, X, X, X, X, X, X, X }, /*02*/ {X, 7, 3, 4, 5, X, 6, 8, X, 9 }, /*03*/ {X, X, X, X, X, X, X, X, X, X }, /*04*/ {X, X, X, X, X, X, X, X, X, X }, /*05*/ {X, X, X, X, X, X, X, X, X, X }, /*06*/ {X, X, X, X, X, X, X, X, X, X }, /*07*/ {X, X, X, X, X, X, X, X, X, X }, /*08*/ {X, X, X, X, X, X, X, X, X, X }, /*09*/ {X, X, X, X, X, X, X, X, X, X }, /*10*/ {X, X, X, X, X, X, X, X, X, X }, /*11*/ {17, X, X, X, X, 16, X, X, X, X }, /*12*/ {17, X, X, X, X, 18, X, X, X, X }, /*13*/ {19, X, X, X, X, X, X, X, X, X }, /*14*/ {X, X, X, X, X, X, X, X, 24, X }, /*15*/ {X, X, X, X, X, X, X, X, X, X }, /*16*/ {X, X, X, X, X, X, X, X, X, X }, /*17*/ {17, X, X, X, X, 27, X, X, X, X }, /*18*/ {X, X, X, X, X, X, X, X, X, X }, /*19*/ {X, X, X, X, X, X, X, X, X, X }, /*20*/ {X, X, X, X, X, X, X, X, X, X }, /*21*/ {X, X, X, X, X, X, X, X, X, X }, /*22*/ {X, X, X, X, X, X, X, X, X, X }, /*23*/ {X, X, X, X, X, X, X, X, X, X }, /*24*/ {X, X, X, X, X, X, X, X, X, X }, /*25*/ {X, X, X, X, X, X, X, X, X, X }, /*26*/ {X, X, X, X, X, X, X, X, X, X }, /*27*/ {X, X, X, X, X, X, X, X, X, X } };
HRESULT MapTokenToType( DWORD dwToken, DWORD *pdwType ) { DWORD dwType; switch(dwToken) { case TOKEN_EQ: dwType = QUERY_EQUAL; break; case TOKEN_LE: dwType = QUERY_LE; break; case TOKEN_GE: dwType = QUERY_GE; break; case TOKEN_APPROX_EQ: dwType = QUERY_APPROX; break; default: return (E_ADS_INVALID_FILTER); } *pdwType = dwType; return (S_OK); }
HRESULT Parse( LPWSTR szQuery, CQueryNode **ppNode, CAttrList **ppAttrList ) { CStack Stack; CQryLexer Query(szQuery); LPWSTR lexeme; DWORD dwToken; DWORD dwState; HRESULT hr = E_ADS_INVALID_FILTER;
CAttrList* pAttrList = new CAttrList; if (!pAttrList) return E_OUTOFMEMORY;
CSyntaxNode *pSynNode = NULL; CQueryNode *pNode1 = NULL; CQueryNode *pNode2 = NULL; CQueryNode *pNode3 = NULL; // Push in State 0
pSynNode = new CSyntaxNode; Stack.Push(pSynNode); pSynNode = NULL;
#ifdef DEBUG_DUMPSTACK
Stack.Dump(); #endif
while (1) { // Getting information for this iteration, dwToken and dwState
hr = Query.GetCurrentToken( &lexeme, &dwToken ); BAIL_ON_FAILURE(hr);
hr = Stack.Current(&pSynNode); BAIL_ON_FAILURE(hr); dwState = pSynNode->_dwState; pSynNode = NULL; // Analysing and processing the data
if (g_action[dwState][dwToken].type == S) { pSynNode = new CSyntaxNode; pSynNode->_dwState = g_action[dwState][dwToken].dwState; pSynNode->_dwToken = dwToken; switch (dwToken) { case TOKEN_ATTRTYPE: { hr = pAttrList->Add(lexeme); BAIL_ON_FAILURE(hr); } case TOKEN_ATTRVAL: // both TOKEN_ATTRTYPE and TOKEN_ATTRVAL will get here
{ LPWSTR szValue = AllocADsStr(lexeme); if (!szValue) { hr = E_OUTOFMEMORY; goto error; } pSynNode->SetNode(szValue); break; } } hr = Stack.Push(pSynNode); BAIL_ON_FAILURE(hr); pSynNode = NULL;
hr = Query.GetNextToken( &lexeme, &dwToken ); BAIL_ON_FAILURE(hr); #ifdef DEBUG_DUMPSTACK
Stack.Dump(); #endif
} else if (g_action[dwState][dwToken].type == R) { DWORD dwRule = g_action[dwState][dwToken].dwState; DWORD dwNumber = g_rule[dwRule].dwNumber; #ifdef DEBUG_DUMPRULE
wprintf(L"%s\n",g_rgszRule[dwRule]); #endif
pSynNode = new CSyntaxNode; CSyntaxNode *pSynNodeRed; switch (dwRule) { case 1: // Reduction of Basic Filter rule
{ // Getting the middle node
hr = Stack.Pop(); BAIL_ON_FAILURE(hr); hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr);
pSynNode->SetNode( pSynNodeRed->_pNode ); pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = Stack.Pop(); BAIL_ON_FAILURE(hr); break; } case 18: // Reduction of PRESENT rule
{ // Getting second node
LPWSTR szType; hr = Stack.Pop(); BAIL_ON_FAILURE(hr); hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); szType = pSynNodeRed->_szValue; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = MakeLeaf( szType, &pNode1 ); BAIL_ON_FAILURE(hr); hr = MakeNode( QUERY_PRESENT, pNode1, NULL, &pNode2 ); BAIL_ON_FAILURE(hr); pNode1 = NULL;
pSynNode->SetNode( pNode2 ); pNode2 = NULL; break; } case 14: // Reduction of SMP rule
{ LPWSTR szType; LPWSTR szValue; DWORD dwType; DWORD dwToken;
hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); szValue = pSynNodeRed->_szValue; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); dwToken = (DWORD)pSynNodeRed->_dwFilterType; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); szType = pSynNodeRed->_szValue; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = MakeLeaf( szType, &pNode1 ); BAIL_ON_FAILURE(hr); hr = MakeLeaf( szValue, &pNode2 ); BAIL_ON_FAILURE(hr); hr = MapTokenToType( dwToken, &dwType ); BAIL_ON_FAILURE(hr); hr = MakeNode( dwType, pNode1, pNode2, &pNode3 ); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pNode3 ); pNode1 = NULL; pNode2 = NULL; pNode3 = NULL;
break; } case 6: // Reduction of AND, OR rules
case 7: { DWORD dwType; Stack.Pop(&pSynNodeRed); pSynNode->SetNode( pSynNodeRed->_pNode ); pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; Stack.Pop(); // Adding in the type information
if (dwRule == 6) dwType = QUERY_AND; else dwType = QUERY_OR; pSynNode->_pNode->_dwType = dwType; break; } case 10: // Reduction of FL rule
{ DWORD dwType; hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); pNode2 = pSynNodeRed->_pNode; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); pNode1 = pSynNodeRed->_pNode; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; if (pNode2->_dwType == QUERY_UNKNOWN) { // It's not new node, append to node1
hr = pNode2->AddChild(pNode1); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pNode2 ); pNode1 = NULL; pNode2 = NULL; } else { // New node
hr = MakeNode( QUERY_UNKNOWN, pNode1, pNode2, &pNode3 ); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pNode3 ); pNode1 = NULL; pNode2 = NULL; pNode3 = NULL; } break; } case 9: // Reduction of FL rule
{ DWORD dwType; hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); pNode1 = pSynNodeRed->_pNode; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = MakeNode( QUERY_UNKNOWN, pNode1, NULL, &pNode3 ); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pNode3 ); pNode1 = NULL; pNode3 = NULL; break; } case 8: // Reduction of NOT rule
{ Stack.Pop(&pSynNodeRed); pNode1 = pSynNodeRed->_pNode; pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; hr = MakeNode( QUERY_NOT, pNode1, NULL, &pNode2 ); BAIL_ON_FAILURE(hr); pNode1 = NULL; hr = Stack.Pop(); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pNode2 ); pNode2 = NULL; break; } case 15: // Reduction of FT rule
case 16: case 17: case 19: { // Propagating the last entry
hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pSynNodeRed->_dwToken ); pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; break; } default: { // For all the other rules, we propogate the last entry
hr = Stack.Pop(&pSynNodeRed); BAIL_ON_FAILURE(hr); pSynNode->SetNode( pSynNodeRed->_pNode ); pSynNodeRed->_dwType = SNODE_NULL; delete pSynNodeRed; for (DWORD i = 0;i<dwNumber-1;i++) Stack.Pop(); } } hr = Stack.Current(&pSynNodeRed); BAIL_ON_FAILURE(hr); dwState = pSynNodeRed->_dwState; DWORD A = g_rule[dwRule].dwA; pSynNode->_dwState = g_goto[dwState][A]; pSynNode->_dwToken = A; hr = Stack.Push(pSynNode); BAIL_ON_FAILURE(hr); pSynNode = NULL; #ifdef DEBUG_DUMPSTACK
Stack.Dump(); #endif
} else if (g_action[dwState][dwToken].type == A){ hr = Stack.Pop(&pSynNode); BAIL_ON_FAILURE(hr); *ppNode = pSynNode->_pNode; *ppAttrList = pAttrList; pSynNode->_dwType = SNODE_NULL; delete pSynNode; return S_OK; } else { hr = E_ADS_INVALID_FILTER; goto error; } } error: if (pAttrList) { delete pAttrList; } if (pSynNode) { delete pSynNode; } if (pNode1) { delete pNode1; } if (pNode2) { delete pNode2; } if (pNode3) { delete pNode3; } return hr; }
CStack::CStack() { _dwStackIndex = 0; }
CStack::~CStack() { DWORD dwIndex = _dwStackIndex; while (dwIndex > 0) { CSyntaxNode *pNode; pNode = _Stack[--dwIndex]; delete pNode; } }
#ifdef DEBUG_DUMPSTACK
void CStack::Dump() { DWORD dwIndex = _dwStackIndex; printf("Stack:\n"); while (dwIndex > 0) { CSyntaxNode *pNode; pNode = _Stack[--dwIndex]; printf( "State=%5.0d, Token=%5.0d\n", pNode->_dwState, pNode->_dwToken ); } } #endif
HRESULT CStack::Push(CSyntaxNode* pNode) { if (_dwStackIndex < MAXVAL) { _Stack[_dwStackIndex++] = pNode; return S_OK; } else return E_FAIL; }
HRESULT CStack::Pop(CSyntaxNode** ppNode) { if (_dwStackIndex > 0) { *ppNode = _Stack[--_dwStackIndex]; return S_OK; } else { return E_FAIL; } }
HRESULT CStack::Pop() { if (_dwStackIndex > 0) { CSyntaxNode *pNode; pNode = _Stack[--_dwStackIndex]; delete pNode; return S_OK; } else { return E_FAIL; } }
HRESULT CStack::Current(CSyntaxNode **ppNode) { if (_dwStackIndex > 0) { *ppNode = _Stack[_dwStackIndex-1]; return S_OK; } else { return E_FAIL; } }
CAttrList::CAttrList() { _rgAttr = NULL; _dwAttrCur = 0; }
CAttrList::~CAttrList() { if (_rgAttr) { for (DWORD i=0;i<_dwAttrCur;i++) FreeADsStr(_rgAttr[i].szName); FreeADsMem(_rgAttr); } }
HRESULT CAttrList::Add(LPWSTR szName) { HRESULT hr = S_OK; LPWSTR pszTemp = NULL;
for (DWORD i=0;i<_dwAttrCur;i++) { if (_wcsicmp( szName, _rgAttr[i].szName ) == 0) break; } if (i != _dwAttrCur) // does not loop till the end, entry exist already
return S_OK; LPWSTR szAttr = AllocADsStr(szName); if (!szAttr) return E_OUTOFMEMORY;
if (_dwAttrCur == _dwAttrMax) { if (!_rgAttr) { _rgAttr = (AttrNode*)AllocADsMem(ATTRNODE_INITIAL*sizeof(AttrNode)); if (!_rgAttr) { hr = E_OUTOFMEMORY; goto error; } _dwAttrMax = ATTRNODE_INITIAL; } else { _rgAttr = (AttrNode*)ReallocADsMem( (void*)_rgAttr, _dwAttrMax*sizeof(AttrNode), (_dwAttrMax+ATTRNODE_INC)*sizeof(AttrNode) ); if (!_rgAttr) { hr = E_OUTOFMEMORY; goto error; } _dwAttrMax+= ATTRNODE_INC; } } _rgAttr[_dwAttrCur].szName = szAttr; _rgAttr[_dwAttrCur].dwType = 0; //UNKNOWN at this point
_dwAttrCur++; return S_OK; error: if (szAttr) FreeADsStr(szAttr); return (hr); }
HRESULT CAttrList::SetupType(LPWSTR szConnection) { DWORD dwStatus; HRESULT hr=S_OK; HANDLE hOperationData = NULL; DWORD dwNumberOfEntries; DWORD dwInfoType; LPNDS_ATTR_DEF lpAttrDefs = NULL; HANDLE hConnection = NULL; DWORD i,j,k; dwStatus = NwNdsOpenObject( szConnection, NULL, NULL, &hConnection, NULL, NULL, NULL, 0, 0 ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto error; }
dwStatus = NwNdsCreateBuffer( NDS_SCHEMA_READ_ATTR_DEF, &hOperationData ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto error; }
for (i=0;i<_dwAttrCur;i++) { dwStatus = NwNdsPutInBuffer( _rgAttr[i].szName, 0, NULL, 0, 0, hOperationData ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto error; } } dwStatus = NwNdsReadAttrDef( hConnection, NDS_INFO_NAMES_DEFS, &hOperationData ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
dwStatus = NwNdsGetAttrDefListFromBuffer( hOperationData, &dwNumberOfEntries, &dwInfoType, (LPVOID *) &lpAttrDefs ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto error; }
if (dwNumberOfEntries != _dwAttrCur) { hr = E_ADS_INVALID_FILTER; goto error; }
for (j = 0; j < dwNumberOfEntries ; j++ ) { for (k = 0; k < dwNumberOfEntries; k++) { if (_wcsicmp( _rgAttr[k].szName, lpAttrDefs[j].szAttributeName ) == 0) { _rgAttr[k].dwType = lpAttrDefs[j].dwSyntaxID; break; } } if (k == dwNumberOfEntries) // cannot find entry
goto error; }
error: if (hOperationData) NwNdsFreeBuffer( hOperationData ); if (hConnection) NwNdsCloseObject( hConnection); RRETURN(hr); }
HRESULT CAttrList::GetType(LPWSTR szName, DWORD *pdwType) { for (DWORD i=0;i<_dwAttrCur;i++) { if (_wcsicmp( szName, _rgAttr[i].szName ) == 0) break; } if (i == _dwAttrCur) // Cannot find attribute
return E_FAIL;
*pdwType = _rgAttr[i].dwType; return S_OK; }
CSyntaxNode::CSyntaxNode() { _dwType = SNODE_NULL; _dwToken = 0; _dwState = 0; _pNode = 0; }
CSyntaxNode::~CSyntaxNode() { switch (_dwType) { case SNODE_SZ: FreeADsStr(_szValue); break; case SNODE_NODE: delete _pNode; break; default: break; } }
void CSyntaxNode::SetNode( CQueryNode *pNode ) { _pNode = pNode; _dwType = SNODE_NODE; }
void CSyntaxNode::SetNode( LPWSTR szValue ) { _szValue = szValue; _dwType = SNODE_SZ; }
void CSyntaxNode::SetNode( DWORD dwFilterType ) { _dwFilterType = dwFilterType; _dwType = SNODE_FILTER; }
//+---------------------------------------------------------------------------
//
// Function: CQueryNode::CQueryNode
//
// Synopsis: Constructor of the CQueryNode
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
CQueryNode::CQueryNode() { _dwType = 0; _szValue = NULL; _dwQueryNode = 0; _rgQueryNode = NULL; _dwQueryNodeMax = 0; }
//+---------------------------------------------------------------------------
//
// Function: CQueryNode::SetToString
//
// Synopsis: Set the Node to be a String Node
//
// Arguments: szValue value of the string
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT CQueryNode::SetToString( LPWSTR szValue ) { _szValue = szValue; /*
_szValue = AllocADsStr(szValue); if (!_szValue) { return E_OUTOFMEMORY; } */ _dwType = QUERY_STRING; return S_OK; }
//+---------------------------------------------------------------------------
//
// Function: CQueryNode::~CQueryNode
//
// Synopsis: Destructor of the CQueryNode
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
CQueryNode::~CQueryNode() { if (_szValue) FreeADsStr(_szValue); if (_rgQueryNode) { for (DWORD i=0;i<_dwQueryNode;i++) { delete _rgQueryNode[i]; } FreeADsMem(_rgQueryNode); } }
//+---------------------------------------------------------------------------
//
// Function: CQueryNode::AddChild
//
// Synopsis: Add a child to the node
//
// Arguments: CQueryNode *pChild pointer to the child to be added
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT CQueryNode::AddChild(CQueryNode *pChild) { if (_dwQueryNode == _dwQueryNodeMax) { if (!_rgQueryNode) { _rgQueryNode = (CQueryNode**)AllocADsMem(QUERYNODE_INITIAL*sizeof(CQueryNode*)); if (!_rgQueryNode) { return E_OUTOFMEMORY; } _dwQueryNodeMax = QUERYNODE_INITIAL; } else { _rgQueryNode = (CQueryNode**)ReallocADsMem( (void*)_rgQueryNode, _dwQueryNodeMax*sizeof(CQueryNode*), (_dwQueryNodeMax+QUERYNODE_INC)*sizeof(CQueryNode*) ); if (!_rgQueryNode) { return E_OUTOFMEMORY; } _dwQueryNodeMax+= QUERYNODE_INC; } } _rgQueryNode[_dwQueryNode] = pChild; _dwQueryNode++; return S_OK; } //+---------------------------------------------------------------------------
//
// Function: CQueryNode::GenerateNDSTree
//
// Synopsis: Generate an NDS tree with the current CQueryNode
//
// Arguments: pAttrList list of attributes to get syntax info
// ppNDSSearchTree output of NDS Search Tree generated
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT CQueryNode::GenerateNDSTree( CAttrList *pAttrList, LPQUERY_NODE *ppNDSSearchTree ) { HRESULT hr = E_FAIL; DWORD dwOperation; DWORD dwStatus = 0;
LPWSTR szAttr = NULL; LPWSTR szValue = NULL; LPQUERY_NODE pQueryNode1 = NULL; LPQUERY_NODE pQueryNode2 = NULL; LPQUERY_NODE pQueryNode3 = NULL;
// Looking at type of operation
switch (_dwType) { case QUERY_EQUAL: case QUERY_LE: case QUERY_GE: case QUERY_APPROX: case QUERY_PRESENT: { ASN1_TYPE_1 Asn1_WSTR; ASN1_TYPE_7 Asn1_BOOL; ASN1_TYPE_8 Asn1_DWORD; ASN1_TYPE_9 Asn1_Binary; void* pValue = NULL; DWORD dwSyntax; DWORD dwAttrType = 0; LPWSTR pszTemp = NULL;
// Getting left node
if (_rgQueryNode[0] && _rgQueryNode[0]->_dwType == QUERY_STRING) { szAttr = AllocADsStr(_rgQueryNode[0]->_szValue); if (!szAttr) { hr = E_OUTOFMEMORY; goto error; }
} else { // No nodes available
goto error; }
// Getting right node
if (_rgQueryNode[1] && _rgQueryNode[1]->_dwType == QUERY_STRING) {
// Get syntax info of right node from attribute list
hr = pAttrList->GetType( szAttr, &dwAttrType ); BAIL_ON_FAILURE(hr);
// Format the node depending on the syntax
switch (dwAttrType) { // 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: szValue = AllocADsStr(_rgQueryNode[1]->_szValue); if (!szValue) { hr = E_OUTOFMEMORY; goto error; } Asn1_WSTR.DNString = szValue; pValue = (void*)&Asn1_WSTR; break;
// BOOLEAN
case NDS_SYNTAX_ID_7: Asn1_BOOL.Boolean = _wtoi(_rgQueryNode[1]->_szValue); pValue = (void*)&Asn1_BOOL; break;
// Binary Strings
case NDS_SYNTAX_ID_9: { //
// change the unicode form of binary encoded data
// to binary
// L"0135ABCDEF0" gets changed to 0x0135ABCDEF0
// same as the Ldap client code.
//
hr = ADsDecodeBinaryData ( _rgQueryNode[1]->_szValue, &Asn1_Binary.OctetString, &Asn1_Binary.Length); BAIL_ON_FAILURE(hr);
pValue = (void*)&Asn1_Binary; } break; // TimeStamp
case NDS_SYNTAX_ID_24 : { SYSTEMTIME st; TCHAR sz[3]; LPWSTR pszSrc = _rgQueryNode[1]->_szValue; //
// Year
//
sz[0] = pszSrc[0]; sz[1] = pszSrc[1]; sz[2] = TEXT('\0'); st.wYear = (WORD) _ttoi(sz); if (st.wYear < 50) { st.wYear += 2000; } else { st.wYear += 1900; } //
// Month
//
sz[0] = pszSrc[2]; sz[1] = pszSrc[3]; st.wMonth = (WORD) _ttoi(sz); //
// Day
//
sz[0] = pszSrc[4]; sz[1] = pszSrc[5]; st.wDay = (WORD) _ttoi(sz); //
// Hour
//
sz[0] = pszSrc[6]; sz[1] = pszSrc[7]; st.wHour = (WORD) _ttoi(sz); //
// Minute
//
sz[0] = pszSrc[8]; sz[1] = pszSrc[9]; st.wMinute = (WORD) _ttoi(sz); //
// Second
//
sz[0] = pszSrc[10]; sz[1] = pszSrc[11]; st.wSecond = (WORD) _ttoi(sz); st.wMilliseconds = 0; hr = ConvertSYSTEMTIMEtoDWORD( &st, &Asn1_DWORD.Integer ); BAIL_ON_FAILURE (hr); pValue = (void*)&Asn1_DWORD; break; } // DWORD
case NDS_SYNTAX_ID_8 : case NDS_SYNTAX_ID_22 : case NDS_SYNTAX_ID_27 : Asn1_DWORD.Integer = _wtol(_rgQueryNode[1]->_szValue); pValue = (void*)&Asn1_DWORD; break;
case NDS_SYNTAX_ID_6 : case NDS_SYNTAX_ID_13 : case NDS_SYNTAX_ID_14 : 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_23 : case NDS_SYNTAX_ID_25 : case NDS_SYNTAX_ID_26 : default: hr = E_ADS_CANT_CONVERT_DATATYPE; goto error; break; } }
hr = MapQueryToNDSType( _dwType, &dwOperation ); BAIL_ON_FAILURE (hr);
dwStatus = NwNdsCreateQueryNode( dwOperation, szAttr, dwAttrType, pValue, ppNDSSearchTree ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); RRETURN (hr); }
if (szAttr) FreeADsStr(szAttr); if (szValue) FreeADsStr(szValue); break; } case QUERY_AND: case QUERY_OR: { hr = MapQueryToNDSType( _dwType, &dwOperation ); BAIL_ON_FAILURE (hr);
// Create first node
if (!_rgQueryNode[0]) goto error;
hr = _rgQueryNode[0]->GenerateNDSTree( pAttrList, &pQueryNode1 ); BAIL_ON_FAILURE (hr);
// Go through a loop creating the rest
for (DWORD i=1;i<_dwQueryNode;i++) { if (!_rgQueryNode[i]) goto error;
hr = _rgQueryNode[i]->GenerateNDSTree( pAttrList, &pQueryNode2 ); BAIL_ON_FAILURE (hr);
dwStatus = NwNdsCreateQueryNode( dwOperation, pQueryNode1, NULL, //not used since this is AND/OR/NOT
pQueryNode2, &pQueryNode3 ); if (dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); RRETURN (hr); } pQueryNode1 = pQueryNode3; } *ppNDSSearchTree = pQueryNode1; break; } case QUERY_NOT: { hr = MapQueryToNDSType( _dwType, &dwOperation ); BAIL_ON_FAILURE (hr);
// Create first node
if (!_rgQueryNode[0]) goto error;
hr = _rgQueryNode[0]->GenerateNDSTree( pAttrList, &pQueryNode1 ); BAIL_ON_FAILURE (hr);
hr = NwNdsCreateQueryNode( dwOperation, pQueryNode1, NULL, NULL, &pQueryNode3 ); BAIL_ON_FAILURE (hr); *ppNDSSearchTree = pQueryNode3; break; } default: goto error; } RRETURN(hr);
error: if (pQueryNode1) NwNdsDeleteQueryTree(pQueryNode1); if (pQueryNode2) NwNdsDeleteQueryTree(pQueryNode2); if (szAttr) FreeADsStr(szAttr); if (szValue) FreeADsStr(szValue); return hr; }
//+---------------------------------------------------------------------------
//
// Function: CQueryNode::MapQueryToNDSType
//
// Synopsis: Maps the node type to the equivalent NDS types
//
// Arguments: dwType input type
// pdwNDSType output type
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT CQueryNode::MapQueryToNDSType( DWORD dwType, DWORD *pdwNDSType ) { DWORD dwNDSType; switch(dwType) { case QUERY_EQUAL: dwNDSType = NDS_QUERY_EQUAL; break; case QUERY_LE: dwNDSType = NDS_QUERY_LE; break; case QUERY_GE: dwNDSType = NDS_QUERY_GE; break; case QUERY_APPROX: dwNDSType = NDS_QUERY_APPROX; break; case QUERY_PRESENT: dwNDSType = NDS_QUERY_PRESENT; break; case QUERY_NOT: dwNDSType = NDS_QUERY_NOT; break; case QUERY_AND: dwNDSType = NDS_QUERY_AND; break; case QUERY_OR: dwNDSType = NDS_QUERY_OR; break;
default: return (E_ADS_INVALID_FILTER); } *pdwNDSType = dwNDSType; return (S_OK); }
// Helper Functions for creating nodes using the CQueryNode Class
//+---------------------------------------------------------------------------
//
// Function: MakeNode
//
// Synopsis: Make a node with the input values
//
// Arguments: dwType type of node
// pLQueryNode pointer to left node
// pRQueryNode pointer to right node
// ppQueryNodeReturn pointer to Return Node
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT MakeNode( DWORD dwType, CQueryNode *pLQueryNode, CQueryNode *pRQueryNode, CQueryNode **ppQueryNodeReturn ) { HRESULT hr = S_OK;
CQueryNode *pQueryNode = new CQueryNode(); if (!pQueryNode) return E_OUTOFMEMORY;
pQueryNode->_dwType = dwType;
hr = pQueryNode->AddChild(pLQueryNode); BAIL_ON_FAILURE(hr);
if (pRQueryNode) { pQueryNode->AddChild(pRQueryNode); BAIL_ON_FAILURE(hr); } *ppQueryNodeReturn = pQueryNode;
RRETURN(hr);
error: delete pQueryNode; RRETURN(hr); }
//+---------------------------------------------------------------------------
//
// Function: MakeLeaf
//
// Synopsis: Constructor of the CQueryNode
//
// Arguments: szValue value of the string
// ppQueryNodeReturn the return node
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT MakeLeaf( LPWSTR szValue, CQueryNode **ppQueryNodeReturn ) { HRESULT hr = S_OK;
CQueryNode *pQueryNode = new CQueryNode(); if (!pQueryNode) return E_OUTOFMEMORY;
hr = pQueryNode->SetToString(szValue); BAIL_ON_FAILURE(hr);
*ppQueryNodeReturn = pQueryNode; RRETURN(hr);
error: delete pQueryNode; RRETURN(hr); }
//+---------------------------------------------------------------------------
//
// Function: ADsNdsGenerateParseTree
//
// Synopsis: Generate an NDS search tree to be used as inputs to NDS search
// functions
//
// Arguments: pszCommandText - Command text for the search
// szConnection - server to get the schema from
// ppQueryNode - the generated NDS search tree
//
// Returns: HRESULT
// S_OK NO ERROR
// E_OUTOFMEMORY no memory
//
// Modifies:
//
// History: 10-29-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT AdsNdsGenerateParseTree( LPWSTR szCommandText, LPWSTR szConnection, LPQUERY_NODE *ppQueryNode ) { HRESULT hr; LPQUERY_NODE pNDSSearchTree; CQueryNode *pNode = NULL; CAttrList *pAttrList = NULL;
// Generate the parse tree and the attribute list
hr = Parse( szCommandText, &pNode, &pAttrList ); BAIL_ON_FAILURE(hr);
// Setup syntax information in the attribute list
hr = pAttrList->SetupType(szConnection); BAIL_ON_FAILURE(hr);
// Generate the NDS tree
hr = pNode->GenerateNDSTree( pAttrList, &pNDSSearchTree ); BAIL_ON_FAILURE(hr);
*ppQueryNode = pNDSSearchTree;
error: if (pNode) delete pNode; if (pAttrList) delete pAttrList; return hr; }
|